I am trying to port some graphics code that is written using java.awt.*
library to instead use the android.graphics.*
library. However, I don't have much experience with graphics.
Here is the java.awt.*
code (which works):
/**
* Converts the given <code>MyImageBitmap</code> to the specified image format and returns it as byte array.
*
* @param myImageBitmapthe given MyImageBitmap, not null
* @param format the given target image format ("png", "gif", "jpg"), not null
* @return the converted data in byte array format, not null
*/
private byte[] convert(MyImageBitmap myImageBitmap, String format) {
final int width = myImageBitmap.getWidth();
final int height = myImageBitmap.getHeight();
final int[] MASKS = {0x000000ff, 0x000000ff, 0x000000ff};
DataBuffer buffer = new DataBufferByte(myImageBitmap.getPixels(), myImageBitmap.getLength());
WritableRaster writableRaster = Raster.createPackedRaster(buffer, width, height, width, MASKS, null);
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
bufferedImage.setData(writableRaster);
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
ImageIO.write(bufferedImage, format, outputStream);
outputStream.close();
return outputStream.toByteArray();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
This is the MyImageBitmap class:
/**
* A <code>MyImageBitmap</code> instance contains an image information in bitmap format.
*/
public class MyImageBitmap implements Serializable {
//...member variables
/**
* Creates an instance of <code>MyImageBitmap</code> with specified data.
*
* @param pixels the image pixes, not null
* @param width the image width, not null
* @param height the image height, not null
* @param ppi pixel per inch, not null
* @param depth the image depth, not null
* @param lossyFlag lossy flag, not null
*/
public MyImageBitmap(byte[] pixels, int width, int height, int ppi, int depth, int lossyFlag) {
this.pixels = pixels;
this.width = width;
this.height = height;
this.ppi = ppi;
this.depth = depth;
this.lossyFlag = lossyFlag;
this.length = pixels != null ? pixels.length : 0;
}
//...getters
}
This is what I have tried (with no success):
private byte[] convert(MyImageBitmap myImageBitmap, String format) {
int width = myImageBitmap.getWidth();
int height = myImageBitmap.getHeight();
byte[] imgRGB888 = myImageBitmap.getPixels();
Bitmap bmp2 = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
int[] colors = new int[width * height];
int r,g,b;
for (int ci = 0; ci < colors.length; ci++)
{
r = (int)(0xFF & imgRGB888[3*ci]);
g = (int)(0xFF & imgRGB888[3*ci+1]);
b = (int)(0xFF & imgRGB888[3*ci+2]);
colors[ci] = Color.rgb(r, g, b);
}
bmp2.setPixels(colors, 0, width, 0, 0, width, height);
Bitmap.CompressFormat compressFormat;
if (format.equals("jpeg")){
compressFormat = android.graphics.Bitmap.CompressFormat.JPEG;
}else if (format.equals("png")){
compressFormat = android.graphics.Bitmap.CompressFormat.PNG;
}else {//must be gif...try to convert to png
compressFormat = android.graphics.Bitmap.CompressFormat.PNG;
}
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()){
bmp2.compress(compressFormat, 100, outputStream);
return outputStream.toByteArray();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
When I run the above code (my attempt at porting over the awt code) I get an ArrayIndexOutOfBoundsException
on this line r = (int)(0xFF & imgRGB888[3*ci]);
.
I ended up figuring out what the issue was. My algorithm for converting from
byte array to int color array was wrong. Below is the correct implementation. The images are now being correctly displayed in the Android ImageView
!
/**
* Converts the given <code>MyImageBitmap</code> to the specified image format and returns it as byte array.
*
* @param myImageBitmap the given bitmap, not null
* @param format the given target image format, not null
* @return the converted data in byte array format, not null
*/
private byte[] convert(MyImageBitmap myImageBitmap, String format) {
int width = myImageBitmap.getWidth();
int height = myImageBitmap.getHeight();
byte[] imgRGB888 = myImageBitmap.getPixels();
Bitmap bmp2 = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
int[] colors = new int[width * height];
//We need to convert the image from a byte array to a
// int color array so we can create the Android Bitmap
int r,g,b;
for (int ci = 0; ci < colors.length; ci++) {
r = (int)(0x000000ff & imgRGB888[ci]);
g = (int)(0x000000ff & imgRGB888[ci]);
b = (int)(0x000000ff & imgRGB888[ci]);
colors[ci] = Color.rgb(r, g, b);
}
bmp2.setPixels(colors, 0, width, 0, 0, width, height);
Bitmap.CompressFormat compressFormat;
if (format.equals("jpeg")){
compressFormat = android.graphics.Bitmap.CompressFormat.JPEG;
}else{//must be png
compressFormat = android.graphics.Bitmap.CompressFormat.PNG;
}
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()){
bmp2.compress(compressFormat, 100, outputStream);
return outputStream.toByteArray();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
User contributions licensed under CC BY-SA 3.0