Get RGB of JPG in Android [duplicate] - java

This question already has an answer here:
Can't import javax.imageio.ImageIO in Android application
(1 answer)
Closed 5 years ago.
first of all thank for your time. I have a jar library which would be included as library in my Android Application.
This jar, among other things, is able to get the RGB values from a jpg image. This works perfectly in my java application but when I runs it in my Android application it does not work because the class ImageIO.read(File file) (Bufferedimage) does not implemented in Android.
I read something about using Bitmap class but i do not find out anything about it.
Could you help me with this method you find here below?
public static int[][][] getImageRgb(BufferedImage image) {
int width = image.getWidth();
int height = image.getHeight();
int[][][] rgb = new int[height][width][3];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int pixel = image.getRGB(j, i);
rgb[i][j] = getPixelRgb(pixel); }
}
return rgb;
}
Where getPixelRgb is a function aims this:
public static int[] getPixelRgb(int pixel) {
// int alpha = (pixel >> 24) & 0xff;
int red = (pixel >> 16) & 0xff;
int green = (pixel >> 8) & 0xff;
int blue = (pixel) & 0xff;
return new int[]{red, green, blue};
}
I really I do not know how to transform this methods for Android.
I look forward to hearing from you.
Thank a lot.

What you need is in the official docs:
int getPixel (int x, int y)
Returns the Color at the specified location.
You can create a Bitmap from a resource in res/drawable folder or if you're downloading the image, you need to first save it to the device storage.

Related

Why set pixels images very slow

I am trying to render an image where I can manipulate all the pixels of the image, it works but I get 40 fps.
While with graphics.fillrect I get 4000 fps and it's really slow and I need this to make a 3D game but it's very very slow.
‍‍‍‍‍
public class Renderer {
private BufferedImage image = TextureLoader.load("./res/image.png");
byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
public void render(Graphics2D g) {
for(int x = 0; x < 1920; x++) {
for(int y = 0; y < 1080; y++) {
setRGB(x,y, Color.RED.getRGB());
}
}
g.drawImage(image, 0, 0, 1920, 1080, null);
}
public void setRGB(int x, int y, int rgb) {
int a = (y * 1920 + x) * 3;
pixels[a] = (byte) ((rgb >> 0) & 0xFF);
pixels[a + 1] = (byte) ((rgb >> 8) & 0xFF);
pixels[a + 2] = (byte) ((rgb >> 16) & 0xFF);
}
}
‍‍‍‍‍
In general, setting every single pixel in a loop is a time consuming process. You could try to speed up your code by using various methods of WritableRaster but personally, I would use a 3d-library like LWJGL or even a 3d-game engine.
Generally it's not a good idea to use Java's provided libraries when one wants to create a 3D game. They are very limited and have poor performance. I would advise looking at third-party libraries such as LWJGL. To replace the Java graphics libraries, use OpenGL and GLFW.
There are many tutorials on OpenGL which will help you learn, such as ThinMatrix's tutorials.
If you don't want to do all the work yourself, try a game engine or framework such as libGDX or jmonkeyengine, which are already optimized and provide an easy way to make your 3D game.

Alpha channel ignored when using ImageIO.read()

I'm currently having an issue with alpha channels when reading PNG files with ImageIO.read(...)
fileInputStream = new FileInputStream(path);
BufferedImage image = ImageIO.read(fileInputStream);
//Just copying data into an integer array
int[] pixels = new int[image.getWidth() * image.getHeight()];
image.getRGB(0, 0, width, height, pixels, 0, width);
However, when trying to read values from the pixel array by bit shifting as seen below, the alpha channel is always returning -1
int a = (pixels[i] & 0xff000000) >> 24;
int r = (pixels[i] & 0xff0000) >> 16;
int g = (pixels[i] & 0xff00) >> 8;
int b = (pixels[i] & 0xff);
//a = -1, the other channels are fine
By Googling the problem I understand that the BufferedImage type needs to be defined as below to allow for the alpha channel to work:
BufferedImage image = new BufferedImage(width, height BufferedImage.TYPE_INT_ARGB);
But ImageIO.read(...) returns a BufferedImage without giving the option to specify the image type. So how can I do this?
Any help is much appreciated.
Thanks in advance
I think, your "int unpacking" code might be wrong.
I used (pixel >> 24) & 0xff (where pixel is the rgba value of a specific pixel) and it worked fine.
I compared this with the results of java.awt.Color and they worked fine.
I "stole" the "extraction" code directly from java.awt.Color, this is, yet another reason, I tend not to perform these operations this way, it's to easy to screw them up
And my awesome test code...
BufferedImage image = ImageIO.read(new File("BYO image"));
int width = image.getWidth();
int height = image.getHeight();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int pixel = image.getRGB(x, y);
//value = 0xff000000 | rgba;
int a = (pixel >> 24) & 0xff;
Color color = new Color(pixel, true);
System.out.println(x + "x" + y + " = " + color.getAlpha() + "; " + a);
}
}
nb: Before some one tells that this is inefficient, I wasn't going for efficiency, I was going for quick to write
You may also want to have a look at How to convert get.rgb(x,y) integer pixel to Color(r,g,b,a) in Java?, which I also used to validate my results
I think the problem is that you're using arithmetic shift (>>) instead of logical shift (>>>). Thus 0xff000000 >> 24 becomes 0xffffffff (i.e. -1)

Using Graphics to Draw a BufferedImage with AlphaBlending Java

I do a lot of game programming in my free time, and am currently working on a game engine library. Previous to this point I have made customized per game engines built straight into the application, however, to challenge my logical skills even further, I decided I wanted to make an engine that I could literally use with any game that I write, kind of like a plugin.
Before this point, I have been pulling textures in using a BufferedImage using getRBG to pull the pixel[] out and by hand writing over the background int[] with the texture int[] array in the (X,Y) position that the Renderable resided. Then when everything was written to the master int[] I would make a new BufferedImage and use setRGB using the master int[] and use a BufferStrategy and it's Graphic to drawImage of the BufferedImage. I liked this method because I felt like i had complete control over the way things were rendered, but I don't think it was very efficient.
Here is a look at the way I used to write to the master int[]
public void draw(Render render, int x, int y, float alphaMul){
for(int i=0; i<render.Width; i++){
int xPix = i + x;
if(Width - 1<xPix || xPix<0)continue;
for(int j=0; j<render.Height; j++){
int yPix = j + y;
if(Height - 1<yPix || yPix<0)continue;
int srcARGB = render.Pixels[i + j * render.Width];
int dstARGB = Pixels[xPix + yPix * Width];
int srcAlpha = (int)((0xFF & (srcARGB >> 24))*alphaMul);
int srcRed = 0xFF & (srcARGB >> 16);
int srcGreen = 0xFF & (srcARGB >> 8);
int srcBlue = 0xFF & (srcARGB);
int dstAlpha = 0xFF & (dstARGB >> 24);
int dstRed = 0xFF & (dstARGB >> 16);
int dstGreen = 0xFF & (dstARGB >> 8);
int dstBlue = 0xFF & (dstARGB);
float srcAlphaF = srcAlpha/255.0f;
float dstAlphaF = dstAlpha/255.0f;
int outAlpha = (int)((srcAlphaF + (dstAlphaF)*(1 - (srcAlphaF)))*255);
int outRed = (int)(srcRed*srcAlphaF) + (int)(dstRed * (1 - srcAlphaF));
int outGreen = (int)(srcGreen*srcAlphaF) + (int)(dstGreen * (1 - srcAlphaF));
int outBlue = (int)(srcBlue*srcAlphaF) + (int)(dstBlue * (1 - srcAlphaF));
int outARGB = (outAlpha<<24)|(outRed << 16) | (outGreen << 8) | (outBlue);
Pixels[xPix + yPix * Width] = outARGB;
}
}
}
I have recently found out it may be multitudes faster, where using drawImage I can loop through all of the Renderables and draw them as BufferedImages using their respective (X,Y) positions. But, I do not know how to work alphaBlending with that. So my questions are, how would I go about getting the results that I want?, and Would it be resource and time beneficial over my previous method?
Thanks
-Craig

How convert image from RGB model to HSV (without built-in functions) and display it in java?

I try to convert image from RGB model to HSV and display it. Unfortunately I dont have any idea how to do this. I dont want to use built-in function but I want write function alone. I want to do this in similar way using RGB channels. I read/checked a lot of example from this site but I have not found any special and helpfull materials. Please help how should I do this.
// image from RGB to grayscale
private static BufferedImage monochromatyczny(BufferedImage obrazek)
{
for(int x = 0; x < obrazek.getWidth(); x++)
for(int y = 0; y < obrazek.getHeight(); y++)
{
int piksel = obrazek.getRGB(x, y);
// kanały r,g,b
int r = (piksel>>16) & 0xff;
int g = (piksel>>8) & 0xff;
int b = (piksel) & 0xff;
int gray = (r+g+b)/3;
piksel = (gray<<16) | (gray<<8) | gray;
obrazek.setRGB(x,y,piksel);
}
return obrazek;
}
Good explanation how to convert color RGB -> HSV i'm found on http://www.rapidtables.com/convert/color/rgb-to-hsv.htm
You may to try this formula in your rgb_2_hsv function

Help on adding plug-in to Java ImageWriter

I am trying to save a BufferedImage as a PNM file. I already installed the JAI (Java Advanced Imaging), and have the PNMWriter plug-in imported. However, I don't know how to add it to my ImageWriter so it can write in .pnm. When I run ImageIO.getWriterFormatNames() to get the possible format names, only the standard ones (.png, .bmp, .jpg....) come up... What do
I implemented this myself for my software. It was only 30 lines of source code and I did not want to add Java Advanced Imaging for something that can be solved so easily. Here is my solution:
public static void write(BufferedImage image, OutputStream stream) throws IOException
{
/*
* Write file header.
*/
int imageWidth = image.getWidth();
int imageHeight = image.getHeight();
stream.write('P');
stream.write('6');
stream.write('\n');
stream.write(Integer.toString(imageWidth).getBytes());
stream.write(' ');
stream.write(Integer.toString(imageHeight).getBytes());
stream.write('\n');
stream.write(Integer.toString(255).getBytes());
stream.write('\n');
/*
* Write each row of pixels.
*/
for (int y = 0; y < imageHeight; y++)
{
for (int x = 0; x < imageWidth; x++)
{
int pixel = image.getRGB(x, y);
int b = (pixel & 0xff);
int g = ((pixel >> 8) & 0xff);
int r = ((pixel >> 16) & 0xff);
stream.write(r);
stream.write(g);
stream.write(b);
}
}
stream.flush();
}
Use JAI (JAI class), not ImageIO (Java standard), use:
JAI.create("ImageWrite", renderedImage, file, "pnm");

Categories

Resources