Reputation: 145
I'm currently trying to convert a piece of matlab code to java. The purpose of the code is to invert and normalize the image pixels of an image file. In java, the pixels are stored in a byte array. Below is the Matlab code of importance:
inp2=1024.-inp.-min; %inp is the input array (double precision). min is the minimum value in that matrix.
The image is 16 bit, but is using only 10 bits for storage, so that's where the 1024 comes from (2^10). I know definitively that this code works in matlab. However, I'm personally not proficient in matlab, and my java translation isn't behaving the same way as its counterpart.
Below is the method where I've tried inverting the image matrix:
//bitsStored is the bit depth. In this test, it is 10.
//imageBytes is the pixel data in a byte array
public static short[] invert(int bitsStored) {
short min = min(imageBytes);//custom method. Gets the minimum value in the byte array.
short range = (short) (2 << bitsStored);
short[] holder = new short[imageBytes.length];
for (int i = 0; i < imageBytes.length; i++) {
holder[i] = (short) (range - imageBytes[i] - min);
}
imageBytes = holder;
return imageBytes;
}
However, instead of inverting the color channels, the image loses some data and becomes much harsher looking (higher contrast, less blend, etc). What am I doing wrong here?
Let me know if I can make anything clearer for you. Thank you.
UPDATE: Hi, I have another question regarding this code. Can the above code (fixed to short[] not byte[]) be used in reverse on the same file? As in, if I rerun through this code using an inverted version of the original image, should I get the original input/image from the start of the program? The only problem with it I think is that the min value changes between runs.
Upvotes: 1
Views: 1839
Reputation: 11875
On your second question about the reversibility of your algorithm.
Your formula looks like result[i] = 1024 - min(data) - data[i]
where data ranges from 0
to 1023
. Let's imagine that all your data points are 1023
. Then min
is 1023
, so all the result[i]
will be -1022
.
So the result
does not even fit in the same range as the data
.
Then, if you run your algorithm with that result
array to produce result1
, all its points will be 1024 - (-1022) - (-1022)
i.e. 3068
, and not the original 1023
.
So the answer is not, double application of this algorithm does not produce result equal to the input.
Please note that the algorithm mentioned in another answer (maxPossibleValue - currentValue[i]
) keeps range and it is reverses when applied twice.
BTW, it should be
short range = (short) (1 << bitsStored);
instead of
short range = (short) (2 << bitsStored);
to produce 2^bitsStored
.
Upvotes: 1
Reputation: 11875
byte
has range from -128 to 127, it cannot hold 1024 different values. So either you need to use a wider type (like short
) to model your points, or your byte array has to be unpacked before processing.
One more thing: double
is floating point and it does not play well with integers used in the rest of your code. The following seems better:
short range = 1 << bitsStored; // 2^bitsStored
Upvotes: 4
Reputation: 336
Correct equation for inversion is:
newValue[i] = maxPossibleValue - currentValue[i]
Your maxPossibleValue
is 1024.
Other thing is that you can't have image with depth of 10 bits in array of bytes (cause they've 8 bits)
Upvotes: 2