Tensorflow in Android: java.nio.BufferOverFlowException - java

Good morning. I'm a developer trying to put a tensorflow model into Android.
I've encountered an error that I've never seen before while trying to fix it with multiple errors.
The java.nio.BufferOverFlowException error i'm facing now is that it didn't happen before, but it happened suddenly.
My code uses a byte array, but i cannot specify which part is the problem.
This source that takes a float array as input and returns an array with 10 classes after passing through the model.
The returned values have softmax value.
public float[] hypothesis(float[] inputFloats, int nFeatures, int nClasses, Context context)
{
try {
int nInstance = inputFloats.length / nFeatures;
// FloatBuffer.wrap(inputFloats);
Toast.makeText(context, "", Toast.LENGTH_LONG).show();
inferenceInterface.feed(INPUT_NODE, FloatBuffer.wrap(inputFloats), INPUT_SIZE);
inferenceInterface.run(OUTPUT_NODES_HYPO);
float[] result = new float[nInstance * nClasses];
inferenceInterface.fetch(OUTPUT_NODE_HYPO, result);
return result;
}
catch(Exception e){
Toast.makeText(context, e+" ...", Toast.LENGTH_LONG).show();
return null;
}
}
The length of the inputfloats is 720 and the nFeatures is 720. nClasses is 10.
Although the value is not correct, it worked before.
e in the catch statement prints java.nio.BufferOverFlowException.
Could there be a problem in the middle of converting a byte array to a float array?
Related source.
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;
}
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.2126 * R + 0.7152 * G + 0.0722 * B);
bmOut.setPixel(x, y, Color.argb(A, R, G, B));
}
}
return bmOut;
}
private void activityPrediction(float[] inputArray){
try {
float[] result = activityInference.hypothesis(inputArray, 20*36, 10, getApplicationContext());
predictionView.setText(Arrays.toString(result));
}
catch (Exception e){
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
}
}
private byte[] bitmapToByteArray(Bitmap bitmap)
{
int chunkNumbers = 10;
int bitmapSize = bitmap.getRowBytes() * bitmap.getHeight();
byte[] imageBytes = new byte[bitmapSize];
int rows, cols;
int chunkHeight, chunkWidth;
rows = cols = (int) Math.sqrt(chunkNumbers);
chunkHeight = bitmap.getHeight() / rows;
chunkWidth = bitmap.getWidth() / cols;
int yCoord = 0;
int bitmapsSizes = 0;
for (int x = 0; x < rows; x++)
{
int xCoord = 0;
for (int y = 0; y < cols; y++)
{
Bitmap bitmapChunk = Bitmap.createBitmap(bitmap, xCoord, yCoord, chunkWidth, chunkHeight);
byte[] bitmapArray = getBytesFromBitmapChunk(bitmapChunk);
System.arraycopy(bitmapArray, 0, imageBytes, bitmapsSizes, bitmapArray.length);
bitmapsSizes = bitmapsSizes + bitmapArray.length;
xCoord += chunkWidth;
bitmapChunk.recycle();
bitmapChunk = null;
}
yCoord += chunkHeight;
}
return imageBytes;
}
private byte[] getBytesFromBitmapChunk(Bitmap bitmap)
{
int bitmapSize = bitmap.getRowBytes() * bitmap.getHeight();
ByteBuffer byteBuffer = ByteBuffer.allocate(bitmapSize);
bitmap.copyPixelsToBuffer(byteBuffer);
byteBuffer.rewind();
return byteBuffer.array();
}
'e.printStackTrace()' result
at com.example.leehanbeen.platerecognize.ActivityInference.hypothesis(ActivityInference.java:58)
at com.example.leehanbeen.platerecognize.MainActivity.activityPrediction(MainActivity.java:148)
at com.example.leehanbeen.platerecognize.MainActivity.access$100(MainActivity.java:28)
at com.example.leehanbeen.platerecognize.MainActivity$2.onClick(MainActivity.java:69)
around MainActivity.java:69
byte[] byteArrayRes = bitmapToByteArray(image_bitmap);
float[] inputArray = bytetofloat(byteArrayRes);
activityPrediction(inputArray);
MainActivity.java:28
public class MainActivity extends AppCompatActivity {
MainActivity.java:148
float[] result = activityInference.hypothesis(inputArray, 20*36, 10, getApplicationContext());
around ActivityInference.java:58
float[] result = new float[nInstance * nClasses];
inferenceInterface.fetch(OUTPUT_NODE_HYPO, result);

Related

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.

org.eclipse.swt.SWTException: Unsupported color depth

I have created a sample SWT application. I am uploading few images into the application. I have to resize all the images which are above 16x16 (Width*Height) resolution and save those in separate location.
For this reason I am scaling the image and saving the scaled image to my destination location. Below is the piece of code which I am using to do that.
Using getImageData() to get the image data and to save I am using ImageLoader save() method.
final Image mySampleImage = ImageResizer.scaleImage(img, 16, 16);
final ImageLoader imageLoader = new ImageLoader();
imageLoader.data = new ImageData[] { mySampleImage.getImageData() };
final String fileExtension = inputImagePath.substring(inputImagePath.lastIndexOf(".") + 1);
if ("GIF".equalsIgnoreCase(fileExtension)) {
imageLoader.save(outputImagePath, SWT.IMAGE_GIF);
} else if ("PNG".equalsIgnoreCase(fileExtension)) {
imageLoader.save(outputImagePath, SWT.IMAGE_PNG);
}
ImageLoader imageLoader.save(outputImagePath, SWT.IMAGE_GIF); is throwing the below exeception when I am trying to save few specific images (GIF or PNG format).
org.eclipse.swt.SWTException: Unsupported color depth
at org.eclipse.swt.SWT.error(SWT.java:4533)
at org.eclipse.swt.SWT.error(SWT.java:4448)
at org.eclipse.swt.SWT.error(SWT.java:4419)
at org.eclipse.swt.internal.image.GIFFileFormat.unloadIntoByteStream(GIFFileFormat.java:427)
at org.eclipse.swt.internal.image.FileFormat.unloadIntoStream(FileFormat.java:124)
at org.eclipse.swt.internal.image.FileFormat.save(FileFormat.java:112)
at org.eclipse.swt.graphics.ImageLoader.save(ImageLoader.java:218)
at org.eclipse.swt.graphics.ImageLoader.save(ImageLoader.java:259)
at mainpackage.ImageResizer.resize(ImageResizer.java:55)
at mainpackage.ImageResizer.main(ImageResizer.java:110)
Let me know If there is any other way to do the same (or) there is any way to resolve this issue.
Finally I got a solution by referring to this existing eclipse bug Unsupported color depth eclipse bug.
In the below code i have created a PaletteData with RGB values and updated my Image Data.
My updateImagedata() method will take the scaled image and will return the proper updated imageData if the image depth is 32 or more.
private static ImageData updateImagedata(Image image) {
ImageData data = image.getImageData();
if (!data.palette.isDirect && data.depth <= 8)
return data;
// compute a histogram of color frequencies
HashMap<RGB, ColorCounter> freq = new HashMap<>();
int width = data.width;
int[] pixels = new int[width];
int[] maskPixels = new int[width];
for (int y = 0, height = data.height; y < height; ++y) {
data.getPixels(0, y, width, pixels, 0);
for (int x = 0; x < width; ++x) {
RGB rgb = data.palette.getRGB(pixels[x]);
ColorCounter counter = (ColorCounter) freq.get(rgb);
if (counter == null) {
counter = new ColorCounter();
counter.rgb = rgb;
freq.put(rgb, counter);
}
counter.count++;
}
}
// sort colors by most frequently used
ColorCounter[] counters = new ColorCounter[freq.size()];
freq.values().toArray(counters);
Arrays.sort(counters);
// pick the most frequently used 256 (or fewer), and make a palette
ImageData mask = null;
if (data.transparentPixel != -1 || data.maskData != null) {
mask = data.getTransparencyMask();
}
int n = Math.min(256, freq.size());
RGB[] rgbs = new RGB[n + (mask != null ? 1 : 0)];
for (int i = 0; i < n; ++i)
rgbs[i] = counters[i].rgb;
if (mask != null) {
rgbs[rgbs.length - 1] = data.transparentPixel != -1 ? data.palette.getRGB(data.transparentPixel)
: new RGB(255, 255, 255);
}
PaletteData palette = new PaletteData(rgbs);
ImageData newData = new ImageData(width, data.height, 8, palette);
if (mask != null)
newData.transparentPixel = rgbs.length - 1;
for (int y = 0, height = data.height; y < height; ++y) {
data.getPixels(0, y, width, pixels, 0);
if (mask != null)
mask.getPixels(0, y, width, maskPixels, 0);
for (int x = 0; x < width; ++x) {
if (mask != null && maskPixels[x] == 0) {
pixels[x] = rgbs.length - 1;
} else {
RGB rgb = data.palette.getRGB(pixels[x]);
pixels[x] = closest(rgbs, n, rgb);
}
}
newData.setPixels(0, y, width, pixels, 0);
}
return newData;
}
To find minimum index:
static int closest(RGB[] rgbs, int n, RGB rgb) {
int minDist = 256*256*3;
int minIndex = 0;
for (int i = 0; i < n; ++i) {
RGB rgb2 = rgbs[i];
int da = rgb2.red - rgb.red;
int dg = rgb2.green - rgb.green;
int db = rgb2.blue - rgb.blue;
int dist = da*da + dg*dg + db*db;
if (dist < minDist) {
minDist = dist;
minIndex = i;
}
}
return minIndex;
}
ColourCounter Class:
class ColorCounter implements Comparable<ColorCounter> {
RGB rgb;
int count;
public int compareTo(ColorCounter o) {
return o.count - count;
}
}

How to write a output file in java using GDAL library?

public class Learn {
public static String getFilename(){
String strFilename = "";
Scanner scnr = new Scanner(System.in);
System.out.print("Enter the file path: ");
strFilename = scnr.next();
return strFilename;
}
public static void main(String[] args) {
gdal.AllRegister();
Dataset inputdata = gdal.Open(getFilename(), gdalconstConstants.GA_ReadOnly);
Dataset dataset = null;
Driver driver = null;
driver = gdal.GetDriverByName("GTiff");
driver.Register();
Band band2=null;
Band poBand = null;
int xsize = inputdata.getRasterXSize();
int ysize = inputdata.getRasterYSize();
int bandCount =inputdata.GetRasterCount();
int pixels = xsize*ysize;
int buf_Type = 0, buf_Size = 0, buf_xSize = 0,buf_ySize = 0;
int[] intArray = new int[pixels];
ByteBuffer[] bands = new ByteBuffer[bandCount];
String filename_out = getFilename();
System.out.println(filename_out+" "+xsize+" "+ysize+" ");
dataset = driver.Create(filename_out, xsize, ysize, 1, gdalconst.GDT_Byte);
dataset.SetGeoTransform(inputdata.GetGeoTransform());
dataset.SetProjection(inputdata.GetProjection());
band2 = dataset.GetRasterBand(1); // writable band
for (int band=0; band<bandCount; band++){
poBand = inputdata.GetRasterBand(band+1);
buf_Type = poBand.getDataType();
buf_Size = pixels * gdal.GetDataTypeSize(buf_Type)/8;
buf_xSize = xsize*gdal.GetDataTypeSize(xsize)/8;
buf_ySize = ysize*gdal.GetDataTypeSize(ysize)/8;
System.out.println(buf_Type+","+gdal.GetDataTypeName(poBand.getDataType()));
ByteBuffer data = ByteBuffer.allocateDirect(buf_Size);
data.order(ByteOrder.nativeOrder());
// reading data into "data" buffer
poBand.ReadRaster_Direct(0, 0, poBand.getXSize(), poBand.getYSize(), xsize, ysize, buf_Type, data);
bands[band] = data;
}
//generating indices;
float[] NDVI= new float[xsize*ysize];
Byte[] Binary_pixels= new Byte[xsize*ysize];
for (int i=0; i< xsize*ysize; i++)
{
int Red = bands[3].get(i) & 0xFF;
int NIR = bands[4].get(i) & 0xFF;
//NDVI
if ((NIR+Red) !=0){
NDVI[i]= (float)(NIR-Red)/(NIR+Red);
// System.out.println("NDVI: " + NDVI[i]);
}
else {
NDVI[i]=0;
// System.out.println("NDVI: " + NDVI[i]);
if (NDVI[i] > 0.3 ){
Binary_pixels[i]= 1;
// System.out.println("Binary=1");
}
else{
Binary_pixels[i]=0;
// System.out.println("Binary = 0");
}
}
// writing data into band2.
// Here I want to write a raster file using the data Binary_pixels[] as a raster file with the same projection and Transformations as the input file.
// here my file is ".tif" file with 4 bands in it.
}
}
here am new to java coding that too using a GDAL library for Remote sensing image processing. need some help to write an image with same dimensions of input image and projection & Transforms.
Thanks in advance.
Look at this example.
Dataset dataset = null;
Driver driver = null;
Band band = null;
int xsize = 4000;
int ysize = 400;
driver = gdal.GetDriverByName("GTiff");
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(4 * xsize);
byteBuffer.order(ByteOrder.nativeOrder());
FloatBuffer floatBuffer = byteBuffer.asFloatBuffer();
int[] intArray = new int[xsize];
float[] floatArray = new float[xsize];
dataset = driver.Create(filename, xsize, ysize, 1, gdalconst.GDT_Float32);
band = dataset.GetRasterBand(1);
for (int iter = 0; iter < nbIters; iter++)
{
if (method == METHOD_DBB)
{
for (int i = 0; i < ysize; i++)
{
for (int j = 0; j < xsize; j++)
{
floatBuffer.put(j, (float) (i + j));
}
band.WriteRaster_Direct(0, i, xsize, 1, gdalconst.GDT_Float32, byteBuffer);
}
}
else
{
for (int i = 0; i < ysize; i++)
{
for (int j = 0; j < xsize; j++)
{
floatArray[j] = (float) (i + j);
}
band.WriteRaster(0, i, xsize, 1, floatArray);
}
}
}
dataset.delete();

Getting exception in assignment of a value to array in android

I am trying to read an Image pixel by pixel and want to save the pixel RGB value in arrays.
but when trying to do so I am getting an exception in the statement
R[i]=redValue;
Someone please suggest what I might doing wrong?
please find the exception stack trace here -
paste.ubuntu.com/6216208
public class AnalyzeImage extends Activity
{
int []R;
int []G;
int []B;
int width, height, i=0;
int a=1;
public int analyzeImagefunc(Bitmap bitmap)
{
try{
width = bitmap.getWidth();
height = bitmap.getHeight();
i = 0;
for(int x = 0;x < width;x++)
{
for(int y = 0;y < height;y++)
{
int pixel = bitmap.getPixel(x,y);
int redValue = Color.red(pixel);
int blueValue = Color.blue(pixel);
int greenValue = Color.green(pixel);
a=5;
R[i]=redValue;
a=6;
i++;
}
}
}
catch(Exception e)
{
//nothing
}
return a;
}
}
Your arrays need to be initialzed first before using. You have jsut declared the arrays:
int []R;
int []G;
int []B;
but not initialized them.So if you try to access any array element it will throw null pointer exception. Try to initialized your array like:
int []R = new int[10];
int []G = new int[10];
int []B = new int[10];
You can change the size of arrays as per your need.
int []R;
int []G;
int []B;
R, G, B is not initialized any where.
initialize the R
width = bitmap.getWidth();
height = bitmap.getHeight();
i = 0;
int size = height * width;
R = new int[size]; // initialize the size of array R
for(int x = 0;x < width;x++)
Array need initialization with fix size. so if array's size is not fix then you should go with ArrayList. and also you can cast ArrayList to array if needed for final output.
public class AnalyzeImage extends Activity {
int[] R;
int[] G;
int[] B;
ArrayList<Integer> R_Lst = new ArrayList<Integer>();
ArrayList<Integer> G_Lst = new ArrayList<Integer>();
ArrayList<Integer> B_Lst = new ArrayList<Integer>();
int width, height, i = 0;
int a = 1;
public int analyzeImagefunc(Bitmap bitmap) {
try {
width = bitmap.getWidth();
height = bitmap.getHeight();
i = 0;
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int pixel = bitmap.getPixel(x, y);
int redValue = Color.red(pixel);
int blueValue = Color.blue(pixel);
int greenValue = Color.green(pixel);
a = 5;
// R[i] = redValue;
R_Lst.add(redValue);
B_Lst.add(blueValue);
G_Lst.add(greenValue);
a = 6;
i++;
}
}
}
catch (Exception e) {
// nothing
}
R=convertIntegers(R_Lst);
return a;
}
public int[] convertIntegers(List<Integer> integers)
{
int[] ret = new int[integers.size()];
for (int i=0; i < ret.length; i++)
{
ret[i] = integers.get(i).intValue();
}
return ret;
}
// (Note that this will throw a NullPointerException if either integers or any element within it is null.)
width = bitmap.getWidth();
height = bitmap.getHeight();
int n = width * height;
R = new int[n];
G = new int[n];
B = new int[n];
i = 0;
By implication, you also require:
R[i] = redValue;
G[i] = greenValue;
B[i] = blueValue;

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