我正在尝试将图像转换为文本程序,将0-255值转换为与其匹配的字符(可视化)。这里重要的是让所有字符具有相同的宽度,因此在文本编辑器中文本是方形的......
基本上我希望32-4000的所有字符都具有与'X'相同的宽度,所以我可以使用'Q'而不是'|' (这个字体是单声道,所以没有区别)
我使用的是Unifont字体。
我目前的工作原理,但我想提供一般范围的大小相同的unicode字符(所以最后在文本中看起来不错)
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)));
}
这段代码工作得很好,但我仍然会在文本编辑器中获得宽度较小的'ȷ'字符,但根据字体指标被视为与'X'相同的宽度(我使用的是Courier new)这是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;
}
}