i ran into the problem yesterday using the BufferedImage Lib, i get a
java.lang.ArrayIndexOutOfBoundsException: 3
but only for pictures "PNG" i get from the net, but if i make my own in Paint it all works. i have tryed looking up the problem but cant see where im wrong.
package grayandconvert;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.File;
import java.io.IOException;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
public class JavaCodeProject { // remain if needed Kim
private final String PATH = "C:\\New folder\\"; //
private final String graypath = PATH + "oZPX0bbg.png"; // filename for Grayscale pic
private final String imgpath = PATH + "oZPX0bb.png"; // filename for Orginal pic
private final String textpath =PATH + "filename.txt"; // filename for Output textfile
private final String imgtype = "png"; // image file type for Grascale "png" "jpg"
public static void main(String[] args)
{
JavaCodeProject main = new JavaCodeProject(); //new class for use of the metoth
main.grayscale();
main.convert();
}
public void convert()
{
try
{
BufferedImage image =ImageIO.read(new File(graypath)); // called the gray pic for image
int[] pixel; // int array named pixel
System.out.print(image.getHeight());
System.out.print(image.getWidth());
for (int y = 0; y < image.getHeight(); y++) // outer forloop to control Y axel image.getWidth
{
for (int x = 0; x < image.getWidth(); x++) //inner forloop to control X axel
{
pixel = image.getRaster().getPixel(x, y, new int[3]); // gets the RGB data from the buffer
if(pixel[0]< 255 && pixel[1]< 255 && pixel[2]< 255)
{
System.out.print(" Y");
writefile("Y");
}
else
{
System.out.print(" N");
writefile("N");
}
}
System.out.print(" L");
System.out.println("");
writefile("L");
}
System.out.print("S");
writefile("S");
}
catch (IOException e) // never used it but it needs to be here
{
}
}
public void writefile(String value)
{
String array = value; //named it array. i know right :P
File file = new File(textpath); //path for new file.txt
try
{
if (!file.exists()) // if file doesnt exists, then this will create it ;)
{
file.createNewFile();
}
FileWriter fw = new FileWriter(file.getAbsoluteFile(),true);
try (BufferedWriter bw = new BufferedWriter(fw)) {
bw.write(array,0,array.length());
}
}
catch (IOException e) // if IO exceptions happens this outputs Stacktrace
{
}
}
public void grayscale()
{
BufferedImage img = null;
try
{
File f = new File(imgpath); //org pic
img = ImageIO.read(f);
}
catch(IOException e)
{
System.out.println(e);
}
for(int y = 0; y < img.getHeight(); y++)
{
for(int x = 0; x < img.getWidth(); x++)
{
int p = img.getRGB(x,y);
int a = (p>>24)&0xff;
int r = (p>>16)&0xff;
int g = (p>>8)&0xff;
int b = p&0xff;
//calculate average
int avg = (r+g+b)/3;
//replace RGB value with avg
p = (a<<24) | (avg<<16) | (avg<<8) | avg;
img.setRGB(x, y, p);
}
}
try
{
File f = new File(graypath); //gray pic
ImageIO.write(img,imgtype,f);
}
catch(IOException e)
{
System.out.println(e);
}
}
}
I get the error
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at java.awt.image.ComponentSampleModel.getPixel(ComponentSampleModel.java:750)
at java.awt.image.Raster.getPixel(Raster.java:1519)
at grayandconvert.JavaCodeProject.convert(JavaCodeProject.java:41)
at grayandconvert.JavaCodeProject.main(JavaCodeProject.java:23)
128128C:\Users\clipcomet\Desktop\JavaApplication10\nbproject\build-impl.xml:1051: The following error occurred while executing this line:
C:\Users\clipcomet\Desktop\JavaApplication10\nbproject\build-impl.xml:805: Java returned: 1
BUILD FAILED (total time: 1 second)
i just started programming a bit ago and i know im using a Lib i dont know fully but needed to use the BufferedImage, ignoring all the bad code i have can someone tell me why i only get that error on some pics
The reason you get the exception in some cases, is that Raster.getPixel(x, y, pixel) tries to copy all the samples for the pixel at x, y into the pixel array. And you have no control over how many samples per pixel your raster has, if you download random pictures from the net, yet you hardcode the pixel array to 3 elements.
From the API doc (emphasis mine):
ArrayIndexOutOfBoundsException - if the coordinates are not in bounds, or if iArray is too small to hold the output.
Most likely, the images where you get the exception, have 4 components and are RGBA (while the ones from Paint have 3 components, RGB). You will probably get rid of the exception by creating a larger array (ie. new int[4]).
However, the best way to fix the problem is to not create the array at all yourself, and instead leave that to the getPixel method, like this:
int[] pixel = null;
for (y...) {
for (x...) {
pixel = raster.getPixel(x, y, pixel);
...
}
}
This also ensures that the allocation happens only once, which is obviously good for performance.
That said, you still need to handle the fact that a random image may not have the expected number of samples per pixel. If your input is gray or uses a color map (IndexColoModel), it will only have one sample (and you'll have an ArrayIndexOutOfBoundsExpcetion for your pixel[1] and pixel[2] array accesses). And for the color map case, the sample values is unrelated to the RGB value you see on screen (it's only an index into a lookup table).
For these reasons, you may find it easier and more intuitive to just use the BufferedImage.getRGB(x, y) method, which always gives you the ARGB values of the pixel as a single packed int sample, in sRGB color space.
Related
I have a java code generating dxf files, I am using jdxf library. Almost everything works fine with it, there is only one thing I could not figure out. When I'm adding a new Layer, I wish to do it with a new color so that all entities I draw under this new layer shall have a "ByLayer" color, which would be this new color I specify.
I can only achieve that the entities shall have the color I specify, but their layer's default color would still be black/white. Here is my DXFHandler object:
public class DXFHandler {
//https://jsevy.com/wordpress/index.php/java-and-android/jdxf-java-dxf-library/
DXFGraphics graphics;
DXFDocument dXFDocument;
int mirrorY, mirrorX;
public DXFHandler() {
dXFDocument = new DXFDocument();
dXFDocument.setUnits(4);//set units to mm
dXFDocument.setPrecisionDigits(1);//set precision digits
dXFDocument.setViewportCenter(0, 0);
graphics = dXFDocument.getGraphics();
mirrorX=1;
mirrorY=-1;
}
public void addLayer(String layerName, Color c) {
dXFDocument.setLayer(layerName);
graphics.setColor(c);//This will only achieve that the drawing entities get this color, but the layer's color would not be touched.
}
public void drawLine(double[]x, double[]y){
if (x!=null&&y!=null&x.length==y.length) {
for (int i = 1; i < x.length; i++) {
graphics.drawLine(mirrorX*x[i-1], mirrorY*y[i-1],mirrorX*x[i],mirrorY*y[i]);
}
}
}
public void drawPoint(double[]x, double[]y){
if (x!=null&&y!=null&x.length==y.length) {
for (int i = 0; i < x.length; i++) {
graphics.drawPoint(mirrorX*x[i], mirrorY*y[i]);
}
}
}
public void drawRect(double x1, double y1, double x2, double y2){
graphics.drawRect(mirrorX*x1, mirrorY*y1, mirrorX*x2, mirrorY*y2);
}
public void saveToDXF(String outputPath) throws IOException {
String stringOutput = dXFDocument.toDXFString();
FileWriter fileWriter = new FileWriter(outputPath);
fileWriter.write(stringOutput);
fileWriter.flush();
fileWriter.close();
}
And here is an example code to test it:
public static void main(String[] args) {
String outputFile="d:\\test.dxf";
int points=500;//Number of drawn points .
String layer1Name="Layer_1";
double[]xCoordinatesOfPoints1=new double[points];//creating first test-pointset_Xcoordinates
double[]yCoordinatesOfPoints1=new double[points];//creating first test-pointset_Ycoordinates
for (int i = 0; i < xCoordinatesOfPoints1.length; i++) {
xCoordinatesOfPoints1[i]=i;
yCoordinatesOfPoints1[i]=i;
}
String layer2Name="Layer_2";
double[]xCoordinatesOfPoints2=new double[points];//creating second test-pointset_Xcoordinates
double[]yCoordinatesOfPoints2=new double[points];//creating second test-pointset_Ycoordinates
for (int i = 0; i < xCoordinatesOfPoints1.length; i++) {
xCoordinatesOfPoints2[i]=-1*i;
yCoordinatesOfPoints2[i]=i;
}
DXFHandler dXFHandler=new DXFHandler(); //Creating dxf handler object
dXFHandler.addLayer(layer1Name, Color.red);//Creating layer1
dXFHandler.drawPoint(xCoordinatesOfPoints1, yCoordinatesOfPoints1);//drawing points of layer1
dXFHandler.addLayer(layer2Name, Color.GREEN);//Creating layer2
dXFHandler.drawPoint(xCoordinatesOfPoints2, yCoordinatesOfPoints2);//drawing points of layer2
try {
dXFHandler.saveToDXF(outputFile);//Exporting dxf file
} catch (IOException ex) {
System.out.println("FAILED");
}
}
As a result I get a "test.dxf" file which has a green and red point-set. That would be fine but both layers' default color is white. I would prefer if the points' color was "ByLayer" and the layer color was green/red, as it is in my "wantedSolution.dxf", which I failed to see how to attach. I will attach it as soon as I figure out how to do that...
I need some help. I created a function that read a single image. Well, it's work, but I want to create something like a loop for get all images from directory and use the imread method for get pixels values. How I can do this? follow my code below.
public void cor() {
String src = ("path_to_folder");
Mat imgread;
imgread = Imgcodecs.imread(src, IMREAD_COLOR);
Mat rgbimage = null; //for conversion bgr2rgb
int lin = imgread.rows(); //get the number of rows
int col = imgread.cols(); //get the number of cols
if (imgread.empty()) {
Log.e("error", "is empty!");
} else {
rgbimage = new Mat(imgread.size(), imgread.type());
Imgproc.cvtColor(imgread, rgbimage, Imgproc.COLOR_BGR2RGB);
}
for (int i = 0; i < lin; i++) {
for (int j = 0; j < col; j++) {
double[] rgb =rgbimage.get(i, j);
pixels.add(rgb); //put data in arraylist
}
}
}
Using File you can get a list of all files in a directory. Then, you can loop through the list to get the absolute path of each file and do whatever you want with it.
public void cor() {
File rootDir= new File("your/path/to/root_directory");
File[] files = rootDir.listFiles();
for(File file :files) {
String src = file.getAbsolutePath();
Mat imgread;
imgread = Imgcodecs.imread(src, IMREAD_COLOR);
/*
* Do the other stuff in your method.
*/
}
}
Note: I was not 100% sure what you were doing with pixels, so I just wrote what you need to loop through a directory.
I'm working in Java and I wanted to create an arrayList of BufferedImages:
ArrayList<BufferedImage> aNoteList = new ArrayList<BufferedImage>();
I then want to populate the arrayList with 197 BufferedImages in the constructor of the DrawPanel class.
public DrawPanel(){
for(int i = 0; i < 197; i++){
try {
aNoteList.add(ImageIO.read(new File("a.png")));
} catch (IOException e) {
e.printStackTrace();
}
}
setPreferredSize(new Dimension(400, 600));
panelSize=getPreferredSize();
height=(int) panelSize.getHeight();
width=(int) panelSize.getWidth();
System.out.printf("%d, %d\n",height,width);
loadImage();
}
Then, in the DrawFrame class, I create an object out of the DrawPanel class called canvas. I then use canvas here.
/*this checks to see if the song is at a specified time and calls the fall method in the DrawPanel class.*/
public void checkIfFall() throws IOException{
if(Song.getTime() / 1000000000 == (jojo.getaArray()[canvas.getaI()] /1000000000)){
//System.out.println("A Fall");
canvas.fall(canvas.getANoteList().get(canvas.getaI() + 1), canvas.getLocA());
canvas.setaI(canvas.getaI()+1);
}
}
I suspect the real issues lie with the fall method, but I don't know why.
public void fall(BufferedImage img, Location loc) throws IOException{
if(img != null){
if(img == ImageIO.read(new File("a.png")))
x = 10;
if(img == ImageIO.read(new File("s.png")))
x = (width-s.getWidth())/2;
if(img == ImageIO.read(new File("d.png")))
x = width-d.getWidth()-20;
if(loc.getY()<=height){
System.out.println(img);
//offgc.drawImage(img, x, loc.getY(), null);
validate();
repaint();
makeMove(movePixel(), loc);
}
}
}
I'm getting a nullPointerException when I pass image into the drawImage method, but I don't know why. The array is populated, it said that the image wasn't null. What's wrong?!
When I print out the image, I got this:
BufferedImage#614c5515: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 color space = java.awt.color.ICC_ColorSpace#1e67b872 transparency = 3 has alpha = true isAlphaPre = false ByteInterleavedRaster: width = 50 height = 50 #numDataElements 4 dataOff[0] = 3
Does that mean anything?
As image is not null, it can only be the Graphics object offgc or the loc object that you call getY() on. Try printing out those two to see if they are null. Also including a full stack trace would be helpful.
Sorry if this bugs anyone, but I'm unsure of the other questions I perused searching for an answer. My issue is I'm creating a class that simply adds Gaussian Noise to the File type passed in. Once I've added the noise, I'd like to return the result to a MainScreen class I have created. The problem is, MainClass uses File in its JPanel.
My question is how do I convert the BufferedImage type into a File type return for my Mainscreen class without causing errors for use with Swing's Jpanel?
Here's the code, if you'd like to see it for clarity. (I'm okay with this being closed if it's the wrong way to ask; I'm new to all of this and I'll be zen about this)
import java.io.*;
import java.util.*;
import java.lang.Math;
import java.awt.Image;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
public class NoiseGenerator {
Image image;
BufferedImage buffered;
Random r;
int width;
int height;
int index;
//The part of the code I'm referring to in the question
//addNoiseToImage takes in a File.
public BufferedImage addNoiseToImage(File imageToBeChanged, int standardDeviation){
try {
image = ImageIO.read(imageToBeChanged);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
buffered = (BufferedImage) image;
width = image.getWidth(null);
height = image.getHeight(null);
index = 0;
double noiseHolder;
int noiseValues[] = new int[100];
int delay = 0;
int check = 0;
do {
noiseHolder = r.nextGaussian() * standardDeviation;
check = (int) Math.round(noiseHolder);
if (check > 0) {
noiseValues[delay] = (int) noiseHolder;
delay++;
}
} while (delay <= 100);
int j;
int i;
for (j=0; j<height; j++) {
for(i=0;i<width;i++) {
index = (int) (Math.random() * (99 - 0)) + 0;
buffered.setRGB(j,i,noiseValues[index]);
}
}
return buffered; //I just have it returning a BufferedImage type to stop the error message; I'd prefer it to be a File type.
}
}
The Image I/O class provides a simple way to save images in a variety of image formats in the following example:
static boolean ImageIO.write(RenderedImage im,
String formatName,
File output) throws IOException
Note: The BufferedImage class implements the RenderedImage interface.
.
The formatName parameter selects the image format in which to save the BufferedImage.
try {
// retrieve image
BufferedImage bi = getMyImage();
File outputfile = new File("saved.png");
ImageIO.write(bi, "png", outputfile);
} catch (IOException e) {
...
}
for more information please look at this example.
Recently I got an opportunity to work with Image Processing Technologies as a part of one of my projects and my task was to find matching images from an image store when a new image is given. I started my project with googling "How to compare images using java" and I got some good articles on finding the similarity of two images. Almost all of them were based on four basic steps, they are:
1.Locating the Region of Interest (Where the Objects appear in the given image),
2.Re-sizing the ROIs in to a common size,
3.Substracting ROIs,
4.Calculating the Black and White Ratio of the resultant image after subtraction.
Though this sounds as a good algorithm to compare images, it takes a considerable amount of time after implementing it using JAI in my project. Therefore I have to find an alternate method of doing it.
Any suggestions?
**// This API will compare two image file //
// return true if both image files are equal else return false//**
public static boolean compareImage(File fileA, File fileB) {
try {
// take buffer data from botm image files //
BufferedImage biA = ImageIO.read(fileA);
DataBuffer dbA = biA.getData().getDataBuffer();
int sizeA = dbA.getSize();
BufferedImage biB = ImageIO.read(fileB);
DataBuffer dbB = biB.getData().getDataBuffer();
int sizeB = dbB.getSize();
// compare data-buffer objects //
if(sizeA == sizeB) {
for(int i=0; i<sizeA; i++) {
if(dbA.getElem(i) != dbB.getElem(i)) {
return false;
}
}
return true;
}
else {
return false;
}
}
catch (Exception e) {
System.out.println("Failed to compare image files ...");
return false;
}
}
Depending on how different the images are, you could do something like this (pseudocode). It's very primitive, but should be pretty efficient. You could speed it up by taking random or patterned pixels instead of every one.
for x = 0 to image.size:
for y = 0 to image.size:
diff += abs(image1.get(x,y).red - image2.get(x,y).red)
diff += abs(image1.get(x,y).blue - image2.get(x,y).blue)
diff += abs(image1.get(x,y).green - image2.get(x,y).green)
end
end
return ((float)(diff)) / ( x * y * 3)
This API will compare two image file and return the percentage of similarity
public float compareImage(File fileA, File fileB) {
float percentage = 0;
try {
// take buffer data from both image files //
BufferedImage biA = ImageIO.read(fileA);
DataBuffer dbA = biA.getData().getDataBuffer();
int sizeA = dbA.getSize();
BufferedImage biB = ImageIO.read(fileB);
DataBuffer dbB = biB.getData().getDataBuffer();
int sizeB = dbB.getSize();
int count = 0;
// compare data-buffer objects //
if (sizeA == sizeB) {
for (int i = 0; i < sizeA; i++) {
if (dbA.getElem(i) == dbB.getElem(i)) {
count = count + 1;
}
}
percentage = (count * 100) / sizeA;
} else {
System.out.println("Both the images are not of same size");
}
} catch (Exception e) {
System.out.println("Failed to compare image files ...");
}
return percentage;
}