I am trying to make an image to text program that converts a 0-255 value to a character that matches it (visually). The important thing here is having all characters the same width so in a text editor the text is square...
basically I want all characters from 32-4000 that have the same width as 'X' so I can use 'Q' but not '|' (this font is mono tho so there is no difference)
I am using the Unifont font.
What I have currently works, but I want to supply a general range of unicode characters that are all the same size (so it looks good in text at the end)
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
Color fntC = new Color(255, 255, 255);
Graphics2D g = img.createGraphics();
g.setFont(f);
FontMetrics fm = g.getFontMetrics();
for (int i = 32; i <= 4000/*126*/; i++) { //33 126
if (fm.charWidth((char)i) == fm.charWidth('X') && Character.isLetter(i))
dictionary.add(new letter((char) i, getValue((char) i)));
}
This code works pretty well, but I still get characters like 'ȷ' that has a smaller width in the text editor but is treated as the same width as 'X' according to font metrics (I'm using Courier new since that's the default of Notepad++)
MOAR CODE:
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.JFileChooser;
import javax.swing.filechooser.FileNameExtensionFilter;
public class MainImageToText {
public static void main(String[] args) {
CharDictionary cd = new CharDictionary(new Font("Unifont", 1, 20));
JFileChooser chooser = new JFileChooser();
/*FileNameExtensionFilter filter = new FileNameExtensionFilter("PNG Images", "png");
chooser.setFileFilter(filter);*/
chooser.setCurrentDirectory(new File(System.getProperty("user.home"), "Desktop"));
int returnVal = chooser.showOpenDialog(null);
File f = chooser.getSelectedFile();
if (returnVal == JFileChooser.APPROVE_OPTION) {
System.out.println("\nYou chose to open this file: " + f);
File output = new File(f.getParentFile(), "$output.txt");
saveTextFile(output, ImageToText(f, cd));
}
}
static String ImageToText(File f, CharDictionary cd) {
BufferedImage img = null;
String text = "";
try {
img = ImageIO.read(f);
} catch (IOException e) {
e.printStackTrace();
}
int w = img.getWidth();
int h = img.getHeight();
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
Color col = new Color(img.getRGB(x, y));
int red = col.getRed();
int green = col.getGreen();
int blue = col.getBlue();
int finalAverage = (red + green + blue) / 3;
text += cd.getDictionaryLetter(finalAverage);
System.out.println(x + ", " + y);
}
text += "\n";
}
cd.debugPrintDictionary();
// System.out.println(text);
return text;
}
static void saveTextFile(File f, String s) {
File desktop = new File(System.getProperty("user.home"), "Desktop");
File outputfile = new File(desktop.toString() + "\\" + "file.txt");
try {
System.out.println("creating file...");
PrintWriter out = new PrintWriter(outputfile, "UTF-8");
out.write(s);
out.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Saved to: " + f);
}
}
class letter {
public String c;
public int val;
letter(String ch, int dub) {
c = ch;
val = dub;
}
public char getChar() {
Random rand = new Random();
return c.charAt(rand.nextInt(c.length()));
}
public void addChar(char ch) {
c += ch;
}
public void addChar(String ch) {
c += ch;
}
}
class LetterComparator implements Comparator<letter> {
#Override
public int compare(letter a, letter b) {
return (a.val - b.val); // *100 for more precision
}
}
class CharDictionary {
private Font f;
private List<letter> dictionary = new ArrayList<letter>();
CharDictionary(Font font) {
f = font;
createDictionary();
}
public void createDictionary() {
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
Color fntC = new Color(255, 255, 255);
Graphics2D g = img.createGraphics();
g.setFont(f);
FontMetrics fm = g.getFontMetrics();
dictionary.add(new letter(" ", getValue(' ')));
for (int i = 32; i <= 65000; i++) { //33 126
if (fm.charWidth(i) == fm.charWidth('X') && !Character.isWhitespace(i))
dictionary.add(new letter((char) i + "", getValue((char) i)));
}
sort();
compact();
}
public void sort() {
Collections.sort(dictionary, new LetterComparator());
}
public void compact() {
int val;
for (int i = dictionary.size()-1; i > 0 ; i--) {
val = dictionary.get(i).val;
if (val == dictionary.get(i-1).val) {
dictionary.get(i-1).addChar(dictionary.get(i).c);
dictionary.remove(i);
}
}
}
public void debugPrintDictionary() {
for (int i = 0; i < dictionary.size(); i++) {
System.out.println("Char: " + dictionary.get(i).c + " Value: " + dictionary.get(i).val);
}
}
/*public int getIndexofVal(int n) {
return null;
}*/
public char getDictionaryLetter(int val) {
for (int i = 0; i < dictionary.size(); i++) {
int charvalue = dictionary.get(i).val;
if (charvalue >= 255-val) {//inverted here
return dictionary.get(i).getChar();
}
}
return dictionary.get(dictionary.size() - 1).getChar(); /// PROBLEM HERE
}
public int getValue(char c) {
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
Color fntC = new Color(255, 255, 255);
Graphics2D g = img.createGraphics();
g.setFont(f);
FontMetrics fm = g.getFontMetrics();
int width = fm.charWidth(c);
int height = fm.getAscent()+ fm.getDescent(); // too big
img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
g = img.createGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(fntC);
g.setFont(f);
// g.fill
g.drawString(c + "", 0, fm.getAscent());
int w = img.getWidth();
int h = img.getHeight();
double finalAverage = 0;
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
Color col = new Color(img.getRGB(x, y));
int red = col.getRed();
int green = col.getGreen();
int blue = col.getBlue();
finalAverage += (red + green + blue) / 3;
}
}
finalAverage /= w * h;
/*try {
File desktop = new File(System.getProperty("user.home"), "Desktop");
File outputfile = new File(desktop.toString() + "\\letters\\" + (int) c + ".png");
ImageIO.write(img, "png", outputfile);
} catch (IOException e) {
}*/
return (int)finalAverage;
}
}
Related
Is there a way in java to get the vertices of a font so they can be displayed as particles in java?
like so:
Yes, there's a way. It's not trivial. I wrote this class as part of a marquee GUI.
Pay particular attention to the getTextPixels method.
package com.ggl.marquee.model;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
public class MarqueeFont {
private static final boolean DEBUG = false;
private int fontHeight;
private Font font;
public MarqueeFont(Font font) {
this.font = font;
FontRenderContext frc = new FontRenderContext(null, true, true);
Rectangle2D r2D = font.getStringBounds("HgH", frc);
this.fontHeight = (int) Math.round(r2D.getHeight());
if (DEBUG) {
System.out.println(font.getFamily() + " " + fontHeight + " pixels");
}
}
public boolean[][] getTextPixels(String s) {
FontRenderContext frc = new FontRenderContext(null, true, true);
Rectangle2D r2D = font.getStringBounds(s, frc);
int rWidth = (int) Math.round(r2D.getWidth());
int rHeight = (int) Math.round(r2D.getHeight());
int rX = (int) Math.round(r2D.getX());
int rY = (int) Math.round(r2D.getY());
if (DEBUG) {
System.out.print(s);
System.out.print(", rWidth = " + rWidth);
System.out.print(", rHeight = " + rHeight);
System.out.println(", rX = " + rX + ", rY = " + rY);
}
BufferedImage bi = generateCharacterImage(rX, -rY, rWidth, rHeight, s);
int[][] pixels = convertTo2D(bi);
if (DEBUG) {
displayPixels(pixels);
}
return createTextPixels(pixels);
}
private BufferedImage generateCharacterImage(int x, int y, int width,
int height, String string) {
BufferedImage bi = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics g = bi.getGraphics();
g.setFont(font);
g.setColor(Color.WHITE);
g.fillRect(0, 0, width, height);
g.setColor(Color.BLACK);
g.drawString(string, x, y);
return bi;
}
private int[][] convertTo2D(BufferedImage image) {
final int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer())
.getData();
final int width = image.getWidth();
final int height = image.getHeight();
int[][] result = new int[height][width];
int row = 0;
int col = 0;
for (int pixel = 0; pixel < pixels.length; pixel++) {
result[row][col] = pixels[pixel];
col++;
if (col == width) {
col = 0;
row++;
}
}
return result;
}
private void displayPixels(int[][] pixels) {
for (int i = 0; i < pixels.length; i++) {
String s = String.format("%03d", (i + 1));
System.out.print(s + ". ");
for (int j = 0; j < pixels[i].length; j++) {
if (pixels[i][j] == -1) {
System.out.print(" ");
} else {
System.out.print("X ");
}
}
System.out.println("");
}
}
private boolean[][] createTextPixels(int[][] pixels) {
// The int array pixels is in column, row order.
// We have to flip the array and produce the output
// in row, column order.
if (DEBUG) {
System.out.println(pixels[0].length + "x" + pixels.length);
}
boolean[][] textPixels = new boolean[pixels[0].length][pixels.length];
for (int i = 0; i < pixels.length; i++) {
for (int j = 0; j < pixels[i].length; j++) {
if (pixels[i][j] == -1) {
textPixels[j][i] = false;
} else {
textPixels[j][i] = true;
}
}
}
return textPixels;
}
public Font getFont() {
return font;
}
public int getFontHeight() {
return fontHeight;
}
#Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append(font.getFamily());
builder.append(", ");
builder.append(getStyleText());
builder.append(", ");
builder.append(font.getSize());
builder.append(" pixels");
return builder.toString();
}
private StringBuilder getStyleText() {
StringBuilder builder = new StringBuilder();
int style = font.getStyle();
if (style == Font.PLAIN) {
builder.append("normal");
} else if (style == Font.BOLD) {
builder.append("bold");
} else if (style == Font.ITALIC) {
builder.append("italic");
} else if (style == (Font.BOLD + Font.ITALIC)) {
builder.append("bold italic");
} else {
builder.append("unknown style");
}
return builder;
}
}
I want to make the displayed image repainted for everytime i change the slider position.
I've already made the Every change of the Variable from JSlider is added to the pixel. But i just don't know how to repaint it.
package training;
import javax.swing.*;
import java.io.*;
import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
import javax.swing.plaf.SliderUI;
import java.awt.Color;
import java.util.Arrays;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Training extends JPanel {
public BufferedImage image;
double maxw, maxh;
double w, h, ratio;
int warna, red, green, blue, abu, value;
int forT1, forT2;
int[][] bmpR;
int[][] bmpG;
int[][] bmpB;
int[][] alpha;
public Training () {
super();
try {
image = ImageIO.read(new File("src/training/V.jpg"));
}
catch (IOException e) {
//Not handled.
}
maxw = 750;
maxh = 600;
w = image.getWidth();
h = image.getHeight();
bmpR = new int[(int)w][(int)h];
bmpG = new int[(int)w][(int)h];
bmpB = new int[(int)w][(int)h];
if (w > h) {
if (w > maxw) {
ratio = maxw / w;
h = h * ratio; // Reset height to match scaled image
w = w * ratio;
}
}
if (w <= h) {
if (h > maxh) {
ratio = maxh / h;
w = w * ratio; // Reset height to match scaled image
h = h * ratio;
}
}
try {
for( int i = 0; i < w; i++ ) {
for( int j = 0; j < h; j++ ) {
Color c = new Color(image.getRGB(i, j));
bmpR [i][j] = c.getRed();
bmpG [i][j] = c.getGreen();
bmpB [i][j] = c.getBlue();
// alpha = c.getAlpha();
}
}
System.out.println(bmpB[40][40]);
}
catch (Exception e) {
System.out.println("Terjadi kesalahan saat mengambil data pixel");
e.printStackTrace();
return;
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Image i = image.getScaledInstance((int)w, (int)h,Image.SCALE_SMOOTH);
g.drawImage(i, 20, 20, null);
}
public static void main(String[] args) {
final Training ns = new Training();
System.out.println("User dir: " + System.getProperty("user.dir"));
JFrame f = new JFrame("Window");
JPanel p = new Training();
f.setSize(1100, 600);
p.setSize(750, 600);
f.add(p);
JSlider Temp = new JSlider(-50, 50, 0);
Temp.setMajorTickSpacing(10);
Temp.setMinorTickSpacing(1);
Temp.addChangeListener(new ChangeListener () {
public void stateChanged(ChangeEvent evt) {
JSlider Temp = (JSlider) evt.getSource();
if (Temp.getValueIsAdjusting()) {
ns.value = Temp.getValue();
for(ns.forT1 = 0; ns.forT1 < ns.w; ns.forT1++ ) {
for(ns.forT2 = 0; ns.forT2 < ns.h; ns.forT2++ ) {
ns.bmpB[ns.forT1][ns.forT2] = ns.bmpB[ns.forT1][ns.forT2] - ns.value;
if (ns.bmpB[ns.forT1][ns.forT2] > 255) {
ns.bmpB[ns.forT1][ns.forT2] = 255;
}
if (ns.bmpB[ns.forT1][ns.forT2] < 0) {
ns.bmpB[ns.forT1][ns.forT2] = 0;
}
ns.bmpR[ns.forT1][ns.forT2] = ns.bmpR[ns.forT1][ns.forT2] + ns.value;
if (ns.bmpR[ns.forT1][ns.forT2] > 255) {
ns.bmpR[ns.forT1][ns.forT2] = 255;
}
if (ns.bmpR[ns.forT1][ns.forT2] < 0) {
ns.bmpR[ns.forT1][ns.forT2] = 0;
}
}
}
}
ns.repaint();
}
});
f.add(Temp, BorderLayout.EAST);
f.setVisible(true);
}
}
Did i misplaced the ChangeListener or should i put paintComponent method after the change listener happens?
The random indentation of your code is making it hard to figure out exactly what's going on, but I don't see repaint() anywhere inside your ChangeListener. You need to use repaint() to trigger the repainting of your component.
I want to recognize the numbers in the Pic1.
I did some work on it and it returns to pic2
Here is my code:
package captchadecproj;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
/*
* #author Mr__Hamid
*/
public class NewClass {
public static void main(String args[]) throws IOException {
int width = 110;
int heigth = 40;
BufferedImage image1 = new BufferedImage(width, heigth, BufferedImage.TYPE_INT_RGB);
BufferedImage num1 = new BufferedImage(width, heigth, BufferedImage.TYPE_INT_RGB);
BufferedImage image = null;
File f = null;
try {
f = new File("E:\\Desktop 2\\Captcha Project\\CaptchaDecoder\\captchaDecProj\\167.png");
image = new BufferedImage(width, heigth, BufferedImage.TYPE_INT_ARGB);
image = ImageIO.read(f);
System.out.println("Read!");
} catch (IOException e) {
System.out.println("Error" + e);
}
int[] pixel = null;
for (int y = 0; y < image.getHeight(); y++) {
for (int x = 0; x < image.getWidth(); x++) {
pixel = image.getRaster().getPixel(x, y, new int[3]);
if (pixel[0] < 30 & pixel[1] > 130 & pixel[2] < 110 & pixel[2] > 60) {
image1.setRGB(x, y, Integer.parseInt("ffffff".trim(), 16));
System.out.println(pixel[0] + " - " + pixel[1] + " - " + pixel[2] + " - " + (image.getWidth() * y + x));
} else {
image1.setRGB(x, y, 1);
System.out.println(pixel[0] + " - " + pixel[1] + " - " + pixel[2] + " - " + (image.getWidth() * y + x));
}
}
}
try {
f = new File("D:\\Original.jpg");
ImageIO.write(image, "jpg", f);
f = new File("D:\\black&White.jpg");
ImageIO.write(image1, "jpg", f);
System.out.println("Writed");
} catch (IOException e) {
System.out.println("Error" + e);
}
}
}
I have two questions:
How can I split these numbers?
How can I recognize which one is my number?
For example in the uploaded pic: 7, 1, 6
This is answer for first question, which is how to split numbers.
I recommend you something, is to convert your image to two dimensional array, then all operations will be perform much quicker than when you use BufferedImage.
BufferedImage image = ImageIO.read(new URL("http://i.stack.imgur.com/QaTj5.jpg"));
int startPos = 0, lastValue = 0;
Set<Integer> colours = new HashSet<>();
for (int x = 0; x < image.getWidth(); x++) {
int histValue = 0;
for (int y = 0; y < image.getHeight(); y++) {
colours.add(image.getRGB(x, y) );
if (image.getRGB(x, y) == 0xffffFFFF) {
histValue++;
}
}
if (histValue == 0 && lastValue == 0) {
startPos = x;
} else if (histValue == 0 && lastValue != 0) {
BufferedImage segment = image.getSubimage(startPos, 0, x
- startPos, image.getHeight());
ImageIO.write(segment, "jpg", new File("Segment" + startPos
+ ".jpg"));
}
lastValue = histValue;
}
if (lastValue!=0){
BufferedImage segment = image.getSubimage(startPos, 0, image.getWidth()
- startPos, image.getHeight());
ImageIO.write(segment, "jpg", new File("Segment" + startPos
+ ".jpg"));
}
Now all what you need to do is to find some decent algorithm for ocr.
I am a beginner to Java. Currently I want to analyze two similar images and check whether the images have different pixel values at position 2 and 4. I already develop some codes but when running it, the code produces error and it doesn't looping and check for all pixel values on both images.
For example, in the 9th pixel, image B pixel value at position 2 and 4 are not the same as image A pixel value. Then, whenever the code notices a differences between both images pixel value it will output the statement saying the pixel are not the same.
Here's the code:
public class getPixelRGB1
{
private static String[][] img_hex2;
private static String[][] img_hex4;
private static String[][] img2_hex2;
private static String[][] img2_hex4;
public static void main(String[] args) throws IOException
{
FileInputStream image = null;
FileInputStream image2 = null;
getPixelData1 newPD = new getPixelData1();
compareHexaRGB hexRGB = new compareHexaRGB();
try {
BufferedImage img, img2;
File file = new File("eye1.jpg");
File file2 = new File("eye2.jpg");
image = new FileInputStream(file);
image2 = new FileInputStream(file2);
img = ImageIO.read(image);
img2 = ImageIO.read(image2);
int rowcol;
int width = img.getWidth();
int height = img.getHeight();
hexRGB.compareHexaRGB(width, height);
System.out.println("Image's Width: " + width);
System.out.println("Image's Height: " + height);
//hexRGB.check();
int[][] pixelData = new int[width * height][3];
System.out.println("Pixel Data: " + pixelData);
int[] rgb;
int count = 0;
img_hex2 = new String[width][height];
img_hex4 = new String[width][height];
for(int i=0; i<width; i++)
{
for(int j=0; j<height; j++)
{
rgb = newPD.getPixelData(img, i, j);
for(int k = 0; k < rgb.length; k++)
{
pixelData[count][k] = rgb[k];
//img_hex2[i][j] = newPD.getHexa2();
//img_hex4[i][j] = newPD.getHexa4();
}
img_hex2[width][height] = newPD.getHexa2();
img_hex4[width][height] = newPD.getHexa4();
System.out.println("Output: " + img_hex2[i][j]);
System.out.println("Output: " + img_hex4[i][j]);
count++;
System.out.println("\nRGB Counts: " + count);
}
}
int width2 = img2.getWidth();
int height2 = img2.getHeight();
System.out.println("Image's Width: " + width2);
System.out.println("Image's Height: " + height2);
int[][] pixelData2 = new int[width2 * height2][3];
System.out.println("Pixel Data: " + pixelData2);
int[] rgb2;
int counter = 0;
img_hex2 = new String[width2][height2];
img_hex4 = new String[width2][height2];
for(int i=0; i<width2; i++)
{
for(int j=0; j<height2; j++)
{
rgb2 = newPD.getPixelData(img2, i, j);
for(int k = 0; k < rgb2.length; k++)
{
pixelData2[counter][k] = rgb2[k];
}
img2_hex2[width2][height2] = newPD.getHexa2();
img2_hex4[width2][height2] = newPD.getHexa4();
counter++;
System.out.println("\nRGB2 Counts: " + counter);
}
}
}
catch (FileNotFoundException ex) {
Logger.getLogger(getPixelRGB1.class.getName()).log(Level.SEVERE, null, ex);
}
finally
{
try {
image.close();
}
catch (IOException ex) {
Logger.getLogger(getPixelRGB1.class.getName()).log(Level.SEVERE, null, ex);
}
}
hexRGB.check();
}
public String[][] display_imgHex2()
{
return img_hex2;
}
public String[][] display_imgHex4()
{
return img_hex4;
}
public String[][] display_img2Hex2()
{
return img2_hex2;
}
public String[][] display_img2Hex4()
{
return img2_hex4;
}
}
//Get Pixel RGB Process
public class getPixelData1
{
private static final double bitPerColor = 4.0;
private static int red;
private static int green;
private static int blue;
private static String hexa2;
private static String hexa4;
public static int[] getPixelData(BufferedImage img, int w, int h) throws IOException
{
int argb = img.getRGB(w, h);
int rgb[] = new int[]
{
(argb >> 16) & 0xff, //red
(argb >> 8) & 0xff, //green
(argb ) & 0xff //blue
};
red = rgb[0];
green = rgb[1]; //RGB Value in Decimal
blue = rgb[2];
System.out.println("\nRGBValue in Decimal --> " + "\nRed: " + red + " Green: " + green + " Blue: " + blue);
//Convert each channel RGB to Hexadecimal value
String rHex = Integer.toHexString((int)(red));
String gHex = Integer.toHexString((int)(green));
String bHex = Integer.toHexString((int)(blue));
System.out.println("\nRGBValue in Hexa --> " + "\nRed Green Blue " + rHex + gHex + bHex);
return rgb;
}
public String getHexa2()
{
//Check position 2 of hexa value for any changes
String hex = String.format("%02X%02X%02X", red, green, blue);
System.out.println("\nString RGB Hexa: " + hex);
hexa2 = hex.substring(1,2);
System.out.println("\nSubstring at position 2: " + hexa2);
return hexa2;
}
public String getHexa4()
{
//Check position 4 of hexa value for any changes
String hex = String.format("%02X%02X%02X", red, green, blue);
System.out.println("\nString RGB Hexa: " + hex);
hexa4 = hex.substring(3,4);
System.out.println("\nSubstring at position 4: " + hexa4);
return hexa4;
}
}
//Compare 2 images process
public class compareHexaRGB
{
private static int w;
private static int h;
public static void compareHexaRGB(int width, int height) throws IOException
{
w = width;
h = height;
}
public void check()
{
getPixelRGB1 newPD = new getPixelRGB1();
for(int i = 0; i < w; i++)
{
for(int j = 0; j < h; j++)
{
if(newPD.display_imgHex2().equals(newPD.display_img2Hex2()) && (newPD.display_imgHex4().equals(newPD.display_img2Hex4())))
{
System.out.println("Pixel values at position 2 and 4 are the same.");
}
else if(!newPD.display_imgHex2().equals(newPD.display_img2Hex2()) || (!newPD.display_imgHex4().equals(newPD.display_img2Hex4())))
{
System.out.println("Pixel values at position 2 are not the same.");
}
else if(!newPD.display_imgHex2().equals(newPD.display_img2Hex2()) || (!newPD.display_imgHex4().equals(newPD.display_img2Hex4())))
{
System.out.println("Pixel values at position 4 are not the same.");
}
}
}
}
}
Errors:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at getPixelRGB1.main(getPixelRGB1.java:79)
The change you have made is fundamentally incorrect. Please refer this updated class.
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
public class getPixelRGB1 {
private static String[][] img_hex2;
private static String[][] img_hex4;
private static String[][] img2_hex2;
private static String[][] img2_hex4;
public static void main(String[] args) throws IOException {
FileInputStream image = null;
FileInputStream image2 = null;
getPixelData1 newPD = new getPixelData1();
compareHexaRGB hexRGB = new compareHexaRGB();
try {
BufferedImage img, img2;
File file = new File("eye1.jpg");
File file2 = new File("eye2.jpg");
image = new FileInputStream(file);
image2 = new FileInputStream(file2);
img = ImageIO.read(image);
img2 = ImageIO.read(image2);
int rowcol;
int width = img.getWidth();
int height = img.getHeight();
hexRGB.compareHexaRGB(width, height);
System.out.println("Image's Width: " + width);
System.out.println("Image's Height: " + height);
// hexRGB.check();
int[][] pixelData = new int[width * height][3];
System.out.println("Pixel Data: " + pixelData);
int[] rgb;
int count = 0;
img_hex2 = new String[width][height];
img_hex4 = new String[width][height];
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
rgb = newPD.getPixelData(img, i, j);
for (int k = 0; k < rgb.length; k++) {
pixelData[count][k] = rgb[k];
// img_hex2[i][j] = newPD.getHexa2();
// img_hex4[i][j] = newPD.getHexa4();
}
img_hex2[i][j] = newPD.getHexa2(); // the code runs and
// stops here
img_hex4[i][j] = newPD.getHexa4();
System.out.println("Output: " + img_hex2[i][j]);
System.out.println("Output: " + img_hex4[i][j]);
count++;
System.out.println("\nRGB Counts: " + count);
}
}
int width2 = img2.getWidth();
int height2 = img2.getHeight();
System.out.println("Image's Width: " + width2);
System.out.println("Image's Height: " + height2);
int[][] pixelData2 = new int[width2 * height2][3];
System.out.println("Pixel Data: " + pixelData2);
int[] rgb2;
int counter = 0;
img2_hex2 = new String[width2][height2];
img2_hex4 = new String[width2][height2];
for (int i = 0; i < width2; i++) {
for (int j = 0; j < height2; j++) {
rgb2 = newPD.getPixelData(img2, i, j);
for (int k = 0; k < rgb2.length; k++) {
pixelData2[counter][k] = rgb2[k];
}
img2_hex2[i][j] = newPD.getHexa2();
img2_hex4[i][j] = newPD.getHexa4();
counter++;
System.out.println("\nRGB2 Counts: " + counter);
}
}
} catch (FileNotFoundException ex) {
Logger.getLogger(getPixelRGB1.class.getName()).log(Level.SEVERE,
null, ex);
} finally {
try {
image.close();
} catch (IOException ex) {
Logger.getLogger(getPixelRGB1.class.getName()).log(
Level.SEVERE, null, ex);
}
}
hexRGB.check();
}
public String[][] display_imgHex2() {
return img_hex2;
}
public String[][] display_imgHex4() {
return img_hex4;
}
public String[][] display_img2Hex2() {
return img2_hex2;
}
public String[][] display_img2Hex4() {
return img2_hex4;
}
}
One possible cause is the four uninitialized variables at the top.
private static String[][] img_hex2;
private static String[][] img_hex4;
private static String[][] img2_hex2;
private static String[][] img2_hex4;
The above four variables are accessed without allocating any memory.
A quick fix is to initialize them before the two for loops that use them.
img_hex2 = new String[width][height];
img_hex4 = new String[width][height];
for(int i=0; i<width; i++)
{
for(int j=0; j<height; j++)
{
.....
img2_hex2 = new String[width2][height2];
img2_hex4 = new String[width2][height2];;
for(int i=0; i<width2; i++)
{
for(int j=0; j<height2; j++
I am utilizing ImageIO.read(). The class which is called by the main method of the original App is this:
import java.awt.*;
import javax.swing.*;
import java.io.File;
import java.awt.image.BufferedImage;
import java.awt.event.*;
import javax.swing.JPanel;
class ImageGenerator extends JPanel{
JpegReader jpeg;
public ImageGenerator(Aplicacion a){
jpeg = new JpegReader();
loadImage();
}
private void loadImage(){
String path = "C:\\image.jpg";
image = new BufferedImage(100,100, BufferedImage.TYPE_INT_RGB); //in case error
try{
image = jpeg.readImage(new File(path));
}catch(Exception e){
System.err.println(e.getMessage());
}
}
public void paint(Graphics g){
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2.drawImage(image, 0, 0, 1000, 800, null);
}
}
I am using the above in conjunction with this other class JpegReader, which I actually found on StackOverflow as an answer, but I forgot the name of the author to quote him.
import java.awt.image.BufferedImage;
import javax.imageio.*;
import javax.imageio.stream.ImageInputStream;
import java.awt.color.*;
import java.awt.image.*;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.ArrayList;
import org.apache.sanselan.Sanselan;
import org.apache.sanselan.common.byteSources.ByteSource;
import org.apache.sanselan.common.byteSources.ByteSourceFile;
import org.apache.sanselan.ImageReadException;
import org.apache.sanselan.formats.jpeg.JpegImageParser;
import org.apache.sanselan.formats.jpeg.segments.UnknownSegment;
public class JpegReader {
public static final int COLOR_TYPE_RGB = 1;
public static final int COLOR_TYPE_CMYK = 2;
public static final int COLOR_TYPE_YCCK = 3;
private int colorType = COLOR_TYPE_RGB;
private boolean hasAdobeMarker = false;
public BufferedImage readImage(File file) throws IOException, ImageReadException {
colorType = COLOR_TYPE_RGB;
hasAdobeMarker = false;
ImageInputStream stream = ImageIO.createImageInputStream(file);
Iterator<ImageReader> iter = ImageIO.getImageReaders(stream);
while (iter.hasNext()) {
ImageReader reader = iter.next();
reader.setInput(stream);
BufferedImage image;
ICC_Profile profile = null;
try {
image = reader.read(0);
} catch (IIOException e) {
System.out.println("Hello");
colorType = COLOR_TYPE_CMYK;
checkAdobeMarker(file);
profile = Sanselan.getICCProfile(file);
WritableRaster raster = (WritableRaster) reader.readRaster(0, null);
if (colorType == COLOR_TYPE_YCCK)
convertYcckToCmyk(raster);
if (hasAdobeMarker)
convertInvertedColors(raster);
image = convertCmykToRgb(raster, profile);
System.out.println("Hello");
}finally {
try {
System.out.println("facebook");
stream.close();
} catch (IOException ioex) {
//omitted.
}
}
return image;
}
return null;
}
public void checkAdobeMarker(File file) throws IOException, ImageReadException {
JpegImageParser parser = new JpegImageParser();
ByteSource byteSource = new ByteSourceFile(file);
#SuppressWarnings("rawtypes")
ArrayList segments = parser.readSegments(byteSource, new int[] { 0xffee }, true);
if (segments != null && segments.size() >= 1) {
UnknownSegment app14Segment = (UnknownSegment) segments.get(0);
byte[] data = app14Segment.bytes;
if (data.length >= 12 && data[0] == 'A' && data[1] == 'd' && data[2] == 'o' && data[3] == 'b' && data[4] == 'e')
{
hasAdobeMarker = true;
int transform = app14Segment.bytes[11] & 0xff;
if (transform == 2)
colorType = COLOR_TYPE_YCCK;
}
}
}
public static void convertYcckToCmyk(WritableRaster raster) {
int height = raster.getHeight();
int width = raster.getWidth();
int stride = width * 4;
int[] pixelRow = new int[stride];
for (int h = 0; h < height; h++) {
raster.getPixels(0, h, width, 1, pixelRow);
for (int x = 0; x < stride; x += 4) {
int y = pixelRow[x];
int cb = pixelRow[x + 1];
int cr = pixelRow[x + 2];
int c = (int) (y + 1.402 * cr - 178.956);
int m = (int) (y - 0.34414 * cb - 0.71414 * cr + 135.95984);
y = (int) (y + 1.772 * cb - 226.316);
if (c < 0) c = 0; else if (c > 255) c = 255;
if (m < 0) m = 0; else if (m > 255) m = 255;
if (y < 0) y = 0; else if (y > 255) y = 255;
pixelRow[x] = 255 - c;
pixelRow[x + 1] = 255 - m;
pixelRow[x + 2] = 255 - y;
}
raster.setPixels(0, h, width, 1, pixelRow);
}
}
public static void convertInvertedColors(WritableRaster raster) {
int height = raster.getHeight();
int width = raster.getWidth();
int stride = width * 4;
int[] pixelRow = new int[stride];
for (int h = 0; h < height; h++) {
raster.getPixels(0, h, width, 1, pixelRow);
for (int x = 0; x < stride; x++)
pixelRow[x] = 255 - pixelRow[x];
raster.setPixels(0, h, width, 1, pixelRow);
}
}
public static BufferedImage convertCmykToRgb(Raster cmykRaster, ICC_Profile cmykProfile) throws IOException {
if (cmykProfile == null)
cmykProfile = ICC_Profile.getInstance(JpegReader.class.getResourceAsStream("/ISOcoated_v2_300_eci.icc"));
if (cmykProfile.getProfileClass() != ICC_Profile.CLASS_DISPLAY) {
byte[] profileData = cmykProfile.getData();
if (profileData[ICC_Profile.icHdrRenderingIntent] == ICC_Profile.icPerceptual) {
intToBigEndian(ICC_Profile.icSigDisplayClass, profileData, ICC_Profile.icHdrDeviceClass); // Header is first
cmykProfile = ICC_Profile.getInstance(profileData);
}
}
ICC_ColorSpace cmykCS = new ICC_ColorSpace(cmykProfile);
BufferedImage rgbImage = new BufferedImage(cmykRaster.getWidth(), cmykRaster.getHeight(), BufferedImage.TYPE_INT_RGB);
WritableRaster rgbRaster = rgbImage.getRaster();
ColorSpace rgbCS = rgbImage.getColorModel().getColorSpace();
ColorConvertOp cmykToRgb = new ColorConvertOp(cmykCS, rgbCS, null);
cmykToRgb.filter(cmykRaster, rgbRaster);
return rgbImage;
}
static void intToBigEndian(int value, byte[] array, int index) {
array[index] = (byte) (value >> 24);
array[index+1] = (byte) (value >> 16);
array[index+2] = (byte) (value >> 8);
array[index+3] = (byte) (value);
}
}
I am using sanselan-0.97-incubator.jar.
If I run this program 31 times approximately, I will get a java heap space error, so I suspect I have a memory leak.
Please help me find the memory leak or suggest how to fix the issue.
Also let me know if the jar file I'm using is OKAY, or maybe it's outdated. I had some issues locating a sanselan jar file.
Thanks in advance.
I have got the same memory issue with this code (JPEGReader). After a few trials, I found that calling reader.dispose() can solve this issue.
I give the method that I have modified. Hope it is helpful to you.
public BufferedImage readImage(File file) throws IOException, ImageReadException {
colorType = COLOR_TYPE_RGB;
hasAdobeMarker = false;
ImageInputStream stream = ImageIO.createImageInputStream(file);
try{
Iterator<ImageReader> iter = ImageIO.getImageReaders(stream);
while (iter.hasNext()) {
ImageReader reader = iter.next();
reader.setInput(stream);
BufferedImage image;
ICC_Profile profile = null;
try {
image = reader.read(0);
} catch (IIOException e) {
colorType = COLOR_TYPE_CMYK;
checkAdobeMarker(file);
profile = Sanselan.getICCProfile(file);
WritableRaster raster = (WritableRaster) reader.readRaster(0, null);
if (colorType == COLOR_TYPE_YCCK)
convertYcckToCmyk(raster);
if (hasAdobeMarker)
convertInvertedColors(raster);
image = convertCmykToRgb(raster, profile);
return image;
}
finally {
reader.dispose();
}
}
return null;
}
finally {
if (stream != null){
stream.close();
}
}
}