OSDN Git Service

mavenによるビルドに変更
[charactermanaj/CharacterManaJ.git] / src / main / java / charactermanaj / clipboardSupport / ImageSelection.java
1 package charactermanaj.clipboardSupport;\r
2 \r
3 import java.awt.Color;\r
4 import java.awt.datatransfer.Clipboard;\r
5 import java.awt.datatransfer.DataFlavor;\r
6 import java.awt.datatransfer.FlavorMap;\r
7 import java.awt.datatransfer.SystemFlavorMap;\r
8 import java.awt.datatransfer.Transferable;\r
9 import java.awt.datatransfer.UnsupportedFlavorException;\r
10 import java.awt.image.BufferedImage;\r
11 import java.io.ByteArrayInputStream;\r
12 import java.io.ByteArrayOutputStream;\r
13 import java.io.IOException;\r
14 import java.io.InputStream;\r
15 import java.util.Arrays;\r
16 import java.util.List;\r
17 import java.util.logging.Level;\r
18 import java.util.logging.Logger;\r
19 \r
20 import javax.imageio.ImageIO;\r
21 \r
22 import charactermanaj.graphics.io.ImageSaveHelper;\r
23 import charactermanaj.model.AppConfig;\r
24 \r
25 /**\r
26  * クリップボードに画像をコピーするためのセレクション.<br>\r
27  * @author seraphy\r
28  */\r
29 public class ImageSelection implements Transferable {\r
30         \r
31         /**\r
32          * ロガー\r
33          */\r
34         private static final Logger logger = Logger.getLogger(ImageSelection.class.getName());\r
35 \r
36         /**\r
37          * 実行環境がWindowsであるか?\r
38          */\r
39         private static final boolean platformWindows;\r
40         \r
41         /**\r
42          * 対象となるイメージ\r
43          */\r
44         private BufferedImage img;\r
45         \r
46         /**\r
47          * 背景色(jpeg画像変換時)\r
48          */\r
49         private Color bgColor;\r
50         \r
51         /**\r
52          * MIME汎用(PNG).\r
53          */\r
54     private static final DataFlavor PNG_FLAVOR = new DataFlavor("image/png", "image/png");\r
55 \r
56         /**\r
57          * MIME汎用(JPEG).\r
58          */\r
59     private static final DataFlavor JPEG_FLAVOR = new DataFlavor("image/jpeg", "image/jpeg");\r
60     \r
61         /**\r
62          * MIME汎用(BMP).\r
63          */\r
64     private static final DataFlavor BMP_FLAVOR = new DataFlavor("image/bmp", "image/bmp");\r
65     \r
66 \r
67     /**\r
68      * サポートされている形式.<br>\r
69      * 順序は優先順.<br>\r
70      */\r
71     private static final List<DataFlavor> SUPPORTED_FLAVORS;\r
72     \r
73     /**\r
74      * クラスイニシャライザ\r
75      */\r
76     static {\r
77         String lcOS = System.getProperty("os.name").toLowerCase(); \r
78         platformWindows = lcOS.indexOf("windows") >= 0;\r
79         if (platformWindows) {\r
80                 // Windowsの場合\r
81                 SUPPORTED_FLAVORS = Arrays.asList(new DataFlavor[] {\r
82                                 PNG_FLAVOR,\r
83                                 DataFlavor.imageFlavor,\r
84                 });\r
85 \r
86         } else {\r
87                 // Linux, Mac OS Xの場合を想定\r
88                 SUPPORTED_FLAVORS = Arrays.asList(new DataFlavor[] {\r
89                                 PNG_FLAVOR,\r
90                                 JPEG_FLAVOR,\r
91                                 BMP_FLAVOR,\r
92                                 DataFlavor.imageFlavor,\r
93                 });\r
94         }\r
95     }\r
96 \r
97     /**\r
98      * システムのフレーバーマップを設定する.<br>\r
99      * @return 正常にセットアップできた場合はtrue、そうでなければfalse\r
100      */\r
101     public static boolean setupSystemFlavorMap() {\r
102         try {\r
103                         AppConfig appConfig = AppConfig.getInstance();\r
104                         if (appConfig.isEnablePNGSupportForWindows()) {\r
105                         // "PNG"へのマップを明示的に設定する.\r
106                         // (Windowsの場合、デフォルトでは、画像はDBI転送となり透過情報を持つことができないため.)\r
107                         FlavorMap defFlavorMap = SystemFlavorMap.getDefaultFlavorMap();\r
108                         if (defFlavorMap instanceof SystemFlavorMap) {\r
109                                 SystemFlavorMap sysFlavorMap = (SystemFlavorMap) defFlavorMap;\r
110                                         sysFlavorMap.setNativesForFlavor(PNG_FLAVOR, new String[] {"PNG"});\r
111                                         sysFlavorMap.setNativesForFlavor(JPEG_FLAVOR, new String[] {"JFIF"});\r
112                         }\r
113                         }\r
114                 return true;\r
115 \r
116         } catch (Exception ex) {\r
117                 logger.log(Level.SEVERE, "systemFlavorMap setup failed.", ex);\r
118         }\r
119         return false;\r
120     }\r
121     \r
122         /**\r
123          * セレクションを構築する.\r
124          * @param img 対象となるイメージ\r
125          */\r
126         public ImageSelection(BufferedImage img, Color bgColor) {\r
127                 if (img == null) {\r
128                         throw new IllegalArgumentException();\r
129                 }\r
130                 this.img = img;\r
131                 this.bgColor = (bgColor == null) ? Color.white : bgColor;\r
132         }\r
133         \r
134         public Object getTransferData(DataFlavor flavor)\r
135                         throws UnsupportedFlavorException, IOException {\r
136                 if (flavor != null) {\r
137                         logger.log(Level.FINE, "getTransferData flavor=" + flavor);\r
138                         try {\r
139                                 ImageSaveHelper imageSaveHelper = new ImageSaveHelper();\r
140         \r
141                                 if (flavor.equals(PNG_FLAVOR) || flavor.equals(JPEG_FLAVOR) || flavor.equals(BMP_FLAVOR)) {\r
142                                         // image/png, image/jpeg, image/bmpの場合は、\r
143                                         // そのファイル形式のデータを生成して、それを返す.\r
144                                     ByteArrayOutputStream bos = new ByteArrayOutputStream();\r
145                                     try {\r
146                                         imageSaveHelper.savePicture(img, bgColor, bos, flavor.getMimeType(), null);\r
147 \r
148                                     } finally {\r
149                                         bos.close();\r
150                                     }\r
151                                 return new ByteArrayInputStream(bos.toByteArray());\r
152                                 }\r
153 \r
154                                 if (flavor.equals(DataFlavor.imageFlavor)) {\r
155                                         // "image/x-java-image"の場合\r
156                                 AppConfig appConfig = AppConfig.getInstance();\r
157                                 if (platformWindows || !appConfig.isEnablePNGSupportForWindows()) {\r
158                                                 // Windowsの場合は、背景色で塗りつぶしたBMP画像に変換して返す. \r
159                                                 // JDK5/6のシステムクリップボードへのコピーでは透過画像をサポートしておらず透過部分が黒色になるため.\r
160                                         // ネイティブPNGとのマッピングが有効であれば、Windowsでは、そちらで対応する.\r
161                                                 return imageSaveHelper.createBMPFormatPicture(img, bgColor);\r
162 \r
163                                 } else {\r
164                                         // Windows以外、且つ、透過サポートが有効の場合\r
165                                         return img;\r
166                                 }\r
167                                 }\r
168         \r
169                         } catch (RuntimeException ex) {\r
170                                 logger.log(Level.WARNING, "The exception occurred during the data transfer of a clipboard.", ex);\r
171                                 throw ex;\r
172                                 \r
173                         } catch (IOException ex) {\r
174                                 logger.log(Level.WARNING, "The exception occurred during the data transfer of a clipboard.", ex);\r
175                                 throw ex;\r
176                         }\r
177                 }\r
178                 \r
179                 throw new UnsupportedFlavorException(flavor);\r
180         }\r
181 \r
182         public DataFlavor[] getTransferDataFlavors() {\r
183                 return SUPPORTED_FLAVORS.toArray(new DataFlavor[SUPPORTED_FLAVORS.size()]);\r
184         }\r
185 \r
186         public boolean isDataFlavorSupported(DataFlavor flavor) {\r
187                 return flavor != null && SUPPORTED_FLAVORS.contains(flavor);\r
188         }\r
189         \r
190         public static boolean isSupprotedFlavorAvailable(Clipboard cb) {\r
191                 if (cb != null) {\r
192                         for (DataFlavor flavor : SUPPORTED_FLAVORS) {\r
193                                 if (cb.isDataFlavorAvailable(flavor)) {\r
194                                         return true;\r
195                                 }\r
196                         }\r
197                 }\r
198                 return false;\r
199         }\r
200         \r
201         public static BufferedImage getImage(Clipboard cb) throws IOException {\r
202                 if (cb == null) {\r
203                         return null;\r
204                 }\r
205                 try {\r
206                         // サポートされている形式をチェックする.\r
207                         for (DataFlavor flavor : cb.getAvailableDataFlavors()) {\r
208                                 logger.log(Level.FINE, "dataFlavor(in Clipboard)=" + flavor);\r
209                         }\r
210                         DataFlavor availableFlavor = null;\r
211                         for (DataFlavor flavor : SUPPORTED_FLAVORS) {\r
212                                 // 優先順にチェックし最初に見つかったサポートされている形式を採用する.\r
213                                 if (cb.isDataFlavorAvailable(flavor)) {\r
214                                         availableFlavor = flavor;\r
215                                         break;\r
216                                 }\r
217                         }\r
218                         logger.log(Level.FINE, "selected flavor=" + availableFlavor);\r
219                         if (availableFlavor != null) {\r
220                                 \r
221                                 if (availableFlavor.equals(DataFlavor.imageFlavor)) {\r
222                                         // 汎用の画像形式で取得を試みる。\r
223                                         // 透過画像は使えないため、ここで取得されるものは非透過画像である。\r
224                                         return (BufferedImage) cb.getData(DataFlavor.imageFlavor);\r
225                                 }\r
226                                 \r
227                                 if (availableFlavor.equals(PNG_FLAVOR)\r
228                                                 || availableFlavor.equals(JPEG_FLAVOR)\r
229                                                 || availableFlavor.equals(BMP_FLAVOR)) {\r
230                                         // image/png, image/bmp, image/jpegのいずれか\r
231                                         \r
232                                         InputStream is = (InputStream) cb.getData(availableFlavor);\r
233                                         if (is != null) {\r
234                                                 BufferedImage img;\r
235                                                 try {\r
236                                                         img = ImageIO.read(is);\r
237                                                 } finally {\r
238                                                         is.close();\r
239                                                 }\r
240                                                 return img;\r
241                                         }\r
242                                 }\r
243                         }\r
244 \r
245                 } catch (IOException ex) {\r
246                         logger.log(Level.WARNING, "The exception occurred in access to a clipboard.", ex);\r
247                         throw ex;\r
248 \r
249                 } catch (UnsupportedFlavorException ex) {\r
250                         // 直前にisDataFlavorAvailableで確認しているので、\r
251                         // よほどタイミングが悪くなければエラーは発生しないはず。\r
252                         logger.log(Level.WARNING, "The exception occurred in access to a clipboard.", ex);\r
253                         throw new IOException(ex.getMessage());\r
254                 }\r
255 \r
256                 // サポートしているものが無い場合.\r
257                 return null;\r
258         }\r
259 }\r