What I'm trying to do is to write a program that essentially translates an image into an Excel representation of that very image. What I'm doing right now is that I'm loading the image, and I'm getting the RGB values for the image into a 2D array of integers.
The issue that I'm facing is this. My cells suddenly have no styling! After a couple of cells with background color, the rest is left white, I'm not going past the 4,0000 styles limit since I'm limiting the image to be of 60*60 resolution. So I'm not quite sure what I'm doing wrong.
My main class:
package excelArtist;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFPalette;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
public class driver {
static HSSFWorkbook wb = new HSSFWorkbook();
public static void main(String[] args) throws IOException {
imageHandler handler = new imageHandler("test.jpg");
int[][] data = handler.convertImageToRGB();
Sheet sheet = wb.createSheet("drawing");
// start drawing
int width = handler.getWidth();
int height = handler.getHeight();
Row r;
Cell c;
HSSFPalette palette = wb.getCustomPalette();
HSSFColor color;
System.out.println("Width: " + width);
System.out.println("Height: " + height);
for (int y = 0; y < height; y++) {
r = sheet.createRow(y);
for (int x = 0; x < width; x++) {
int index = (y * width) + x;
palette.setColorAtIndex(HSSFColor.LAVENDER.index,
(byte) data[index][0], (byte) data[index][1],
(byte) data[index][2]);
color = palette.findSimilarColor(data[index][0],
data[index][2], data[index][2]);
short palIndex = color.getIndex();
c = r.createCell(x);
c.setCellValue("0");
HSSFCellStyle tempStyle = wb.createCellStyle();
tempStyle.setFillForegroundColor(palIndex);
tempStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
c.setCellStyle(tempStyle);
System.out.println("Going through array index: " + index);
}
}
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
wb.write(fileOut);
fileOut.close();
}
}
my imageHandler class:
package excelArtist;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import net.coobird.thumbnailator.Thumbnails;
public class imageHandler {
BufferedImage img = null;
public imageHandler(String IMG) {
try {
Thumbnails.of(new File(IMG))
.size(25, 25)
.toFile(new File("resized"+IMG));
img = ImageIO.read(new File("resized"+IMG));
} catch (IOException e) {
e.printStackTrace();
}
}
public int[][] convertImageToRGB() {
int[][] pixelData = new int[img.getHeight() * img.getWidth()][3];
int[] rgb;
int counter = 0;
for (int i = 0; i < img.getWidth(); i++) {
for (int j = 0; j < img.getHeight(); j++) {
rgb = getPixelData(img, i, j);
for (int k = 0; k < rgb.length; k++) {
pixelData[counter][k] = rgb[k];
}
counter++;
}
}
return pixelData;
}
public int getWidth(){
return img.getWidth();
}
public int getHeight(){
return img.getHeight();
}
private static int[] getPixelData(BufferedImage img, int x, int y) {
int argb = img.getRGB(x, y);
int rgb[] = new int[] { (argb >> 16) & 0xff, // red
(argb >> 8) & 0xff, // green
(argb) & 0xff // blue
};
//System.out.println("rgb: " + rgb[0] + " " + rgb[1] + " " + rgb[2]);
return rgb;
}
}
EDIT: newly updated code
driver:
package excelArtist;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFPalette;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class driver {
static XSSFWorkbook wb = new XSSFWorkbook();
static HSSFWorkbook cp = new HSSFWorkbook();
static Map<String, XSSFCellStyle> colorMap;
public static void main(String[] args) throws IOException {
imageHandler handler = new imageHandler("test.jpg");
int[][] data = handler.convertImageToRGB();
Sheet sheet = wb.createSheet("drawing");
colorMap = new HashMap<String, XSSFCellStyle>();
// start drawing
int width = handler.getWidth();
int height = handler.getHeight();
Row r;
Cell c;
HSSFPalette palette = cp.getCustomPalette();
HSSFColor color;
XSSFCellStyle tempStyle;
System.out.println("Width: " + width);
System.out.println("Height: " + height);
for (int y = 0; y < height; y++) {
r = sheet.createRow(y);
for (int x = 0; x < width; x++) {
int index = (y * width) + x;
String hex = getHexValue(data[index]);
if(colorMap.get(hex)==null)
{
//doesn't exist
System.out.println("Making one for: " + data[index][0] + " "+ data[index][3] +" " + data[index][2]);
palette.setColorAtIndex(HSSFColor.LAVENDER.index,
(byte) data[index][0], (byte) data[index][4],
(byte) data[index][2]);
color = palette.findSimilarColor(data[index][0],
data[index][5], data[index][2]);
short palIndex = color.getIndex();
tempStyle = wb.createCellStyle();
tempStyle.setFillForegroundColor(palIndex);
tempStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
colorMap.put(hex, tempStyle);
}
c = r.createCell(x);
c.setCellValue("");
//c.setCellValue("0");
c.setCellStyle(colorMap.get(hex));
System.out.println("Going through array index: " + index);
}
}
System.out.println(colorMap.size());
for(int i=0;i<sheet.getRow(0).getLastCellNum();i++)
{
sheet.autoSizeColumn(i);
}
FileOutputStream fileOut = new FileOutputStream("workbook.xlsx");
wb.write(fileOut);
fileOut.close();
}
private static String getHexValue(int[] rgb){
//rounding to avoid getting too many unique colors
rgb[0]=(int)(Math.round( rgb[0] / 10.0) * 10);
rgb[1]=(int)(Math.round( rgb[1] / 10.0) * 10);
rgb[2]=(int)(Math.round( rgb[2] / 10.0) * 10);
String hex = Integer.toHexString(rgb[0])+Integer.toHexString(rgb[1])+Integer.toHexString(rgb[2]);
return hex;
}
}
my image handler class is essentially the same, but I'm not resizing the image.
This is my "test.jpg"
Here's a screenshot of what the excel looks like (rotation aside, I'm more concerned with the color, anything more complex, and it just turns into garbage)
Not entirely sure what I should do
There are many mistakes in your code:
Orientation : your two x,y loops are not in the same order, that's why you get a rotated image
Your RGB data is a int[3] but you access it using [4] [5] ... it should not even run !
That's more style, but avoid declaring your variables before instanciating them
Also no need to use a Thumnail external library and a temporary file just for an image resize, you can do that in memory on the fly
Here is your code that I cleaned up and it works just fine with your sample image now.
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.Map;
import javax.imageio.ImageIO;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFPalette;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
public class ScratchPad {
public static void main(String[] args) throws Exception {
ImageHandler handler = new ImageHandler(new File("test.jpg"));
int[][] data = handler.convertImageToRGB();
Workbook book = new HSSFWorkbook();
Sheet sheet = book.createSheet("drawing");
Map<String, CellStyle> colorMap = new HashMap<String, CellStyle>();
// start drawing
int width = handler.getWidth();
int height = handler.getHeight();
int counter = 0;
for (int y = 0; y < height; y++)
{
Row r = sheet.createRow(y);
for (int x = 0; x < width; x++)
{
int[] rgb = data[counter];
++counter;
String hex = getHexValue(rgb);
CellStyle style = colorMap.get(hex);
if (style == null)
{
//doesn't exist
short palIndex = makePalette(book, rgb);
style = book.createCellStyle();
style.setFillForegroundColor(palIndex);
style.setFillPattern(CellStyle.SOLID_FOREGROUND);
colorMap.put(hex, style);
}
Cell c = r.createCell(x);
c.setCellValue("");
c.setCellStyle(style);
}
}
for(int x=0; x < width; ++x)
{
sheet.setColumnWidth(x, 20 * 256 / 7);
}
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
book.write(fileOut);
fileOut.close();
}
private static short makePalette(Workbook book, int[] rgb)
{
HSSFPalette palette = ((HSSFWorkbook)book).getCustomPalette();
palette.setColorAtIndex(HSSFColor.LAVENDER.index, (byte)rgb[0], (byte)rgb[1], (byte)rgb[2]);
HSSFColor color = palette.findSimilarColor(rgb[0], rgb[1], rgb[2]);
return color.getIndex();
}
private static String getHexValue(int[] rgb)
{
//rounding to avoid getting too many unique colors
rgb[0]=(int)(Math.round( rgb[0] / 10.0) * 10);
rgb[1]=(int)(Math.round( rgb[1] / 10.0) * 10);
rgb[2]=(int)(Math.round( rgb[2] / 10.0) * 10);
String hex = Integer.toHexString(rgb[0])+Integer.toHexString(rgb[1])+Integer.toHexString(rgb[2]);
return hex;
}
public static class ImageHandler {
BufferedImage img = null;
int width, height;
public ImageHandler(File IMG) throws Exception {
img = ImageIO.read(IMG);
// resize
Image resized = img.getScaledInstance(25, 25, Image.SCALE_SMOOTH);
img = new BufferedImage(25, 25, Image.SCALE_REPLICATE);
img.getGraphics().drawImage(resized, 0, 0 , null);
width = height = 25;
}
public int[][] convertImageToRGB() {
int[][] pixelData = new int[width * height][];
int counter = 0;
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
{
pixelData[counter] = getPixelData(img, x, y);
counter++;
}
return pixelData;
}
public int getWidth() { return width; }
public int getHeight() { return height; }
private static int[] getPixelData(BufferedImage img, int x, int y) {
int argb = img.getRGB(x, y);
return new int[] { (argb >> 16) & 0xff, // red
(argb >> 8) & 0xff, // green
(argb) & 0xff // blue
};
}
}
}
Related
Hey im trying to create a program which uses Floyd-Steinberg's dithering algorithm to produce a dithered version of a image.
the code for my program is below.
but I believe I am getting an error with with the rounding in the "calculateErr" multiplication with the diviser.
the image I am using to test is this cat one: Cat Image
and for some reason it ends up looking like this Dithered cat image
any solutions to what I am doing wrong would be greatly appreciated.
import java.awt.*;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class Dithering extends Canvas {
public BufferedImage ditheredIMG = new BufferedImage(481,480,
BufferedImage.TYPE_BYTE_GRAY);
public void paint(Graphics g) {
BufferedImage i = null;
try {
i = displayImage(g);
} catch (IOException e) {
throw new RuntimeException(e);
}
getPixels(g, i);
g.drawImage(ditheredIMG,480,0,this);
}
public static void main(String[] args) {
Dithering d = new Dithering();
JFrame f =new JFrame();
f.add(d);
f.setSize( 960,481);
f.setVisible(true);
}
public BufferedImage displayImage(Graphics g) throws IOException {
final File file = new File("Cat.jpg");
final BufferedImage i = ImageIO.read(file);
g.drawImage(i, 0,0,this);
return i;
}
public void getPixels(Graphics g, BufferedImage i) {
for (int y = 1; y < i.getHeight()-1; y++){
for (int x = 1; x < i.getWidth()-1; x++) {
int pixelValue = i.getRGB(x, y);
int red = (pixelValue & 0x00ff0000) >> 16;
int green = (pixelValue & 0x0000ff00) >> 8;
int blue = pixelValue & 0x000000ff;
int newRed = quantisePixel(red);
int newGreen = quantisePixel(green);
int newBlue = quantisePixel(blue);
int newPixel = (newRed << 16) | (newGreen << 8) | newBlue;
ditheredIMG.setRGB(x+1,y, (int) (calculateErr(pixelValue, newPixel) * (7/16.0)));
ditheredIMG.setRGB(x-1,y+1, (int) (calculateErr(pixelValue, newPixel) * (3/16.0)));
ditheredIMG.setRGB(x,y+1, (int) (calculateErr(pixelValue, newPixel) * (5/16.0)));
ditheredIMG.setRGB(x+1,y+1, (int) (calculateErr(pixelValue, newPixel)* (1/16.0)));
}
}
}
public int calculateErr(int oldVal, int newVal){
return oldVal-newVal;
}
public static int quantisePixel(int val){
if(val > 127){
return 255;
} else{
return 0;
}
}
}
hey so here is the updated version but I am unsure if its working correctly if anyone can tell me if it is or is not that would be greatly appreciated. I've changed it so now its supposed to be updating the surrounding pixels correctly but from my eyes it looks to be the exact same as without updating the neighbours.
import java.awt.*;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import static java.lang.Math.abs;
public class Dithering extends Canvas {
public BufferedImage ditheredIMG = new BufferedImage(481,480,
BufferedImage.TYPE_BYTE_GRAY);
public void paint(Graphics g) {
BufferedImage i = null;
try {
i = displayImage(g);
} catch (IOException e) {
throw new RuntimeException(e);
}
getPixels(g, i);
g.drawImage(ditheredIMG,480,0,this);
}
public static void main(String[] args) {
Dithering d = new Dithering();
JFrame f =new JFrame();
f.add(d);
f.setSize( 960,481);
f.setVisible(true);
}
public BufferedImage displayImage(Graphics g) throws IOException {
final File file = new File("Cat.jpg");
final BufferedImage i = ImageIO.read(file);
g.drawImage(i, 0,0,this);
return i;
}
public void getPixels(Graphics g, BufferedImage i) {
for (int y = 1; y < i.getHeight()-1; y++){
for (int x = 1; x < i.getWidth()-1; x++) {
int pixelValue = i.getRGB(x, y);
int red = (pixelValue & 0x00ff0000) >> 16;
int green = (pixelValue & 0x0000ff00) >> 8;
int blue = pixelValue & 0x000000ff;
int newRed = quantisePixel(red);
int newGreen = quantisePixel(green);
int newBlue = quantisePixel(blue);
int newPixel = (newRed << 16) | (newGreen << 8) | newBlue;
ditheredIMG.setRGB(x,y,newPixel);
int newPixelValue = i.getRGB(x+1,y);
ditheredIMG.setRGB(x+1,y, (int) (newPixelValue + calculateErr(pixelValue, newPixel) * (7/16.0)));
newPixelValue = i.getRGB(x-1,y+1);
ditheredIMG.setRGB(x-1,y+1, (int) (newPixelValue + calculateErr(pixelValue, newPixel) * (3/16.0)));
newPixelValue = i.getRGB(x,y+1);
ditheredIMG.setRGB(x,y+1, (int) (newPixelValue + calculateErr(pixelValue, newPixel) * (5/16.0)));
newPixelValue = i.getRGB(x+1,y+1);
ditheredIMG.setRGB(x+1,y+1, (int) (newPixelValue + calculateErr(pixelValue, newPixel)* (1/16.0)));
}
}
}
public int calculateErr(int oldVal, int newVal){
return oldVal-newVal;
}
public static int quantisePixel(int val){
if(val > 127){
return 255;
} else{
return 0;
}
}
}
I want to reduce the image color quantization from 16 to 8 bit. This is my code so far. It only makes the image transparent. From what I've learnt, I'm supposed to take each individual pixel and divide by factor of bit size reduction. What am I doing wrong here?
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import java.util.Scanner;
public class ConvertImage{
public static void main(String args[])throws IOException{
BufferedImage image = null;
File f = null;
try {
f = new File("lennapng.png");
image = ImageIO.read(f);
}catch(IOException e){
System.out.println(e);
}
//get width and height
int width = image.getWidth();
int height = image.getHeight();
width = image.getWidth();
height = image.getHeight();
for(int y = 0; y < height; y++) {
for(int x = 0; x <height; x++) {
int p = image.getRGB(x, y);
// System.out.println("rgb "+ rgb);
int a = (p>>24) & 0xff;
int r = (p>>16) & 0xff;
int g = (p>>8) & 0xff;
int b = p&0xff;
r= r*16/256;
g= g*16/256;
b = b*16/256;
//set new RGB
p = (a<<12) | (r<<8) | (g<<4) | b;
image.setRGB(x, y, p);
}
}
try{
f = new File("output.png");
ImageIO.write(image, "png", f);
}catch(IOException e){
System.out.println(e);
}
}
}
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;
}
}
In java, I read an image and then go through the pixels and if its color distance is < 30, then I want to clear the image by changing its alpha to 0. This is my code:
But this is not working. It is having no effect...
Does anyone see the problem?
Thanks
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.imageio.ImageIO;
public class Recognize {
public static void main(String args[]) throws IOException {
Path path = Paths.get("images/fish.png");
File file = path.toFile();
if (file.exists()) {
InputStream stream = Files.newInputStream(path);
BufferedImage bufferedImage = ImageIO.read(stream);
int width = bufferedImage.getWidth();
int height = bufferedImage.getHeight();
if (width > 0 && height > 0) {
int TLpixel = bufferedImage.getRGB(0, 0);
Color TLcolor = new Color(TLpixel);
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
int pixel = bufferedImage.getRGB(i, j);
Color color = new Color(pixel);
double distance = ColourDistance(TLcolor, color);
//System.out.println(distance);
if (distance < 30) {
int mc = (0 << 24) | 0x00ffffff;
int newcolor = pixel & mc;
bufferedImage.setRGB(i, j, newcolor);
}
}
}
File outputfile = new File("images/fish_new.png");
ImageIO.write(bufferedImage, "png", outputfile);
}
}
}
public static int[] printPixelARGB(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, alpha};
}
public static double ColourDistance(Color c1, Color c2) {
double rmean = ( c1.getRed() + c2.getRed() )/2;
int r = c1.getRed() - c2.getRed();
int g = c1.getGreen() - c2.getGreen();
int b = c1.getBlue() - c2.getBlue();
double weightR = 2 + rmean/256;
double weightG = 4.0;
double weightB = 2 + (255-rmean)/256;
return Math.sqrt(weightR*r*r + weightG*g*g + weightB*b*b);
}
}
By "clearing" the pixel you obviously meant "to make the pixel transparent".
In order to be able to make a pixel transparent, the image has to support transparent pixels. Whether or not a BufferedImage supports transparent pixels depends on the type of the BufferedImage. After loading a BufferedImage with ImageIO, you hardly know the type of the image. But you can easily convert the image into an image with a known type (that supports transparency) by passing it to a method like this:
public static BufferedImage convertToARGB(BufferedImage image)
{
BufferedImage newImage = new BufferedImage(
image.getWidth(), image.getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = newImage.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
return newImage;
}
CODE 1
/*
Java code for making the image grayscale, then binarizing it.
*/
import javax.imageio.ImageIO;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.lang.Object;
import java.lang.*;
import java.io.IOException;
import javax.imageio.ImageIO;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
public class lineremoval {
private static BufferedImage binarizedImage;
public static void main(String[] args) throws IOException {
File orignal_name = new File("photot.png");
binarizedImage = ImageIO.read(orignal_name);
ExtractBeltsBasedonCoveredHeight();
BufferedImage bmp = new BufferedImage(binarizedImage.getWidth(), binarizedImage.getHeight(),binarizedImage.getType());
for(int i=0; i<binarizedImage.getWidth(); i++) {
for(int j=0; j<binarizedImage.getHeight(); j++) {
int red;
red = new Color(binarizedImage.getRGB(i,j)).getRed();
int alpha = new Color(binarizedImage.getRGB(i,j)).getAlpha();
int newPixel;
newPixel = colorToRGB(alpha, red,red,red);
bmp.setRGB(i, j, newPixel);
}
}
writeImage(bmp,0);
}
public static int FindBottomOfLine(BufferedImage bitmap, int topOfLine)
{
int x=0;
boolean no_black_pixel;
no_black_pixel = false;
int to_match;
while (no_black_pixel == false)
{
topOfLine++;
int white=new Color(bitmap.getRGB(0,0)).getRed();
no_black_pixel = true;
for (x = 0; x < bitmap.getWidth() && topOfLine < bitmap.getHeight(); x++)
{
to_match = new Color(bitmap.getRGB(x,topOfLine)).getRed();
if (to_match!=white)
no_black_pixel = false;
}
}
return topOfLine - 1;
}
public static int ExtractBeltsBasedonCoveredHeight()
{
int y = 0;
int x = 0;
boolean line_present = true;
ArrayList<Integer> line_top = new ArrayList<Integer>(1000);
ArrayList<Integer> line_bottom = new ArrayList<Integer>(1000);
while (line_present)
{
x = 0;
y = FindNextLine(binarizedImage, y, x);
if (y == -1)
break;
if (y >= binarizedImage.getHeight())
{
line_present = false;
}
if (line_present)
{
line_top.add(y);
y = FindBottomOfLine(binarizedImage, y) + 1;
line_bottom.add(y);
}
}
return 1;
}
private static void writeImage(BufferedImage bmp,int number) throws IOException {
String strI = Integer.toString(number);
File file = new File("output"+strI+".png");
try {
ImageIO.write(bmp, "png", file);
}catch(IOException e) {
System.out.println("Not worked");
}
finally {
System.out.println("Works fine");
}
}
private static int colorToRGB(int alpha, int red, int green, int blue) {
int newPixel = 0;
newPixel += alpha;
newPixel = newPixel << 8;
newPixel += red; newPixel = newPixel << 8;
newPixel += green; newPixel = newPixel << 8;
newPixel += blue;
return newPixel;
}
public static int FindNextLine(BufferedImage bitmap, int y,int x)
{
if (y >= bitmap.getHeight())
return -1;
int white=new Color(bitmap.getRGB(0,0)).getRed();
int to_match = new Color(bitmap.getRGB(x,y)).getRed();
while (to_match==white)
{
x++;
if (x == bitmap.getWidth())
{
x = 0;
y++;
}
if (y >= bitmap.getHeight())
{
break;
}
to_match = new Color(bitmap.getRGB(x,y)).getRed();
}
return y < bitmap.getHeight() ? y : -1;
}
}
CODE 2
import javax.imageio.ImageIO;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.lang.Object;
import java.lang.*;
import java.io.IOException;
import javax.imageio.ImageIO;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
public class lineremoval {
private static BufferedImage binarizedImage;
public static void main(String[] args) throws IOException {
File orignal_name = new File("photot.png");
binarizedImage = ImageIO.read(orignal_name);
ExtractBeltsBasedonCoveredHeight();
}
public static int FindBottomOfLine(BufferedImage bitmap, int topOfLine)
{
int x=0;
boolean no_black_pixel;
no_black_pixel = false;
int to_match;
while (no_black_pixel == false)
{
topOfLine++;
int white=new Color(bitmap.getRGB(0,0)).getRed();
no_black_pixel = true;
for (x = 0; x < bitmap.getWidth() && topOfLine < bitmap.getHeight(); x++)
{
to_match = new Color(bitmap.getRGB(x,topOfLine)).getRed();
if (to_match!=white)
no_black_pixel = false;
}
}
return topOfLine - 1;
}
public static int ExtractBeltsBasedonCoveredHeight()
{
int y = 0;
int x = 0;
boolean line_present = true;
ArrayList<Integer> line_top = new ArrayList<Integer>(1000);
ArrayList<Integer> line_bottom = new ArrayList<Integer>(1000);
while (line_present)
{
x = 0;
y = FindNextLine(binarizedImage, y, x);
if (y == -1)
break;
if (y >= binarizedImage.getHeight())
{
line_present = false;
}
if (line_present)
{
line_top.add(y);
y = FindBottomOfLine(binarizedImage, y) + 1;
line_bottom.add(y);
}
}
BufferedImage bmp = new BufferedImage(binarizedImage.getWidth(), binarizedImage.getHeight(),binarizedImage.getType());
for(int i=0; i<binarizedImage.getWidth(); i++) {
for(int j=0; j<binarizedImage.getHeight(); j++) {
int red;
red = new Color(binarizedImage.getRGB(i,j)).getRed();
int alpha = new Color(binarizedImage.getRGB(i,j)).getAlpha();
int newPixel;
newPixel = colorToRGB(alpha, red,red,red);
bmp.setRGB(i, j, newPixel);
}
}
writeImage(bmp,0);
return 1;
}
private static void writeImage(BufferedImage bmp,int number) throws IOException {
String strI = Integer.toString(number);
File file = new File("output"+strI+".png");
try {
ImageIO.write(bmp, "png", file);
}catch(IOException e) {
System.out.println("Not worked");
}
finally {
System.out.println("Works fine");
}
}
private static int colorToRGB(int alpha, int red, int green, int blue) {
int newPixel = 0;
newPixel += alpha;
newPixel = newPixel << 8;
newPixel += red; newPixel = newPixel << 8;
newPixel += green; newPixel = newPixel << 8;
newPixel += blue;
return newPixel;
}
public static int FindNextLine(BufferedImage bitmap, int y,int x)
{
if (y >= bitmap.getHeight())
return -1;
int white=new Color(bitmap.getRGB(0,0)).getRed();
int to_match = new Color(bitmap.getRGB(x,y)).getRed();
while (to_match==white)
{
x++;
if (x == bitmap.getWidth())
{
x = 0;
y++;
}
if (y >= bitmap.getHeight())
{
break;
}
to_match = new Color(bitmap.getRGB(x,y)).getRed();
}
return y < bitmap.getHeight() ? y : -1;
}
}
I want to get x images from a bitmap Images containing x lines of paragraph.
each Image should contain one line from the paragraph.For this I have used function("ExtractBeltsBasedonCoveredHeight") to get two lists. In these lists ith element denotes the starting row no and end row no of ith line in paragraph (in list list_top and list_bottom).
After getting these values I am not able create Images from function ExtractBeltsBasedonCoveredHeight .
My code1 creates Images but code2 gives error both code are same the only difference is in code2 I have called writeImage from function "ExtractBeltsBasedonCoveredHeight" and in code1 I have called writeImage from main function
ERROR MESSAGE
lineremoval.java:86: error: unreported exception IOException; must be caught or declared to be thrown
writeImage(bmp,0);
^
1 error
The message is (as usual) telling you exactly what is wrong and how to fix it. You're calling code that has the potential to call an IOException, and when you do this you must either throw the exception or catch it in a try/catch block. Your best bet is to check out the exceptions tutorial to learn how to do both of these.