OSDN Git Service

mavenによるビルドに変更
[charactermanaj/CharacterManaJ.git] / src / main / java / charactermanaj / graphics / io / ImageSaveHelper.java
1 package charactermanaj.graphics.io;\r
2 \r
3 import java.awt.BorderLayout;\r
4 import java.awt.Color;\r
5 import java.awt.Component;\r
6 import java.awt.Font;\r
7 import java.awt.Graphics2D;\r
8 import java.awt.GridBagConstraints;\r
9 import java.awt.GridBagLayout;\r
10 import java.awt.Insets;\r
11 import java.awt.RenderingHints;\r
12 import java.awt.image.BufferedImage;\r
13 import java.io.File;\r
14 import java.io.IOException;\r
15 import java.io.OutputStream;\r
16 import java.util.Arrays;\r
17 import java.util.Iterator;\r
18 import java.util.List;\r
19 import java.util.Properties;\r
20 import java.util.logging.Level;\r
21 import java.util.logging.Logger;\r
22 \r
23 import javax.imageio.IIOImage;\r
24 import javax.imageio.ImageIO;\r
25 import javax.imageio.ImageWriteParam;\r
26 import javax.imageio.ImageWriter;\r
27 import javax.imageio.event.IIOWriteWarningListener;\r
28 import javax.imageio.stream.ImageOutputStream;\r
29 import javax.swing.BorderFactory;\r
30 import javax.swing.Box;\r
31 import javax.swing.JCheckBox;\r
32 import javax.swing.JComboBox;\r
33 import javax.swing.JFileChooser;\r
34 import javax.swing.JLabel;\r
35 import javax.swing.JOptionPane;\r
36 import javax.swing.JPanel;\r
37 import javax.swing.JSpinner;\r
38 import javax.swing.SpinnerNumberModel;\r
39 import javax.swing.filechooser.FileFilter;\r
40 \r
41 import charactermanaj.graphics.io.OutputOption.PictureMode;\r
42 import charactermanaj.graphics.io.OutputOption.ZoomRenderingType;\r
43 import charactermanaj.util.LocalizedMessageComboBoxRender;\r
44 import charactermanaj.util.LocalizedResourcePropertyLoader;\r
45 \r
46 \r
47 /**\r
48  * イメージを保存するためのヘルパークラス.<br>\r
49  */\r
50 public class ImageSaveHelper {\r
51         \r
52         /**\r
53          * ロガー\r
54          */\r
55         private static final Logger logger = Logger.getLogger(ImageSaveHelper.class.getName());\r
56 \r
57         /**\r
58          * リソース\r
59          */\r
60         protected static final String STRINGS_RESOURCE = "languages/imageSaveHelper";\r
61 \r
62         /**\r
63          * このヘルパクラス用のファイルフィルタの抽象実装\r
64          * @author seraphy\r
65          */\r
66         protected static abstract class ImageSaveHelperFilter extends FileFilter {\r
67 \r
68                 @Override\r
69                 public boolean accept(File f) {\r
70                         if (f.isDirectory()) {\r
71                                 // ディレクトリは選択可\r
72                                 return true;\r
73                         }\r
74 \r
75                         return isSupported(f);\r
76                 }\r
77                 \r
78                 protected boolean isSupported(File f) {\r
79                         // サポートしている拡張子のいずれかにマッチするか?\r
80                         // (大文字・小文字は区別しない.)\r
81                         String lcName = f.getName().toLowerCase();\r
82                         for (String ext : getSupprotedExtension()) {\r
83                                 if (lcName.endsWith("." + ext.toLowerCase())) {\r
84                                         return true;\r
85                                 }\r
86                         }\r
87                         return false;\r
88                 }\r
89 \r
90                 /**\r
91                  * 現在の選択されたファイル名を取得し、そのファイル名がデフォルトの拡張子で終端していなければ\r
92                  * デフォルトの拡張子を設定してファイルチューザに設定し直す.<Br> \r
93                  * @param fileChooser ファイルチューザ\r
94                  * @return デフォルトの拡張子で終端されたファイル\r
95                  */\r
96                 public File supplyDefaultExtension(JFileChooser fileChooser) {\r
97                         File outFile = fileChooser.getSelectedFile();\r
98                         if (outFile == null) {\r
99                                 return null;\r
100                         }\r
101                         \r
102                         if ( !isSupported(outFile)) {\r
103                                 String extName = "." + getSupprotedExtension()[0];\r
104                                 outFile = new File(outFile.getPath() + extName);\r
105                                 fileChooser.setSelectedFile(outFile);\r
106                         }\r
107                         return outFile;\r
108                 }\r
109                 \r
110                 /**\r
111                  * サポートするファイルの拡張子を取得する.<br>\r
112                  * 最初のものがデフォルトの拡張子として用いられる.<br>\r
113                  * @return ファイルの拡張子\r
114                  */\r
115                 protected abstract String[] getSupprotedExtension();\r
116         }\r
117         \r
118         /**\r
119          * PNGファイルフィルタ\r
120          */\r
121         protected static final FileFilter pngFilter = new ImageSaveHelperFilter() {\r
122                 @Override\r
123                 public String getDescription() {\r
124                         return "PNG(*.png)";\r
125                 }\r
126                 @Override\r
127                 protected String[] getSupprotedExtension() {\r
128                         return new String[] {"png"};\r
129                 }\r
130         };\r
131 \r
132         /**\r
133          * JPEGファイルフィルタ\r
134          */\r
135         protected static final FileFilter jpegFilter = new ImageSaveHelperFilter() {\r
136                 @Override\r
137                 public String getDescription() {\r
138                         return "JPEG(*.jpg;*.jpeg)";\r
139                 }\r
140                 @Override\r
141                 protected String[] getSupprotedExtension() {\r
142                         return new String[] {"jpeg", "jpg"};\r
143                 }\r
144         };\r
145 \r
146         /**\r
147          * BMPファイルフィルタ\r
148          */\r
149         protected static final FileFilter bmpFilter = new ImageSaveHelperFilter() {\r
150                 @Override\r
151                 public String getDescription() {\r
152                         return "Bitmap(*.bmp)";\r
153                 }\r
154                 @Override\r
155                 protected String[] getSupprotedExtension() {\r
156                         return new String[] {"bmp"};\r
157                 }\r
158         };\r
159         \r
160         /**\r
161          * このヘルパクラスで定義されているファイルフィルタのリスト\r
162          */\r
163         protected static final List<FileFilter> fileFilters = Arrays.asList(\r
164                         pngFilter, jpegFilter, bmpFilter);\r
165         \r
166         /**\r
167          * イメージビルダファクトリ\r
168          */\r
169         protected OutputImageBuilderFactory imageBuilderFactory;\r
170 \r
171         /**\r
172          * 最後に使用した出力オプション.<br>\r
173          * 未使用であれば規定値.<br>\r
174          */\r
175         protected OutputOption outputOption;\r
176         \r
177         /**\r
178          * 最後に使用したディレクトリ\r
179          */\r
180         protected File lastUseSaveDir;\r
181         \r
182         /**\r
183          * 最後に使用したフィルタ\r
184          */\r
185         protected FileFilter lastUseFilter = pngFilter;\r
186         \r
187         /**\r
188          * 最後に使用したディレクトリを設定する\r
189          * @param lastUseSaveDir 最後に使用したディレクトリ、設定しない場合はnull\r
190          */\r
191         public void setLastUseSaveDir(File lastUseSaveDir) {\r
192                 this.lastUseSaveDir = lastUseSaveDir;\r
193         }\r
194         \r
195         /**\r
196          * 最後に使用したディレクトリを取得する\r
197          * @return 最後に使用したディレクトリ、なければnull\r
198          */\r
199         public File getLastUsedSaveDir() {\r
200                 return lastUseSaveDir;\r
201         }\r
202         \r
203 \r
204         /**\r
205          * コンストラクタ\r
206          */\r
207         public ImageSaveHelper() {\r
208                 imageBuilderFactory = new OutputImageBuilderFactory();\r
209                 outputOption = imageBuilderFactory.createDefaultOutputOption();\r
210         }\r
211 \r
212         /**\r
213          * 画像ファイルの保存用ダイアログを表示する.\r
214          * @param parent 親ウィンドウ\r
215          * @return ファイル名\r
216          */\r
217         public File showSaveFileDialog(Component parent) {\r
218 \r
219                 // 最後に使用したディレクトリを指定してファイルダイアログを構築する.\r
220                 JFileChooser fileChooser = new JFileChooser(lastUseSaveDir) {\r
221                         private static final long serialVersionUID = -9091369410030011886L;\r
222 \r
223                         /**\r
224                          * OKボタン押下時の処理.\r
225                          */\r
226                         @Override\r
227                         public void approveSelection() {\r
228                                 File outFile = getSelectedFile();\r
229                                 if (outFile == null) {\r
230                                         return;\r
231                                 }\r
232 \r
233                                 // 選択したファイルフィルタに従ってデフォルトの拡張子を付与する.\r
234                                 FileFilter selfilter = getFileFilter();\r
235                                 if (selfilter instanceof ImageSaveHelperFilter) {\r
236                                         outFile = ((ImageSaveHelperFilter) selfilter).supplyDefaultExtension(this);\r
237                                 }\r
238                                 \r
239                                 // ファイルが存在すれば上書き確認する.\r
240                                 if (outFile.exists()) {\r
241                                         Properties strings = LocalizedResourcePropertyLoader.getCachedInstance()\r
242                                                 .getLocalizedProperties(STRINGS_RESOURCE);\r
243 \r
244                                         if (JOptionPane.showConfirmDialog(this,\r
245                                                         strings.getProperty("confirmOverwrite"),\r
246                                                         strings.getProperty("confirm"),\r
247                                                         JOptionPane.YES_NO_OPTION,\r
248                                                         JOptionPane.WARNING_MESSAGE) != JOptionPane.YES_OPTION) {\r
249                                                 return;\r
250                                         }\r
251                                 }\r
252                                 \r
253                                 super.approveSelection();\r
254                         }\r
255                 };\r
256                 \r
257 //              // アクセサリパネルの追加˙\r
258 //              final OutputOptionPanel accessoryPanel = new OutputOptionPanel(this.outputOption);\r
259 //              fileChooser.setAccessory(accessoryPanel);\r
260                 \r
261                 // ファイルフィルタ設定\r
262                 fileChooser.setAcceptAllFileFilterUsed(false);\r
263                 for (FileFilter fileFilter : fileFilters) {\r
264                         fileChooser.addChoosableFileFilter(fileFilter);\r
265                 }\r
266 \r
267                 // 最後に使用したファイルフィルタが既定のフィルタでないか未設定であればPNGにする.\r
268                 if (lastUseFilter == null || !fileFilters.contains(lastUseFilter)) {\r
269                         lastUseFilter = pngFilter;\r
270                 }\r
271 \r
272                 // 最後に使用したフィルタをデフォルトのフィルタに設定する.\r
273                 fileChooser.setFileFilter(lastUseFilter);\r
274 \r
275                 // ファイルダイアログを開く.\r
276                 int ret = fileChooser.showSaveDialog(parent);\r
277                 if (ret != JFileChooser.APPROVE_OPTION) {\r
278                         return null;\r
279                 }\r
280                 \r
281 //              // 出力オプションの保存\r
282 //              OutputOption outputOption = accessoryPanel.getOutputOption();\r
283 //              this.outputOption = outputOption;\r
284 \r
285                 // 最後に使用したフィルタ、および選択したディレクトリを記憶する.\r
286                 File outFile = fileChooser.getSelectedFile();\r
287                 lastUseSaveDir = outFile.getParentFile();\r
288                 lastUseFilter = fileChooser.getFileFilter();\r
289                 \r
290                 // 選択したファイルを返す.\r
291                 return outFile; \r
292         }\r
293         \r
294         public OutputOption getOutputOption() {\r
295                 return outputOption.clone();\r
296         }\r
297         \r
298         public void setOutputOption(OutputOption outputOption) {\r
299                 if (outputOption == null) {\r
300                         throw new IllegalArgumentException();\r
301                 }\r
302                 this.outputOption = outputOption.clone();\r
303         }\r
304 \r
305         /**\r
306          * ファイル名を指定してイメージをファイルに出力します.<br>\r
307          * 出力形式は拡張子より判定します.<br>\r
308          * サポートされていない拡張子の場合はIOException例外が発生します.<br>\r
309          * @param img イメージ\r
310          * @param imgBgColor JPEGの場合の背景色\r
311          * @param outFile 出力先ファイル(拡張子が必須)\r
312          * @param warnings 警告を記録するバッファ、必要なければnull\r
313          * @throws IOException 失敗\r
314          */\r
315         public void savePicture(BufferedImage img, Color imgBgColor,\r
316                         File outFile, final StringBuilder warnings) throws IOException {\r
317                 if (img == null || outFile == null) {\r
318                         throw new IllegalArgumentException();\r
319                 }\r
320                 \r
321                 // ファイル名から拡張子を取り出します.\r
322                 String fname = outFile.getName();\r
323                 int extpos = fname.lastIndexOf(".");\r
324                 if (extpos < 0) {\r
325                         throw new IOException("missing file extension.");\r
326                 }\r
327                 String ext = fname.substring(extpos + 1).toLowerCase();\r
328 \r
329                 // 拡張子に対するImageIOのライタを取得します.\r
330                 Iterator<ImageWriter> ite = ImageIO.getImageWritersBySuffix(ext);\r
331                 if (!ite.hasNext()) {\r
332                         throw new IOException("unsupported file extension: " + ext);\r
333                 }\r
334                 \r
335                 ImageWriter iw = ite.next();\r
336                 \r
337                 // ライタを使いイメージを書き込みます.\r
338                 savePicture(img, imgBgColor, iw, outFile, warnings);\r
339         }\r
340         \r
341         /**\r
342          * イメージをMIMEで指定された形式で出力します.\r
343          * @param img イメージ\r
344          * @param imgBgColor JPEGの場合の背景色\r
345          * @param outstm 出力先\r
346          * @param mime MIME\r
347          * @param warnings 警告を書き込むバッファ、必要なければnull\r
348          * @throws IOException 例外\r
349          */\r
350         public void savePicture(BufferedImage img, Color imgBgColor,\r
351                         OutputStream outstm, String mime, final StringBuilder warnings)\r
352                         throws IOException {\r
353                 if (img == null || outstm == null || mime == null) {\r
354                         throw new IllegalArgumentException();\r
355                 }\r
356 \r
357                 // mimeがパラメータ付きの場合は、パラメータを除去する.\r
358                 int pt = mime.indexOf(';');\r
359                 if (pt >= 0) {\r
360                         mime = mime.substring(0, pt).trim();\r
361                 }\r
362 \r
363                 // サポートしているmimeタイプを検出.\r
364                 Iterator<ImageWriter> ite = ImageIO.getImageWritersByMIMEType(mime);\r
365                 if (!ite.hasNext()) {\r
366                         throw new IOException("unsupported mime: " + mime);\r
367                 }\r
368 \r
369                 ImageWriter iw = ite.next();\r
370                 savePicture(img, imgBgColor, iw, outstm, warnings);\r
371                 outstm.flush();\r
372         }\r
373         \r
374         protected void savePicture(BufferedImage img, Color imgBgColor, ImageWriter iw,\r
375                         Object output, final StringBuilder warnings)\r
376                         throws IOException {\r
377                 try {\r
378                         iw.addIIOWriteWarningListener(new IIOWriteWarningListener() {\r
379                                 public void warningOccurred(ImageWriter source, int imageIndex,\r
380                                                 String warning) {\r
381                                         if (warnings.length() > 0) {\r
382                                                 warnings.append(System.getProperty("line.separator"));\r
383                                         }\r
384                                         if (warnings != null) {\r
385                                                 warnings.append(warning);\r
386                                         }\r
387                                         logger.log(Level.WARNING, warning);\r
388                                 }\r
389                         });\r
390 \r
391                         boolean jpeg = false;\r
392                         boolean bmp = false;\r
393                         for (String mime : iw.getOriginatingProvider().getMIMETypes()) {\r
394                                 if (mime.contains("image/jpeg") || mime.contains("image/jpg")) {\r
395                                         jpeg = true;\r
396                                         break;\r
397                                 }\r
398                                 if (mime.contains("image/bmp") || mime.contains("image/x-bmp")\r
399                                                 || mime.contains("image/x-windows-bmp")) {\r
400                                         bmp = true;\r
401                                         break;\r
402                                 }\r
403                         }\r
404 \r
405                         ImageWriteParam iwp = iw.getDefaultWriteParam();\r
406                         IIOImage ioimg;\r
407 \r
408                         if (jpeg) {\r
409                                 iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);\r
410                                 iwp.setCompressionQuality((float) outputOption.getJpegQuality());\r
411 \r
412                                 // JPEGは透過色をサポートしていないので背景色を設定する.\r
413                                 ioimg = new IIOImage(createJpegFormatPicture(img, imgBgColor), null, null);\r
414 \r
415                         } else if (bmp) {\r
416                                 // BMPは透過色をサポートしていないので背景色を設定する.\r
417                                 ioimg = new IIOImage(createBMPFormatPicture(img, imgBgColor), null, null);\r
418 \r
419                         } else if (outputOption.isForceBgColor()) {\r
420                                 // 背景色強制\r
421                                 // JPEG, BMP以外(PNGを想定)\r
422                                 ioimg = new IIOImage(createOpaquePNGFormatPicture(img, imgBgColor), null, null);\r
423 \r
424                         } else {\r
425                                 // 透過有効のまま\r
426                                 // JPEG, BMP以外(PNGを想定)\r
427                                 ioimg = new IIOImage(img, null, null);\r
428                         }\r
429 \r
430                         ImageOutputStream imgstm = ImageIO.createImageOutputStream(output);\r
431                         try {\r
432                                 iw.setOutput(imgstm);\r
433                                 iw.write(null, ioimg, iwp);\r
434 \r
435                         } finally {\r
436                                 imgstm.close();\r
437                         }\r
438 \r
439                 } finally {\r
440                         iw.dispose();\r
441                 }\r
442         }\r
443         \r
444         /**\r
445          * ARGB形式から、アルファチャンネルを削除し、かわりに背景色を設定したBGR形式画像を返します.<br>\r
446          * JPEG画像として用いることを想定しています.<br>\r
447          * @param img 変換するイメージ\r
448          * @param imgBgColor 背景色\r
449          * @return 変換されたイメージ\r
450          */\r
451         public BufferedImage createJpegFormatPicture(BufferedImage img, Color imgBgColor) {\r
452                 if (imgBgColor == null) {\r
453                         imgBgColor = Color.WHITE;\r
454                 }\r
455                 return createFormatPicture(img, imgBgColor, BufferedImage.TYPE_INT_BGR);\r
456         }\r
457 \r
458         /**\r
459          * ARGB形式から、アルファチャンネルを削除し、かわりに背景色を設定したBGR形式画像を返します.<br>\r
460          * BMP画像として用いることを想定しています.<br>\r
461          * @param img 変換するイメージ\r
462          * @param imgBgColor 背景色\r
463          * @return 変換されたイメージ\r
464          */\r
465         public BufferedImage createBMPFormatPicture(BufferedImage img, Color imgBgColor) {\r
466                 if (imgBgColor == null) {\r
467                         imgBgColor = Color.WHITE;\r
468                 }\r
469                 return createFormatPicture(img, imgBgColor, BufferedImage.TYPE_3BYTE_BGR);\r
470         }\r
471 \r
472         /**\r
473          * ARGB形式から、アルファチャンネルを削除し、かわりに背景色を設定したRGB形式画像を返します.<br>\r
474          * 背景付きPNG画像として用いることを想定しています.<br>\r
475          * @param img 変換するイメージ\r
476          * @param imgBgColor 背景色\r
477          * @return 変換されたイメージ\r
478          */\r
479         public BufferedImage createOpaquePNGFormatPicture(BufferedImage img, Color imgBgColor) {\r
480                 if (imgBgColor == null) {\r
481                         imgBgColor = Color.WHITE;\r
482                 }\r
483                 return createFormatPicture(img, imgBgColor, BufferedImage.TYPE_INT_ARGB);\r
484         }\r
485 \r
486         /**\r
487          * ARGB形式から、アルファチャンネルを削除し、かわりに背景色を設定したBGR形式画像を返します.<br>\r
488          * JPEG画像として用いることを想定しています.<br>\r
489          * @param img 変換するイメージ\r
490          * @param imgBgColor 背景色\r
491          * @return 変換されたイメージ\r
492          */\r
493         protected BufferedImage createFormatPicture(BufferedImage img, Color imgBgColor, int type) {\r
494                 if (img == null) {\r
495                         throw new IllegalArgumentException();\r
496                 }\r
497                 int w = img.getWidth();\r
498                 int h = img.getHeight();\r
499                 BufferedImage tmpImg = new BufferedImage(w, h, type);\r
500                 Graphics2D g = tmpImg.createGraphics();\r
501                 try {\r
502                         g.setRenderingHint(\r
503                                         RenderingHints.KEY_ALPHA_INTERPOLATION,\r
504                                         RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);\r
505 \r
506                         if (imgBgColor != null) {\r
507                                 g.setColor(imgBgColor);\r
508                                 g.fillRect(0, 0, w, h);\r
509                         }\r
510                         g.drawImage(img, 0, 0, w, h, 0, 0, w, h, null);\r
511 \r
512                 } finally {\r
513                         g.dispose();\r
514                 }\r
515                 return tmpImg;\r
516         }\r
517 }\r
518 \r
519 /**\r
520  * 出力オプションパネル\r
521  * @author seraphy\r
522  */\r
523 class OutputOptionPanel extends JPanel {\r
524         private static final long serialVersionUID = 1L;\r
525 \r
526         private JSpinner jpegQualitySpinner;\r
527         \r
528         private JCheckBox lblZoom;\r
529         \r
530         private JSpinner zoomSpinner;\r
531         \r
532         private JComboBox zoomAlgoCombo;\r
533         \r
534         private JComboBox pictureModeCombo;\r
535         \r
536         private JCheckBox checkForceBgColor;\r
537 \r
538         \r
539         public OutputOptionPanel() {\r
540                 this(new OutputOption());\r
541         }\r
542 \r
543         public OutputOptionPanel(OutputOption outputOption) {\r
544 \r
545                 Properties strings = LocalizedResourcePropertyLoader.getCachedInstance()\r
546                         .getLocalizedProperties(ImageSaveHelper.STRINGS_RESOURCE);\r
547 \r
548                 setBorder(BorderFactory.createCompoundBorder(\r
549                                 BorderFactory.createEmptyBorder(3, 3, 3, 3),\r
550                                 BorderFactory.createTitledBorder(\r
551                                                 strings.getProperty("ouputOption.caption"))));\r
552                 setLayout(new GridBagLayout());\r
553                 GridBagConstraints gbc = new GridBagConstraints();\r
554 \r
555                 gbc.anchor = GridBagConstraints.EAST;\r
556                 gbc.fill  = GridBagConstraints.BOTH;\r
557                 gbc.insets = new Insets(3, 3, 3, 3);\r
558                 gbc.gridheight = 1;\r
559                 gbc.ipadx = 0;\r
560                 gbc.ipady = 0;\r
561                 gbc.weighty = 0;\r
562 \r
563                 // 左端余白\r
564                 gbc.gridx = 0;\r
565                 gbc.gridy = 0;\r
566                 gbc.gridwidth = 1;\r
567                 gbc.weightx = 0.;\r
568                 add(Box.createHorizontalStrut(6), gbc);\r
569                 \r
570                 // JPEG\r
571                 gbc.gridx = 0;\r
572                 gbc.gridy = 0;\r
573                 gbc.gridwidth = 3;\r
574                 gbc.weightx = 1.;\r
575                 JLabel lblJpeg = new JLabel(\r
576                                 strings.getProperty("outputOption.jpeg.caption"));\r
577                 lblJpeg.setFont(lblJpeg.getFont().deriveFont(Font.BOLD));\r
578                 add(lblJpeg, gbc);\r
579                 \r
580                 gbc.gridx = 1;\r
581                 gbc.gridy = 1;\r
582                 gbc.gridwidth = 1;\r
583                 gbc.weightx = 0.;\r
584                 add(new JLabel(\r
585                                 strings.getProperty("outputOption.jpeg.quality"),\r
586                                 JLabel.RIGHT), gbc);\r
587                 \r
588                 SpinnerNumberModel spmodel = new SpinnerNumberModel(100, 10, 100, 1);\r
589                 this.jpegQualitySpinner = new JSpinner(spmodel);\r
590                 \r
591                 gbc.gridx = 2;\r
592                 gbc.gridy = 1;\r
593                 gbc.gridwidth = 1;\r
594                 add(jpegQualitySpinner, gbc);\r
595 \r
596                 gbc.gridx = 3;\r
597                 gbc.gridy = 1;\r
598                 gbc.gridwidth = 1;\r
599                 add(new JLabel("%"), gbc);\r
600 \r
601                 // ZOOM\r
602                 gbc.gridx = 0;\r
603                 gbc.gridy = 2;\r
604                 gbc.gridwidth = 3;\r
605                 gbc.weightx = 1.;\r
606                 gbc.insets = new Insets(10, 3, 3, 3);\r
607                 lblZoom = new JCheckBox(strings.getProperty("outputOption.zoom.caption"));\r
608                 lblZoom.setFont(lblJpeg.getFont().deriveFont(Font.BOLD));\r
609                 add(lblZoom, gbc);\r
610                 \r
611                 gbc.gridx = 1;\r
612                 gbc.gridy = 3;\r
613                 gbc.gridwidth = 1;\r
614                 gbc.weightx = 0.;\r
615                 gbc.insets = new Insets(3, 3, 3, 3);\r
616                 add(new JLabel(\r
617                                 strings.getProperty("outputOption.zoom.factor"), JLabel.RIGHT), gbc);\r
618                 \r
619                 SpinnerNumberModel zoomSpModel = new SpinnerNumberModel(100, 20, 800, 1);\r
620                 this.zoomSpinner = new JSpinner(zoomSpModel);\r
621                 \r
622                 gbc.gridx = 2;\r
623                 gbc.gridy = 3;\r
624                 gbc.gridwidth = 1;\r
625                 add(zoomSpinner, gbc);\r
626                 \r
627                 gbc.gridx = 3;\r
628                 gbc.gridy = 3;\r
629                 gbc.gridwidth = 1;\r
630                 add(new JLabel("%"), gbc);\r
631 \r
632                 gbc.gridx = 1;\r
633                 gbc.gridy = 4;\r
634                 gbc.gridwidth = 1;\r
635                 gbc.weightx = 1.;\r
636                 add(new JLabel(\r
637                                 strings.getProperty("outputOption.zoom.renderingMode"),\r
638                                 JLabel.RIGHT), gbc);\r
639                 \r
640                 this.zoomAlgoCombo = new JComboBox(ZoomRenderingType.values());\r
641                 this.zoomAlgoCombo.setRenderer(new LocalizedMessageComboBoxRender(strings));\r
642                 gbc.gridx = 2;\r
643                 gbc.gridy = 4;\r
644                 gbc.gridwidth = 2;\r
645                 gbc.weightx = 0.;\r
646                 add(zoomAlgoCombo, gbc);\r
647                 \r
648                 // 画像モード\r
649                 gbc.gridx = 0;\r
650                 gbc.gridy = 5;\r
651                 gbc.gridwidth = 3;\r
652                 gbc.insets = new Insets(10, 3, 3, 3);\r
653                 JLabel lblPictureMode = new JLabel(\r
654                                 strings.getProperty("outputOption.picture"));\r
655                 lblPictureMode.setFont(lblJpeg.getFont().deriveFont(Font.BOLD));\r
656                 add(lblPictureMode, gbc);\r
657                 \r
658                 gbc.gridx = 1;\r
659                 gbc.gridy = 6;\r
660                 gbc.gridwidth = 1;\r
661                 gbc.insets = new Insets(3, 3, 3, 3);\r
662                 add(new JLabel(\r
663                                 strings.getProperty("outputOption.picture.type"),\r
664                                 JLabel.RIGHT), gbc);\r
665                 \r
666                 this.pictureModeCombo = new JComboBox(PictureMode.values());\r
667                 this.pictureModeCombo.setRenderer(\r
668                                 new LocalizedMessageComboBoxRender(strings));\r
669                 gbc.gridx = 2;\r
670                 gbc.gridy = 6;\r
671                 gbc.gridwidth = 2;\r
672                 gbc.weightx = 1.;\r
673                 add(pictureModeCombo, gbc);             \r
674                 \r
675                 gbc.gridx = 1;\r
676                 gbc.gridy = 7;\r
677                 gbc.gridwidth = 3;\r
678                 gbc.weightx = 0.;\r
679                 checkForceBgColor = new JCheckBox(\r
680                                 strings.getProperty("outputOption.picture.forceBgColor"));  \r
681                 add(checkForceBgColor, gbc);\r
682                 \r
683                 JPanel pnlBgAlpha = new JPanel(new BorderLayout(3, 3));\r
684                 pnlBgAlpha.add(new JLabel("背景アルファ"), BorderLayout.WEST);\r
685                 \r
686                 SpinnerNumberModel bgAlphaModel = new SpinnerNumberModel(255, 0, 255, 1);\r
687                 JSpinner bgAlphaSpinner = new JSpinner(bgAlphaModel);\r
688 \r
689                 pnlBgAlpha.add(bgAlphaSpinner, BorderLayout.CENTER);\r
690                 \r
691                 gbc.gridx = 1;\r
692                 gbc.gridy = 8;\r
693                 gbc.gridwidth = 3;\r
694                 gbc.weightx = 0.;\r
695                 add(pnlBgAlpha, gbc);\r
696 \r
697                 // 余白\r
698                 gbc.gridx = 0;\r
699                 gbc.gridy = 9;\r
700                 gbc.gridwidth = 4;\r
701                 gbc.weightx = 1.;\r
702                 gbc.weighty = 1.;\r
703                 add(Box.createGlue(), gbc);\r
704                 \r
705                 // update\r
706                 setOutputOption(outputOption);\r
707         }\r
708         \r
709         public void setOutputOption(OutputOption outputOption) {\r
710                 if (outputOption == null) {\r
711                         outputOption = new OutputOption();\r
712                 }\r
713                 \r
714                 jpegQualitySpinner.setValue((int) (outputOption.getJpegQuality() * 100));\r
715                 lblZoom.setSelected(outputOption.isEnableZoom());\r
716                 zoomSpinner.setValue((int) (outputOption.getZoomFactor() * 100));\r
717                 zoomAlgoCombo.setSelectedItem(outputOption.getZoomRenderingType());\r
718                 pictureModeCombo.setSelectedItem(outputOption.getPictureMode());\r
719                 checkForceBgColor.setSelected(outputOption.isForceBgColor());\r
720         }\r
721 \r
722         public OutputOption getOutputOption() {\r
723                 OutputOption outputOption = new OutputOption();\r
724 \r
725                 outputOption.setJpegQuality(((Integer) jpegQualitySpinner.getValue() / 100.));\r
726                 outputOption.setEnableZoom(lblZoom.isSelected());\r
727                 outputOption.setZoomFactor(((Integer) zoomSpinner.getValue() / 100.));\r
728                 outputOption.setZoomRenderingType((ZoomRenderingType) zoomAlgoCombo.getSelectedItem());\r
729                 outputOption.setPictureMode((PictureMode) pictureModeCombo.getSelectedItem());\r
730                 outputOption.setForceBgColor(checkForceBgColor.isSelected());\r
731                 \r
732                 return outputOption;\r
733         }\r
734 }\r
735 \r