java圖片轉字符畫

java圖片轉字符畫

先來效果圖,如下

將圖片轉換爲字符畫

思路:讀取圖片,圖片灰化,根據色彩程度選擇對應的字符,按照座標創建圖片並將字符畫上去

成品圖

代碼結構圖

MainGUI是程序入口,beautyeye_Inf.jar是界面主題jar包,可不需要,gifdecoder.jar是處理gif動態圖的jar包,網上不好找,但是可以找到對應的代碼,自行打包成jar,請見:

https://blog.csdn.net/rico_zhou/article/details/81301566

代碼

MainGUI

package mainGUI;

import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import javax.imageio.ImageIO;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileSystemView;
import javax.swing.plaf.FontUIResource;

import org.jb2011.lnf.beautyeye.BeautyEyeLNFHelper;

import controller.CharImgController;
import utils.ImageUtils;

public class MainGUI extends JFrame implements ActionListener {
	public JPanel jp1;
	public JLabel jlb1, jlb2, jlb3, jlb4, jlb5, jlb6, jlb7, jlb8, jlb9, jlb10;
	public JButton button1, button2, button3, button4;
	public SwingWorker<ReturnMsg, String> sw1;
	private JComboBox jcb1, jcb2, jcb3, jcb4, jcb5;
	public JRadioButton jrb1, jrb2;
	public ButtonGroup bg1;
	public JTextField tt1, tt2, tt3, tt4, tt5, tt6, tt7;
	public JFileChooser jfc1, jfc2;
	public File file;
	public BufferedImage bi1, bi2;
	public static int numImage = 0;
	public ImageUtils iu = new ImageUtils();
	private static boolean isRunning;
	public CharImgController cic = new CharImgController();
	public ReturnMsg f;
	// 是否是gif
	public boolean isGif;
	// gif圖片集合
	public List<BufferedImage> list = new ArrayList<BufferedImage>();
	// 縮放後集合
	public List<BufferedImage> list2 = new ArrayList<BufferedImage>();
	public List<Integer> list3 = new ArrayList<Integer>();
	public GifMsg gm = new GifMsg();

	public MainGUI() {
		// 初始化主題
		initTheme();
		// 初始化界面
		init();
	}

	private void initTheme() {
		// 國人牛逼主題,值得學習
		// 初始化字體
		InitGlobalFont(new Font("微軟雅黑", Font.PLAIN, 13));
		// 設置本屬性將改變窗口邊框樣式定義
		// 系統默認樣式 osLookAndFeelDecorated
		// 強立體半透明 translucencyAppleLike
		// 弱立體感半透明 translucencySmallShadow
		// 普通不透明 generalNoTranslucencyShadow
		BeautyEyeLNFHelper.frameBorderStyle = BeautyEyeLNFHelper.FrameBorderStyle.generalNoTranslucencyShadow;
		// 設置主題爲BeautyEye
		try {
			org.jb2011.lnf.beautyeye.BeautyEyeLNFHelper.launchBeautyEyeLNF();
		} catch (Exception e) {
			e.printStackTrace();
		}
		// 隱藏“設置”按鈕
		UIManager.put("RootPane.setupButtonVisible", false);
		// 開啓/關閉窗口在不活動時的半透明效果
		// 設置此開關量爲false即表示關閉之,BeautyEye LNF中默認是true
		BeautyEyeLNFHelper.translucencyAtFrameInactive = false;
		// 設置BeantuEye外觀下JTabbedPane的左縮進
		// 改變InsetsUIResource參數的值即可實現
		UIManager.put("TabbedPane.tabAreaInsets", new javax.swing.plaf.InsetsUIResource(3, 20, 2, 20));
		//

		// 切換主題,此主題在圓形窗口有標題欄

		try {
			// UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// font
	private static void InitGlobalFont(Font font) {
		FontUIResource fontRes = new FontUIResource(font);
		for (Enumeration<Object> keys = UIManager.getDefaults().keys(); keys.hasMoreElements();) {
			Object key = keys.nextElement();
			Object value = UIManager.get(key);
			if (value instanceof FontUIResource) {
				UIManager.put(key, fontRes);
			}
		}
	}

	// 主方法
	public static void main(String[] args) {
		// 線程啓動截圖主程序
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				new MainGUI();
			}
		});
	}

	private void init() {
		// 初始化面板
		jp1 = new JPanel();
		jp1.setLayout(null);

		// 基本設置
		jlb1 = new JLabel("基本設置:");
		jlb1.setBounds(20, 10, 80, 25);
		jp1.add(jlb1);

		jlb2 = new JLabel("縮放圖片大小:");
		jlb2.setBounds(47, 40, 100, 25);
		jp1.add(jlb2);

		String[] sfImage = { "原圖尺寸", "100x100", "200x200", "300x300", "400x400", "500x500", "自定義" };
		jcb1 = new JComboBox(sfImage);
		// 設置默認顯示值
		jcb1.setSelectedIndex(0);
		jp1.add(jcb1);
		jcb1.setBounds(140, 40, 100, 25);

		tt1 = new JTextField();
		tt1.setBounds(250, 40, 60, 25);
		jp1.add(tt1);
		tt1.setVisible(false);

		jlb3 = new JLabel("x");
		jlb3.setBounds(317, 40, 10, 25);
		jp1.add(jlb3);
		jlb3.setVisible(false);

		tt2 = new JTextField();
		tt2.setBounds(330, 40, 60, 25);
		jp1.add(tt2);
		tt2.setVisible(false);

		jcb1.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				// 自定義
				if (jcb1.getSelectedIndex() == sfImage.length - 1) {
					tt1.setVisible(true);
					jlb3.setVisible(true);
					tt2.setVisible(true);
				} else {
					tt1.setVisible(false);
					jlb3.setVisible(false);
					tt2.setVisible(false);
				}
			}
		});

		jlb4 = new JLabel("生成圖片大小:");
		jlb4.setBounds(47, 70, 100, 25);
		jp1.add(jlb4);

		String[] createImage = { "原圖尺寸", "100x100", "200x200", "300x300", "400x400", "500x500", "自定義" };
		jcb2 = new JComboBox(createImage);
		// 設置默認顯示值
		jcb2.setSelectedIndex(0);
		jp1.add(jcb2);
		jcb2.setBounds(140, 70, 100, 25);

		tt3 = new JTextField();
		tt3.setBounds(250, 70, 60, 25);
		jp1.add(tt3);
		tt3.setVisible(false);

		jlb5 = new JLabel("x");
		jlb5.setBounds(317, 70, 10, 25);
		jp1.add(jlb5);
		jlb5.setVisible(false);

		tt4 = new JTextField();
		tt4.setBounds(330, 70, 60, 25);
		jp1.add(tt4);
		tt4.setVisible(false);

		jcb2.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				// 自定義
				if (jcb2.getSelectedIndex() == createImage.length - 1) {
					tt3.setVisible(true);
					jlb5.setVisible(true);
					tt4.setVisible(true);
				} else {
					tt3.setVisible(false);
					jlb5.setVisible(false);
					tt4.setVisible(false);
				}
			}
		});

		jlb6 = new JLabel("字符畫字符集:");
		jlb6.setBounds(47, 100, 100, 25);
		jp1.add(jlb6);

		String[] customChar = { "默認字符", "8@#&$%*o!;.", "自定義" };
		jcb3 = new JComboBox(customChar);
		// 設置默認顯示值
		jcb3.setSelectedIndex(0);
		jp1.add(jcb3);
		jcb3.setBounds(140, 100, 100, 25);

		tt5 = new JTextField();
		tt5.setBounds(250, 100, 60, 25);
		jp1.add(tt5);
		tt5.setVisible(false);

		jlb7 = new JLabel("(左->右 = 複雜->簡單)");
		jlb7.setBounds(315, 100, 170, 25);
		jp1.add(jlb7);
		jlb7.setVisible(false);

		jcb3.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				// 自定義
				if (jcb3.getSelectedIndex() == customChar.length - 1) {
					tt5.setVisible(true);
					jlb7.setVisible(true);
				} else {
					tt5.setVisible(false);
					jlb7.setVisible(false);
				}
			}
		});

		jlb8 = new JLabel("選擇字符大小:");
		jlb8.setBounds(47, 130, 100, 25);
		jp1.add(jlb8);

		String[] charSize = { "自適應", "10", "12", "14", "16", "18", "20", "自定義" };
		jcb4 = new JComboBox(charSize);
		// 設置默認顯示值
		jcb4.setSelectedIndex(0);
		jp1.add(jcb4);
		jcb4.setBounds(140, 130, 100, 25);

		tt6 = new JTextField();
		tt6.setBounds(250, 130, 60, 25);
		jp1.add(tt6);
		tt6.setVisible(false);

		jcb4.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				// 自定義
				if (jcb4.getSelectedIndex() == charSize.length - 1) {
					tt6.setVisible(true);
				} else {
					tt6.setVisible(false);
				}
			}
		});

		// 密集度
		jlb10 = new JLabel("字符密集度:");
		jlb10.setBounds(318, 130, 100, 25);
		jp1.add(jlb10);

		String[] imgIntensity = { "1", "2", "3", "4", "5" };
		jcb5 = new JComboBox(imgIntensity);
		// 設置默認顯示值
		jcb5.setSelectedIndex(0);
		jp1.add(jcb5);
		jcb5.setBounds(395, 130, 70, 25);

		button1 = new JButton("選擇圖片");
		button1.setBounds(30, 170, 80, 30);
		button1.addActionListener(this);
		jp1.add(button1);

		button2 = new JButton("生成圖片");
		button2.setBounds(150, 170, 80, 30);
		button2.addActionListener(this);
		button2.setEnabled(false);
		jp1.add(button2);

		button3 = new JButton("另存圖片");
		button3.setBounds(270, 170, 80, 30);
		button3.addActionListener(this);
		button3.setEnabled(false);
		jp1.add(button3);

		button4 = new JButton("下載文本");
		button4.setBounds(390, 170, 80, 30);
		button4.setEnabled(false);
		button4.addActionListener(this);
		jp1.add(button4);

		jlb9 = new JLabel("", SwingConstants.CENTER);
		jlb9.setBounds(30, 210, 440, 450);
		jp1.add(jlb9);

		jfc1 = new JFileChooser();
		jp1.add(jfc1);

		this.add(jp1);
		this.setTitle("字符畫生成器");
		this.setSize(500, 715);
		this.setLocationRelativeTo(null);
		this.setVisible(true);
		this.setResizable(false);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		ImageIcon imageIcon = new ImageIcon(getClass().getResource("img2.png"));
		this.setIconImage(imageIcon.getImage());
		// 監聽界面關閉事件
		this.addWindowListener(new WindowAdapter() {
			// 當關閉時
			public void windowClosing(WindowEvent e) {

			}
		});
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		// 監聽選擇文件夾按鈕
		if (e.getSource().equals(button1)) {// 判斷觸發方法的按鈕是哪個
			jfc1.setFileSelectionMode(0);// 設定選擇到文件
			jfc1.setFileFilter(new FileCanChoose());
			int state = jfc1.showOpenDialog(this);// 此句是打開文件選擇器界面的觸發語句
			if (state == 1) {
				return;
			} else {
				file = jfc1.getSelectedFile();// f爲選擇到的文件
				// 判斷是否是動態圖
				Timer timer = new Timer();
				if (file.getName().endsWith(".gif") || file.getName().endsWith(".GIF")) {
					isGif = true;
					list.clear();
					list2.clear();
					// 讀取並拆分gif
					gm = iu.splitGif(file.getAbsolutePath());
					list = gm.getList();
					// 延遲時間
					list3 = gm.getList2();
					int time = (list3.size() > 0 && list3 != null) ? list3.get(0) : 300;
					// 縮放圖片組
					for (BufferedImage bi : list) {
						list2.add(iu.zoomImage(bi, 440, 450));
					}
					// thread = new CountThread();
					// thread.start();

					timer.scheduleAtFixedRate(new TimerTask() {
						int i = 0;

						public void run() {
							if (list2.size() > 0 && list2.get(i) != null) {
								if (numImage != 0) {
									// 移除之前的圖片
									jlb9.setText("");
								}
								numImage++;
								jlb9.setIcon(new ImageIcon(list2.get(i)));
								i++;
								if (i > list2.size() - 1) {
									i = 0;
								}
							}
						}
					}, time, time);
					// 輪播圖片組模擬gif

					// 每100ms執行一次,1000ms重新執行
					button2.setEnabled(true);
				} else {
					isGif = false;
					if (timer != null) {
						System.out.println(2);
						timer.cancel();
						jlb9.setText("");
					}
					list.clear();
					list2.clear();
					// 縮放圖片
					bi1 = iu.zoomImage(file.getAbsolutePath(), 440, 450, null);
					if (bi1 != null) {
						if (numImage != 0) {
							// 移除之前的圖片
							jlb9.setText("");
						}
						numImage++;
						jlb9.setIcon(new ImageIcon(bi1));
						button2.setEnabled(true);
					} else {
						JOptionPane.showMessageDialog(null, "加載圖片失敗!請重試!", "提示消息", JOptionPane.WARNING_MESSAGE);
					}
				}
			}
		}

		// 監聽生成圖片
		if (e.getSource().equals(button2)) {
			// get params
			CharImgParams cip = getCharImgPra();
			// check
			int flag = checkParams(cip);
			if (flag == 0) {
				// 轉換參數
				CharImgParams2 cip2 = iu.turnPro(cip);
				button1.setEnabled(false);
				button2.setEnabled(false);
				button3.setEnabled(false);
				button4.setEnabled(false);

				// start times
				MainGUI.isRunning = true;

				sw1 = new SwingWorker<ReturnMsg, String>() {
					// 此方法是耗時任務
					@Override
					protected ReturnMsg doInBackground() throws Exception {
						f = cic.charImgController(cip2);
						return f;
					}

					// done
					protected void done() {
						ReturnMsg f = null;
						try {
							f = get();
						} catch (Exception e) {
							e.printStackTrace();
						}
						if (f != null && f.isSucc) {
							// 顯示在一個窗口
							if (!isGif) {
								ShowImgJF sij = new ShowImgJF(f.getBi());
							} else {
								ShowImgJF sij = new ShowImgJF(f.getList(), f.getList4());
							}
						} else {
							JOptionPane.showMessageDialog(null, "創建字符畫失敗!", "提示消息", JOptionPane.WARNING_MESSAGE);
						}
						button1.setEnabled(true);
						button2.setEnabled(true);
						button3.setEnabled(true);
						button4.setEnabled(true);
					}
				};
				sw1.execute();
			} else if (flag == 1) {
				JOptionPane.showMessageDialog(null, "不能爲空!請重新填寫!", "提示消息", JOptionPane.WARNING_MESSAGE);
			} else if (flag == 2) {
				JOptionPane.showMessageDialog(null, "數字格式不正確!請重新填寫!", "提示消息", JOptionPane.WARNING_MESSAGE);
			} else if (flag == 3) {
				JOptionPane.showMessageDialog(null, "字符集超長!請重新填寫!", "提示消息", JOptionPane.WARNING_MESSAGE);
			}
		}

		// 監聽另存圖片
		if (e.getSource().equals(button3) || e.getSource().equals(button4)) {
			if (f != null && f.isSucc()) {
				// 打開文件夾
				// 接收文件
				JFileChooser chooser = new JFileChooser();
				// 設定只能選擇到文件夾
//				chooser.setFileSelectionMode(1);
				chooser.setDialogTitle("保存文件框");
				// 默認文件名稱還有放在當前目錄下
				
				// 保存路徑
				SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
				String fileName = sdf.format(new Date());
				if (e.getSource().equals(button3)) {
					if (isGif) {
						fileName = sdf.format(new Date()) + ".gif";
					} else {
						fileName = sdf.format(new Date()) + ".jpg";
					}
				} else if (e.getSource().equals(button4)) {
					fileName = sdf.format(new Date()) + ".txt";
				}
				File filePath = FileSystemView.getFileSystemView().getHomeDirectory();
				File defaultFile = new File(filePath + File.separator + fileName);
				chooser.setSelectedFile(defaultFile);
				int s = chooser.showSaveDialog(this);
				String saveFilePath = chooser.getSelectedFile().getPath();
				if (s == 1) {
					return;
				} else {
					try {
						if (e.getSource().equals(button3)) {
							if (isGif) {
								// 生成動態圖
								iu.jpgToGif(f.getList(), f.getList4(), saveFilePath);
							} else {
								ImageIO.write(f.getBi(),
										fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length()),
										new File(saveFilePath));
							}
						} else if (e.getSource().equals(button4)) {
							if (isGif) {
								// 動態圖全部輸出(時間戳+"_"+延遲時間+後綴123+文件格式)
								String pathName = null;
								Writer out = null;
								for (int i = 0; i < f.getList3().size(); i++) {
									pathName = saveFilePath.substring(0, saveFilePath.length() - 4) + "_"
											+ f.getList4().get(i) + "_" + i + ".txt";
									out = new FileWriter(new File(pathName));
									out.write(f.getList3().get(i).getTextImg());
									out.close();
								}

							} else {
								Writer out = new FileWriter(new File(saveFilePath));
								out.write(f.getTextImg());
								out.close();
							}
						}
						JOptionPane.showMessageDialog(null, "保存成功!", "提示消息", JOptionPane.WARNING_MESSAGE);
					} catch (Exception e1) {
						JOptionPane.showMessageDialog(null, "保存失敗!請重試!", "提示消息", JOptionPane.WARNING_MESSAGE);
						e1.printStackTrace();
					}
				}
			} else {
				JOptionPane.showMessageDialog(null, "保存失敗!請重試!", "提示消息", JOptionPane.WARNING_MESSAGE);
			}

		}

	}

	// 校驗參數
	private int checkParams(CharImgParams cip) {
		// 不能爲空
		if ("".equals(cip.getSfImgSizeW()) || "".equals(cip.getSfImgSizeH()) || "".equals(cip.getCreateImgSizeW())
				|| "".equals(cip.getCreateImgSizeH()) || "".equals(cip.getCharArray())
				|| "".equals(cip.getCharSize())) {
			return 1;
		}
		// 數字校驗
		if (!cip.getSfImgSizeW().matches("^[0-9]*$") || cip.getSfImgSizeW().length() > 8
				|| !cip.getSfImgSizeH().matches("^[0-9]*$") || cip.getSfImgSizeH().length() > 8
				|| !cip.getCreateImgSizeW().matches("^[0-9]*$") || cip.getCreateImgSizeW().length() > 8
				|| !cip.getCreateImgSizeH().matches("^[0-9]*$") || cip.getCreateImgSizeH().length() > 8
				|| !cip.getCharSize().matches("^[0-9]*$") || cip.getCharSize().length() > 8) {

			return 2;
		}
		// 字符校驗
		if (cip.getCharArray().length() > 15) {
			return 3;
		}
		return 0;
	}

	// 獲取參數
	private CharImgParams getCharImgPra() {
		CharImgParams cip = new CharImgParams();
		// 縮放圖片大小
		if (jcb1.getSelectedIndex() == 0) {
			// 原尺寸
			cip.setSfImgSizeW("0");
			cip.setSfImgSizeH("0");
		} else if (jcb1.getSelectedIndex() == jcb1.getItemCount() - 1) {
			// 最後是自定義
			cip.setSfImgSizeW(tt1.getText().trim());
			cip.setSfImgSizeH(tt2.getText().trim());
		} else {
			String[] s = jcb1.getSelectedItem().toString().replaceAll(" ", "").split("x");
			cip.setSfImgSizeW(s[0]);
			cip.setSfImgSizeH(s[1]);
		}

		// 生成圖片的大小
		if (jcb2.getSelectedIndex() == 0) {
			// 原尺寸
			cip.setCreateImgSizeW("0");
			cip.setCreateImgSizeH("0");
		} else if (jcb2.getSelectedIndex() == jcb2.getItemCount() - 1) {
			// 最後是自定義
			cip.setCreateImgSizeW(tt3.getText().trim());
			cip.setCreateImgSizeH(tt4.getText().trim());
		} else {
			String[] s = jcb2.getSelectedItem().toString().replaceAll(" ", "").split("x");
			cip.setCreateImgSizeW(s[0]);
			cip.setCreateImgSizeH(s[1]);
		}
		// 獲取字符集
		if (jcb3.getSelectedIndex() == 0) {
			// 默認
			cip.setCharArray("8@#&$%*o!;.");
		} else if (jcb3.getSelectedIndex() == jcb3.getItemCount() - 1) {
			// 最後是自定義
			cip.setCharArray(tt5.getText().trim());
		} else {
			cip.setCharArray(jcb3.getSelectedItem().toString().trim());
		}

		// 獲取字符大小
		if (jcb4.getSelectedIndex() == 0) {
			// 默認
			cip.setCharSize("10");
		} else if (jcb4.getSelectedIndex() == jcb4.getItemCount() - 1) {
			// 最後是自定義
			cip.setCharSize(tt6.getText().trim());
		} else {
			cip.setCharSize(jcb4.getSelectedIndex() * 2 + 8 + "");
		}
		// 獲取文件地址
		cip.setGif(isGif);
		if (isGif) {
			cip.setList(list2);
			cip.setList3(list3);
		} else {
			cip.setFilePath(file.getAbsolutePath());
		}
		// 字符密集度
		cip.setImgIntensity(jcb5.getSelectedIndex() + 1);
		return cip;
	}

	// 文件過濾器
	class FileCanChoose extends FileFilter {
		public boolean accept(File file) {
			String name = file.getName();
			return (name.toLowerCase().endsWith(".jpg") || name.toLowerCase().endsWith(".bmp")
					|| name.toLowerCase().endsWith(".png") || name.toLowerCase().endsWith(".jpeg")
					|| name.toLowerCase().endsWith(".gif") || file.isDirectory());
		}

		@Override
		public String getDescription() {
			return "圖片文件:*.jpg、 *.bmp、 *.png、 *.jpeg、 *.gif";
		}
	}

}

CharImgController

package controller;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;

import mainGUI.CImgPro;
import mainGUI.CharImgParams;
import mainGUI.CharImgParams2;
import mainGUI.ReturnMsg;
import utils.ImageUtils;

public class CharImgController {
	public ImageUtils iu = new ImageUtils();

	// 控制類
	public ReturnMsg charImgController(CharImgParams2 cip2) {
		if (cip2.isGif()) {
			return charImgController2(cip2);
		} else {
			ReturnMsg f = new ReturnMsg();
			// 獲取圖片
			BufferedImage image = iu.getImage(cip2.getFilePath());
			if (image == null) {
				f.setSucc(false);
				return f;
			}
			// 對獲取的圖片進行縮放
			if (cip2.getSfImgSizeW() != 0) {
				try {
					image = iu.zoom2(image, cip2.getSfImgSizeW(), cip2.getSfImgSizeH());
				} catch (Exception e) {
					e.printStackTrace();
				}
			}

			// 創建一個緩存圖片用於寫入字符
			int w = image.getWidth();
			int h = image.getHeight();
			if (cip2.getCreateImgSizeW() != 0) {
				w = cip2.getCreateImgSizeW();
				h = cip2.getCreateImgSizeH();
			}
			BufferedImage createImg = iu.createBufferedImage(w, h);
			// 處理下字體
			int fontSize = 10;
			if (cip2.getCharSize() == 0) {
				// 如果自適應的話
				// 先不處理
				fontSize = 10;
			} else {
				fontSize = cip2.getCharSize();
			}

			// 生成
			CImgPro cp = iu.createAsciiPic(image, createImg, cip2.getCharArray(), fontSize, cip2.getImgIntensity());
			f.setBi(cp.getBi());
			f.setTextImg(cp.getTextImg());
			f.setSucc(true);
			return f;
		}
	}

	// 單獨處理gif
	private ReturnMsg charImgController2(CharImgParams2 cip2) {
		ReturnMsg f = new ReturnMsg();
		List<BufferedImage> list = new ArrayList<BufferedImage>();
		List<BufferedImage> list2 = new ArrayList<BufferedImage>();
		// 對獲取的圖片進行縮放
		if (cip2.getSfImgSizeW() != 0) {
			try {
				for (BufferedImage bi : cip2.getList()) {
					list.add(iu.zoom2(bi, cip2.getSfImgSizeW(), cip2.getSfImgSizeH()));
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		// 創建一個緩存圖片用於寫入字符
		int w = list.get(0).getWidth();
		int h = list.get(0).getHeight();
		if (cip2.getCreateImgSizeW() != 0) {
			w = cip2.getCreateImgSizeW();
			h = cip2.getCreateImgSizeH();
		}
		for (int i = 0; i < list.size(); i++) {
			list2.add(iu.createBufferedImage(w, h));
		}
		// 處理下字體
		int fontSize = 10;
		if (cip2.getCharSize() == 0) {
			// 如果自適應的話
			// 先不處理
			fontSize = 10;
		} else {
			fontSize = cip2.getCharSize();
		}

		// 生成
		List<CImgPro> list3 = new ArrayList<CImgPro>();
		for (int i = 0; i < list2.size(); i++) {
			list3.add(iu.createAsciiPic(list.get(i), list2.get(i), cip2.getCharArray(), fontSize,
					cip2.getImgIntensity()));
		}
		// 直接返回動態圖組
		f.setList(list2);
		f.setList3(list3);
		f.setList4(cip2.getList3());
		f.setSucc(true);
		return f;
	}
}

ImageUtils

package utils;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import javax.imageio.ImageIO;

import gifdecoder.AnimatedGifEncoder;
import gifdecoder.GifDecoder;
import mainGUI.CImgPro;
import mainGUI.CharImgParams;
import mainGUI.CharImgParams2;
import mainGUI.GifMsg;

public class ImageUtils {

	// 縮放gif
	public BufferedImage zoomImage(BufferedImage bufImg, int jpwidth, int jpheight) {
		return zoomImage(null, jpwidth, jpheight, bufImg);
	}

	// 縮放圖片
	public BufferedImage zoomImage(String absolutePath, int jpwidth, int jpheight, BufferedImage bufImg) {
		double wr = 0, hr = 0;
		if (absolutePath != null) {
			File srcFile = new File(absolutePath);
			bufImg = null;
			try {
				bufImg = ImageIO.read(srcFile);
			} catch (IOException e) {
				e.printStackTrace();
				return null;
			}
		}

		int w = bufImg.getWidth();
		int h = bufImg.getHeight();
		int[] wh = proImage(w, h, jpwidth, jpheight);

		Image Itemp = bufImg.getScaledInstance(wh[0], wh[1], bufImg.SCALE_SMOOTH);
		wr = wh[0] * 1.0 / bufImg.getWidth();
		hr = wh[1] * 1.0 / bufImg.getHeight();
		AffineTransformOp ato = new AffineTransformOp(AffineTransform.getScaleInstance(wr, hr), null);
		Itemp = ato.filter(bufImg, null);
		return (BufferedImage) Itemp;
	}

	private int[] proImage(int w, int h, int jpwidth, int jpheight) {
		// 判斷大小
		// 先以寬爲縮放準則
		if (jpwidth * h / w <= jpheight) {
			// 如果高不超過
			return new int[] { jpwidth, jpwidth * h / w };
		} else {
			// 如果高超過了
			// 則以高爲準則
			if (w * jpheight / h <= jpwidth) {
				return new int[] { w * jpheight / h, jpheight };
			} else {
				return null;
			}
		}
	}

	// 轉換參數
	public CharImgParams2 turnPro(CharImgParams cip) {
		CharImgParams2 cip2 = new CharImgParams2();
		if (cip != null) {
			cip2.setSfImgSizeW(Integer.valueOf(cip.getSfImgSizeW()));
			cip2.setSfImgSizeH(Integer.valueOf(cip.getSfImgSizeH()));
			cip2.setCreateImgSizeW(Integer.valueOf(cip.getCreateImgSizeW()));
			cip2.setCreateImgSizeH(Integer.valueOf(cip.getCreateImgSizeH()));
			cip2.setCharSize(Integer.valueOf(cip.getCharSize()));
			cip2.setCharArray(cip.getCharArray());
			cip2.setGif(cip.isGif());
			if (cip.isGif()) {
				cip2.setList(cip.getList());
				cip2.setList3(cip.getList3());
			} else {
				cip2.setFilePath(cip.getFilePath());
			}
			cip2.setImgIntensity(cip.getImgIntensity());
		}

		return cip2;
	}

	// 獲取圖片
	public BufferedImage getImage(String filePath) {
		File f = new File(filePath);
		BufferedImage image;
		if (f.exists()) {
			try {
				image = ImageIO.read(f);
			} catch (IOException e) {
				e.printStackTrace();
				return null;
			}
		} else {
			return null;
		}
		return image;
	}

	// 另外一種壓縮
	public BufferedImage zoom(BufferedImage bimg, int w, int h) throws IOException {
		int height = bimg.getHeight();
		int width = bimg.getWidth();
		BufferedImage bi = new BufferedImage(w, height * h / width, BufferedImage.TYPE_BYTE_GRAY);

		Graphics g = bi.getGraphics();
		g.drawImage(bimg, 0, 0, w, height * h / width, null);
		g.dispose();

		return bi;
	}

	// 縮放圖片
	public BufferedImage zoom2(BufferedImage bufImg, int jpwidth, int jpheight) {
		double wr = 0, hr = 0;

		Image Itemp = bufImg.getScaledInstance(jpwidth, jpheight, bufImg.SCALE_SMOOTH);
		wr = jpwidth * 1.0 / bufImg.getWidth();
		hr = jpheight * 1.0 / bufImg.getHeight();
		AffineTransformOp ato = new AffineTransformOp(AffineTransform.getScaleInstance(wr, hr), null);
		Itemp = ato.filter(bufImg, null);
		return (BufferedImage) Itemp;
	}

	// 創建一個緩衝圖片
	public BufferedImage createBufferedImage(int w, int h) {
		BufferedImage image2 = new BufferedImage(w, h, BufferedImage.TYPE_INT_BGR);
		Graphics g = image2.createGraphics();
		// 背景色
		g.setColor(Color.WHITE);
		// 背景
		g.fillRect(0, 0, w, h);
		// 前景色
		g.setColor(Color.BLACK);
		return image2;
	}

	// 創建字符畫
	public CImgPro createAsciiPic(BufferedImage image, BufferedImage createImg, String charText, int fontSize,
			int imgIntensity) {
		CImgPro cp = new CImgPro();
		StringBuilder sb = new StringBuilder();
		// 字符串由複雜到簡單
		String base = "8@#&$%*o!;.";
		if (charText != null && !"".equals(charText)) {
			base = charText;
		}
		try {
			int w = image.getWidth();
			int h = image.getHeight();
			int ww = createImg.getWidth();
			int hh = createImg.getHeight();
			double xc = (double) (ww / w);
			double yc = (double) (hh / h);
			Graphics g2 = createGraphics(createImg);
			// 設置字體
			g2.setFont(new Font("微軟雅黑", Font.PLAIN, fontSize));
			for (int y = 0; y < image.getHeight(); y += imgIntensity) {
				for (int x = 0; x < image.getWidth(); x += imgIntensity) {
					int pixel = image.getRGB(x, y);
					int r = (pixel & 0xff0000) >> 16, g = (pixel & 0xff00) >> 8, b = pixel & 0xff;
					float gray = 0.299f * r + 0.578f * g + 0.114f * b;
					int index = Math.round(gray * (base.length() + 1) / 255);
					sb.append(index >= base.length() ? " " : String.valueOf(base.charAt(index)));
					g2.drawString(index >= base.length() ? " " : String.valueOf(base.charAt(index)),
							(int) ((x + 1) * xc), (int) ((y + 1) * yc));
				}
				sb.append("\r\n");
			}
			cp.setBi(createImg);
			cp.setTextImg(sb.toString());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return cp;
	}

	private Graphics createGraphics(BufferedImage createImg) {
		Graphics g = createImg.createGraphics();
		g.setColor(Color.WHITE); // 設置背景色
		g.fillRect(0, 0, createImg.getWidth(), createImg.getHeight());// 繪製背景
		g.setColor(Color.BLACK); // 設置前景色
		return g;
	}

	// 拆分gif
	public GifMsg splitGif(String gifName) {
		GifMsg gm = new GifMsg();
		List<BufferedImage> list = new ArrayList<BufferedImage>();
		List<Integer> list2 = new ArrayList<Integer>();
		try {
			GifDecoder decoder = new GifDecoder();
			decoder.read(gifName);
			// 個數
			int n = decoder.getFrameCount();

			for (int i = 0; i < n; i++) {
				BufferedImage frame = decoder.getFrame(i);
				list2.add(decoder.getDelay(i));
				list.add(frame);
				// ImageIO.write(frame, "jpg", new File(i + ".jpg"));
			}
			gm.setList(list);
			gm.setList2(list2);
			return gm;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return gm;
	}

	// 合成gif
	public void jpgToGif(List<BufferedImage> list, List<Integer> list2, String newPicPath) {
		try {
			// 實例化處理對象
			AnimatedGifEncoder e = new AnimatedGifEncoder();
			e.setRepeat(0);
			e.start(newPicPath);
			for (int i = 0; i < list.size(); i++) {
				// 設置播放的延遲時間
				e.setDelay(list2.get(i));
				// 添加到幀中
				e.addFrame(list.get(i));
			}
			e.finish();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

其他代碼請見源碼

效果圖

源碼GitHub:https://github.com/ricozhou/imgtochar1.0

發佈了56 篇原創文章 · 獲贊 42 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章