Are there similar android methods of java getData().getPixels()? - java

I'm trying to use the following code of java to read image data on android. Since ImageIO is not supported, what are some ways I may use getData().getPixels()?
By changing BufferedImage into Bitmap, I can get all other codes working besides bi.getData().getPixels()?
Any method in the android library I may use to replace it?
In android Bitmap class:
public void getPixels (int[] pixels, int offset, int stride, int x, int y, int width, int height)
This method supports int[], but not double[]. I'm not familiar with image processing will they be different?
Thank you.
private double[] getImageData(String imageFileName) throws FaceRecError {
BufferedImage bi = null;
double[] inputFace = null;
try{
bi = ImageIO.read(new File(imageFileName));
}catch(IOException ioe){
throw new FaceRecError(ioe.getMessage());
}
if (bi != null){
int imageWidth = bi.getWidth();
int imageHeight = bi.getHeight();
inputFace = new double[imageWidth * imageHeight];
bi.getData().getPixels(0, 0, imageWidth, imageHeight,inputFace);
}
return inputFace;
}

This code is used for getting color of all pixels in Bitmap in android.This return array of color
Bitmap bitmap=BitmapFactory.decodeFile("file path");
int height=bitmap.getHeight();
int width=bitmap.getWidth();
int[] pixel=new int[height*width];
bitmap.getPixels(pixel, 0, width, 0, width, width, height);
So your color will be saved in pixel array. getPixels() have many parameter to customize which pixel color you want
Updated For Casting Integer array to double
public double[] getDoubleNumbers(int[] numbers)
//changed double to double[]
{double[] newNumbers = new double[numbers.length]; //changed 99 to numbers.length
for (int index = 0; index < numbers.length; index++)
newNumbers[index] = (double)numbers[index];
return newNumbers;
}
}

Related

Data too big for QR Code Generation with XZing in Android with Java

I am trying to generate a QR Code and set it to an ImageView out of a PGP Public Key in my Android Application with Java. The libary I use is XZing and I am on Android Studio.
This worked well before with smaller Strings, however when I try to do it with something as big as a PGP Public Key I get this error:
com.google.zxing.WriterException: Data too big
So my data is too big. Is there any possibility to create a QR Code with a String this big in XZing?
I have tried it with two different methods but both lead to the same exception.
Method one:
private void generateQR(String value) {
qrImage.setVisibility(View.VISIBLE);
QRGEncoder qrgEncoder = new QRGEncoder(value, null, QRGContents.Type.TEXT, 1000);
try {
// Getting QR-Code as Bitmap
Bitmap bm = qrgEncoder.encodeAsBitmap();
qrImage.setImageBitmap(bm);
// Setting Bitmap to ImageView
} catch (WriterException e) {
Log.v(TAG, e.toString());
}
}
Method two:
private Bitmap textToImage(String text, int width, int height) throws WriterException, NullPointerException {
BitMatrix bitMatrix;
try {
bitMatrix = new MultiFormatWriter().encode(text, BarcodeFormat.DATA_MATRIX.QR_CODE,
width, height, null);
} catch (IllegalArgumentException Illegalargumentexception) {
return null;
}
int bitMatrixWidth = bitMatrix.getWidth();
int bitMatrixHeight = bitMatrix.getHeight();
int[] pixels = new int[bitMatrixWidth * bitMatrixHeight];
int colorWhite = 0xFFFFFFFF;
int colorBlack = 0xFF000000;
for (int y = 0; y < bitMatrixHeight; y++) {
int offset = y * bitMatrixWidth;
for (int x = 0; x < bitMatrixWidth; x++) {
pixels[offset + x] = bitMatrix.get(x, y) ? colorBlack : colorWhite;
}
}
Bitmap bitmap = Bitmap.createBitmap(bitMatrixWidth, bitMatrixHeight, Bitmap.Config.ARGB_4444);
bitmap.setPixels(pixels, 0, width, 0, 0, bitMatrixWidth, bitMatrixHeight);
return bitmap;
}
QR Codes have a max size.
I changed the error correction level to L and this then can fit in a longer URL.
This may work for you:
new MultiFormatWriter().encode(qrCodeText, BarcodeFormat.QR_CODE, width, height, mapWith(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L));

What order does PixelGrabber put pixels into the array in java?

What order does PixelGrabber put pixels into the array in java? Does it take the pixels along the width of the image first? Or along the height of the image first?
public static int[] convertImgToPixels(Image img, int width, int height) {
int[] pixel = new int[width * height];
PixelGrabber pixels = new PixelGrabber(img, 0, 0, width, height, pixel, 0, width);
try {
pixels.grabPixels();
} catch (InterruptedException e) {
throw new IllegalStateException("Interrupted Waiting for Pixels");
}
if ((pixels.getStatus() & ImageObserver.ABORT) != 0) {
throw new IllegalStateException("Image Fetch Aborted");
}
return pixel;
}
In the code example provided by the documentation
It has the following for loops:
for (int j = 0; j < h; j++) {
for (int i = 0; i < w; i++) {
handlesinglepixel(x+i, y+j, pixels[j * w + i]);
}
}
The access pixels[j * w + i] shows that it goes first along the row, then by along the columns. It grabs the pixels along the width first.
I'm pretty sure it uses row major order, but the easiest way is to actually grab the pixels, set a sequence of them to a particular color (for easy identification) and then save them out to an image. If the pixel strip appears vertical than the order is column major, otherwise it is row major. You can use code like: here
public static Image getImageFromArray(int[] pixels, int width, int height) {
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
WritableRaster raster = (WritableRaster) image.getData();
raster.setPixels(0,0,width,height,pixels);
return image;
}
To convert an the int[] to an image.
Also, I use ((DataBufferInt)img.grtRaster().getDataBuffer()).getData() to quickly grab the pixels of the image. Any modifications to that int[] will reflect in the image and vice versa. And that is row major for sure.

int array to BufferedImage

I'm making with the Robot class a printscreen and I convert the BufferedImage into an int array. Then I want to convert the int array back to a bufferedimage but that gives an error. This is my code:
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
BufferedImage printscreen = robot.createScreenCapture(new Rectangle(screen));
int[] pixels = ((DataBufferInt) printscreen.getRaster().getDataBuffer()).getData();
BufferedImage image = new BufferedImage(screen.width, screen.height, BufferedImage.TYPE_INT_RGB);
WritableRaster raster = (WritableRaster) image.getRaster();
raster.setPixels(0, 0, screen.width, screen.height, pixels);
But I get the error: ArrayIndexOutOfBoundsException: 2073600 but why?
I'm getting the exception on this line:
raster.setPixels(0, 0, screen.width, screen.height, pixels);
EDIT: It is working if I change the second bufferedimage type to TYPE_BYTE_GRAY.
int[] bitMasks = new int[]{0xFF0000, 0xFF00, 0xFF, 0xFF000000};
SinglePixelPackedSampleModel sm = new SinglePixelPackedSampleModel(
DataBuffer.TYPE_INT, width, height, bitMasks);
DataBufferInt db = new DataBufferInt(pixels, pixels.length);
WritableRaster wr = Raster.createWritableRaster(sm, db, new Point());
BufferedImage image = new BufferedImage(ColorModel.getRGBdefault(), wr, false, null);
Changed to:
getRaster().getPixels(0, 0, screen.width, screen.height, pixels)
and it works! Thanks for help anyway
The ArrayIndexOutOfBounds exception occurs as and when you try to access an element at index which is beyond the size of the array. In this case, you're passing the array to setPixels method, which accordingly to its javadocs doesn't explicitly check for the bounds or size of the array. So you should be doing that explicitly before calling that method. e.g.
if(x >= 0 && x < arr.length) {
// some code
}
This is the relevant code from SampleModel class used by WritableRaster.
public int[] getPixels(int x, int y, int w, int h,
int iArray[], DataBuffer data) {
int pixels[];
int Offset=0;
if (iArray != null)
pixels = iArray;
else
pixels = new int[numBands * w * h];
for (int i=y; i<(h+y); i++) {
for (int j=x; j<(w+x); j++) {
for(int k=0; k<numBands; k++) {
pixels[Offset++] = getSample(j, i, k, data);
}
}
}
return pixels;
}
The size of pixels in raster.setPixels(0, 0, screen.width, screen.height, pixels); should be width*height*3 when you set BufferedImage.TYPE_INT_RGB.
BufferedImage image = new BufferedImage(screen.width*3, screen.height,BufferedImage.TYPE_INT_RGB);
WritableRaster raster = (WritableRaster) image.getRaster();
raster.setPixels(0, 0, screen.width*3, screen.height, pixels);

Java: Take the image from Graphics and turn it into a temporary BufferedImage

Hey guys I am making a 2D game and I have generating a random grassy background from 4 preset images. My problem is this, my game draws each image from an array which is created on game start using this code:
public static void createBackground() {
for(int x = 0; x < 640; x+= 32) {
for(int y = 0; y < 496; y+= 32) {
random = new Random();
int grassTex = random.nextInt(grassTextures.size());
grassPos.add(grassTextures.get(grassTex));
}
}
}
That works fine, but this is where the problem occurs. I am re-drawing every image that was put into that array using this:
public static void paintBackground(Graphics g) {
counter = 0;
for(int x = 0; x < 640; x+= 32) {
for(int y = 0; y < 496; y+= 32) {
random = new Random();
int grassTex = random.nextInt(grassTextures.size());
g.drawImage(grassPos.get(counter), x, y, null);
counter++;
}
}
}
This causes a drop in fps (It's not a lot, but it is noticeable). Is there anyway that I can draw all those grass images into one BufferedImage so that it is only one image that is being drawn? Or is there a more efficient way of doing this?
Thanks.
There is no way to take "the image from Graphics", as you ask, but it is not very hard to just create BufferedImage and then draw the image into it, instead. If anything, AWT's imaging model is quite complex, and you'll have to construct a couple of auxiliary data structures and stuff, but here's a template which creates 32-bit RGBA images:
private static final ComponentColorModel colormodel =
new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
new int[] {8, 8, 8, 8}, true, false,
ComponentColorModel.TRANSLUCENT, DataBuffer.TYPE_BYTE);
public static BufferedImage makeimage(int w, int h) {
WritableRaster buf = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, w, h, 4, null);
return(new BufferedImage(colormodel, buf, false, null));
}
Once you have a BufferedImage as created by makeimage(), just call getGraphics() on it and paint to your heart's content.

Java equivalent of JavaScript's Canvas getImageData

I'm porting a HTML5's Canvas sample to Java, so far so good, until i get on this function call :
Canvas.getContext('2d').getImageData(0, 0, 100, 100).data
I googled for a while and found this page of the canvas specification
http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#pixel-manipulation
After reading it, I created this function below :
public int[] getImageDataPort(BufferedImage image) {
int width = image.getWidth();
int height = image.getHeight();
int[] ret = new int[width * height * 4];
int idx = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int color = image.getRGB(x, y);
ret[idx++] = getRed(color);
ret[idx++] = getGreen(color);
ret[idx++] = getBlue(color);
ret[idx++] = getAlpha(color);
}
}
return ret;
}
public int getRed(int color) {
return (color >> 16) & 0xFF;
}
public int getGreen(int color) {
return (color >> 8) & 0xFF;
}
public int getBlue(int color) {
return (color >> 0) & 0xFF;
}
public int getAlpha(int color) {
return (color >> 24) & 0xff;
}
There is any class on Java Graphics API that has this function built-in or i should use the one that i had created?
I think the closest thing you'll find in the standard Java API is the Raster class. You can get hold of a WritableRaster (used for low-level image manipulation) through BufferedImage.getRaster. The Raster class then provides methods such as getSamples which fills an int[] with image data.
Thanks aioobe, i've looked at the WritableRaster class and found the getPixels function which does exactly what i needed, the final result is :
public int[] getImageDataPort(BufferedImage image) {
int width = image.getWidth();
int height = image.getHeight();
int[] ret = null;
ret = image.getRaster().getPixels(0, 0, width, height, ret);
return ret;
}
The only problem that may happen is when the image.getType isn't a type that supports alpha in comparison with the code of the question, resulting in a smaller int[] ret, but one can simply convert the image type with :
public BufferedImage convertType(BufferedImage image,int type){
BufferedImage ret = new BufferedImage(image.getWidth(), image.getHeight(), type);
ColorConvertOp xformOp = new ColorConvertOp(null);
xformOp.filter(image, ret);
return ret;
}
Try
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(bi, "jpg", baos);
where bi - BufferendImage

Categories