Bitmap to integer array? - android

in my application i have a database where i store image .i want to retrieve images.images are easly retrieve in BitMap but the problem is how can i convert that BitMap image into integer format.
this is code:
DataBaseClass objOfDataBaseClass=new DataBaseClass(context);
Cursor mCursor=objOfDataBaseClass.showData();//here is all data taken from dataBase
if(mCursor.moveToNext()) {
byte[] mg=null;
mg = mCursor.getBlob(mCursor.getColumnIndex("image"));
Bitmap bitmap = BitmapFactory.decodeByteArray(mg, 0, mg.length);
int[] store=?//how can i bitMap store in this array.
}

You can use the Bitmap.getPixels method (documentation)
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int[] store = new int[width * height];
bitmap.getPixels(store, 0, width, 0, 0, width, height);

You shouldn't store the pixels of the bitmap itself, as a bitmap contains the image in uncompressed form and that would result in a huge amount of data (e.g. 1024 x 768 x 32 bit is 3.1 MB).
Better compress the bitmap to e.g. an PNG and store that in the database. You can use Bitmap.compress() for that purpose and use a ByteArrayOutputStream to write the data to. Then, store the bytes of that outputstream to your database.

Related

How to scale an image saved as byte array?

When you have an image (PNG in this case) saved as byte array on android, how can scale it to get a new image scaled in byte array format?
Have in mind that the image to scaling is to a smaller size, avoiding loss of data.
Image croping byte uri image convert byte array the step
InputStream iStream = getContentResolver().openInputStream(uri);
byte[] inputData = getBytes(iStream);
One quick way of doing this, it's letting Android to resolve the algorithm for us.
So, we convert the byte array to a bitmap, the bitmap can create a new bitmap with new sizes defined and finally convert back to byte array.
private byte[] getScaledImage(byte[] originalImage, int newWidth, int newHeight) {
// PNG has not losses, it just ignores this field when compressing
final int COMPRESS_QUALITY = 0;
// Get the bitmap from byte array since, the bitmap has the the resize function
Bitmap bitmapImage = (BitmapFactory.decodeByteArray(originalImage, 0, originalImage.length));
// New bitmap with the correct size, may not return a null object
Bitmap mutableBitmapImage = Bitmap.createScaledBitmap(bitmapImage,newWidth, newHeight, false);
// Get the byte array from tbe bitmap to be returned
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
mutableBitmapImage.compress(Bitmap.CompressFormat.PNG, 0 , outputStream);
if (mutableBitmapImage != bitmapImage) {
mutableBitmapImage.recycle();
} // else they are the same, just recycle once
bitmapImage.recycle();
return outputStream.toByteArray();
}

Bitmap.getPixel () processing 1D array

My doubt is bitmap.getPixels(allPixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
is processing 1D array. But a bitmap is always 2D picture representation. But why there is single dimentional array?
And how the packing of bytes in 1D array?
I know this is anoob question, but I can't understand it.
Thanks
But a bitmap is always 2D picture representation. But why there is
single dimentional array?
Bitmap stored in memory as 1-dimensional array of bytes (not only bitmap, but most binary data). All pixels of the bitmap are placed in memory row by row and each row with width of bitmap. I think, method Bitmap.getPixels() do nothing but copy bytes from memory into int[] array. You are free to create your own method that will convert 1D array to 2D array, but in most cases this is not required (see below).
And how the packing of bytes in 1D array?
Method Bitmap.getPixels() accepts and fills int[] array with length of bitmap width multiply by bitmap height. The part of result array corresponding to the rectangle, specified in parameters of the method, will be filled with colors of pixels, and rest of array will filled with zeros.
It's very easy to get the color of the desired pixel from this array. Index of pixel is x + y * bitmapWidth:
...
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int[] allPixels = new int[width * height];
bitmap.getPixels(allPixels, 0, width, 0, 0, width, height);
int x = 64;
int y = 128;
int pixelColor = allPixels[x + y * width];
...

Android: Get float or int array from image that corresponds to pixel values

I have an application that currently takes black and white 176 x 144 images via camera2 in jpeg format and saves it to storage. In addition to this, I also need an int/float array where each point corresponds to the intensity of one pixel from the jpeg image. As the image is black and white this array of numbers should be sufficient to reconstruct my image by simply plotting it as a heatmap along the appropriate dimensions, as only one value per pixel is needed in black and white space.
The way I have found to do this is to convert the jpeg into a byte array into a bitmap into an int array of sRGB values into an int array of R values. This does work (code below), but seems like a really longwinded and inefficient way of doing this. Is anyone able to suggest a more direct way? Such as getting pixel values directly from the original jpeg Image?
// Convert photo (176 x 144) to byte array (1x25344)
Image mImage = someImage // jpeg capture from camera
ByteBuffer buffer = mImage.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
//Save photo as jpeg
savePhoto(bytes);
//Save pixel values by converting to Bitmap first
Bitmap image = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
int x = image.getWidth();
int y = image.getHeight();
int[] intArray = new int[x * y];
image.getPixels(intArray, 0, x, 0, 0, x, y);
for(int i = 0; i < intArray.length; i++) {
intArray[i] = Color.red(intArray[i]); //Any colour will do
}
//Save pixel values
saveIntArray(intArray);

How to save Bitmap image in Native memory using ByteBuffer and recover it

I'm getting direct stream from camera and I need to save a Bitmap into a ByteBuffer and recover it. Here is my code:
YuvImage yuv = new YuvImage(data.getExtractImageData(), previewFormat, width, height, null);
ByteArrayOutputStream out = new ByteArrayOutputStream();
yuv.compressToJpeg(new Rect(0, 0, width, height), 50, out);
byte[] bytes = out.toByteArray();
Bitmap image = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Bitmap imageResult = RotateImage(image, 4 - rotation);
imageResult = cropBitmap(imageResult, data.getRect());
int nBytes = imageResult.getByteCount();
ByteBuffer buffer = ByteBuffer.allocateDirect(nBytes);
imageResult.copyPixelsToBuffer(buffer);
return buffer.array();
Code to convert byte[] back to Bitmap:
Bitmap bitmap = BitmapFactory.decodeByteArray(images.getImage(), 0, images.getImage().length);
But then, bitmap is Null after conversion...
Any idea on what's wrong?
To clarify: I need to save the byte[] image in the Native memory, that's why I do a ByteBuffer.allocateDirect. I need to crop the image in a specific point, that's why I need the bitmap.
decodeByteArray() decodes a compressed image (e.g. a JPEG or PNG) stored in a byte array. However copyPixelsToBuffer() copies the contents of a Bitmap into a byte buffer "as is" (i.e. uncompressed), so it can't be decoded by decodeByteArray().
If you don't want to re-encode your bitmap, you can use copyPixelsToBuffer() like you are doing, and change your second code block to use copyPixelsFromBuffer() instead of decodeByteArray().
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer(ByteBuffer.wrap(images.getImage()));
You'll need to save the width and height. Also make sure the Bitmap.Config is the same.
Basically, if you save it compressed then you have to load it compressed, and if you save it uncompressed then you have to load it uncompressed.
You should also set the byte order when you allocate the buffer because Java is big endian, the buffer is therefore big endian by default, android is little endian and the underlying cpu architecture can vary but is mostly little endian wrt android:
buffer.order( ByteOrder.nativeOrder() );

OutOfMemory when inverting a bitmap?

I'm having the OutOfMemory error when inverting a bitmap.. Here is the code I use to invert:
public Bitmap invertBitmap(Bitmap bm) {
Bitmap src = bm.copy(bm.getConfig(), true);
// image size
int height = src.getHeight();
int width = src.getWidth();
int length = height * width;
int[] array = new int[length];
src.getPixels(array, 0, src.getWidth(), 0, 0, src.getWidth(), src.getHeight());
int A, R, G, B;
for (int i = 0; i < array.length; i++) {
A = Color.alpha(array[i]);
R = 255 - Color.red(array[i]);
G = 255 - Color.green(array[i]);
B = 255 - Color.blue(array[i]);
array[i] = Color.argb(A, R, G, B);
}
src.setPixels(array, 0, src.getWidth(), 0, 0, src.getWidth(), src.getHeight());
return src;
}
The image is ~80 kb big, the dimensions are 800x1294 and the picture has words which are black and an invisible background..
The images are in a ViewPager..
when you copy bm, try: bm = null;
In android , due to 16MB (on almost all phones) memory cap for applications, it is not wise to hold entire bitmap in memory. This is a common scenario and is happening to may developers.
You can get many information about this problem in this stackoverflow thread. But I really urges you to read android's official document about efficient usage of Bitmaps. They are here and here.
The memory size used by an image in completelly different from the file size of that image.
While in a file the image may be compressed using different alghorithms (jpg, png, etc.) and when loaded in memory as a bitmap, it uses 2 or 4 bytes per pixel.
So in your case (you are not sowing the code but it lloks like you are using 4 bytes per pixel), the memory size per image is:
size = width * height * 4; // this is aprox 2MB
In your code, first you copy the original bitmap to a new one, and then ceate an array to manipulate the colors. So in total you are using size x 3 = 6MB per image inversion.
There are plenty of examples on how to handle large bitmap in Android, but I'll leave you what I think is the most important topics:
Try to use only one copy of bitmap in your code above
If you are only having words in your image use Bitmap.Config = RGB_565. This only uses 2 bytes per pixel, reducing size by half.
Call recycle() on a bitmap that you don't need anymore.
Have a lool at scale option in Bitmap.Factory. You may reduce the size of image that still fit your needs.
good luck.

Categories

Resources