I have an image (of size 1024x1024) in an int array (int[] pixels) and I am inverting one channel using the following loop...
int i = 0;
for (int y = 0; y < H; y++) {
for (int x = 0; x < W; x++) {
int color = pixels[i];
pixels[i] = Color.argb(Color.alpha(color), 255 - Color.red(color), Color.green(color), Color.blue(color));
i++;
}
}
This takes more than 1 second on my new Galaxy S4 phone. Similar loop runs in a blink of an eye even on an older iPhone. Is there something I am doing wrong here?
If I replace "Color.argb(Color.alpha(color), 255 - Color.red(color), Color.green(color), Color.blue(color))" with "Color.BLUE", it gets much faster.
Found a workaround.
If I use my own bitwise operators instead of Color functions, it gets much faster...
int i = 0;
for (int y = 0; y < H; y++) {
for (int x = 0; x < W; x++) {
int color = pixels[i];
int red = ((color & 0x00ff0000) >> 16);
pixels[i] = (color & 0xff00ffff) | ((255 - red) << 16);
//pixels[i] = Color.argb(Color.alpha(color), 255 - Color.red(color), Color.green(color), Color.blue(color));
i++;
}
}
You may want to consider using the ColorMatrix class to get this done: http://developer.android.com/reference/android/graphics/ColorMatrix.html
There is most likely considerable overhead involved when manipulating individual pixels the way you are doing it. The ColorMatrix class is your friend.
I think if you replace this piece of code by this, it will be relatively fast
int w = bitmap.getWidth();
int h = bitmap.getHeight();
int pixels[] = new int[w * h];
bitmap.getPixels(pixels, 0, w, 0, 0, w, h);
int n = w * h;
for (int i = 0; i < n; i++) {
int color = pixels[i];
pixels[i] = Color.argb(Color.alpha(color), 255 - Color.red(color), Color.green(color), Color.blue(color));
}
bitmap.setPixels(pixels, 0, w, 0, 0, w, h);
Related
I want to pixelize a Image with JavaFx.
My problem is that I only have one written pixel in the end, so that it works for just one time.
i tried a
Here is my code:
Image img = imgView.getImage();
PixelReader pixelReader = img.getPixelReader();
WritableImage wImage = new WritableImage(
(int) img.getWidth(),
(int) img.getHeight());
PixelWriter pixelWriter = wImage.getPixelWriter();
for (int y = 1; y < img.getHeight(); y += 3) {
for (int x = 1; x < img.getWidth(); x += 3) {
Color px = pixelReader.getColor(x, y);
float red = (float) px.getRed();
float green = (float) px.getGreen();
float blue = (float) px.getBlue();
Color all = new Color(red / 3, green / 3, blue / 3, 1);
for (int u = 0; u <= 3; u++) {
for (int i = 0; i <= 3; i++) {
pixelWriter.setColor(u, i, all);
}
}
}
}
Just check the part where you set the color:
for (int u = 0; u <= 3; u++) {
for (int i = 0; i <= 3; i++) {
pixelWriter.setColor(u, i, all);
}
}
As you can see you always set the color of pixel at (0,0) - (3,3).
You need to use
pixelWriter.setColor(x + u, y + i, all);
However, you need to be sure that you won't try to set color of some pixels outside the image. Check the boundaries of loops by x, y, u and i.
I'm creating a method that takes two parameters with 2 indexes a start and an end that takes a location of the picture being edited and turn those pixels to a different color. Using a while loop to index start and end.
The problem I'm having is I'm only a getting a really small portion to change color:
Don't mind some of the code that is commented out. I was trying a bunch of different things.
public void negative(int start, int end)
{
Pixel[] pixelArray = this.getPixels(); //pixelarray index
Pixel pixel = null;
// int height = this.getHeight();
//int paintPoint = height / 2;
//int width = this.getWidth();
int i = 0;
int red, green, blue = 0;
// int x = 0;
Pixel topPixel = null;
Pixel bottomPixel = null;
//int startY;
//int startX;
int y = start;
int x = end;
//int count;
while( y < this.getHeight())
{
y++;
while (x < this.getWidth()) //loops through index
{
pixel = this.getPixel(x,y);
red = pixel.getRed();
green = pixel.getGreen();//collects color green
blue = pixel.getBlue();//collects color blue
Color negColor = new Color( 255 - red, 255 - green, 255 - blue);//sets new values of pixels
pixel.setColor(negColor);
x++;
//count = count + 1;
i++;//indexes continuing
}
}
}
A picture is 2D yet you are treating it as 1D (notice after once through your inner x loop it never is reset to its min value). If you wish to color an arbitrary rectangle within a given photo the parms should include two points : minx, miny and maxx maxy then your pair of 2D loops visits each point in that region line by line.
// do sanity checks on your parms
if (this.getWidth() < maxx) {
maxx = this.getWidth();
}
if (this.getHeight() < maxy) {
maxy = this.getHeight();
}
if (minx < 0) {
minx = 0;
}
if (miny < 0) {
miny = 0;
}
for (y = mixy; y < maxy; y++) {
for (x = mixx; x < maxx; x++) {
// now your have valid x and y values
}
}
i wrote this method:
public static Bitmap matrixToBitmap(int[][] slika)
{
int w = slika[0].length;
int h = slika[1].length;
Bitmap into = Bitmap.createBitmap(w, h, Config.ARGB_8888);
for (int x = 0; x < w; x++)
{
for (int y = 0; y < h; y++)
{
if(slika[x][y] < 128)
into.setPixel(x, y, Color.BLACK);
else
into.setPixel(x, y, Color.WHITE);
}
}
return into;
}
and when I call it inside my android app with an int[454][454] array, it says this in Logcat:
Caused by: java.lang.ArrayIndexOutOfBoundsException: length=452; index=452
pointing at this line of matrixToBitmap method:
if(slika[x][y] < 128)
Can someone figure why is it happening? Values for w and h become 454 and 454, just as they should be.
error is here:
int w = slika[0].length;
int h = slika[1].length;
what happened is, you set up length of first row from your array to be w, and length of your second row to be h
to make it work, change it to:
int w = slika.length;
int h = slika[0].length;
I am writing a java code that divides an image into chunks and rotate to some degree and combine the chunks to become one final image. Then use same code to divide the image into chunks and rotate opposite. I expect to get the same image as the original but I get an image with black line separated between them. For example an image is divided into 8 rows and 8 columns and conduct rotation. I have googled it and come up with the following code:
public static BufferedImage Didvide( BufferedImage image , int Bz ,double angle ){
int rows = Bz;
int cols = Bz;
int chunks = rows * cols;
int chunkWidth = image.getWidth() / cols;
int chunkHeight = image.getHeight() / rows;
int count = 0;
BufferedImage imgs[] = new BufferedImage[chunks];
for (int x = 0; x < rows; x++) {
for (int y = 0; y < cols; y++) {
imgs[count] = new BufferedImage(chunkWidth, chunkHeight,
image.getType());
// draws image chunk
Graphics2D gr = imgs[count++].createGraphics();
gr.drawImage(image, 0, 0, chunkWidth, chunkHeight, chunkWidth
* y, chunkHeight * x, chunkWidth * y + chunkWidth,
chunkHeight * x + chunkHeight, null);
gr.dispose();
}
}
BufferedImage[] Rimgs = new BufferedImage[imgs.length];
for (int i = 0; i < imgs.length; i++) {
Rimgs[i] = rotate(imgs[i], angle);
}
chunkWidth = Rimgs[0].getWidth();
chunkHeight = Rimgs[0].getHeight();
// Initializing the final image
BufferedImage finalImg = new BufferedImage(chunkWidth * cols,
chunkHeight * rows, BufferedImage.TYPE_3BYTE_BGR);
int num = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
finalImg.createGraphics().drawImage(Rimgs[num], chunkWidth * j,
chunkHeight * i, null);
num++;
} } return finalImg; }
public static BufferedImage rotate(BufferedImage image, double angle) {
double sin = Math.abs(Math.sin(angle)), cos = Math.abs(Math.cos(angle));
int w = image.getWidth(), h = image.getHeight();
int neww = (int) Math.floor(w * cos + h * sin), newh = (int) Math
.floor(h * cos + w * sin);
GraphicsConfiguration gc = getDefaultConfiguration();
BufferedImage result = gc.createCompatibleImage(neww, newh,
Transparency.OPAQUE);
Graphics2D g = result.createGraphics();
g.translate((neww - w) / 2, (newh - h) / 2);
g.rotate(angle, w / 2, h / 2);
g.drawRenderedImage(image, null);
g.dispose();
return result;
}
The problem I face after dividing an image of baboo gray-scale 298X298 pixel into 8 col and 8 row, the resulting image has black lines separating columns. However when I divide the image into 12 or 4 it works fine. Can you please let me know where I should consider.
Seems I can not post image.
When I divide and rotate the image into 8 rows and 8 columns of an image with 298X298, I get a result of 296X296 pixel. How can I fix this. So the size of before dividing and rotating is same as after.
Thanks in advance for your help.
I know how to get the RGB values of individual pixels of a bitmap. How can I get the average RGB value for all of the pixels of a bitmap?
I think below code for exact answer to you.
Get the Average(Number of pixels)of Red, Green and Blue value for the given bitmap.
Bitmap bitmap = someBitmap; //assign your bitmap here
int redColors = 0;
int greenColors = 0;
int blueColors = 0;
int pixelCount = 0;
for (int y = 0; y < bitmap.getHeight(); y++)
{
for (int x = 0; x < bitmap.getWidth(); x++)
{
int c = bitmap.getPixel(x, y);
pixelCount++;
redColors += Color.red(c);
greenColors += Color.green(c);
blueColors += Color.blue(c);
}
}
// calculate average of bitmap r,g,b values
int red = (redColors/pixelCount);
int green = (greenColors/pixelCount);
int blue = (blueColors/pixelCount);
The answer from john sakthi does not work correctly if the Bitmap has transparency (PNGs). I modified the answer for correctly getting the red/green/blue averages while accounting for transparent pixels:
/**
* Calculate the average red, green, blue color values of a bitmap
*
* #param bitmap
* a {#link Bitmap}
* #return
*/
public static int[] getAverageColorRGB(Bitmap bitmap) {
final int width = bitmap.getWidth();
final int height = bitmap.getHeight();
int size = width * height;
int pixelColor;
int r, g, b;
r = g = b = 0;
for (int x = 0; x < width; ++x) {
for (int y = 0; y < height; ++y) {
pixelColor = bitmap.getPixel(x, y);
if (pixelColor == 0) {
size--;
continue;
}
r += Color.red(pixelColor);
g += Color.green(pixelColor);
b += Color.blue(pixelColor);
}
}
r /= size;
g /= size;
b /= size;
return new int[] {
r, g, b
};
}
you can use this method for this purpose: Bitmap.createBitmap
For instance:
int[] colors = new int[yourWidth * yourHeight];
Arrays.fill(colors, Color.Black);
Bitmap bitamp = Bitamp.createBitmap(colors, yourWidth, yourHeight, Bitmap.Config.ARGB_8888);
Check for typo