OSDN Git Service

dmg作成バージョンの取得方法の修正
[charactermanaj/CharacterManaJ.git] / src / main / java / charactermanaj / graphics / io / UkagakaImageSaveHelper.java
1 package charactermanaj.graphics.io;\r
2 \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
9 import java.io.File;\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
15 \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
29 \r
30 import charactermanaj.ui.UkagakaConvertDialog;\r
31 import charactermanaj.util.LocalizedResourcePropertyLoader;\r
32 \r
33 /**\r
34  * 伺か用PNG/PNA出力ヘルパ.\r
35  * @author seraphy\r
36  *\r
37  */\r
38 public class UkagakaImageSaveHelper {\r
39         \r
40         /**\r
41          * ロガー\r
42          */\r
43         private static final Logger logger = Logger.getLogger(UkagakaImageSaveHelper.class.getName());\r
44 \r
45         /**\r
46          * リソース\r
47          */\r
48         protected static final String STRINGS_RESOURCE = "languages/ukagakaImageSaveHelper";\r
49 \r
50         /**\r
51          * PNGファイルフィルタ\r
52          */\r
53         protected static final FileFilter pngFilter = new FileFilter() {\r
54                 @Override\r
55                 public boolean accept(File f) {\r
56                         return f.isDirectory() || f.getName().endsWith(".png");\r
57                 }\r
58                 @Override\r
59                 public String getDescription() {\r
60                         return "PNG(*.png)";\r
61                 }\r
62         };\r
63 \r
64         /**\r
65          * 最後に開いたディレクトリ.<br>\r
66          * まだ使用していなければnull.<br>\r
67          */\r
68         protected File lastUseOpenDir;\r
69         \r
70         /**\r
71          * 最後に保存したディレクトリ.<br>\r
72          * まだ使用していなければnull.<br>\r
73          */\r
74         protected File lastUseSaveDir;\r
75         \r
76         /**\r
77          * 最後に保存したファイル名\r
78          */\r
79         protected String lastUseSaveName = "surface";\r
80 \r
81         /**\r
82          * 最後に使用した透過色キー.<br>\r
83          * まだ使用していなければnull.<br>\r
84          */\r
85         protected Color transparentColorKey;\r
86         \r
87         /**\r
88          * 最後に使用した透過色キーモード.\r
89          */\r
90         protected boolean autoTransparentColor = true;\r
91         \r
92         /**\r
93          * コンストラクタ\r
94          */\r
95         public UkagakaImageSaveHelper() {\r
96                 Properties strings = LocalizedResourcePropertyLoader.getCachedInstance()\r
97                         .getLocalizedProperties(STRINGS_RESOURCE);\r
98 \r
99                 lastUseSaveName = strings.getProperty("default.lastUseSaveName"); \r
100         }\r
101         \r
102         protected JFileChooser createFileChooser(final boolean save) {\r
103                 JFileChooser fileChooser = new JFileChooser() {\r
104                         private static final long serialVersionUID = 1L;\r
105 \r
106                         @Override\r
107                         public void approveSelection() {\r
108                                 File outFile = getSelectedFile();\r
109                                 if (outFile == null) {\r
110                                         return;\r
111                                 }\r
112                                 \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
119                                         }\r
120                                 }\r
121 \r
122                                 if (save && outFile.exists()) {\r
123                                         Properties strings = LocalizedResourcePropertyLoader.getCachedInstance()\r
124                                                 .getLocalizedProperties(STRINGS_RESOURCE);\r
125 \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
131                                                 return;\r
132                                         }\r
133                                 }\r
134                                 super.approveSelection();\r
135                         }\r
136                 };\r
137 \r
138                 if (lastUseSaveDir != null) {\r
139                         fileChooser.setCurrentDirectory(lastUseSaveDir);\r
140                 }\r
141                 \r
142                 fileChooser.setFileFilter(pngFilter);\r
143                 if ( !save) {\r
144                         fileChooser.setAcceptAllFileFilterUsed(false);\r
145                 }\r
146                 fileChooser.addChoosableFileFilter(pngFilter);\r
147                 \r
148                 return fileChooser;\r
149         }\r
150         \r
151         /**\r
152          * 透過画像(TYPE_INT_ARGB)から、伺か用のPNG/PNAファイルに出力する.\r
153          * @param parent 親フレーム\r
154          * @param img 対象イメージ\r
155          * @param colorKey マニュアル指定時の候補(前回のものを優先)\r
156          * @throws IOException 出力に失敗した場合\r
157          */\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
163                 }\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
170 \r
171                                 int ret = fileChooser.showSaveDialog(dlg);\r
172                                 if (ret != JFileChooser.APPROVE_OPTION) {\r
173                                         return;\r
174                                 }\r
175 \r
176                                 // 結果\r
177                                 dlg.setResult(fileChooser.getSelectedFile());\r
178                                 dlg.dispose();\r
179                         }\r
180                 });\r
181                 dlg.setVisible(true);\r
182                 \r
183                 File selectedFile = (File) dlg.getResult();\r
184                 if (selectedFile == null) {\r
185                         return;\r
186                 }\r
187                 \r
188                 lastUseSaveName = selectedFile.getName();\r
189                 lastUseSaveDir = selectedFile.getParentFile();\r
190                 \r
191                 File pngFile = selectedFile;\r
192                 File pnaFile = makePNAFileName(pngFile);\r
193 \r
194                 File[] outfiles = {pngFile, pnaFile};\r
195                 BufferedImage[] outimages = {\r
196                                 dlg.getOpaqueImage(),\r
197                                 dlg.getAlphaImage()\r
198                 };\r
199 \r
200                 savePNGImages(outfiles, outimages);\r
201         }\r
202 \r
203         /**\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
212          */\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
216                 }\r
217                 if (outfiles.length != outimages.length) {\r
218                         throw new IllegalArgumentException("ファイルおよびイメージの個数は一致していなければなりません.");\r
219                 }\r
220                 \r
221                 ImageWriter iw = ImageIO.getImageWritersByFormatName("png").next();\r
222                 try {\r
223                         iw.addIIOWriteWarningListener(new IIOWriteWarningListener() {\r
224                                 public void warningOccurred(ImageWriter source, int imageIndex,\r
225                                                 String warning) {\r
226                                         logger.log(Level.WARNING, warning);\r
227                                 }\r
228                         });\r
229 \r
230                         for (int idx = 0; idx < outfiles.length; idx++) {\r
231                                 File outfile = outfiles[idx];\r
232                                 BufferedImage outimage = outimages[idx];\r
233                         \r
234                                 BufferedOutputStream bos = new BufferedOutputStream(\r
235                                                 new FileOutputStream(outfile));\r
236                                 try {\r
237                                         ImageWriteParam iwp = iw.getDefaultWriteParam();\r
238                                         IIOImage ioimg = new IIOImage(outimage, null, null);\r
239                                         \r
240                                         ImageOutputStream imgstm = ImageIO.createImageOutputStream(bos);\r
241                                         try {\r
242                                                 iw.setOutput(imgstm);\r
243                                                 iw.write(null, ioimg, iwp);\r
244                                         \r
245                                         } finally {\r
246                                                 imgstm.close();\r
247                                         }\r
248                                         \r
249                                 } finally {\r
250                                         bos.close();\r
251                                 }\r
252                         }\r
253 \r
254                 } finally {\r
255                         iw.dispose();\r
256                 }\r
257         }\r
258         \r
259         /**\r
260          * 複数ファイルを指定して既存のファイルから伺かPNG/PNAに変換して出力する.(ユーテリティ)\r
261          * @param parent 親フレーム\r
262          * @param colorKey 透過色キー(候補)\r
263          * @throws IOException 失敗\r
264          */\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
269                 \r
270                 int ret = fileChooser.showOpenDialog(parent);\r
271                 if (ret != JFileChooser.APPROVE_OPTION) {\r
272                         return;\r
273                 }\r
274 \r
275                 // 選択したディレクトリを記憶する.\r
276                 File[] files = fileChooser.getSelectedFiles();\r
277                 if (files == null || files.length == 0) {\r
278                         return;\r
279                 }\r
280                 lastUseOpenDir = files[0].getParentFile();\r
281                 \r
282                 final UkagakaConvertDialog dlg = new UkagakaConvertDialog(parent, null, true);\r
283                 if (!autoTransparentColor && transparentColorKey != null) {\r
284                         // 前回マニュアル透過色キー指定であれば、それを使う.\r
285                         colorKey = transparentColorKey;\r
286                 }\r
287                 dlg.setAutoTransparentColor(autoTransparentColor);\r
288 \r
289                 ImageReader ir = ImageIO.getImageReadersByFormatName("png").next();\r
290                 try {\r
291                         for (final File file : files) {\r
292                                 String fname = file.getName();\r
293                                 \r
294                                 ImageReadParam param = ir.getDefaultReadParam();\r
295                                 \r
296                                 BufferedImage img;\r
297                                 ImageInputStream iis = ImageIO.createImageInputStream(file);\r
298                                 try {\r
299                                         ir.setInput(iis);\r
300                                         img = ir.read(0, param);\r
301 \r
302                                 } finally {\r
303                                         iis.close();\r
304                                 }\r
305                                 \r
306                                 img = convertIntARGB(img);\r
307 \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
316 \r
317                                                         int ret = fileChooser.showSaveDialog(dlg);\r
318                                                         if (ret != JFileChooser.APPROVE_OPTION) {\r
319                                                                 return;\r
320                                                         }\r
321 \r
322                                                         // 選択結果\r
323                                                         dlg.setResult(fileChooser.getSelectedFile());\r
324 \r
325                                                 } else {\r
326                                                         // ソースと同じ (上書き)\r
327                                                         dlg.setResult(file);\r
328                                                 }\r
329 \r
330                                                 dlg.dispose();\r
331                                         }\r
332                                 });\r
333                                 dlg.setVisible(true);\r
334                                 \r
335                                 File selectedFile = (File) dlg.getResult();\r
336                                 if (selectedFile == null) {\r
337                                         // キャンセルされた場合\r
338                                         break;\r
339                                 }\r
340 \r
341                                 File pngFile = selectedFile;\r
342                                 File pnaFile = makePNAFileName(pngFile);\r
343 \r
344                                 File[] outfiles = {pngFile, pnaFile};\r
345                                 BufferedImage[] outimages = {\r
346                                                 dlg.getOpaqueImage(),\r
347                                                 dlg.getAlphaImage()\r
348                                 };\r
349 \r
350                                 savePNGImages(outfiles, outimages);\r
351                         }\r
352                         \r
353                 } finally {\r
354                         ir.dispose();\r
355                 }\r
356         }\r
357         \r
358         /**\r
359          * BufferedImageをINT_TYPE_ARGBに設定する.<br>\r
360          * @param img イメージ\r
361          * @return 形式をINT_ARGBに変換されたイメージ\r
362          */\r
363         protected BufferedImage convertIntARGB(BufferedImage img) {\r
364                 if (img == null || img.getType() == BufferedImage.TYPE_INT_ARGB) {\r
365                         // nullであるか、変換不要であれば、そのまま返す.\r
366                         return img;\r
367                 }\r
368                 \r
369                 int w = img.getWidth();\r
370                 int h = img.getHeight();\r
371                 \r
372                 BufferedImage dst = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);\r
373                 Graphics2D g = dst.createGraphics();\r
374                 try {\r
375                         g.drawImage(img, 0, 0, w, h, 0, 0, w, h, null);\r
376                         \r
377                 } finally {\r
378                         g.dispose();\r
379                 }\r
380                 \r
381                 return dst;\r
382         }\r
383                 \r
384         \r
385         /**\r
386          * 拡張子をPNAに変換して返す.\r
387          * @param pngFile PNGファイル名\r
388          * @return PNAファイル名\r
389          */\r
390         protected File makePNAFileName(File pngFile) {\r
391                 if (pngFile == null) {\r
392                         return null;\r
393                 }\r
394                 String fname = pngFile.getName();\r
395                 int extpos = fname.lastIndexOf('.');\r
396                 if (extpos >= 0) {\r
397                         fname = fname.substring(0, extpos);\r
398                 }\r
399                 fname += ".pna";\r
400                 return new File(pngFile.getParent(), fname);\r
401         }\r
402 }\r
403 \r