How to load pixel from one image in another - java

I'm new to Java and ImageJ and I'm trying to write a PluginFilter with ImageJ and Java. I want it to crop the right and left side of an image (500 pixel each), turn those parts 90 degrees to the outside and load them in a new image.
I already tried couple of options and now I got totally confused. I don't think there is any mistake in the algorith itself, but in the handling of ImageProcessor etc..
import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.filter.*;
public class Cropping28_Plugin implements PlugInFilter {
ImagePlus imp;
public int setup(String arg, ImagePlus imp){
imp = IJ.getImage();
this.imp = imp;
return DOES_ALL;
}
public void run(ImageProcessor ip){
// int[] p = null;
// int[] q = null;
int height = imp.getHeight();
int width = imp.getWidth();
// New Image
ImagePlus new_image = IJ.createImage("Nr1", "RGB", height, 500, 1);
// turning the picture for y=0:500 (left side of picture)
for(int x = 0; x < height; x++){
for(int y = 0; y < 500; y++){
int k = 0;
// loading pixel
int q = imp.getProcessor().getPixel(x, y);
int [] convert = {q, q, q};
// pixel in newimage
int a = height - k;
int b = x;
new_image.getProcessor().putPixel(a, b, convert);
k++;
}
}
// turning the picture for y=get.Length:get.Length-500 (right side of picture)
for(int x = 0; x < height; x++){
for(int y = width -500; y < width; y++){
int k = 0;
// loading pixel
int q = imp.getProcessor().getPixel(x, y);
int [] convert = {q, q, q};
// pixel in new image
int a = height - k;
int b = x;
new_image.getProcessor().putPixel(a, b, convert);
k++;
}
}
// draw new picture
new_image.show();
}
}
I expect the output to be a picture containing the pixel of the right and left edge of the original image. The actual output is a write image of the size I expect.
It would be awesome if someone had an idea!

Related

Trying two different methods to transform a picture - JavaFX

So Im still learning Java. Now Im learning JavaFX.
I have a picture of a tree. And I want to try two different method. the first method I use was using unary operator to turn the image colour to grey.
Now I want to try a second method using the ColourTransformer interface that I made to get a 10 pixel wide gray frame replacing the pixels on the border of an image.
This is what I have done. for the second method, im not quite sure how to specify the pixel. Any suggestions?
this is what I have done
public class ColourFilter extends Application {
//Using Unary Operator to transform image to grayscale - Method 1
public static Image transform(Image in, UnaryOperator<Color> f) {
int width = (int) in.getWidth();
int height = (int) in.getHeight();
WritableImage out = new WritableImage(
width, height);
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++)
out.getPixelWriter().setColor(x, y,
f.apply(in.getPixelReader().getColor(x, y)));
return out;
}
public static <T> UnaryOperator<T> compose(UnaryOperator<T> op1, UnaryOperator<T> op2) {
return t -> op2.apply(op1.apply(t));
}
//Using ColourTransformer interface to get 10 pixel wide gray frame replacing the pixels on the border of an image - Method 2
public static Image transform(Image in, ColourTransformer f) {
int width = (int) in.getWidth();
int height = (int) in.getHeight();
WritableImage out = new WritableImage(
width, height);
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++)
out.getPixelWriter().setColor(x, y, f.apply(x, y, in.getPixelReader().getColor(x, y)));
return out;
}
#FunctionalInterface
interface ColourTransformer {
Color apply(int x, int y, Color colorAtXY);
}
public void start(Stage stage) {
Image image = new Image("amazing-trees.jpg");
Image image2 = transform(image, Color::brighter);
Image image3 = transform(image2, Color::grayscale);
// alternative to two previous image transforms -- composition
//Image image3 = transform(image, compose(Color::brighter, Color::grayscale));
stage.setScene(new Scene(new VBox(
new ImageView(image),
// new ImageView(image2),
new ImageView(image3))));
stage.show();
}
}
As the compile error message says, you are trying to call
f.apply(Color);
where f is a ColourTransformer: however you defined the apply method in ColorTransformer with three parameters: apply(int, int, Color).
You need to replace
f.apply(in.getPixelReader().getColor(x, y))
with
f.apply(x, y, in.getPixelReader().getColor(x, y))
i.e.
public static Image transform(Image in, ColourTransformer f) {
int width = (int) in.getWidth();
int height = (int) in.getHeight();
WritableImage out = new WritableImage(
width, height);
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++)
out.getPixelWriter().setColor(x, y, f.apply(x, y, in.getPixelReader().getColor(x, y)));
return out;
}
You can get the 10-pixel gray border by doing:
Image image = new Image("amazing-trees.jpg");
int width = (int) image.getWidth();
int height = (int) image.getHeight();
Image framedImage = transform(image, (x, y, color) -> {
if (x < 10 || y < 10 || width - x < 10 || height - y < 10) {
return Color.GRAY ;
} else return color ;
});

Copying the pixels of an image to a canvas in java

EDIT: I've changed some of my code to reflect what AlamasB said. I still don't understand how I should be populating my byte array and what conversions I need to do.
I'm trying to manipulate the pixels of an image uploaded by the user and write the new image onto a canvas. Right now I'm just trying to copy the original image without changing the RGB of the pixels. I've been stuck in the same spot for quite a while now and can't figure out where to go next. In the first section of the code I make a copy of the original image uploaded by the user.
Image image = imageView.getImage();
PixelReader pixelReader = image.getPixelReader();
PixelFormat format = pixelReader.getPixelFormat();
int width= (int)image.getWidth();
int height = (int) image.getHeight();
GraphicsContext gc = canvas.getGraphicsContext2D();
PixelWriter pw = gc.getPixelWriter();
byte[] imageData = new byte[width * height * 4];
imageData = createImageData(imageData, pixelReader, width, height);
//..
//...the next function populates my byte array with what's in the image
public byte[] createImageData(byte[] imageData, PixelReader pr, int width, int height){
int i = 0;
for(int y=0; y<height; y++){
for(int x = 0; x < width; x++){
int argb = pixelReader.getArgb(x, y);
imageData[i] = (byte) argb;
imageData[i+1] = (byte) argb;
imageData[i+2] = (byte) argb;
i+=3;
pw.setArgb(x, y, argb);
}
}
return imageData;
}
EDIT: No longer using this function. The next function is really confusing me. I'm referring to this http://docs.oracle.com/javafx/2/image_ops/jfxpub-image_ops.htm as a reference but I can't figure out what's going on.
//...
//... the next function sets the pixels of the canvas to what's in the byte array
public void drawImageData(byte[] imageData, PixelWriter pw, int width, int height){
boolean on = true;
PixelFormat<ByteBuffer> pixelFormat = PixelFormat.getByteRgbInstance();
for(int y = 50; y < 150; y+=height){
for(int x = 50; x < 150; x+=width){
if(on){
pw.setPixels(x, y, width, height, pixelFormat, imageData, 0, width*3);
}
on = !on;
}
on=!on;
}
}
Considering that PixelReader provides getARGB your best bet in this case is probably to use 32-bit representation. Subsequently converting it to a 4-byte array, i.e. width * height * 4. Finally use setARGB to draw the image.
int argb = pixelReader.getArgb(x, y);
// populate imageData[i,i+1,i+2,i+3] by converting argb
...
// convert imageData[i,i+1,i+2,i+3] into a 32bit argb, say int argb2
pixelWriter.setArgb(x, y, argb2);
Alternatively, you can use Color's getOpacity() to get the A from RGBA. Again, using the 32-bit representation.
At the very least this will provide you with a minimal working example, which you can then extend.
Here's a quick version (self-contained, just copy and paste):
import javafx.application.Application;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.*;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import java.nio.ByteBuffer;
import java.util.Arrays;
public class ImageManipulationApp extends Application {
private static final int APP_W = 800;
private static final int APP_H = 600;
private Parent createContent() {
Image image = makeMockImage();
byte[] imageData = imageToData(image);
byte[] modifiedImageData = modify(imageData);
Image modifiedImage = dataToImage(modifiedImageData);
HBox root = new HBox(25);
root.getChildren().addAll(new ImageView(image), new ImageView(modifiedImage));
return root;
}
private Image makeMockImage() {
WritableImage image = new WritableImage(APP_W / 2, APP_H);
PixelWriter writer = image.getPixelWriter();
for (int y = 0; y < APP_H; y++) {
for (int x = 0; x < APP_W / 2; x++) {
writer.setColor(x, y, Math.random() < 0.00005 ? Color.YELLOW : Color.BLACK);
}
}
return image;
}
/**
* Modifies the pixel data.
*
* #param data original image data
* #return modified image data
*/
private byte[] modify(byte[] data) {
// this is where changes happen
return data;
}
private byte[] imageToData(Image image) {
int width = (int) image.getWidth();
int height = (int) image.getHeight();
byte[] data = new byte[width * height * 4];
int i = 0;
for (int y = 0; y < height; y++){
for (int x = 0; x < width; x++){
int argb = image.getPixelReader().getArgb(x, y);
byte[] pixelData = ByteBuffer.allocate(4).putInt(argb).array();
data[i++] = pixelData[0];
data[i++] = pixelData[1];
data[i++] = pixelData[2];
data[i++] = pixelData[3];
}
}
return data;
}
private Image dataToImage(byte[] data) {
// if we don't know the image size beforehand we can encode width and height
// into image data too
WritableImage image = new WritableImage(APP_W / 2, APP_H);
PixelWriter writer = image.getPixelWriter();
int i = 0;
for (int y = 0; y < APP_H; y++) {
for (int x = 0; x < APP_W / 2; x++) {
int argb = ByteBuffer.wrap(Arrays.copyOfRange(data, i, i + 4)).getInt();
writer.setArgb(x, y, argb);
i += 4;
}
}
return image;
}
#Override
public void start(Stage stage) throws Exception {
stage.setScene(new Scene(createContent()));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}

How to get average RGB value of Bitmap on Android?

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

Drawing rectangle and grid

I would be very thankful if someone could help me.
My program has 2 classes. One draws a rectangle and a grid, the other is a viewer.
The problem is, when I try to change the position for the greed+rectangle, i.e. update X and Y constants in the Viewer class, the proportions change. The grid fits in only when X=0 and Y=0.
I'm using the same arrays of coordinates to draw the grid and the rectangle, but somehow the proportions are wrong, which surprises me.
Thank you.
My code:
import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.math.BigDecimal;
public class Viewer extends Applet {
public static final double R_WDTH = 12;//rectangle width
public static final double X = 10;//the grid fits in only when X=Y=0
public static final double Y = 10;
public static final int ROWS = 25;
public static final int COLUMNS = 12;
RectangleAndGrid cup = new RectangleAndGrid(X, Y, R_WDTH, ROWS, COLUMNS);
public void paint(Graphics g) {
cup.draw((Graphics2D)g);
}
}
public class RectangleAndGrid {
private double x, y, blockWidth;
private int rows, columns;
private double coordX[][], coordY[][];
private Rectangle2D.Double cupSpace;
public RectangleAndGrid(double cX, double cY, double givenBlockWidth, int r, int c){
x = cX;
y = cY;
blockWidth = givenBlockWidth;
rows = r;
columns = c;
BigDecimal currX = BigDecimal.valueOf(x);
BigDecimal currY = BigDecimal.valueOf(y);
coordX = new double[rows + 1][columns + 1];
coordY = new double[rows + 1][columns + 1];
for(int i = 0; i <= rows; i++){
for(int j = 0; j <= columns; j++){
coordX[i][j] = currX.doubleValue();
coordY[i][j] = currY.doubleValue();
currX = currX.add(BigDecimal.valueOf(blockWidth));
}
currX = BigDecimal.valueOf(x);
currY = currY.add(BigDecimal.valueOf(blockWidth));
}
cupSpace = new Rectangle2D.Double(coordX[0][0], coordY[0][0], coordX[rows][columns], coordY[rows][columns]);
}
public void draw(Graphics2D g2d){
g2d.setColor(Color.CYAN);
g2d.fill(cupSpace);
g2d.setColor(Color.BLACK);
g2d.draw(cupSpace);
Line2D.Double line = new Line2D.Double();
for(int i = 0; i <= rows; i++){
line.setLine(coordX[i][0], coordY[i][0], coordX[i][columns], coordY[i][columns]);
g2d.draw(line);
}
for(int i = 0; i <= columns; i++){
line.setLine(coordX[0][i], coordY[0][i], coordX[rows][i], coordY[rows][i]);
g2d.draw(line);
}
}
}
Firstly, your approach is a "little" weird, not entirely bad, just a little weird - IMHO
Rectangle2D takes four parameters, x, y, width and height. In you code you are passing the top, left and bottom right corners of your grid, this means, the width/height of your "cup" is actually wider by x pixels (and y pixels higher)
Basically, you need to subtract the x/y offset from the bottom right coordinates...
cupSpace = new Rectangle2D.Double(coordX[0][0], coordY[0][0], coordX[rows][columns] - coordX[0][0], coordY[rows][columns] - coordY[0][0]);

Grab x,y coordinates for a given pixel RGB?

I have a screenshot method in my code and a BufferedImage instance. I'm wondering if it's possible to search the image data for a specific RGB, then return the X,Y coordinates for the pixel.
What could I use for that? Is it possible at all?
public int[] searchForColor(BufferedImage bi, int searchColor)
{
for (int x = 0; x < bi.getWidth(); ++x)
for (int y = 0; y < bi.getHeight(); ++y)
{
if ((bi.getRGB(x, y) & 0x00FFFFFF) == searchColor)
return new int[]{x, y};
}
}
Usage:
BufferedImage bi = takeScreenShot();
int searchColor = 0x2D5E83; // A random color
int[] coordinate = searchForColor(bi, searchColor);
int x = coordinate[0];
int y = coordinate[1];
http://www.roseindia.net/java/java-get-example/get-color-of-pixel.shtml and loop thru the image data

Categories

Resources