Saving Bitmap to PNG file changes Pixel data - android

I'm trying to modify the LSB in Pixels in order to Store Information in a Picture. The Encoding and Decoding does work how ever when i store the Bitmap to a png file which should be lossless and reload it the Pixel values have changed. This ofcourse leads to wrong values when i put the character back to gether however most of the times this can be fixed by substracting 136 from the Byte before making a char out of it. The Problem has to be the storing and reloading as when i pass the Bitmap directly to the Decoder everything works fine.

Please try with giving quality value when you store image.
bitmap.compress(Bitmap.CompressFormat.PNG,0, imageOut)
Second parameter is quality value which is between 0 to 100.

Related

Android : Save jpeg image without compression

I'm trying to build an image steganography android app to hide information in jpeg images.
I'm encoding the information in the DCT Coefficients of the image.
I'm using OpenCv to perform the following steps :
Load image bitmap and get image mat from it.
Convert image from RGB to YCrCb
Divide the image into blocks of 8 x 8 blocks.
Center pixel values around 0 [0-255 => -128-127]
Apply DCT transformation to get DCT coefficients for the block.
Quantization [divide the DCT coefficients with quant matrix]
Now substitute the LSBs of the non 0/1/DC coefficients with our secret message.
inverse quantization
inverse DCT
[0-255 <= -128-127]
YCbCr to RGB
Get bitmap from image mat
Save the bitmap as jpeg.
The idea is that since I'm just extracting and repacking a jpeg image using jpeg compression algo, the jpeg compression algorithm should not destroy the data in the DCT coefficients (a lot of jpeg there :P)
Problem :
The data I just saved in the LSB of DCT coefficients gets destroyed int the 12th step. I want a way to save the image without its data being destroyed (which should be theoretically possible since I have followed the jpeg compression algorithm only.
Somethings I have tried :
this is the normal method, which leads to dataloss.
I used this method. It does not destroys the data, but it increases the file size by around 6 times and the final file received is not jpeg, it is pure bytes (which can be viewed in image viewer if the extension is set to jpeg or png)
I thought that the jpeg image I used might have a different level of compression as compared to the one while saving the jpeg image by android. So I used the image saved by the app to hide data. Even in that a lot of data is lost(less compared to before).
saving the image as png. This works, no data is lost and dct algorithm can be applied to extract the hidden information. But the point was to get a jpeg image as output, bcz jpeg is the most common image extension out there.

Bitmap pixel values differ after setPixel() and getPixel() on same pixel

I'm developing a steganography app for a class project which allows a user to encode a secret message image with in another image. I use Bitmap.getPixel(x,y) to retrieve pixel information after modifying the pixel integer value to contain the message value. I then used Bitmap.setPixel(x,y) to place the modified pixel in the bitmap. After decoding the image and retrieving the hidden message I've noticed some pixels were discolored. I've found that certain pixels do not contain the correct value after being modified. if I use
int before = encoded_value;
bitmap.setPixel(x,y, before);
int after = bitamp.getPixel(x,y);
for most of the pixels before==after however on some before!=after. If I continuously modify before by adding or subtracting one( this only changes the color slightly in the message image ) and then set the pixel again the values of before and after still differ. Having a few pixels off in the decoded image wouldn't be that big of a deal. However, when one of the problem pixels shows up where I encoded the message image information( the images dimensions ) the decoded dimensions will usually contain a non digit value such as "2q3x300". Which will through an exception when the application tries to turn this string into integer values. I've also tried to get and set pixels using a integer buffer however the same pixels cause problem. Also through some debugging I've found that certain pixels cause problems and certain values cause problems if I encode the image with with a doubled dimension string "213213x300300" the string is decoded from the image as "2q32q3x300300". I'm not sure if this is a problem that start when decoding the bitmap from an image file or its a bug in the getPixel() and setPixel() methods. It seems that certain pixels cause a bit to be off. In the above example 1( which contains an ascii value of 49 or 00110001) is decoded as q( which contains an ascii value of 113 or 01110001) only a single bit value differs from the set and get however it can cause bit problems. The Bitmap is in ARGB_8888 and thus should be able to contain any value that can also be contained in an integer value. For the stereography to work I'm modifying the least 2 bits of the alpha, red, green and blue values to store 1 byte. I reduce the message image to RGB_332 so that It can be contained in the least bits. One more example is trying to set a pixel to -53029643.
I put -53029643 = 1111 1100 1101 0110 1101 0100 1111 0101
and get returns -53029387 = 1111 1100 1101 0110 1101 0101 1111 0101
----------------------------------------------------XOR
= 0000 0000 0000 0000 0000 0001 0000 0000 = 256
Although these two only differ in the least bit of the green value. The decoding of this integer value by taking the least 2 bits from each bit yields 00100101 instead of 00100001 the bytes are in the form RRRGGGBB thus green value is changing from 000 to 001 and the resulting bit map will contain a pixel with a green value of 001000 instead of 000000 since the decoded bit map is in RGB_565 and thuse the decimal value from green is 8 instead of 0. Here the 3 png images the first is the carrier image( the image that has the message image encoded into it) the second is the message image( the image that is encoded in the carrier image) and the third is the message image after it has been decoded from the carrier image.
carrier image
message image
decoded message image. This image is in 8 bit color the pixels that are more red or green are the ones affected by this error.
This defect in the android api appears to relate to the same issue i'm having. Since there was no way to solve this issue while creating the bitmap from a pixel array or when decoding into the message image I've had to resort to using image filtering after the image has been decoded. I'm using a median filter that has been modified to target problem pixels here is an example of an image with and without the median filter.
unfiltered
filtered
This looks very much like an issue I had where (only on some devices) bitmaps loaded from the drawables folder would be changed slightly. I solved it by putting the bitmaps in the "raw" folder (e.g. res\raw). Hope that helps.
Your bitmap is probably set up as 565, i.e. 5 bits for red, 6 for green, 5 for blue. As such, you can only have 32 distinct values for red/blue and 64 for green.
If you need more precision, you need to create an 8888 bitmap.
Example:
Bitmap bitmap = Bitmap.createBitmap(128, 128, Bitmap.Config.ARGB_8888);
I know this is an old post, but I was able to solve the issue by alternating adding and subtracting 1 from each incorrect byte in the ARGB integer until the least significant bit of each of those bytes was correct. I believe this is the optimally closest the pixel can get while having the least significant bit of each byte correct.
Additionally, I have reported this bug to google.

Access to separate pixel of JPEG image in Android

In my android project I need to get access for each separate pixel of JPEG image. Image created by built-in photo application. I try to convert JPEG into Bitmap class instance, but OutOfMemoryException was thrown. After searching info about this problem I have found the following solution: resize image! But quality of image is important in my project, and i can't resize it. Is there any way to get each-pixel access?
if your image is too big and the quality is important i suppose the best way is to use or create your own class to cut the image in zone (eg : 50*50 px) , there is several jpeg info class in the internet to help you understand how work jpeg files.
Have you tried BufferedImage ? (it's not in the sdk but maybe usable)
The nature of jpeg makes it very hard to get the value of a single pixel. The main reason is that the data is not byte aligned, another is that everything is encoded in blocks that can be of sizes 8x16, 16x8 and 8x8. Also, you need to handle subsampling of chroma values.
If the image contains restart markers, maybe you can skip into the image so you don't have to decode the whole image before getting the pixel value.

How to access pixels of a Bitmap image on Android?

In short I am unable to access all the pixels of a bitmap image.
I have used an intent to fire the native Camera app and returned a Bitmap image to my application activity. The data is definitely a bitmap object and I am able to display, get the height/width etc and access some pixels using getPixel(). However when I use the values of getHeight() and getWidth() I get an array out of bounds error. By trail and error I have found I can only access a reduced number of pixels of the image, for example with one image which returned a height and width value of 420,380, I could also access 200,100. I then do some image processing and used setPixel() on the original image. When I display the image it shows the, say 200,100, processing pixels and the rest normal, therefore the pixels are obviously there and accessible by android but not by me. I have to spoken to other people who have also had this problem with images.
Does anyone know anything more about this, reasons? or a work around?
Many thanks in advance.
It seems that there's no way around this, does anyone think it would be better/possible to access the image directly in memory maybe using the NDK?
You won't be able to access the pixel at (getWidth(),getHeight()) in any image because like everything else they are 0-indexed. The valid range of pixels is (0 to getWidth()-1, 0 to getHeight()-1), and thus the bottomrightmost pixel is obtained by b.getPixel(b.getWidth()-1, b.getHeight()-1).
Got an answer from Albert Pucciani on the Android forums. I now create an int buffer and copy the pixels to it, then use get() and put() to extract the pixels. It's also much quicker to use get() and put() instead of the get/setPixel() from the Bitmap class. Need to test now whether this does return all the pixels to the buffer for all images.
After more testing I have discovered this is simply a memory issue as the amount allocated for each process includes all bitmaps.

Image Processing on Android

I'm writing an application for Android.
I need to make some image processing on the picture taken from camera.
I use Camera.PictureCallback to get the photo, and I get picture in byte array.
The problem is I want to make operations on every pixel of photo (some filtering and other stuff) so I guess, have photo in byte array is not a bad idea. But I don't know how interpret information in this byte array... The only way I know to make the processing is use BitmapFactory.decodeByteArray() and then use Bitmap object. Is this a good way to handle a lot of image processing?
Right now I use something look like this:
Bitmap mPhotoPicture mPhotoPicture = BitmapFactory.decodeByteArray(imageData, 0 , imageData.length);
mPhotoPicture = mPhotoPicture.copy(Bitmap.Config.RGB_565, true);
I appreciate any help.
I'm not sure if decoding into a byte array is the best way to do it on Android, but I can offer what I know about image processing in general.
If you're using RGB_565, that means each pixel is 16 bits, or two of those bytes. The first 5 bits are red, the next 6 are green, and the last 5 are blue. Dealing with that is hairy in Java. I suggest you work with an easier format like ARGB_8888, which will mean you have 32 bits, or four bytes per pixel, and each byte is its own value (alpha, red, green, blue).
To test, try setting every fourth byte, like [3], [7], [11], etc., to 0. That should take out all of a particular channel, in this case, all the blue.
[2], [6], [10], etc. would be all the green values for each pixel.
(Note, the four components might go in the opposite order because I'm not sure about endianness! So I might have just told you how to take out the alpha, not the blue…)

Categories

Resources