JNA Convert HICON to Java Image - java

I knwo there is already an question like this. But its solution was not suitable for me because with the Sehellfolder Methode you can only get 16x16 and 32x32 sized icons.
I have extracted a HICO with size of 256x256 and want to convert it into and Java Image like BufferedImage. I found and method for it to. But it does not work properly:
public static BufferedImage getIcon(final WinDef.HICON hIcon,int ICON_SIZE,short ICON_DEPTH,int ICON_BYTE_SIZE) {
final int width = ICON_SIZE;
final int height = ICON_SIZE;
final short depth = ICON_DEPTH;
final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
final Memory lpBitsColor = new Memory(width * height * depth / ICON_BYTE_SIZE);
final Memory lpBitsMask = new Memory(width * height * depth / ICON_BYTE_SIZE);
final WinGDI.BITMAPINFO info = new WinGDI.BITMAPINFO();
final WinGDI.BITMAPINFOHEADER hdr = new WinGDI.BITMAPINFOHEADER();
info.bmiHeader = hdr;
hdr.biWidth = width;
hdr.biHeight = height;
hdr.biPlanes = 1;
hdr.biBitCount = depth;
hdr.biCompression = WinGDI.BI_RGB;
final WinDef.HDC hDC = User32.INSTANCE.GetDC(null);
final WinGDI.ICONINFO piconinfo = new WinGDI.ICONINFO();
User32.INSTANCE.GetIconInfo(hIcon, piconinfo);
GDI32.INSTANCE.GetDIBits(hDC, piconinfo.hbmColor, 0, height, lpBitsColor, info, WinGDI.DIB_RGB_COLORS);
GDI32.INSTANCE.GetDIBits(hDC, piconinfo.hbmMask, 0, height, lpBitsMask, info, WinGDI.DIB_RGB_COLORS);
int r, g, b, a, argb;
int x = 0, y = height - 1;
for (int i = 0; i < lpBitsColor.size(); i = i + 3) {
b = lpBitsColor.getByte(i) & 0xFF;
g = lpBitsColor.getByte(i + 1) & 0xFF;
r = lpBitsColor.getByte(i + 2) & 0xFF;
a = 0xFF - lpBitsMask.getByte(i) & 0xFF;
argb = a << 24 | r << 16 | g << 8 | b;
image.setRGB(x, y, argb);
x = (x + 1) % width;
if (x == 0) {
y--;
}
}
User32.INSTANCE.ReleaseDC(null, hDC);
GDI32.INSTANCE.DeleteObject(piconinfo.hbmColor);
GDI32.INSTANCE.DeleteObject(piconinfo.hbmMask);
return image;
}
Resulting Image
Do you know andy method that works better?
EDIT:
public static BufferedImage getImageByHICON(final int width, final int height, final WinNT.HANDLE hicon, final WinGDI.BITMAPINFOHEADER info) {
final WinGDI.ICONINFO iconinfo = new WinGDI.ICONINFO();
try {
// GDI32 g32 = GDI32.INSTANCE;
// get icon information
if (!User32.INSTANCE.GetIconInfo(new WinDef.HICON(hicon.getPointer()), iconinfo)) { return null; }
final WinDef.HWND hwdn = new WinDef.HWND();
final WinDef.HDC dc = User32.INSTANCE.GetDC(hwdn);
if (dc == null) {
return null; }
try {
final int nBits = width * height * 4;
// final BitmapInfo bmi = new BitmapInfo(1);
final Memory colorBitsMem = new Memory(nBits);
// // Extract the color bitmap
final WinGDI.BITMAPINFO bmi = new WinGDI.BITMAPINFO();
bmi.bmiHeader.biWidth = width;
bmi.bmiHeader.biHeight = -height;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = WinGDI.BI_RGB;
GDI32.INSTANCE.GetDIBits(dc, iconinfo.hbmColor, 0, height, colorBitsMem, bmi, WinGDI.DIB_RGB_COLORS);
// g32.GetDIBits(dc, iconinfo.hbmColor, 0, size, colorBitsMem,
// bmi,
// GDI32.DIB_RGB_COLORS);
final int[] colorBits = colorBitsMem.getIntArray(0, width * height);
if (info.biBitCount < 32) {
final Memory maskBitsMem = new Memory(nBits);
// // Extract the mask bitmap
GDI32.INSTANCE.GetDIBits(dc, iconinfo.hbmMask, 0, height, maskBitsMem, bmi, WinGDI.DIB_PAL_COLORS);
// g32.GetDIBits(dc, iconinfo.hbmMask, 0, size,
// maskBitsMem,
// bmi,
// // GDI32.DIB_RGB_COLORS);
final int[] maskBits = maskBitsMem.getIntArray(0, width * height);
// // // Copy the mask alphas into the color bits
for (int i = 0; i < colorBits.length; i++) {
colorBits[i] = colorBits[i] | (maskBits[i] != 0 ? 0 : 0xFF000000);
}
}
final BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
bi.setRGB(0, 0, width, height, colorBits, 0, height);
return bi;
} finally {
com.sun.jna.platform.win32.User32.INSTANCE.ReleaseDC(hwdn, dc);
}
} finally {
User32.INSTANCE.DestroyIcon(new WinDef.HICON(hicon.getPointer()));
GDI32.INSTANCE.DeleteObject(iconinfo.hbmColor);
GDI32.INSTANCE.DeleteObject(iconinfo.hbmMask);
}
}
Better Image

You need to use the method from Example 3 from this website

Related

ZXing BinaryBitmap to BufferedImage

I'm using zxing to read barcodes from scanned images like this:
Ideally the barcode is always placed at 2/5 position but sometime the barcode is blurred, dirt or scratched, for testing purpose is required to save the bitmap sent to reader, based on this answer: Convert byte array of data type TYPE_4BYTE_ABGR to BufferedImage I'm trying to save the croppedBitmap without success, any help really appreciated.
private static String decodeFile(File file) throws IOException, NotFoundException {
BufferedImage bufferedImage = ImageIO.read(file);
LuminanceSource source = new
BufferedImageLuminanceSource(bufferedImage);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
System.out.println(bitmap.getWidth() + " x " + bitmap.getHeight());
int width = bitmap.getWidth();
int height = bitmap.getHeight() / 5;
int top = height;
BinaryBitmap croppedBitmap = bitmap.crop(0, top, width, height);
int[] dst = new int[width * height];
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
int a = croppedBitmap.getBlackMatrix().get(i, j) ? 1 & 0xff : 0;
int b = croppedBitmap.getBlackMatrix().get(i, j) ? 1 & 0xff : 0;
int g = croppedBitmap.getBlackMatrix().get(i, j) ? 1 & 0xff : 0;
int r = croppedBitmap.getBlackMatrix().get(i, j) ? 1 & 0xff : 0;
dst[(i + 1) * j] = (a << 24) | (r << 16) | (g << 8) | b;
}
}
BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_ARGB);
image.setRGB(0, 0, width, height, dst, 0, width);
boolean r = ImageIO.write(image, "bmp", new File("croppedBitmap.bmp"));
System.out.println("Write bmp:" + r);
Hashtable<DecodeHintType, Object> hint = new Hashtable<DecodeHintType, Object>();
hint.put(DecodeHintType.TRY_HARDER, BarcodeFormat.CODE_39);
try {
MultiFormatReader reader = new MultiFormatReader();
Result result = reader.decode(bitmap, hint);
return result.getText();
} catch (NotFoundException e) {
System.out.println("Decode failed.");
return null;
}
}
Use toBufferedImage:
BitMatrix blackMatrix = croppedBitmap.getBlackMatrix();
BufferedImage image = MatrixToImageWriter.toBufferedImage(blackMatrix);

Tensorflow in Android: java.lang.illegalArgumentsException

I want to put a tensorflow model on Anroid.
I recently noticed that the results of running the same data in Python and Android, respectively, are inconsistent.
After several trial and error, I found that the input data I entered when I ran the model on Android was wrong.
It was just a java.lang.IllegalArgumentException error, and I think I put the data correctly, but I have no idea what went wrong.
I used images that were transformed into image resizing and gray scale as learning data. in Python
I did the same preprocessing on Android.
My image type is .jpg
I attached my source.
Source related to image preprocessing
btntrans.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
try {
image_bitmap = resizeBitmapImage(image_bitmap, 28);
image_bitmap = RGB2GRAY(image_bitmap);
image.setImageBitmap(image_bitmap);
byte[] byteArrayRes = bitmapToByteArray(image_bitmap);
float[] inputArray = bytetofloat(byteArrayRes);
activityPrediction(inputArray);
}
catch(Exception e){
}
}
});
Everything happens when I click the button
resizeBitmapImage method
public Bitmap resizeBitmapImage(Bitmap source, int maxResolution)
{
int width = source.getWidth();
int height = source.getHeight();
int newWidth = width;
int newHeight = height;
float rate = 0.0f;
if(width > height)
{
if(maxResolution < width)
{
rate = maxResolution / (float) width;
newHeight = (int) (height * rate);
newWidth = maxResolution;
}
}
else
{
if(maxResolution < height)
{
rate = maxResolution / (float) height;
newWidth = (int) (width * rate);
newHeight = maxResolution;
}
}
return Bitmap.createScaledBitmap(source, newWidth, newHeight, true);
}
RGB2GRAY method
public Bitmap RGB2GRAY(Bitmap image){
int width = image.getWidth();
int height = image.getHeight();
Bitmap bmOut;
bmOut = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444);
for(int x = 0; x < width; x++){
for(int y = 0 ; y < height; y++){
int pixel = image.getPixel(x, y);
int A = Color.alpha(pixel);
int R = Color.red(pixel);
int G = Color.green(pixel);
int B = Color.blue(pixel);
R = G = B = (int)(0.299 * R + 0.587 * G + 0.114 * B);
bmOut.setPixel(x, y, Color.argb(A, R, G, B));
}
}
return bmOut;
}
bitmap to byte array method
private byte[] bitmapToByteArray(Bitmap bitmap){
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
return stream.toByteArray();
}
bytetofloat method
public float[] bytetofloat(byte[] array){
int[] returnArr = new int[array.length/4];
float[] returnArr1 = new float[array.length/4];
for(int i = 0 ; i < returnArr.length; i++){
//array[i] = 0;
returnArr[i] = array[i*4] & 0xFF;
if(returnArr[i] < 0 || returnArr[i]>255)
Log.d("ARRAY", returnArr[i]+" ");
returnArr1[i] = (float)returnArr[i];
}
return returnArr1;
}
When I run it with the above source, I get this error exactly.
java.lang.IllegalArgumentException: buffer with 308 elements is not
compatible with a Tensor with shape [1, 28, 28]
28 * 28 is Input image size
Before image resizing, it had an average width of 20 and a height of 36.
The strange thing is that the number 308 is changed to 306, 307 and fixed.
What can i do?
Here is my method for converting Java BufferedImage to Tensor object:
private static Tensor<?> convertImageToArray(BufferedImage bf) {
int width = bf.getWidth();
int height = bf.getHeight();
float[][][][] rgbArray = new float[1][height][width][3];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
bf.getRaster().getPixel(i, j, rgbArray[0][i][j]);
}
}
return Tensor.create(rgbArray);
}
Your problem is probably in missed channels of your image. Float array length must be equal to
height * width * channels
of the image.

how i can rotate image by array of byte in java?

I have array of byte for image , and I want to rotate image by this array ,
this is my code :
BufferedImage img = ImageUtil.load(inputImagePath);
WritableRaster raster = img .getRaster();
DataBufferByte data = (DataBufferByte) raster.getDataBuffer();
byte [] pixel = data.getData();
how i can do this ? ,
thanks
After some work, I came up with this:
public class ImageRotation {
public static void main(String[] args) throws IOException {
BufferedImage img = ImageIO.read(
ImageRotation.class
.getResourceAsStream("Capture.PNG"));
JPanel pane = new JPanel();
pane.setLayout(new BorderLayout());
pane.add(
new JLabel("Original", new ImageIcon(img), JLabel.CENTER),
BorderLayout.WEST);
pane.add(
new JLabel("Rotated", new ImageIcon(rotateClockwise(img)), JLabel.CENTER),
BorderLayout.EAST);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(pane);
frame.setVisible(true);
frame.pack();
}
static BufferedImage rotateClockwise(BufferedImage img) {
int[] origPix = getIntBuff(img);
int newWidth = img.getHeight();
int newHeight = img.getWidth();
int[] buff = new int[newWidth * newHeight];
// formula for determining pixel mapping
// (sizeOf(old y) - 1) - old y -> new x
// old x -> new y
for (int x = 0; x < img.getWidth(); x++)
for (int y = 0; y < img.getHeight(); y++) {
int pix = origPix[x + (y * img.getWidth())];
int newX = img.getHeight() - 1 - y, newY = x;
buff[newX + (newWidth * newY)] = pix;
}
// we have now rotated the array clockwise, time to place the buffer in an image
int type = BufferedImage.TYPE_INT_ARGB;
BufferedImage ret = new BufferedImage(newWidth, newHeight, type);
WritableRaster wr = ret.getRaster();
wr.setDataElements(0, 0, newWidth, newHeight, buff);
return ret;
}
// variation of convertTo2DWithoutUsingGetRGB http://stackoverflow.com/a/9470843/4683264
private static int[] getIntBuff(BufferedImage image) {
final byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
final int width = image.getWidth();
final int height = image.getHeight();
final boolean hasAlphaChannel = image.getAlphaRaster() != null;
int[] result = new int[height * width];
final int pixelLength = hasAlphaChannel ? 4 : 3;
for (int pixel = 0, resInd = 0; pixel < pixels.length; pixel += pixelLength) {
int argb = 0;
if (hasAlphaChannel)
argb += (((int) pixels[pixel] & 0xff) << 24); // alpha
else
argb += -16777216; // 255 alpha
argb += ((int) pixels[pixel + 1] & 0xff); // blue
argb += (((int) pixels[pixel + 2] & 0xff) << 8); // green
argb += (((int) pixels[pixel + 3] & 0xff) << 16); // red
result[resInd++] = argb;
}
return result;
}
}
Result:
Right now it only rotates the image clockwise, but once you find the pixel mappings from the old to new image for, say, counterclockwise, all you need to change is in the nested for loop in the rotateClockwise method to:
int newX = y, newY = img.getWidth() - 1 - x;

problem with combining RGB binary image

im doing an edge detection which will detect edges of each RGB channel and then combine them to show it as a final output. im now having a problem with combining the three as it doesnt show me a binary image, instead it has some colors on it. i have checked each binary image of the RGB and it works fine which gives the black and white image. to be clearer, following is the code:
private void processActionPerformed(java.awt.event.ActionEvent evt) {
width = inputimage.getWidth(null);
height = inputimage.getHeight(null);
inputbuff = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
Graphics r = inputbuff.getGraphics();
r.drawImage(inputimage, 0, 0, null);
r.dispose();
process_red = new int[width * height];
process_green = new int[width * height];
process_blue = new int[width * height];
process_grey = new int[width * height];
process_rgb = new int[width * height];
process_combine = new int[width * height];
for (int i = 0; i < 256; i++) {
freq_red[i] = freq_green[i] = freq_blue[i] = freq_grey[i] = 0;
}
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int clr = inputbuff.getRGB(y, x);
int red = (clr & 0x00ff0000) >> 16;
int green = (clr & 0x0000ff00) >> 8;
int blue = clr & 0x000000ff;
int grey = (11 * red + 16 * green + 5 * blue) / 32;
freq_red[red] += 1;
freq_green[green] += 1;
freq_blue[blue] += 1;
freq_grey[grey] += 1;
}
}
int threshold = 150;
for (int i = 0; i < 256; i++) {
freq_red[i] = applyThreshold(threshold, freq_red[i]);
freq_green[i] = applyThreshold(threshold, freq_green[i]);
freq_blue[i] = applyThreshold(threshold, freq_blue[i]);
freq_grey[i] = applyThreshold(threshold, freq_grey[i]);
}
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int clr = inputbuff.getRGB(y, x);
int red = (clr & 0x00ff0000) >> 16;
int green = (clr & 0x0000ff00) >> 8;
int blue = clr & 0x000000ff;
int grey = (11 * red + 16 * green + 5 * blue) / 32;
red = freq_red[red];
green = freq_green[green];
blue = freq_blue[blue];
grey = freq_grey[grey];
int alpha = 0xff000000;
int combine = alpha | (red <<16) |(green <<8)|blue;
process_red[x * height + y] = (0xFF<<24)|(red<<16)|(red<<8)|red;
process_green[x * height + y] = (0xFF<<24)|(green<<16)|(green<<8)|green;
process_blue[x * height + y] = (0xFF<<24)|(blue<<16)|(blue<<8)|blue;
process_grey[x * height + y] = (0xFF<<24)|(grey<<16)|(grey<<8)|grey;
process_rgb[x * height + y] = clr;
process_combine[x * height + y] = combine;
}
}
image_red = new JFrame().createImage(new MemoryImageSource(width, height, process_red, 0, width));
image_green = new JFrame().createImage(new MemoryImageSource(width, height, process_green, 0, width));
image_blue = new JFrame().createImage(new MemoryImageSource(width, height, process_blue, 0, width));
image_grey = new JFrame().createImage(new MemoryImageSource(width, height, process_grey, 0, width));
image_rgb = new JFrame().createImage(new MemoryImageSource(width, height, process_rgb, 0, width));
image_combine = new JFrame().createImage(new MemoryImageSource(width, height, process_combine, 0, width));
buff_red = new BufferedImage(width,height, BufferedImage.TYPE_INT_RGB);
buff_green = new BufferedImage(width,height, BufferedImage.TYPE_INT_RGB);
buff_blue = new BufferedImage(width,height, BufferedImage.TYPE_INT_RGB);
buff_grey = new BufferedImage(width,height, BufferedImage.TYPE_INT_RGB);
buff_rgb = new BufferedImage(width,height, BufferedImage.TYPE_INT_RGB);
buff_combine = new BufferedImage(width,height, BufferedImage.TYPE_INT_RGB);
graph_red = buff_red.getGraphics();
graph_green = buff_green.getGraphics();
graph_blue = buff_blue.getGraphics();
graph_grey = buff_grey.getGraphics();
graph_rgb = buff_rgb.getGraphics();
graph_combine = buff_combine.getGraphics();
graph_red.drawImage(image_red, 0, 0, null);
graph_green.drawImage(image_green, 0, 0, null);
graph_blue.drawImage(image_blue, 0, 0, null);
graph_grey.drawImage(image_grey, 0, 0, null);
graph_rgb.drawImage(image_rgb, 0, 0, null);
graph_combine.drawImage(image_combine, 0, 0, null);
graph_red.dispose();
graph_green.dispose();
graph_blue.dispose();
graph_grey.dispose();
graph_rgb.dispose();
graph_combine.dispose();
repaint();
}
i suspected that the problem is with the alpha value:
int alpha = 0xff000000;
int combine = alpha | (red <<16) | (green <<8)|blue;
however, when i removed the alpha value it doesnt display anything. can anyone please help me? thanks in advance!
I am guessing that freq_red etc. are byte arrays. If so then you are being bitten by byte sign extension.
Try replacing this
red = freq_red[red];
green = freq_green[green];
blue = freq_blue[blue];
grey = freq_grey[grey];
with this:
red = freq_red[red] & 0xFF;
green = freq_green[green] & 0xFF;
blue = freq_blue[blue] & 0xFF;
grey = freq_grey[grey] & 0xFF;
Update: your method is longer than it needs to be because of all the temporary images (graph_red etc.) You can avoid them by defining a method like this:
private BufferedImage wrapPixelArray(int width,
int height,
int[] process) {
DataBuffer db = new DataBufferInt(process, width * height);
SampleModel sm =
new SinglePixelPackedSampleModel(DataBuffer.TYPE_INT, width, height, MASK);
WritableRaster wr =
Raster.createWritableRaster(sm, db, null);
return new BufferedImage(RGB, wr, false, null);
}
private static final int[] MASK = {0xFF0000, 0xFF00, 0xFF};
private static final ColorModel RGB =
new DirectColorModel(32, MASK[0], MASK[1], MASK[2]);

Colorizing images in Java

I'm working on some code to colorize an image in Java. Basically what I'd like to do is something along the lines of GIMP's colorize command, so that if I have a BufferedImage and a Color, I can colorize the Image with the given color. Anyone got any ideas? My current best guess at doing something like this is to get the rgb value of each pixel in the BufferedImage and add the RGB value of the Color to it with some scaling factor.
Let Y = 0.3*R + 0.59*G + 0.11*B for each pixel in the image, then set them to be
((R1+Y)/2,(G1+Y)/2,(B1+Y)/2)
if (R1,G1,B1) is what you are colorizing with.
I have never used GIMP's colorize command. However, if your getting the RGB value of each pixel and adding RGB value to it you should really use a LookupOp. Here is some code that I wrote to apply a BufferedImageOp to a BufferedImage.
Using Nicks example from above heres how I would do it.
Let Y = 0.3*R + 0.59*G + 0.11*B for
each pixel
(R1,G1,B1) is what you are colorizing
with
protected LookupOp createColorizeOp(short R1, short G1, short B1) {
short[] alpha = new short[256];
short[] red = new short[256];
short[] green = new short[256];
short[] blue = new short[256];
int Y = 0.3*R + 0.59*G + 0.11*B
for (short i = 0; i < 256; i++) {
alpha[i] = i;
red[i] = (R1 + i*.3)/2;
green[i] = (G1 + i*.59)/2;
blue[i] = (B1 + i*.11)/2;
}
short[][] data = new short[][] {
red, green, blue, alpha
};
LookupTable lookupTable = new ShortLookupTable(0, data);
return new LookupOp(lookupTable, null);
}
It creates a BufferedImageOp that will mask out each color if the mask boolean is true.
Its simple to call too.
BufferedImageOp colorizeFilter = createColorizeOp(R1, G1, B1);
BufferedImage targetImage = colorizeFilter.filter(sourceImage, null);
If this is not what your looking for I suggest you look more into BufferedImageOp's.
This is would also be more efficient since you would not need to do the calculations multiple times on different images. Or do the calculations over again on different BufferedImages as long as the R1,G1,B1 values don't change.
This works exactly like the Colorize function in GIMP and it preserves the transparency. I've also added a few things like Contrast and Brightness, Hue, Sat, and Luminosity - 0circle0 Google Me --> ' Sprite Creator 3'
import java.awt.Color;
import java.awt.image.BufferedImage;
public class Colorizer
{
public static final int MAX_COLOR = 256;
public static final float LUMINANCE_RED = 0.2126f;
public static final float LUMINANCE_GREEN = 0.7152f;
public static final float LUMINANCE_BLUE = 0.0722f;
double hue = 180;
double saturation = 50;
double lightness = 0;
int[] lum_red_lookup;
int[] lum_green_lookup;
int[] lum_blue_lookup;
int[] final_red_lookup;
int[] final_green_lookup;
int[] final_blue_lookup;
public Colorizer()
{
doInit();
}
public void doHSB(double t_hue, double t_sat, double t_bri, BufferedImage image)
{
hue = t_hue;
saturation = t_sat;
lightness = t_bri;
doInit();
doColorize(image);
}
private void doInit()
{
lum_red_lookup = new int[MAX_COLOR];
lum_green_lookup = new int[MAX_COLOR];
lum_blue_lookup = new int[MAX_COLOR];
double temp_hue = hue / 360f;
double temp_sat = saturation / 100f;
final_red_lookup = new int[MAX_COLOR];
final_green_lookup = new int[MAX_COLOR];
final_blue_lookup = new int[MAX_COLOR];
for (int i = 0; i < MAX_COLOR; ++i)
{
lum_red_lookup[i] = (int) (i * LUMINANCE_RED);
lum_green_lookup[i] = (int) (i * LUMINANCE_GREEN);
lum_blue_lookup[i] = (int) (i * LUMINANCE_BLUE);
double temp_light = (double) i / 255f;
Color color = new Color(Color.HSBtoRGB((float) temp_hue, (float) temp_sat, (float) temp_light));
final_red_lookup[i] = (int) (color.getRed());
final_green_lookup[i] = (int) (color.getGreen());
final_blue_lookup[i] = (int) (color.getBlue());
}
}
public void doColorize(BufferedImage image)
{
int height = image.getHeight();
int width;
while (height-- != 0)
{
width = image.getWidth();
while (width-- != 0)
{
Color color = new Color(image.getRGB(width, height), true);
int lum = lum_red_lookup[color.getRed()] + lum_green_lookup[color.getGreen()] + lum_blue_lookup[color.getBlue()];
if (lightness > 0)
{
lum = (int) ((double) lum * (100f - lightness) / 100f);
lum += 255f - (100f - lightness) * 255f / 100f;
}
else if (lightness < 0)
{
lum = (int) (((double) lum * (lightness + 100f)) / 100f);
}
Color final_color = new Color(final_red_lookup[lum], final_green_lookup[lum], final_blue_lookup[lum], color.getAlpha());
image.setRGB(width, height, final_color.getRGB());
}
}
}
public BufferedImage changeContrast(BufferedImage inImage, float increasingFactor)
{
int w = inImage.getWidth();
int h = inImage.getHeight();
BufferedImage outImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
for (int i = 0; i < w; i++)
{
for (int j = 0; j < h; j++)
{
Color color = new Color(inImage.getRGB(i, j), true);
int r, g, b, a;
float fr, fg, fb;
r = color.getRed();
fr = (r - 128) * increasingFactor + 128;
r = (int) fr;
r = keep256(r);
g = color.getGreen();
fg = (g - 128) * increasingFactor + 128;
g = (int) fg;
g = keep256(g);
b = color.getBlue();
fb = (b - 128) * increasingFactor + 128;
b = (int) fb;
b = keep256(b);
a = color.getAlpha();
outImage.setRGB(i, j, new Color(r, g, b, a).getRGB());
}
}
return outImage;
}
public BufferedImage changeGreen(BufferedImage inImage, int increasingFactor)
{
int w = inImage.getWidth();
int h = inImage.getHeight();
BufferedImage outImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
for (int i = 0; i < w; i++)
{
for (int j = 0; j < h; j++)
{
Color color = new Color(inImage.getRGB(i, j), true);
int r, g, b, a;
r = color.getRed();
g = keep256(color.getGreen() + increasingFactor);
b = color.getBlue();
a = color.getAlpha();
outImage.setRGB(i, j, new Color(r, g, b, a).getRGB());
}
}
return outImage;
}
public BufferedImage changeBlue(BufferedImage inImage, int increasingFactor)
{
int w = inImage.getWidth();
int h = inImage.getHeight();
BufferedImage outImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
for (int i = 0; i < w; i++)
{
for (int j = 0; j < h; j++)
{
Color color = new Color(inImage.getRGB(i, j), true);
int r, g, b, a;
r = color.getRed();
g = color.getGreen();
b = keep256(color.getBlue() + increasingFactor);
a = color.getAlpha();
outImage.setRGB(i, j, new Color(r, g, b, a).getRGB());
}
}
return outImage;
}
public BufferedImage changeRed(BufferedImage inImage, int increasingFactor)
{
int w = inImage.getWidth();
int h = inImage.getHeight();
BufferedImage outImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
for (int i = 0; i < w; i++)
{
for (int j = 0; j < h; j++)
{
Color color = new Color(inImage.getRGB(i, j), true);
int r, g, b, a;
r = keep256(color.getRed() + increasingFactor);
g = color.getGreen();
b = color.getBlue();
a = color.getAlpha();
outImage.setRGB(i, j, new Color(r, g, b, a).getRGB());
}
}
return outImage;
}
public BufferedImage changeBrightness(BufferedImage inImage, int increasingFactor)
{
int w = inImage.getWidth();
int h = inImage.getHeight();
BufferedImage outImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
for (int i = 0; i < w; i++)
{
for (int j = 0; j < h; j++)
{
Color color = new Color(inImage.getRGB(i, j), true);
int r, g, b, a;
r = keep256(color.getRed() + increasingFactor);
g = keep256(color.getGreen() + increasingFactor);
b = keep256(color.getBlue() + increasingFactor);
a = color.getAlpha();
outImage.setRGB(i, j, new Color(r, g, b, a).getRGB());
}
}
return outImage;
}
public int keep256(int i)
{
if (i <= 255 && i >= 0)
return i;
if (i > 255)
return 255;
return 0;
}
}
I wanted to do the exact same thing as the question poster wanted to do but the above conversion did not remove colors like the GIMP does (ie green with a red overlay made an unpleasant brown color etc). So I downloaded the source code for GIMP and converted the c code over to Java.
Posting it in this thread just in case anyone else wants to do the same (since it is the first thread that comes up in Google). The conversion still changes the white color when it should not, it's probably a casting issue from double to int. The class converts a BufferedImage in-place.
public class Colorize {
public static final int MAX_COLOR = 256;
public static final float LUMINANCE_RED = 0.2126f;
public static final float LUMINANCE_GREEN = 0.7152f;
public static final float LUMINANCE_BLUE = 0.0722f;
double hue = 180;
double saturation = 50;
double lightness = 0;
int [] lum_red_lookup;
int [] lum_green_lookup;
int [] lum_blue_lookup;
int [] final_red_lookup;
int [] final_green_lookup;
int [] final_blue_lookup;
public Colorize( int red, int green, int blue )
{
doInit();
}
public Colorize( double t_hue, double t_sat, double t_bri )
{
hue = t_hue;
saturation = t_sat;
lightness = t_bri;
doInit();
}
public Colorize( double t_hue, double t_sat )
{
hue = t_hue;
saturation = t_sat;
doInit();
}
public Colorize( double t_hue )
{
hue = t_hue;
doInit();
}
public Colorize()
{
doInit();
}
private void doInit()
{
lum_red_lookup = new int [MAX_COLOR];
lum_green_lookup = new int [MAX_COLOR];
lum_blue_lookup = new int [MAX_COLOR];
double temp_hue = hue / 360f;
double temp_sat = saturation / 100f;
final_red_lookup = new int [MAX_COLOR];
final_green_lookup = new int [MAX_COLOR];
final_blue_lookup = new int [MAX_COLOR];
for( int i = 0; i < MAX_COLOR; ++i )
{
lum_red_lookup [i] = ( int )( i * LUMINANCE_RED );
lum_green_lookup[i] = ( int )( i * LUMINANCE_GREEN );
lum_blue_lookup [i] = ( int )( i * LUMINANCE_BLUE );
double temp_light = (double)i / 255f;
Color color = new Color( Color.HSBtoRGB( (float)temp_hue,
(float)temp_sat,
(float)temp_light ) );
final_red_lookup [i] = ( int )( color.getRed() );
final_green_lookup[i] = ( int )( color.getGreen() );
final_blue_lookup [i] = ( int )( color.getBlue() );
}
}
public void doColorize( BufferedImage image )
{
int height = image.getHeight();
int width;
while( height-- != 0 )
{
width = image.getWidth();
while( width-- != 0 )
{
Color color = new Color( image.getRGB( width, height ) );
int lum = lum_red_lookup [color.getRed ()] +
lum_green_lookup[color.getGreen()] +
lum_blue_lookup [color.getBlue ()];
if( lightness > 0 )
{
lum = (int)((double)lum * (100f - lightness) / 100f);
lum += 255f - (100f - lightness) * 255f / 100f;
}
else if( lightness < 0 )
{
lum = (int)(((double)lum * lightness + 100f) / 100f);
}
Color final_color = new Color( final_red_lookup[lum],
final_green_lookup[lum],
final_blue_lookup[lum],
color.getAlpha() );
image.setRGB( width, height, final_color.getRGB() );
}
}
}

Categories

Resources