How to put rounded corners to canvas image? - 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

Related

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.

Skiasharp text rendering off canvas

I'm creating a custom control with skiasharp and xamarin forms. Something I've run into is when I try draw text in the top left corner of my canvas I have to offset the y co ord in order for the text to render within the canvas. I'd expect the x y co ord of the text to be in the same position as the x y co ord of the rect. What am I missing?
Using Skiasharp.View.Forms - v1.68.1 off nuget
Thanks!
protected override void OnPaintSurface(SKPaintSurfaceEventArgs args)
{
base.OnPaintSurface(args);
SKImageInfo info = args.Info;
SKSurface surface = args.Surface;
SKCanvas canvas = surface.Canvas;
canvas.Clear();
canvas.Save();
using var paint = new SKPaint {IsAntialias = true, Color = Color.Black.ToSKColor(), Style = SKPaintStyle.Stroke};
canvas.DrawRect(0, 0, info.Width, info.Height, paint);
canvas.DrawText("Off screen", 0, 0, paint);
canvas.DrawText("On screen", 0, 10, paint);
canvas.Restore();
}
You could set y coordinate as SKPaint.FontSpacing , it is the recommend line spacing.
canvas.DrawText("SKCanvasView Height and Width:", 0, paint.FontSpacing, paint);
Refer https://github.com/xamarin/xamarin-forms-samples/blob/f7cc661331b5db605e64e7efe83ef2b9fc644afb/SkiaSharpForms/Demos/Demos/SkiaSharpFormsDemos/Basics/SurfaceSizePage.cs#L38

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;
}

Rotate Bitmap 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);
}

Processing: transparent image over curves

Im new to Processing. I would like to put a .jpg or .png over curves and ellipses, so that they can see only where the image is transparent.
My code is below. The problem with it is that the transparent area is not fully transparent, but transparent white and the not-transparent parts have also decreased opacity.
PImage img;
void setup() {
size(300,500);
frameRate(30);
strokeWeight(4);
img = loadImage("sziluettmeret.jpg");
}
void draw() {
background(0, 50, 70);
stroke(0,70,90);
noFill();
beginShape();
curveVertex(-100, -100);
curveVertex(10, 10);
curveVertex(250, 250);
curveVertex(300, 300);
endShape();
fill(255);
ellipse(20 ,20,15,15);
noFill();
tint(255, 100);
image(img, 0, 0);
}
UPDATE:
I have this in my code:
loadPixels();
for(int i=0; i < img.pixels.length; i++) {
tmpColor = img.pixels[i];
tmpRed = red(tmpColor);
tmpGreen = blue(tmpColor);
tmpBlue = green(tmpColor);
tmpAlpha = 255 - ((tmpRed + tmpGreen + tmpBlue)/3);
img.pixels[i] = color(2*tmpRed,tmpGreen/2,tmpBlue,0);
if(0xFFFFFF == tmpColor)
}
updatePixels();
The picture does not become transparent. (But it becomes purple, so the loop runs on every pixel for sure)
tint() doesn't do greenscreening. It'll recolor your image (if you use a non-neutral colour), and set the mix transparancy, so with tint(255,100), you effective gave the image an opacity of (approximately) 0.39
If you want to do greenscreening (or in your case, whitescreening), you want to run through the image's pixels when you load the image, then set opacity to 0 whenever r/g/b are 255, effectively "removing" all your white pixels.

Resources