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.
Related
how to compress GIF image before upload it to the server ?, i tried some android libraries to compress gif image but it convert it to png image. is there any way to compress gif image ?
im using a bitmap in my projects.
Bitmap
Example code:
ImageView carView = (ImageView) v.findViewById(R.id.imagen_cr7);
byte[] decodedString = Base64.decode(picture, Base64.NO_WRAP);
InputStream input=new ByteArrayInputStream(decodedString);
Bitmap ext_pic = BitmapFactory.decodeStream(input);
carView.setImageBitmap(ext_pic);
GIF is a lossless image compression format: it is set up to reproduce the image exactly.
As a consequence, there is no "image quality" slider (as in JPEG encoders); although a GIF will likely be much smaller than an uncompressed format (such as many camera RAW or common TIFF options), there is a limit to how far it can go.
Also, you should know that GIF is limited to 8 bits per pixel (so it is most appropriate for line art, not photo-like images). If your source image is a full 24 bits, it must be dithered to fit into a 256-entry color palette. So, although the GIF format itself is lossless, the image processing required to use it in the first place may be lossy.
There are a number of things you can do to reduce the size of your image file:
You can choose a lossy format (such as JPEG), which will allow much greater compression. Note that JPEG works well on photo-like images, but not so well on line art. Also, (although your question explicitly rejects it) PNG may be a reasonable option, as it (losslessly) supports 24-bpp images.
As mentioned in a comment, you can try reducing the resolution of your image, and shipping the reduced version. If you can't generate a smaller image to start with, image resizing typically works well on photo-like images, and there are nonlinear resizing filters available that are specifically intended to handle line art.
If a full-resolution GIF is mandatory for your application, you may be able to generate an image that is more compressible by the GIF format. GIF compresses solid blocks of color extremely well -- but does less well on dithered or noisy images (such as you might get from converting a 24-bpp image to GIF format).
Since you have not given any information on your requirements (what kind of image you have, where you got it, and what you need it for), it is hard to come up with specific advice.
However, there is a good chance that your GIF has far more resolution than you need for your particular application (leading to option #2).
JPEG is a compressed format.
Does BitmapFactory.decodeFile("path to a JPEG file") decompress the JPEG image when decoding it as a Bitmap in the memory?
And when I use Bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream) on the resulting bitmap from the decoded JPEG file, then the size of the compressed image is more than the size of the original image. Can anybody exactly explain this phenomenon?
Does BitmapFactory.decodeFile("path to a JPEG file") decompress the JPEG image when decoding it as a Bitmap in the memory?
Yes.
And when I use Bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream) on the resulting bitmap from the decoded JPEG file, then the size of the compressed image is more than the size of the original image
That is very possible. With a quality level of 100, I would consider it likely, though perhaps not assured.
Can anybody exactly explain this phenomenon?
There is no requirement that they be the same for a JPEG. In fact, it will be almost random chance if they are the same.
Suppose we start with an in-memory image (Boriginal, where B is short for bitmap). We then compress that image to a JPEG (Joriginal). JPEG incorporates a lossy compression algorithm, to achieve better compression on real-world images (e.g., photos) by taking into account the fact that human eyes cannot discern small amounts of change.
Suppose we then decode Joriginal back into an in-memory bitmap (Breloaded). Breloaded will not be the same image as Boriginal, because the JPEG compression will have changed the image. How close Breloaded is to Boriginal will depend on a variety of factors, partly tied to the image itself, and partly tied to the quality level used when saving the JPEG (the 100 in your code). This quality level ranges from 0 to 100, with 100 meaning highest quality.
If we then compress Breloaded to a second JPEG (Jreloaded), the new JPEG will not be the same as the original JPEG (Joriginal). Partly, that is because the source bitmap changed, per the previous paragraph. Partly, that is because we might not choose the same quality level as we did with the original compression work.
In your case, you did not create Joriginal. You do not necessarily know what quality level was used (that information might be stored in the JPEG header; I forget). But because Breloaded will be different that the original bitmap (wherever it came from), when you compress the bitmap to Jreloaded, it is going to be different than Joriginal. On the whole, whether it is larger or smaller is difficult to say in the abstract. However, since you are choosing a quality level of 100, and Joriginal might well have been compressed with a lower quality level, your compressed image very easily could be larger.
This has nothing to do with Android. This is purely a function of how JPEG works. If you have further questions about JPEG itself, you may wish to read more about JPEG and ask questions on some site that has something to do with image formats.
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.
I am developing an image manipulation application which has to be able to work on large images e.g. those taken by a camera, the approach I'm taking is to split the source image into multiple suitably sized tiles so that the tiles can be loaded individually into memory as a Bitmap without exceeding the dreaded VM limit, next image manipulation is performed on a tile by tile basis, this is all well and good but until I want to stitch these tiles back to a final jpeg image.
I'm looking for a built in sdk api or free ware solution that can perform the following:
Open jpeg output file as output stream
Stream RGB pixels from bitmap (tile 1) to jpeg output stream
Stream RGB pixels from bitmap (tile 2) to jpeg output stream
etc.. for all tiles
Close jpeg output stream
Any ideas or pointers other than writing my own jpeg encoder?
What about this:
FileOutputStream outFile = new FileOutputStream(output_file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outFile);
outFile.flush();
outFile.close();
You can adjust the quality setting (100). See the docs
You'll still need to decide how to slice it. But if you're taking the image on the device, why would it be a problem loading the whole image if it didn't cause a memory problem in the first place?
Stitching Tiles back together: Here's one simple approach used by slippy maps the I know works.
Cut tiles in standard size (say 256x256)
Assign each tile an x,y value - this could be a directory structure or filename convention: i.e. "0_0.jpg"
Tile names (numbers) are related to their top/left pixel position.
Each tile number can be calculated by the following:
tileX = floor(pixelX / 256)
tileY = floor(pixelY / 256)
So the tile at pixels 0,0 = tile (0,0), the tile at pixels 256,0 is tile (1,0), etc...
Your stitching approach has two major issues and will ultimately fail. If you ask the system to decode a JPEG file in parts, the decode time will end up being close to N times longer (N = number of parts). The next problem is that when trying to save the image you will run out of memory. JPEG images need to be compressed in one shot. If your entire uncompressed image can't fit in memory, then you won't be able to use the technique you're using.
The hard truth is that, with Android as it is currently designed, you must use native code to hold on to the bitmap in order to manage an image larger than the VM memory limit. It's not that difficult, but it does require a re-design of your app.
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.