I am currently trying to write a program to encode text into a png file only changing the least significant bit for each letter i want to encode in the picture, example
I have a 'A' which is 65 and I use 8 different bytes to encode the letter A. So
01010100<- 10101101<- 11011010<- 10101010<- each of these I change the last bit and the put
10110110<- 01010100<- 01010100<- 01010101<- them together so 65 is 01000001 each number by
the arrow is changed according to the 65.
If I should approach this a different way suggestions would be awesome :). This is just
a fun little project I wanted to do. But anyways back to my question.
When I read in a image that is only 4 pixels big I get like 680 bytes which is crazy, or at least I think it is, maybe im wrong? 4 pixels with ARGB at 8 bits each should be 16 bytes with a few bytes im sure to tell the operating system that it is a png and how to handle it. So i was expecting maybe like 30 bytes. Maybe less. Am I looking at this the wrong way? When png images are compressed do they become bigger if it is a small picture? And also, when I was saving it back to the Hard drive I always got a larger file. The original picture was 8,554 kb and then it turned into like 16kb when I saved it back. Here is the code for getting the image bytes and for saving the image. Maybe I am doing something wrong or I am just not understanding it correctly.
These are the ways I get the image (I tried 2 different things)
// BufferedImage img = ImageIO.read(new File("image.png"));
BufferedImage img= robot.createScreenCapture(new Rectangle(1,2,2,2));
how I saved two different ways again.
try {
InputStream in = new ByteArrayInputStream(imgBytes);
BufferedImage bImageFromConvert = ImageIO.read(in);
ImageIO.write(bImageFromConvert, "png", new File(
"image.png"));
//FileOutputStream fos = new FileOutputStream("image.png");
//fos.write(b);
//fos.close();
}catch(Exception e){}
How I got the bytes from the Image, again I tried two different ways, the second way that is commented out actually did give me the 16 bytes like I want but when I saved it the Windows couldnt Open it because it didnt know what it was i guess? Not sure, just said file not supported.
byte[] imageBytes = null;
try{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "jpg", baos );
baos.flush();
imageBytes = baos.toByteArray();
baos.close();
}catch(IOException e){System.out.println(e.getMessage());}
// imageBytes = ((DataBufferByte) image.getData().getDataBuffer()).getData();
return imageBytes;
Thanks!
A png consists of a lot of image meta data as well as the raw image data. That is what is giving you crazy 680 bytes.
I had pretty much the same problem with my barcode fonts. I just wanted to encode 5 bits of data into the smallest PNG I could get. What I didn't want to do is write a custom program, based on libpng. I tried quite a few editors and the smallest file size I could get was around 170 bytes.
Finally I found Gimp 2.0. There is a feature you can use to export a PNG file without all the metadata. I also changed to 8 bit grayscale. I think I could shave a couple of bytes off by switching to 2 bit grayscale, but Gimp wouldn't do that for me. In the end, I was happy with ~75 bytes per character.
Related
I use Base64 system for encode from image to string this code
Bitmap bitmap = BitmapFactory.decodeFile(picturePath);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, stream);
byte[] image = stream.toByteArray();
String img_str = Base64.encodeToString(image, 0);
and decode this code
byte[] decodedString = Base64.decode(decode, Base64.NO_WRAP);
Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
imageView.setImageBitmap(decodedByte);
but string is too long, very very long. I can't use this way. How can I do short string ?,
You can't. Images typically contain a lot of data. When you convert that to text as base64 it becomes even bigger (4 characters for every 3 bytes). So yes, that will typically be very long if it's a large image.
You could compress the image more heavily in order to reduce the size, but eventually it will be hard to even recognize as the original image - and may well be quite large even so.
Another way of reducing the size in bytes is to create a smaller image in terms of the number of pixels - for example, shrinking a 1000x1000 image to 100x100... is that an option in your case?
You haven't given us much context, but could you store the data elsewhere and then just use a URL instead?
I believe the only answer for this is that if you want a shorter string, you should use smaller image
Depends on the size of the image. A larger image is gonna yield a larger string. Images contain a lot of data. That is why people usually only do base64 encoding for very small images like icons, etc.
You could try reducing the quality of the JPEG compression, but I doubt you'd save much space. Reducing the dimensions (if possible) of the image would probably save some space. Either way, doing base64 on anything larger than a really small gif or png image is almost always counter productive.
How do you convert bmp to jpg in Java? I know how to use the ImageIO way but is there a much faster or better way of doing it?
This is the ImageIO way of doing that I found on the web.
`//Create file for the source
File input = new File("c:/temp/image.bmp");
//Read the file to a BufferedImage
BufferedImage image = ImageIO.read(input);`
//Create a file for the output
File output = new File("c:/temp/image.jpg");
//Write the image to the destination as a JPG
ImageIO.write(image, "jpg", output);
If I use this way will I lose quality?
Thanks
Yes you will. Actually regardless of the way to convert a BMP (lossless) to JPG (lossy) you always lose quality. You can limit the damage if you set the JPG quality to 100% (which kind of defeats the purpose in my opinion).
Use this tutorial to fix it.
I'm loading a jpeg-file via BitmapFactory and try to save it again (later I want to do some calculation on the pixel data before I save it again).
But if I try to save it with
FileOutputStream fos = new FileOutputStream(new File("/sdcard/test.jpg"));
originalImage.compress(Bitmap.CompressFormat.JPEG, 100, fos);
then it is not exactly the same result as in the original picture. Some pixel have got different color values and this ist not useful for my later calculation.
Is there a possibility to safe it lossless? Or is the problem already when I load the picture with
Bitmap originalImage = BitmapFactory.decodeFile("/sdcard/input.jpg");
few lines before?
Is there a possibility to safe it lossless?
No. The JPEG format uses a lossy compression. It makes no formal guarantees even if you set the quality to 100.
Or is the problem already when I load the picture with [...]
No, bitmaps are... maps of bits, i.e. they represent the exact bits of the image data.
I have a program that
Accepts an encoded base64 string
Converts it to a byte array.
It does this fine.
The final step involves writing this byte array to a file. For example C:\example.jpg.
I know simply writing the bytes won't work so was not sure what I would need to do to take the byte array and create a jpg with the picture that is coming in.
I have to actually send the picture as an attachment in email, but for testing purposes wanted to see if I can see a file saved and when I open up the jpg opens up. Thanks.
I'm guessing you're in need of something like this?
BufferedImage image = ImageIO.read( new ByteArrayInputStream( byteArray ) );
ImageIO.write(image, "BMP", new File("filename.bmp"));
Check out this question and answer, that's where I acquired it from:
How to create a BMP file from raw byte[] in Java
I am using a common format all over application for images as png.Any jpg image uploaded still gets saved as png using code as below.
java.awt.image.BufferedImage bufferedImage = ImageIO.read(jpgImagePAth);
if(!IsExtensionPng(jpgImagePath)){
ImageIO.write(bufferedImage, "png", new File(pptFolder, justNamePng));
}
But this preserves alpha even though it was not there in the jpg so makes a 2MB Image 7MB and 6MB to 16MB . Is there anyway to save png without maintaining the alpha ?
The reason I need to conver to PNG is that later on when I add text on image it looses the actual resolution. I already tried loseless JPEG which didnt fix it.
It's not the alpha channel that is causing the file size to grow, it's the file type. JPG uses lossy compression; PNG is lossless compression. In other words, JPG is throwing out some data to reduce the size of the file. That's why you get to choose a "quality" level when saving to JPG - that determines how much is thrown out.
How do you know you're getting the alpha channel anyway? If you still want PNG and want to be sure you're dropping the alpha channel, set the image type to BufferedImage.TYPE_RGB, e.g.
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_RGB);
You'll have to get the graphics object associated with your new BufferedImage and copy the jpg onto it, then write it out. This question isn't quite the same as yours but has sample code you may find useful.
Paul
I don't know exactly in what situation you are. But I should keep JPEG JPEG. The only advantage of converting JPEG to PNG is wasting hdd space.