How convert Bitmap to byte array and back without quality reduction? - java

When I convert a picture into bytes and back, the quality deteriorates a lot. How to do it without reducing quality?
I need to save the photo in the database or send it to the server. I can consider other options to do this.
public static byte[] fromBitmap(Bitmap bitmap) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
return stream.toByteArray();
}
public static Bitmap toBitmap(byte[] bytes) {
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
}

How to do it without reducing quality?
Use a lossless image format, such as PNG.

It's not a good way to save the picture in the database directly. The best way is to upload pictures to the server in a directory and save the picture path in the database. Here you can find out a complete tutorial to upload the picture on the server and save its path in the MYSQL database.

Related

Convert BMP image to PNG or JPG in Java without loading the entire image in memory

I am trying to use a BitmapRegionDecoder to load parts of a large Bitmap image in Android but am stuck because the BMP file format is not supported(only JPG and PNG).
Is is possible to "transcode" a bitmap image into JPG or PNG (compression doesn't really matter) without loading the entire image into memory?
Something like
FileOutputStream fos = new FileOutputStream(pngFile);
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = bmpInputStream.read(buffer)) > 0) {
// Process bytes to PNG format
fos.write(buffer, 0, bytesRead);
}
Managed to do it using this PNGJ library , written in pure Java so usable in android, and which allows to write PNG files line by line without loading the whole image into memory.

Question regarding jpeg and png file structure and header information

I need to be able to modify the contents of a jpeg or png files and am able to successfully break the image down into bytes and vice versa. The only problem is that i do not know how many bytes make up a jpeg file header or a png file header. The information on most websites is pretty vague and/or way too informative for a beginner like me.
Id really appreciate if someone can provide a simple answer telling me how many bytes i need to skip to get past the header and how to identify if the image is a jpeg image or a png image as well as any other important information that i may not have mentioned.
Ive added the code below which im using to extract the bytes from an image and to convert the image into bytes.
Note: This code works on android OS
Code used to convert image to bytes:
public byte[] imgtobytes(File f)
{
FileInputStream fis=null;
try
{
fis = new FileInputStream(f);
}
catch(Exception e) {}
Bitmap bm = BitmapFactory.decodeStream(fis);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100 , baos);
byte[] b = baos.toByteArray();
return b;
}
Code used to convert bytes to image and display it on an imageview:
public void bytestoimg(byte[] bytearray, ImageView imgv)
{
Bitmap bmp = BitmapFactory.decodeByteArray(bytearray, 0, bytearray.length);
imgv.setImageBitmap(Bitmap.createScaledBitmap(bmp, imgv.getWidth(),
imgv.getHeight(), false));
}
I've done some similar work in python a while ago playing with encryption. I believe that what you are looking for can be found in this wikipedia article under "Examples" section.
Also you can check out this answer

Android - Save Bitmap Image on Mobile Storage without Compressing

The typical way (based on research) for saving bitmap images from a remote url is:
Bitmap bmImage = null;
InputStream in = new java.net.URL(imageUrl).openStream();
bmImage = BitmapFactory.decodeStream(in);
File file = new File(myPath);
FileOutputStream outputStream;
outputStream = new FileOutputStream(file);
bmImage.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
outputStream.close();
I cannot save bitmap unless it is compressed (Bitmap is always uncompressed).
The remote image size is 32KB, after compression it gets 110KB.
I know I have to lower compression parameter to get smaller size, but the remote image is optimize and much more efficient.
Is there a way I can save the remote image on mobile storage without compressing it?
===== ANSWER TO MY PROBLEM =====
First I apologize for misleading content; all I wanted is to save images that could be png|jpeg|gif|etc.. Probably I mislead you guys that the image I am trying to save is in BMP format, but it is not.
Nevertheless, for those who want to save images WITHOUT compressing, have a look to this answer
Use AndroidBmpUtil as shown in the code below:
new AndroidBmpUtil().save(bmImage, file);

Inserting 1 MB image in neo4j returns a different size (536 KB) when retrieved

I am trying to insert a 1 MB image inside neo4j using the following code:
File fnew = new File("C:\\Users\\myimage.jpg");
BufferedImage originalImage = ImageIO.read(fnew);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.flus();
ImageIO.write(originalImage, "jpg", baos);
return baos.toByteArray();
Then I insert this byte array using:
user.setProperty("photo", photo);
This all goes fine. When I try to select the photo, using the following method, it writes it on my hard drive disk as 536KB instead of the 1 MB original size.
byte[] imageInByte = (byte[]) user.getProperty("photo");
InputStream in = new ByteArrayInputStream(imageInByte);
BufferedImage bImageFromConvert = ImageIO.read(in);
ImageIO.write(bImageFromConvert, "jpg", new File("C:\\newimage.jpg"));
Now the weird part: I can see the image, open it, same resolution, I don't see any difference in terms of quality though. Looks like it is compressed.
Why is this happening?
Saving a jpg image through ImageIO results in lossy compression of the jpg (I believe the quality defaults to 70%). You can a) Change the the quality of the image when you write to file (see Setting jpg compression level with ImageIO in Java ) or b) if you don't actually need the BufferedImage, just read/write the bytes from file to database.

Proper way of transporting files in the source code

I need to transport several files inside the source code. Horrible, I know, but I don't have any other option. So far I'm only storing images, so I do this:
Encoding the image:
Bitmap bm = BitmapFactory.decodeFile(imagePath);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(CompressFormat.PNG, 100, baos);
byte[] b = baos.toByteArray();
String encodedimage = Base64.encodeToString(b, Base64.DEFAULT);
Decoding the image:
public static Bitmap decodeBitmap(imageString) {
return BitmapFactory.decodeStream(new ByteArrayInputStream(Base64.decode(imageString, Base64.DEFAULT)));
}
I use base64 so that putting a new image in the program is easier because it's just a simple string.
Now I'm trying to expand the functionality to any file format so I seek guidance as to find out if there is less bad way of storing files inside code.
for images you should be using the resources folder. It's built into the system for that.
For general final you should use the asset folder and access just like shown on this stackoverflow question: How to get URI from an asset File?
If you want to keep some data files, you can keep them in Assets folders and you can use AssetManager to get the files.

Categories