1 package charactermanaj.graphics.io;
\r
3 import java.awt.Color;
\r
4 import java.awt.Graphics2D;
\r
5 import java.awt.event.ActionEvent;
\r
6 import java.awt.event.ActionListener;
\r
7 import java.awt.image.BufferedImage;
\r
8 import java.io.BufferedOutputStream;
\r
10 import java.io.FileOutputStream;
\r
11 import java.io.IOException;
\r
12 import java.util.Properties;
\r
13 import java.util.logging.Level;
\r
14 import java.util.logging.Logger;
\r
16 import javax.imageio.IIOImage;
\r
17 import javax.imageio.ImageIO;
\r
18 import javax.imageio.ImageReadParam;
\r
19 import javax.imageio.ImageReader;
\r
20 import javax.imageio.ImageWriteParam;
\r
21 import javax.imageio.ImageWriter;
\r
22 import javax.imageio.event.IIOWriteWarningListener;
\r
23 import javax.imageio.stream.ImageInputStream;
\r
24 import javax.imageio.stream.ImageOutputStream;
\r
25 import javax.swing.JFileChooser;
\r
26 import javax.swing.JFrame;
\r
27 import javax.swing.JOptionPane;
\r
28 import javax.swing.filechooser.FileFilter;
\r
30 import charactermanaj.ui.UkagakaConvertDialog;
\r
31 import charactermanaj.util.LocalizedResourcePropertyLoader;
\r
38 public class UkagakaImageSaveHelper {
\r
43 private static final Logger logger = Logger.getLogger(UkagakaImageSaveHelper.class.getName());
\r
48 protected static final String STRINGS_RESOURCE = "languages/ukagakaImageSaveHelper";
\r
53 protected static final FileFilter pngFilter = new FileFilter() {
\r
55 public boolean accept(File f) {
\r
56 return f.isDirectory() || f.getName().endsWith(".png");
\r
59 public String getDescription() {
\r
60 return "PNG(*.png)";
\r
66 * まだ使用していなければnull.<br>
\r
68 protected File lastUseOpenDir;
\r
71 * 最後に保存したディレクトリ.<br>
\r
72 * まだ使用していなければnull.<br>
\r
74 protected File lastUseSaveDir;
\r
79 protected String lastUseSaveName = "surface";
\r
83 * まだ使用していなければnull.<br>
\r
85 protected Color transparentColorKey;
\r
90 protected boolean autoTransparentColor = true;
\r
95 public UkagakaImageSaveHelper() {
\r
96 Properties strings = LocalizedResourcePropertyLoader.getCachedInstance()
\r
97 .getLocalizedProperties(STRINGS_RESOURCE);
\r
99 lastUseSaveName = strings.getProperty("default.lastUseSaveName");
\r
102 protected JFileChooser createFileChooser(final boolean save) {
\r
103 JFileChooser fileChooser = new JFileChooser() {
\r
104 private static final long serialVersionUID = 1L;
\r
107 public void approveSelection() {
\r
108 File outFile = getSelectedFile();
\r
109 if (outFile == null) {
\r
113 String lcName = outFile.getName().toLowerCase();
\r
114 FileFilter selfilter = getFileFilter();
\r
115 if (selfilter == pngFilter) {
\r
116 if (!lcName.endsWith(".png")) {
\r
117 outFile = new File(outFile.getPath() + ".png");
\r
118 setSelectedFile(outFile);
\r
122 if (save && outFile.exists()) {
\r
123 Properties strings = LocalizedResourcePropertyLoader.getCachedInstance()
\r
124 .getLocalizedProperties(STRINGS_RESOURCE);
\r
126 if (JOptionPane.showConfirmDialog(this,
\r
127 strings.getProperty("confirmOverwrite"),
\r
128 strings.getProperty("confirm"),
\r
129 JOptionPane.YES_NO_OPTION,
\r
130 JOptionPane.WARNING_MESSAGE) != JOptionPane.YES_OPTION) {
\r
134 super.approveSelection();
\r
138 if (lastUseSaveDir != null) {
\r
139 fileChooser.setCurrentDirectory(lastUseSaveDir);
\r
142 fileChooser.setFileFilter(pngFilter);
\r
144 fileChooser.setAcceptAllFileFilterUsed(false);
\r
146 fileChooser.addChoosableFileFilter(pngFilter);
\r
148 return fileChooser;
\r
152 * 透過画像(TYPE_INT_ARGB)から、伺か用のPNG/PNAファイルに出力する.
\r
153 * @param parent 親フレーム
\r
154 * @param img 対象イメージ
\r
155 * @param colorKey マニュアル指定時の候補(前回のものを優先)
\r
156 * @throws IOException 出力に失敗した場合
\r
158 public void save(JFrame parent, BufferedImage img, Color colorKey) throws IOException {
\r
159 final UkagakaConvertDialog dlg = new UkagakaConvertDialog(parent);
\r
160 if (!autoTransparentColor && transparentColorKey != null) {
\r
161 // 前回マニュアル透過色キー指定であれば、それを使う.
\r
162 colorKey = transparentColorKey;
\r
164 dlg.setExportImage(img, colorKey);
\r
165 dlg.setAutoTransparentColor(autoTransparentColor);
\r
166 dlg.setSaveActionListener(new ActionListener() {
\r
167 public void actionPerformed(ActionEvent e) {
\r
168 JFileChooser fileChooser = createFileChooser(true);
\r
169 fileChooser.setSelectedFile(new File(lastUseSaveDir, lastUseSaveName));
\r
171 int ret = fileChooser.showSaveDialog(dlg);
\r
172 if (ret != JFileChooser.APPROVE_OPTION) {
\r
177 dlg.setResult(fileChooser.getSelectedFile());
\r
181 dlg.setVisible(true);
\r
183 File selectedFile = (File) dlg.getResult();
\r
184 if (selectedFile == null) {
\r
188 lastUseSaveName = selectedFile.getName();
\r
189 lastUseSaveDir = selectedFile.getParentFile();
\r
191 File pngFile = selectedFile;
\r
192 File pnaFile = makePNAFileName(pngFile);
\r
194 File[] outfiles = {pngFile, pnaFile};
\r
195 BufferedImage[] outimages = {
\r
196 dlg.getOpaqueImage(),
\r
197 dlg.getAlphaImage()
\r
200 savePNGImages(outfiles, outimages);
\r
204 * 複数のファイルとイメージを指定して書き込みます.<br>
\r
205 * ファイルとイメージの個数は一致していなければなりません.<br>
\r
206 * 同じ添え字のファイルに対して、その添え字のイメージが出力されます.<br>
\r
207 * いずれかで失敗した場合、その時点で処理は打ち切られて例外が返されます.<br>
\r
208 * (すでに出力されたファイル、もしくは書き込み中のファイルは放置されます.)<br>
\r
209 * @param outfiles ファイルの配列
\r
210 * @param outimages イメージの配列
\r
211 * @throws IOException 失敗
\r
213 protected void savePNGImages(File[] outfiles, BufferedImage[] outimages) throws IOException {
\r
214 if (outfiles == null || outimages == null) {
\r
215 throw new IllegalArgumentException("引数にnullは指定でまきせん。");
\r
217 if (outfiles.length != outimages.length) {
\r
218 throw new IllegalArgumentException("ファイルおよびイメージの個数は一致していなければなりません.");
\r
221 ImageWriter iw = ImageIO.getImageWritersByFormatName("png").next();
\r
223 iw.addIIOWriteWarningListener(new IIOWriteWarningListener() {
\r
224 public void warningOccurred(ImageWriter source, int imageIndex,
\r
226 logger.log(Level.WARNING, warning);
\r
230 for (int idx = 0; idx < outfiles.length; idx++) {
\r
231 File outfile = outfiles[idx];
\r
232 BufferedImage outimage = outimages[idx];
\r
234 BufferedOutputStream bos = new BufferedOutputStream(
\r
235 new FileOutputStream(outfile));
\r
237 ImageWriteParam iwp = iw.getDefaultWriteParam();
\r
238 IIOImage ioimg = new IIOImage(outimage, null, null);
\r
240 ImageOutputStream imgstm = ImageIO.createImageOutputStream(bos);
\r
242 iw.setOutput(imgstm);
\r
243 iw.write(null, ioimg, iwp);
\r
260 * 複数ファイルを指定して既存のファイルから伺かPNG/PNAに変換して出力する.(ユーテリティ)
\r
261 * @param parent 親フレーム
\r
262 * @param colorKey 透過色キー(候補)
\r
263 * @throws IOException 失敗
\r
265 public void convertChooseFiles(JFrame parent, Color colorKey) throws IOException {
\r
266 JFileChooser fileChooser = createFileChooser(false);
\r
267 fileChooser.setCurrentDirectory(lastUseOpenDir);
\r
268 fileChooser.setMultiSelectionEnabled(true);
\r
270 int ret = fileChooser.showOpenDialog(parent);
\r
271 if (ret != JFileChooser.APPROVE_OPTION) {
\r
275 // 選択したディレクトリを記憶する.
\r
276 File[] files = fileChooser.getSelectedFiles();
\r
277 if (files == null || files.length == 0) {
\r
280 lastUseOpenDir = files[0].getParentFile();
\r
282 final UkagakaConvertDialog dlg = new UkagakaConvertDialog(parent, null, true);
\r
283 if (!autoTransparentColor && transparentColorKey != null) {
\r
284 // 前回マニュアル透過色キー指定であれば、それを使う.
\r
285 colorKey = transparentColorKey;
\r
287 dlg.setAutoTransparentColor(autoTransparentColor);
\r
289 ImageReader ir = ImageIO.getImageReadersByFormatName("png").next();
\r
291 for (final File file : files) {
\r
292 String fname = file.getName();
\r
294 ImageReadParam param = ir.getDefaultReadParam();
\r
297 ImageInputStream iis = ImageIO.createImageInputStream(file);
\r
300 img = ir.read(0, param);
\r
306 img = convertIntARGB(img);
\r
308 dlg.setCaption(fname);
\r
309 dlg.setExportImage(img, colorKey);
\r
310 dlg.setSaveActionListener(new ActionListener() {
\r
311 public void actionPerformed(ActionEvent e) {
\r
312 if ( !dlg.isOverwriteOriginalFile()) {
\r
313 JFileChooser fileChooser = createFileChooser(true);
\r
314 fileChooser.setCurrentDirectory(file.getParentFile());
\r
315 fileChooser.setSelectedFile(file);
\r
317 int ret = fileChooser.showSaveDialog(dlg);
\r
318 if (ret != JFileChooser.APPROVE_OPTION) {
\r
323 dlg.setResult(fileChooser.getSelectedFile());
\r
327 dlg.setResult(file);
\r
333 dlg.setVisible(true);
\r
335 File selectedFile = (File) dlg.getResult();
\r
336 if (selectedFile == null) {
\r
341 File pngFile = selectedFile;
\r
342 File pnaFile = makePNAFileName(pngFile);
\r
344 File[] outfiles = {pngFile, pnaFile};
\r
345 BufferedImage[] outimages = {
\r
346 dlg.getOpaqueImage(),
\r
347 dlg.getAlphaImage()
\r
350 savePNGImages(outfiles, outimages);
\r
359 * BufferedImageをINT_TYPE_ARGBに設定する.<br>
\r
361 * @return 形式をINT_ARGBに変換されたイメージ
\r
363 protected BufferedImage convertIntARGB(BufferedImage img) {
\r
364 if (img == null || img.getType() == BufferedImage.TYPE_INT_ARGB) {
\r
365 // nullであるか、変換不要であれば、そのまま返す.
\r
369 int w = img.getWidth();
\r
370 int h = img.getHeight();
\r
372 BufferedImage dst = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
\r
373 Graphics2D g = dst.createGraphics();
\r
375 g.drawImage(img, 0, 0, w, h, 0, 0, w, h, null);
\r
387 * @param pngFile PNGファイル名
\r
390 protected File makePNAFileName(File pngFile) {
\r
391 if (pngFile == null) {
\r
394 String fname = pngFile.getName();
\r
395 int extpos = fname.lastIndexOf('.');
\r
397 fname = fname.substring(0, extpos);
\r
400 return new File(pngFile.getParent(), fname);
\r