Here's my code that draws a BitmapMesh, as well as a circle on canvas.
canvas.drawBitmapMesh(GirlBitmap, WIDTH, HEIGHT, matrixVertsMoved, 0, null, 0, null); // need to offset this by "addOffset"
canvas.drawCircle(pointX+addOffset, pointY, bubbleSize, p3);
Both of which have to be offset by x by addOffset. It wors fine with the circle, but I can't figure out how to make the bitmap offset?
Any ideas? Maybe I should draw it on a separate canvas and then draw it on the old one, with an offset?
Thanks!
Can't you just translate the Canvas by (addOffset, 0)? Like this:
final int saveCount = canvas.save();
try {
canvas.translate(addOffset, 0);
canvas.drawBitmapMesh(GirlBitmap, WIDTH, HEIGHT, matrixVertsMoved, 0, null, 0, null);
canvas.drawCircle(pointX, pointY, bubbleSize, p3);
} finally {
canvas.restoreToCount(saveCount);
}
Related
Im trying to merge to bitmap using this code
Bitmap bitmapMerged = Bitmap.createBitmap(
w, h,
bitmapOriginal.getConfig());
Canvas canvasMerged = new Canvas(bitmapMerged);
canvasMerged.drawBitmap(bitmapOriginal, 0, 0, null);
canvasMerged.drawBitmap(bitmapSecond, bitmapOriginal.getWidth(), 0, null);
It merge successfully, my next goal is to rotate the merged bitmap so I used this code
Matrix matrix = new Matrix();
matrix.postRotate(10);
canvasMerged.setMatrix(matrix);
But the image is cutted/trim the side it seems it didnt fit in how to fix this?
Use matrix.postRotate(); with center. So,
matrix.postRotate( 10, centerX, centerY );
i'm trying to make a photo crop app and i want to load a large size image and scale it to to 480 Width and 800 Height (keep aspect ratio) but the problem is if i scale bitmap it shrinks image and when i save it the result get low quality so i decided to scale its canvas to keep bitmap original size.
i need to keep original size but scale the image to fit in screen?
here is my code:
public void setBitmap(Bitmap bitmap) {
finalBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
myCanvas = new Canvas(finalBitmap);
myCanvas.drawBitmap(bitmap, 0, 0, null);
myCanvas.scale(scaleFactor,scaleFactor);
isLoaded = true;
}
draw method:
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (isLoaded)
canvas.drawBitmap(finalBitmap, 0, 0, null);
}
i changed scalefactor with 0.9f ,480,... but non of them had effect on bitmap
Your code should look like this
canvas.save();
canvas.scale(mScaleFactor, mScaleFactor);
canvas.drawBitmap(bitmap, 0, 0, null);
canvas.restore();
Another option is to use the drawBitmap that does the scaling for you with the following call canvas.drawBitmap (Bitmap bitmap, Rect src, Rect dst, Paint paint)
I'm trying to play with canvas. I could draw some triangles and fill it partially drawing a path and paint it.I used Path, Points and Line. It was a great exercise to remember trigonometry. For now I would like to do the same with a circle, as you can see below. I want set a percentage and to fill this circle until the circle's height * percentage. How could me draw a circle like that with canvas or some lib?
You should think about it a little differently. The way I'd do it is to draw a coloured rectangle (where the height is a percentage of the circle's intended height) and then crop it with a circle. This answer explains how to crop an image in a circular shape (I'd rather link than retype the code here).
I finally got do it. I created two methods. As roarster suggested, I created a white rectangle as mask where the height is a percentage of the circle's intended height.
private Bitmap drawWithPorterDuff(Bitmap original, Bitmap mask, PorterDuff.Mode mode) {
Bitmap bitmap = Bitmap.createBitmap(original.getWidth(), original.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint maskPaint = new Paint();
maskPaint.setAntiAlias(true);
canvas.drawBitmap(original, 0, 0, null);
maskPaint.setXfermode(new PorterDuffXfermode(mode));
canvas.drawBitmap(mask, 0, 0, maskPaint);
Bitmap edge = BitmapFactory.decodeResource(getResources(), R.drawable.edge);
maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
canvas.drawBitmap(edge, 0, 0, maskPaint);
return bitmap;
}
public Bitmap createMask(int width, int height) {
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
paint.setAntiAlias(true);
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawRect(0, 0, width, height, paint);
return bitmap;
}
At view's constructor I created a init() method with the folling code
PorterDuff.Mode mode = PorterDuff.Mode.SRC_IN;
Bitmap original = BitmapFactory.decodeResource(getResources(), R.drawable.blue_graph);
Bitmap mask = createMask(original.getWidth(), (int) ((original.getHeight()) * (1 - percentage)));
Bitmap result = drawWithPorterDuff(original, mask, mode);
imageView.setImageBitmap(result);
I'm struggling to understand how to merge 4 pictures together in java, I want to copy each image to the merged image with the overlapping 20 pixels blended in a 50% merge. To give the merged image a 20 pixel boundary that is a blend of the appropriate portion of each image.
So a 4 image box with the images blended into each other by 20 pixels. Not sure how I should use the width and height of the images as it is very confusing.
Something like this. How to do it?
I got all of my info from: AlphaComposite, Compositing Graphics, Concatenating Images.
The following program is improved. It uses two methods: joinHorizontal and joinVertical to join the images. Inside the methods, the following happens
the second image is copied, but only the part that overlaps
the copied image is set at half alpha (transparency)
on the canvas of the 'return image', the first image is painted, followed by the second without the overlapping part
the copied image is painted onto the canvas.
the image is returned
Why do I only set one image at half alpha and not both?
Picture a clear, glass window:
Paint random points red so that half of the window is covered with red. Now, treat the window with the red dots as your new canvas.
Paint random points blue so that the new "canvas" is half covered with blue. The window won't be completely covered; you will still be able to see through it.
But let's imagine that we first painted the window red, and then painted half of it blue. Now, it will be half blue and half red, but not transparent at all.
public class ImageMerger {
/**
* #param args
* #throws IOException
*/
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
BufferedImage img1 = //some code here
BufferedImage img2 = //some code here
BufferedImage img3 = //some code here
BufferedImage img4 = //some code here
int mergeWidth = 20; // pixels to merge.
BufferedImage merge = ImageMerger.joinVertical(
ImageMerger.joinHorizontal(img1, img2, mergeWidth),
ImageMerger.joinHorizontal(img3, img4, mergeWidth),mergeWidth);
//do whatever you want with merge. gets here in about 75 milliseconds
}
public static BufferedImage joinHorizontal(BufferedImage i1, BufferedImage i2, int mergeWidth){
if (i1.getHeight() != i2.getHeight()) throw new IllegalArgumentException("Images i1 and i2 are not the same height");
BufferedImage imgClone = new BufferedImage(mergeWidth, i2.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D cloneG = imgClone.createGraphics();
cloneG.drawImage(i2, 0, 0, null);
cloneG.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_IN, 0.5f));
cloneG.drawImage(i2, 0, 0, null);
BufferedImage result = new BufferedImage(i1.getWidth() + i2.getWidth()
- mergeWidth, i1.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g = result.createGraphics();
g.drawImage(i1, 0, 0, null);
g.drawImage(i2.getSubimage(mergeWidth, 0, i2.getWidth() - mergeWidth,
i2.getHeight()), i1.getWidth(), 0, null);
g.drawImage(imgClone, i1.getWidth() - mergeWidth, 0, null);
return result;
}
public static BufferedImage joinVertical(BufferedImage i1, BufferedImage i2, int mergeWidth){
if (i1.getWidth() != i2.getWidth()) throw new IllegalArgumentException("Images i1 and i2 are not the same width");
BufferedImage imgClone = new BufferedImage(i2.getWidth(), mergeWidth, BufferedImage.TYPE_INT_ARGB);
Graphics2D cloneG = imgClone.createGraphics();
cloneG.drawImage(i2, 0, 0, null);
cloneG.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_IN, 0.5f));
cloneG.drawImage(i2, 0, 0, null);
BufferedImage result = new BufferedImage(i1.getWidth(),
i1.getHeight() + i2.getHeight() - mergeWidth, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = result.createGraphics();
g.drawImage(i1, 0, 0, null);
g.drawImage(i2.getSubimage(0, mergeWidth, i2.getWidth(),
i2.getHeight() - mergeWidth), 0, i1.getHeight(), null);
g.drawImage(imgClone, 0, i1.getHeight() - mergeWidth, null);
return result;
}
}
I am creating a tile game where I need to flip images. With the code I have it produces this error:
Exception in thread "main" java.lang.IllegalArgumentException: Width (-1) and height (-1) cannot be <= 0
from this line:
Image newImage = gc.createCompatibleImage(
image.getWidth(null),
image.getHeight(null),
Transparency.BITMASK);
here is the coding i have:
public Image getMirrorImage(Image image) {
return getScaledImage(image, -1, 1);
}
private Image getScaledImage(Image image, float x, float y) {
// set up the transform
AffineTransform transform = new AffineTransform();
transform.scale(x, y);
transform.translate(
(x-1) * image.getWidth(null) / 2,
(y-1) * image.getHeight(null) / 2);
// create a transparent (not translucent) image
Image newImage = gc.createCompatibleImage(
image.getWidth(null),
image.getHeight(null),
Transparency.BITMASK);
// draw the transformed image
Graphics2D g = (Graphics2D)newImage.getGraphics();
g.drawImage(image, transform, null);
g.dispose();
return newImage;
}
Can anyone explain to me what i might need to do different or how i can make it work? Many thanks
It's possible for image.getWidth(null) and image.getHeight(null) to return -1 if they're not known yet. Image processing can be done concurrently and it might still be going when you try to call those methods (even locally it'll do this IIRC). Here's a snippet of code I've used before to wait for an image to be loaded before trying to access its width and height:
private void waitForImage(Image image) {
Container container = new Container();
MediaTracker tracker = new MediaTracker(container);
tracker.addImage(image, 0);
try {
tracker.waitForID(0, 1000);
} catch (Exception e) {
}
}
I just tried a local test and the wait times were generally 1ms for some small images. It's not really any additional time, it just forces your code to wait for the last stage to complete to get the width and height.
The easiest way to flip the image is by negative scaling it. Example:
g2.drawImage(image, x, y, -width, height, null);
That will flip it vertically. This will flip it horizontally:
g2.drawImage(image, x, y, width, -height, null);