Paint alpha mask bitmap as specific color - java

How do you paint an alpha mask image/Bitmap as a specific color. I'm trying to multiply the alpha (white) on the image by a color and draw it.
A couple examples of masks:
Simple
Translucent
I'd like to have the black be transparent and the alpha/white be the color.

black = 0x00ffffff
white = 0xffffffff
The first two hex chars of a 32bit value of ARGB determine your alpha
final int FULL_ALPHA = 0xFF000000;
int pixel = FULL_ALPHA + some_value;
Paint p = new Paint();
p.setColor(pixel);
c.drawCircle(width, height, radius, p);

I think I may have found my answer, thanks to #petey.
Paint colorMultiplier = new Paint();
colorMultiplier.setColorFilter(new PorterDuffFilter(Color.parseColor("#123456"), PorterDuff.Mode.MULTIPLY));
canvas.drawBitmap(alphaMask, 0, 0, colorMultiplier);

Related

Change hue scale of an imagepattern with a rectangle as container

I have a grayscale image, this image is set to a rectangle with an ImagePattern. like this:
ImagePattern imagePattern = new ImagePattern(new Image("File:resources/images/image.png"));
Rectangle rectangle = new Rectangle();
rectangle.setFill(imagePattern);
The only problem is I want the user to choose the colour of the image, so I want to change the hue of the image.
I found following question on StackOverflow, the first answer https://stackoverflow.com/a/18124868/15277155
shows how a coloured image is changed to a red image.
The only problem I have is that answer is done with an ImageView instead of an Imagepattern.
Is there any way This can be done with an ImagePattern.
Or that I can place the ImageView inside a rectangle?
Based on #jewelsea's comment this is the code I have.
ImagePattern imagePattern = new ImagePattern(new
Image("File:resources/images/image.png"));
Rectangle rectangle = new Rectangle();
rectangle.setFill(imagePattern);
ColorAdjust colorAdjust = new ColorAdjust();
// define target color
Color targetColor = Color.GREEN;
double hue = map( (targetColor.getHue() + 180) % 360, 0, 360, -1, 1);
colorAdjust.setHue(hue);
// use saturation as it is enter code here
double saturation = targetColor.getSaturation();
colorAdjust.setSaturation(saturation);
double brightness = map( targetColor.getBrightness(), 0, 1, -1, 0);
colorAdjust.setBrightness(brightness);
// apply color adjustment
rectangle.setEffect(colorAdjust);
rectangle.setFill(imagePattern);
I tested this on a yellow image (PNG with transparent background, but no opacity) and it worked.
Then I tried it on an image with only colors ranging from white to black (and grey) (also a PNG with transparent background, but also with opacity in the colors) and it didn't change those colors.
The ColorAdjust effect will work with any node, not just an ImageView.
So you can apply the ColorAdjust effect to your rectangle, which is filled with the ImagePattern, and the effect will be applied to the ImagePattern.

How to draw a circle on a bitmap without filling it?

I am ddrawing a circle on the bitmap and setting this bitmap to ImageView. the circle is drawn correctly but i dont want it to be a filled circle is there any way to make the filled area transparent?
i am using the following code
Bitmap bmp = RasterImageConverter.convertToBitmap(_loadedImage, ConvertToImageOptions.NONE.getValue());
Canvas c = new Canvas(bmp);
c = new Canvas(bmp);
myimgview.draw(c);
Paint p = new Paint();
p.setColor(Color.RED);
float x=(float) circleX;
float y=(float) circleY;
float Tx=(float) textX;
float Ty=(float)textY;
// c.drawLine(x, y, xend, yend, p);
c.drawCircle(300, 300, 200, p);
c.drawText(myText, Tx, Ty, p);
myimgview.setImageBitmap(bmp);
You need to inform the paint that you dont' use a fill style, but a stroke style.
The default is FILL
The Style specifies if the primitive being drawn is filled, stroked, or both (in the same color). The default is FILL.
So your code must be:
Paint p = new Paint();
p.setStyle(Paint.Style.STROKE);
Here are explained the differences between the different styles.
STROKE
Geometry and text drawn with this style will be stroked, respecting the stroke-related fields on the paint.
FILL
Geometry and text drawn with this style will be filled, ignoring all stroke-related settings in the paint.
FILL_AND_STROKE
Geometry and text drawn with this style will be both filled and stroked at the same time, respecting the stroke-related fields on the paint.
You need to change the Paint style to stroke:
Paint p = new Paint();
p.setStyle(Paint.Style.STROKE);
Use the setStyle(Paint.Style.STROKE) method on your paint p instance.
You are almost there... you need to set the style of the Paint object...
by invoking the method
p.setStyle(Paint.Style.STROKE);
The options are:
Example:
Bitmap bmp = RasterImageConverter.convertToBitmap(_loadedImage, ConvertToImageOptions.NONE.getValue());
Canvas c = new Canvas(bmp);
c = new Canvas(bmp);
myimgview.draw(c);
Paint p = new Paint();
p.setColor(Color.RED);
p.setStyle(Paint.Style.STROKE);

Java, image is changing to wrong rgb values

i wrote a java code to change all the red values of a black and white image to 255, so the output would be a red image.
But its not red, instead it outputs a brighter image.
What did I do wrong?
File bwgFile = new File("X:/Java/Documents/NetBeansProjects/colour/input/bwg.png");
BufferedImage bwgImage = ImageIO.read(bwgFile);
int width=bwgImage.getWidth();
int height=bwgImage.getHeight();
for(int w=0; w<width; w++){
for(int h=0; h<height; h++){
int pixel = bwgImage.getRGB(w,h);
Color bwg = new Color(pixel);
int c=bwg.getRed();
Color red = new Color(255,c,c);
int cpixel = red.getRGB();
bwgImage.setRGB(w,h,cpixel);
}
}
ImageIO.write(bwgImage, "png", new File("X:/Java/Documents/NetBeansProjects/colour/output/c.png"));
input
output
EDIT:
I have found out what the problem was, apparently when the input is a greyscale image it will try to make the output a greyscale image as well thus making it darker when blue and green colors get removed and brighter when red gets added. not using a grayscale image as input fixed it.
If I understand what you're trying to do, you're trying to create a greyscale image, except that it is "redscale", using only shades of red. Therefore, you need to compute the greyscale constant of each pixel.
From wikipedia (Greyscale), the luminance of a pixel Y = 0.2126R + 0.7152G + 0.0722B. So, try this
int pixel = bwgImage.getRGB(w,h);
Color bwg = new Color(pixel);
float c = (0.2126f * bwg.getRed() + 0.7152f * bwg.getGreen() + 0.0722f * bwg.getBlue());
int cc = (int)Math.round(c);
Color red = new Color(cc, 0, 0);
int cpixel = red.getRGB();
bwgImage.setRGB(w,h,cpixel);
Alternatively, you can simply retain the red component and set green and blue to 0. This will leave you with just the "redness" of each pixel.
int pixel = bwgImage.getRGB(w,h);
Color bwg = new Color(pixel);
int c=bwg.getRed();
Color red = new Color(c,0,0);
int cpixel = red.getRGB();
bwgImage.setRGB(w,h,cpixel);
NOTE: This solution above only works on images that are not using IndexColorModel. You can check the color model using BufferedImage's getColorModel(). For IndexColorModel, setRGB() does not work directly and instead picks a color in the index closest to the set color, as per HaraldK's comment. To achieve the desired result for images using IndexColorModel, you can create a new BufferedImage with TYPE_INT_ARGB:
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Then, write the calculated pixel colors to this new image and save the new image instead.

Add text with grey background to pictures like Snapchat does? Android/Java

Bitmap newBm = ...
Canvas canvas = new Canvas(newBm);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.WHITE);
paint.setTextSize((int) (44 * scale));
Rect bounds = new Rect();
paint.getTextBounds(gText, 0, gText.length(), bounds);
canvas.drawText(gText, x, y, paint);
I drew text on the Bitmap like so. How could I get a grey background that is the same height as the text but covers the whole screen??
You could use a Rect. Before drawing the text draw the Rect to the screen:
int screenWidth = getApplicationContext().getResources().getDisplayMetrics().widthPixels;
Rect greyBack = new Rect(0,top,screenWidth,bottom);
Paint paint = new Paint();
paint.setARGB(128, 100, 100, 100); //added alpha because Snapchat has translucent //grey background
canvas.drawRect(greyBack, paint);
top and bottom need to be coordinates above and below the text. You could use y's value and take away a bit for top and add a bit for bottom. How much you add/subtract is up to you and changes the height of the greyBack background.
The best way to see and learn how these sort of things are done with well written code is to look at the android source code itself. For example here is the onDraw method for a TextView it includes additional stuff you won't probably need like compoundPadding, but you can follow it through and get the basic concept of how it's done.

java image crop

I am aware of BufferedImage.getSubimage However, it cant deal with cropping images that are smaller than the cropping size throwing the exception:
java.awt.image.RasterFormatException: (y + height) is outside raster
I want to be able to crop either a PNG/JPG/GIF to a certain size however if the image is smaller than the cropping area centre itself on a white background. Is there a call to do this? Or do I need to create an image manually to centre the image on if so, how would I go about this?
Thanks
You cannot crop an image larger, only smaller. So, you start with the goal dimension,let's say 100x100. And your BufferedImage (bi), let's say 150x50.
Create a rectangle of your goal:
Rectangle goal = new Rectangle(100, 100);
Then intersect it with the dimensions of your image:
Rectangle clip = goal.intersection(new Rectangle(bi.getWidth(), bi.getHeight());
Now, clip corresponds to the portion of bi that will fit within your goal. In this case 100 x50.
Now get the subImage using the value of clip.
BufferedImage clippedImg = bi.subImage(clip,1, clip.y, clip.width, clip.height);
Create a new BufferedImage (bi2), the size of goal:
BufferedImage bi2 = new BufferedImage(goal.width, goal.height);
Fill it with white (or whatever bg color you choose):
Graphics2D big2 = bi2.getGraphics();
big2.setColor(Color.white);
big2.fillRect(0, 0, goal.width, goal.height);
and draw the clipped image onto it.
int x = goal.width - (clip.width / 2);
int y = goal.height - (clip.height / 2);
big2.drawImage(x, y, clippedImg, null);

Categories