Rotate Bitmap Xamarin - xamarin

I am loading an image from a webserver, I want to rotate it if the orientation is wrong. I've seen how to do it from a bitmap on my phone, it takes the filename but nothing with an actual bitmap. I am using this to resize it, but unsure on the rotate part.
public Bitmap resizeAndRotate(Bitmap image, int width, int height)
{
Bitmap newImage= Bitmap.createScaledBitmap(image, newWidth, newHeight, true);
return newImage;
}

You can scale and rotate the bitmap in one call by passing a Android.Graphics.Matrix that include both the scale and rotation in the transformation to Bitmap.CreateBitmap:
public Bitmap resizeAndRotate(Bitmap image, int width, int height)
{
var matrix = new Matrix();
var scaleWidth = ((float)width) / image.Width;
var scaleHeight = ((float)height) / image.Height;
matrix.PostRotate(90);
matrix.PreScale(scaleWidth, scaleHeight);
return Bitmap.CreateBitmap(image, 0, 0, image.Width, image.Height, matrix, true);
}

Related

How to put rounded corners to canvas image?

I am drawing an image on Canvas in following manner.
void paint(Canvas canvas, Size size) {
Paint paint = Paint();
paint.color = Colors.white;
canvas.drawImageRect(
img,
Rect.fromLTWH(0, 0, img.width.toDouble(), img.height.toDouble()),
Rect.fromLTWH(0, 0, newImgWidth, newImgHeight),
paint);
}
I want to give rounded corners to this image.
Can anyone provide some help on how to do something like that?
Lets make a try to use clipRRect() method of Canvas class
Add following code snippet inside your paint() method and
change the value 20 with your required radius value
canvas.clipRRect(
RRect.fromLTRBAndCorners(20, 20, 20, 20); // left, top, right, bottom
);
Full version
void paint(Canvas canvas, Size size) {
Paint paint = Paint();
paint.color = Colors.white;
canvas.clipRRect(
RRect.fromLTRBAndCorners(20, 20, 20, 20); // left, top, right, bottom
);
canvas.drawImageRect(
img,
Rect.fromLTWH(0, 0, img.width.toDouble(), img.height.toDouble()),
Rect.fromLTWH(0, 0, newImgWidth, newImgHeight),
paint);
}
let me give you code sample
void paint(Canvas canvas, Size size) {
Paint paint = Paint();
paint.color = Colors.white;
canvas.clipRRect(
RRect.fromLTRBAndCorners(0, 0, img.width.toDouble(), img.height.toDouble(),topLeft:20,topRight:20,bottomLeft:20,bottomRight:20); // left, top, right, bottom
);
canvas.drawImageRect(
img,
Rect.fromLTWH(0, 0, img.width.toDouble(), img.height.toDouble()),
Rect.fromLTWH(0, 0, newImgWidth, newImgHeight),
paint);
}
you have to match the coordinates of RRect and the ImageRect that you want to clip

Image auto-cropping, issue with borders

I'm talking photo in my application. After I take it, on next screen in layout I want it be automatically cropped like in image.
But I'm constantly lose the boundaries of the photo and I have strange borders (indicated by RED in the image).
Here is my code:
Android code
private void NewElement_OnDrawBitmap(object sender, EventArgs e)
{
if (this.ViewGroup != null)
{
//get the subview
Android.Views.View subView = ViewGroup.GetChildAt(0);
int width = subView.Width;
int height = subView.Height;
//create and draw the bitmap
Bitmap b = Bitmap.CreateBitmap(width, height, Bitmap.Config.Argb8888);
Canvas c = new Canvas(b);
ViewGroup.Draw(c);
//save the bitmap to file
bytes = SaveBitmapToFile(b);
}
}
iOS code
UIGraphics.BeginImageContextWithOptions(this.Bounds.Size, true, 0);
this.Layer.RenderInContext(UIGraphics.GetCurrentContext());
var img = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
using (NSData imageData = img.AsPNG())
{
bytes = new Byte[imageData.Length];
System.Runtime.InteropServices.Marshal.Copy(imageData.Bytes, bytes, 0, Convert.ToInt32(imageData.Length));
}
private byte[] SaveBitmapToFile(Bitmap bm)
{
MemoryStream ms = new MemoryStream();
bm.Compress(Bitmap.CompressFormat.Png, 100, ms);
return ms.ToArray();
}
}
From your shared code, you're not doing any cropping, so your app just put your origin picture into the view, and the border you mentioned, is probably the background of your view.
And your project code, I saw you added
Bitmap bitmap = Bitmap.CreateBitmap(b, 0, 0, (98 * width) / 100, (82 * height) / 100);
Yes this is cropping the picture, but this just crop the image from top-left corner to 98% width and 82% height. much like
If you want to crop the picture into a square focused in center, you can simply:
int offset = (height - width) / 2;
Bitmap bitmap = Bitmap.CreateBitmap(b, 0, offset, width, height- offset);
But if you want to do more operations on Image like move/zoom... and then crop, I'd like to suggest you turn to existing solutions like FFImageLoading or Syncfusion. Or you'll have to calculate all the move/zoom data to do the crop.

How can I show only a part of an image in Processing?

I want to compare two images (same size) fr a presentation with a shifting line. On the left side of this line the one image is should be displayed while on the right side the other picture should stay visible.
This is what I tried (bitmap and ch are the images)
PImage bitmap;
PImage ch;
int framerate = 1000;
void setup() {
size(502, 316);
bitmap = loadImage("bitmap_zentriert.jpg"); // Load an image into the program
ch = loadImage("Karte_schweiz_zentriert.jpg"); // Load an image into the program
frameRate(40); //framerate
}
void draw() {
background(255);
image(ch, 10, 10); // the one image in the back
image(bitmap, 10, 10, bitmap.width, bitmap.height, 10, 10, mouseX, bitmap.height); //show part of the second image in front
rect(mouseX, 10, 1, bitmap.height-1); //make line
}
But the image "bitmap" is the whole image distorted.
How can I do that?
I'd recommend using a PGraphics buffer, which is essentially "Another sketch" that also acts as an Image for drawing purposes, and most definitely not looping at "a thousand frames per second". Only draw something when you have something new to draw, using the redraw function in combination with mouse move events:
PImage img1, img2;
PGraphics imagebuffer;
void setup() {
size(502, 316);
imagebuffer = createGraphics(width, height);
img1 = loadImage("first-image.jpg");
img2 = loadImage("second-image.jpg");
noLoop();
}
void mouseMoved() {
redraw();
}
void draw() {
image(img1, 0, 0);
if (mouseX>0) {
imagebuffer = createGraphics(mouseX, height);
imagebuffer.beginDraw();
imagebuffer.image(img2, 0, 0);
imagebuffer.endDraw();
image(imagebuffer, 0, 0);
}
}
In our setup we load the image and turn off looping because we'll be redrawing based on redraw, and then in response to mouse move events, we generate a new buffer that is only as wide as the current x-coordinate of the mouse, draw our image, which gets cropped "for free" because the buffer is only limited width, and then we draw that buffer as if it were an image on top of the image we already have.
There are many ways to do it, one thing I suggest is to create a 3rd image with the same width and height, then you load the two images pixels and insert in your 3rd image part of image1 pixels and then second part from image2, I wrote this code to test it out, works fine:
PImage img1, img2, img3;
void setup() {
size(500, 355);
img1 = loadImage("a1.png"); // Load an image into the program
img2 = loadImage("a2.png"); // Load an image into the program
img3 = createImage(width, height, RGB); //create your third image with same width and height
img1.loadPixels(); // Load the image pixels so you can access the array pixels[]
img2.loadPixels();
frameRate(40); // frame rate
}
void draw() {
background(255);
// Copy first half from first image
for(int i = 0; i < mouseX; i++)
{
for (int j = 0; j < height ; j++) {
img3.pixels[j*width+i] = img1.pixels[j*width+i];
}
}
// Copy second half from second image
for(int i = mouseX; i < width; i++)
{
for (int j = 0; j < height ; j++) {
img3.pixels[j*width+i] = img2.pixels[j*width+i];
}
}
// Update the third image pixels
img3.updatePixels();
// Simply draw that image
image(img3, 0, 0); // The one image in the back
// Draw the separation line
rect(mouseX, 0, 0, height); // Make line
}
Result :

How to merge two images in Xamarin Android and position it the same way like CGRect for iOS?

I successfully get out the two images in my resources folder in my project like this.
string BackGroundImage = "background_image";
string ObjectImage = "object_image";
var TheBackGroundImage = BitmapFactory.DecodeResource(Resources, Resources.GetIdentifier(BackGroundImage, "drawable", PackageName));
var TheObjectImage = BitmapFactory.DecodeResource(Resources, Resources.GetIdentifier(ObjectImage, "mipmap", PackageName));
What i have done after is very the tricky part comes in and I do not know how to quite get it right. What i try to do is create a new Bitmap where the BackgroundImage is the base. Then i create a canvas with my second image (ObjectImage) that is the image that will be on top of the BackgroundImage and try to merge it all together.
Bitmap Result = Bitmap.CreateBitmap(TheBackGroundImage.Width, TheBackGroundImage.Height, TheBackGroundImage.GetConfig());
Canvas canvas = new Canvas(Result);
canvas.DrawBitmap(ObjectImage, new Matrix(), null);
canvas.DrawBitmap(ObjectImage, 79, 79, null);
This does not work as anticipated, is canvas the way to go or is there somethinig else i should look at?
If we look at my iOS solution then i do it like this:
UIImage PhoneImage = UIImage.FromFile(PhonePath);
UIImage IconImage = UIImage.FromFile(IconPath);
UIImage ResultImage;
CGSize PhoneSize = PhoneImage.Size;
CGSize IconSize = IconImage.Size;
UIGraphics.BeginImageContextWithOptions(IconSize, false, IconImage.CurrentScale); //UIGraphics.BeginImageContextWithOptions(IconSize, false, IconImage.CurrentScale);
UIGraphics.BeginImageContext(PhoneSize);
CGRect Frame = (new CoreGraphics.CGRect(25, 29.5, 79, 79));
UIBezierPath RoundImageCorner = new UIBezierPath();
RoundImageCorner = UIBezierPath.FromRoundedRect(Frame, cornerRadius: 15);
PhoneImage.Draw(PhoneImage.AccessibilityActivationPoint);
RoundImageCorner.AddClip();
IconImage.Draw(Frame);
UIColor.LightGray.SetStroke();
RoundImageCorner.LineWidth = 2;
RoundImageCorner.Stroke();
ResultImage = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
var documentsDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
string jpgFilename = System.IO.Path.Combine(documentsDirectory, "app.png");
NSData image = ResultImage.AsPNG();
And it works beautifully with a border around my second image as well.
How can i adjust my code to successfully merge two images together and position the second image preferably like a CGRect?
Try this:
public Bitmap mergeBitmap(Bitmap backBitmap, Bitmap frontBitmap)
{
Bitmap bitmap = backBitmap.Copy(Bitmap.Config.Argb8888, true);
Canvas canvas = new Canvas(bitmap);
Rect baseRect = new Rect(0, 0, backBitmap.Width, backBitmap.Height);
Rect frontRect = new Rect(0, 0, frontBitmap.Width, frontBitmap.Height);
canvas.DrawBitmap(frontBitmap, frontRect, baseRect, null);
return bitmap;
}
Update:
Here is the DrawBitmap method's introduce. I add annotations in the method.
public Bitmap mergeBitmap(Bitmap backBitmap, Bitmap frontBitmap)
{
Bitmap bitmap = backBitmap.Copy(Bitmap.Config.Argb8888, true);
Canvas canvas = new Canvas(bitmap);
//this Rect will decide which part of your frontBitmap will be drawn,
//(0,0,frontBitmap.Width, frontBitmap.Height) means that the whole of frontBitmap will be drawn,
//(0,0,frontBitmap.Width/2, frontBitmap.Height/2) means that the half of frontBitmap will be drawn.
Rect frontRect = new Rect(0, 0, frontBitmap.Width, frontBitmap.Height);
//this Rect will decide where the frontBitmap will be drawn on the backBitmap,
//(200, 200, 200+ frontBitmap.Width, 200+frontBitmap.Height) means that
//the fontBitmap will drawn into the Rect which left is 200, top is 200, and its width and
//height are your frontBitmap's width and height.
//I suggest the baseRect's width and height should be your fontBitmap's width and height,
//or, your fontBitmap will be stretched or shrunk.
Rect baseRect = new Rect(200, 200, 200+ frontBitmap.Width, 200+frontBitmap.Height);
canvas.DrawBitmap(frontBitmap, frontRect, baseRect, null);
return bitmap;
}

How to make Flying Saucer generate an image with transparent background?

I'm using flyingsaucer to render HTML to an image, using Java2DRenderer:
Map<Key,Object> renderingHints = new HashMap<Key,Object>();
renderingHints.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
renderingHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
renderingHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
renderingHints.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE);
hints = new RenderingHints(renderingHints);
Java2DRenderer renderer = new Java2DRenderer(dom, width, height);
renderer.setRenderingHints(renderingHints);
renderer.getSharedContext().setDPI(DPI);
renderer.setBufferedImageType(BufferedImage.TYPE_INT_ARGB);
img = renderer.getImage();
Then I add the rendered image to a PDF document, scaling it to fit the entire page.
com.lowagie.text.Document pdf = new com.lowagie.text.Document(isLandscape ? PageSize.A4.rotate() : PageSize.A4);
pdf.setMargins(MARGIN, MARGIN, MARGIN, MARGIN);
Rectangle ps = pdf.getPageSize();
PdfWriter.getInstance(pdf, outputStream);
pdf.open();
com.lowagie.text.Image pdfImage = com.lowagie.text.Image.getInstance(img, null);
pdfImage.scaleAbsolute(
ps.getWidth() - pdf.leftMargin() - pdf.rightMargin(),
ps.getHeight() - pdf.topMargin() - pdf.bottomMargin()
);
pdf.add(pdfImage);
pdf.close();
The problem is that the image rendered by FS has as background color solid white... so the printer fills the entire page with a very light gray (I believe that scaling transforms the solid white into a light grey).
How can I force flyingsaucer generate a transparent image so I can avoid this problem?
For the Java2DRenderer there is a way by subclassing the Java2DRender
final java.awt.Color TRANSPARENT = new Color(255, 255, 255, 0);
final int imageType = BufferedImage.TYPE_INT_ARGB;
final Java2DRenderer java2dRenderer = new Java2DRenderer(doc, width, height) {
#Override
protected BufferedImage createBufferedImage(final int width, final int height) {
final BufferedImage image = org.xhtmlrenderer.util.ImageUtil.createCompatibleBufferedImage(width, height, imageType);
org.xhtmlrenderer.util.ImageUtil.clearImage(image, TRANSPARENT);
return image;
}
};
java2dRenderer.setBufferedImageType(imageType);

Resources