/src/mpv5/utils/images/MPIcon.java

http://mp-rechnungs-und-kundenverwaltung.googlecode.com/ · Java · 338 lines · 170 code · 33 blank · 135 comment · 23 complexity · 3e4dd2481d382621b04f07a6e98a0227 MD5 · raw file

  1. /*
  2. * This file is part of YaBS.
  3. *
  4. * YaBS is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * YaBS is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with YaBS. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. package mpv5.utils.images;
  18. import java.awt.Component;
  19. import java.awt.Graphics;
  20. import java.awt.Graphics2D;
  21. import java.awt.GraphicsConfiguration;
  22. import java.awt.GraphicsDevice;
  23. import java.awt.GraphicsEnvironment;
  24. import java.awt.HeadlessException;
  25. import java.awt.Image;
  26. import java.awt.RenderingHints;
  27. import java.awt.Transparency;
  28. import java.awt.image.BufferedImage;
  29. import java.awt.image.ColorModel;
  30. import java.awt.image.PixelGrabber;
  31. import java.net.URL;
  32. import java.util.HashMap;
  33. import javax.swing.Icon;
  34. import javax.swing.ImageIcon;
  35. import mpv5.logging.Log;
  36. /**
  37. *
  38. */
  39. public class MPIcon extends ImageIcon {
  40. private static final long serialVersionUID = 1L;
  41. public static String DIRECTORY_DEFAULT_ICONS = "/mpv5/resources/images/22/mimetypes/";
  42. public static Icon ICON_ENABLED = new javax.swing.ImageIcon(MPIcon.class.getResource("/mpv5/resources/images/16/yes.png"));
  43. /**
  44. *
  45. * @param icon
  46. */
  47. public MPIcon(Icon icon) {
  48. super(iconToImage(icon));
  49. }
  50. /**
  51. *
  52. * @param icon
  53. */
  54. public MPIcon(ImageIcon icon) {
  55. super(icon.getImage());
  56. }
  57. /**
  58. *
  59. * @param icon
  60. */
  61. public MPIcon(Image icon) {
  62. super(icon);
  63. }
  64. /**
  65. * Internal resources only!
  66. * @param resource
  67. */
  68. public MPIcon(String resource) {
  69. super(MPIcon.class.getResource(resource));
  70. }
  71. /**
  72. * @param pathToImage
  73. */
  74. public MPIcon(URL pathToImage) {
  75. super(pathToImage);
  76. }
  77. private MPIcon() {
  78. super();
  79. }
  80. /**
  81. *
  82. * @param icon
  83. * @return
  84. */
  85. public static Image iconToImage(Icon icon) {
  86. if (icon instanceof ImageIcon) {
  87. return ((ImageIcon) icon).getImage();
  88. } else {
  89. int w = icon.getIconWidth();
  90. int h = icon.getIconHeight();
  91. GraphicsEnvironment ge =
  92. GraphicsEnvironment.getLocalGraphicsEnvironment();
  93. GraphicsDevice gd = ge.getDefaultScreenDevice();
  94. GraphicsConfiguration gc = gd.getDefaultConfiguration();
  95. BufferedImage image = gc.createCompatibleImage(w, h);
  96. Graphics2D g = image.createGraphics();
  97. icon.paintIcon(null, g, 0, 0);
  98. g.dispose();
  99. return image;
  100. }
  101. }
  102. // /**
  103. // * Paints the icon.
  104. // * The top-left corner of the icon is drawn at
  105. // * the point (<code>x</code>, <code>y</code>)
  106. // * in the coordinate space of the graphics context <code>g</code>.
  107. // * If this icon has no image observer,
  108. // * this method uses the <code>c</code> component
  109. // * as the observer.
  110. // *
  111. // * @param c the component to be used as the observer
  112. // * if this icon has no image observer
  113. // * @param g the graphics context
  114. // * @param x the X coordinate of the icon's top-left corner
  115. // * @param y the Y coordinate of the icon's top-left corner
  116. // */
  117. // @Override
  118. // public synchronized void paintIcon(Component c, Graphics g, int x, int y) {
  119. // Image image = getImage();
  120. // if (super.getImageObserver() == null) {
  121. // g.drawImage(image, x, y, c);
  122. // } else {
  123. // g.drawImage(image, x, y, super.getImageObserver());
  124. // }
  125. // }
  126. /**
  127. * Creates an Icon with the specified size, fast and ugly
  128. * @param maxWidthHeigth
  129. * @return
  130. */
  131. public Icon getIcon(int maxWidthHeigth) {
  132. return getIcon(maxWidthHeigth, -1);
  133. }
  134. /**
  135. * Creates an Icon with the specified size, nice but slowly
  136. * @param maxWidth
  137. * @param maxHeight
  138. * @return
  139. */
  140. public Icon getIcon(int maxWidth, int maxHeight) {
  141. if (!cache.containsKey(maxWidth + "@" + maxHeight)) {
  142. BufferedImage bi = toBufferedImage(this.getImage());
  143. bi = getScaledInstance(bi, maxWidth, maxHeight, RenderingHints.VALUE_INTERPOLATION_BILINEAR, maxHeight > 0);
  144. MPIcon imic = new MPIcon(bi);
  145. cache.put(maxWidth + "@" + maxHeight, imic);
  146. return imic;
  147. } else {
  148. return cache.get(maxWidth + "@" + maxHeight);
  149. }
  150. }
  151. private HashMap<String, MPIcon> cache = new HashMap<String, MPIcon>();
  152. /**
  153. * Convenience method that returns a scaled instance of the
  154. * provided {@code BufferedImage}.
  155. *
  156. * @param img the original image to be scaled
  157. * @param targetWidth the desired width of the scaled instance,
  158. * in pixels
  159. * @param targetHeight the desired height of the scaled instance,
  160. * in pixels
  161. * @param hint one of the rendering hints that corresponds to
  162. * {@code RenderingHints.KEY_INTERPOLATION} (e.g.
  163. * {@code RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR},
  164. * {@code RenderingHints.VALUE_INTERPOLATION_BILINEAR},
  165. * {@code RenderingHints.VALUE_INTERPOLATION_BICUBIC})
  166. * @param higherQuality if true, this method will use a multi-step
  167. * scaling technique that provides higher quality than the usual
  168. * one-step technique (only useful in downscaling cases, where
  169. * {@code targetWidth} or {@code targetHeight} is
  170. * smaller than the original dimensions, and generally only when
  171. * the {@code BILINEAR} hint is specified)
  172. * @return a scaled version of the original {@code BufferedImage}
  173. */
  174. public static BufferedImage getScaledInstance(BufferedImage img,
  175. int targetWidth,
  176. int targetHeight,
  177. Object hint,
  178. boolean higherQuality) {
  179. int type = (img.getTransparency() == Transparency.OPAQUE) ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
  180. BufferedImage ret = img;
  181. int w, h;
  182. if (higherQuality) {
  183. // Use multi-step technique: start with original size, then
  184. // scale down in multiple passes with drawImage()
  185. // until the target size is reached
  186. w = img.getWidth();
  187. h = img.getHeight();
  188. } else {
  189. return toBufferedImage(img.getScaledInstance(targetWidth, -1, BufferedImage.SCALE_SMOOTH));
  190. }
  191. do {
  192. if (higherQuality && w > targetWidth) {
  193. w /= 2;
  194. if (w < targetWidth) {
  195. w = targetWidth;
  196. }
  197. }
  198. if (higherQuality && h > targetHeight) {
  199. h /= 2;
  200. if (h < targetHeight) {
  201. h = targetHeight;
  202. }
  203. }
  204. BufferedImage tmp = new BufferedImage(w, h, type);
  205. Graphics2D g2 = tmp.createGraphics();
  206. g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
  207. g2.drawImage(ret, 0, 0, w, h, null);
  208. g2.dispose();
  209. ret = tmp;
  210. } while (w > targetWidth || h > targetHeight);
  211. return ret;
  212. }
  213. //
  214. /**
  215. * This method returns a buffered image with the contents of an image
  216. * @param image
  217. * @return
  218. */
  219. public static BufferedImage toBufferedImage(Image image) {
  220. if (image instanceof BufferedImage) {
  221. return (BufferedImage) image;
  222. }
  223. // This code ensures that all the pixels in the image are loaded
  224. image = new ImageIcon(image).getImage();
  225. // Determine if the image has transparent pixels; for this method's
  226. // implementation, see e661 Determining If an Image Has Transparent Pixels
  227. boolean hasAlpha = false;
  228. try {
  229. hasAlpha = hasAlpha(image);
  230. } catch (Exception e) {
  231. Log.Debug(MPIcon.class, "Could not determine alpha of image: " + image);
  232. }
  233. // Create a buffered image with a format that's compatible with the screen
  234. BufferedImage bimage = null;
  235. GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
  236. try {
  237. // Determine the type of transparency of the new buffered image
  238. int transparency = Transparency.OPAQUE;
  239. if (hasAlpha) {
  240. transparency = Transparency.BITMASK;
  241. }
  242. // Create the buffered image
  243. GraphicsDevice gs = ge.getDefaultScreenDevice();
  244. GraphicsConfiguration gc = gs.getDefaultConfiguration();
  245. bimage = gc.createCompatibleImage(
  246. image.getWidth(null), image.getHeight(null), transparency);
  247. } catch (HeadlessException e) {
  248. // The system does not have a screen
  249. }
  250. if (bimage == null) {
  251. // Create a buffered image using the default color model
  252. int type = BufferedImage.TYPE_INT_RGB;
  253. if (hasAlpha) {
  254. type = BufferedImage.TYPE_INT_ARGB;
  255. }
  256. bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
  257. }
  258. // Copy image to buffered image
  259. Graphics g = bimage.createGraphics();
  260. // Paint the image onto the buffered image
  261. g.drawImage(image, 0, 0, null);
  262. g.dispose();
  263. return bimage;
  264. }
  265. //
  266. /**
  267. * This method returns true if the specified image has transparent pixels
  268. * @param image
  269. * @return
  270. */
  271. public static boolean hasAlpha(Image image) {
  272. // If buffered image, the color model is readily available
  273. if (image instanceof BufferedImage) {
  274. BufferedImage bimage = (BufferedImage) image;
  275. return bimage.getColorModel().hasAlpha();
  276. }
  277. // Use a pixel grabber to retrieve the image's color model;
  278. // grabbing a single pixel is usually sufficient
  279. PixelGrabber pg = new PixelGrabber(image, 0, 0, 1, 1, false);
  280. try {
  281. pg.grabPixels();
  282. } catch (InterruptedException e) {
  283. }
  284. // Get the image's color model
  285. ColorModel cm = pg.getColorModel();
  286. return cm.hasAlpha();
  287. }
  288. /**
  289. * Scale the image of this icon
  290. * @param width
  291. * @param height
  292. * @return
  293. */
  294. public MPIcon getScaledIcon(int maxWidth, int maxHeight) {
  295. if (!cache.containsKey(maxWidth + "@" + maxHeight)) {
  296. BufferedImage bi = toBufferedImage(this.getImage());
  297. bi = getScaledInstance(bi, maxWidth, maxHeight, RenderingHints.VALUE_INTERPOLATION_BILINEAR, maxHeight > 0);
  298. MPIcon imic = new MPIcon(bi);
  299. cache.put(maxWidth + "@" + maxHeight, imic);
  300. return imic;
  301. } else {
  302. return cache.get(maxWidth + "@" + maxHeight);
  303. }
  304. }
  305. }