Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

830
LINES

< > BotCompany Repo | #2000557 // Image classes

New Tinybrain snippet

1  
class RGB {
2  
  public final float r, g, b;
3  
4  
  public RGB(float r, float g, float b) {
5  
    this.r = r;
6  
    this.g = g;
7  
    this.b = b;
8  
  }
9  
10  
  public RGB(double r, double g, double b) {
11  
    this.r = (float) r;
12  
    this.g = (float) g;
13  
    this.b = (float) b;
14  
  }
15  
16  
  public RGB(double brightness) {
17  
    this.r = this.g = this.b = (float) brightness;
18  
  }
19  
20  
  public RGB(Color color) {
21  
    this.r = color.getRed()/255f;
22  
    this.g = color.getGreen()/255f;
23  
    this.b = color.getBlue()/255f;
24  
  }
25  
26  
  public RGB(String hex) {
27  
    r = Integer.parseInt(hex.substring(0, 2), 16)/255f;
28  
    g = Integer.parseInt(hex.substring(2, 4), 16)/255f;
29  
    b = Integer.parseInt(hex.substring(4, 6), 16)/255f;
30  
  }
31  
32  
  public float getComponent(int i) {
33  
    return i == 0 ? r : i == 1 ? g : b;
34  
  }
35  
36  
  public Color getColor() {
37  
    return new Color(normalize(r), normalize(g), normalize(b));
38  
  }
39  
  
40  
  static float normalize(float x) { return Math.max(0f, Math.min(1f, x)); }
41  
42  
  public static RGB newSafe(float r, float g, float b) {
43  
    return new RGB(Math.max(0, Math.min(1, r)), Math.max(0, Math.min(1, g)), Math.max(0, Math.min(1, b)));
44  
  }
45  
46  
  public int asInt() {
47  
    return getColor().getRGB() & 0xFFFFFF;
48  
  }
49  
50  
  public float getBrightness() {
51  
    return (r+g+b)/3.0f;
52  
  }
53  
54  
  public String getHexString() {
55  
    return Integer.toHexString(asInt() | 0xFF000000).substring(2).toUpperCase();
56  
  }
57  
58  
  @Override
59  
  public boolean equals(Object o) {
60  
    if (this == o) return true;
61  
    if (!(o instanceof RGB)) return false;
62  
63  
    RGB rgb = (RGB) o;
64  
65  
    if (Float.compare(rgb.b, b) != 0) return false;
66  
    if (Float.compare(rgb.g, g) != 0) return false;
67  
    if (Float.compare(rgb.r, r) != 0) return false;
68  
69  
    return true;
70  
  }
71  
72  
  @Override
73  
  public int hashCode() {
74  
    int result = (r != +0.0f ? Float.floatToIntBits(r) : 0);
75  
    result = 31 * result + (g != +0.0f ? Float.floatToIntBits(g) : 0);
76  
    result = 31 * result + (b != +0.0f ? Float.floatToIntBits(b) : 0);
77  
    return result;
78  
  }
79  
80  
  public boolean isBlack() {
81  
    return r == 0f && g == 0f && b == 0f;
82  
  }
83  
84  
  public boolean isWhite() {
85  
    return r == 1f && g == 1f && b == 1f;
86  
  }
87  
88  
  public String toString() {
89  
    return getHexString();
90  
  }
91  
}
92  
93  
class RGBImage {
94  
  private BufferedImage bufferedImage;
95  
  private File file;
96  
  private int width, height;
97  
  private int[] pixels;
98  
99  
  // color returned when getPixel is called with out-of-bounds position
100  
  private int background = 0xFFFFFF;
101  
102  
  public RGBImage(BufferedImage image) {
103  
    this(image, null);
104  
  }
105  
106  
  public RGBImage(BufferedImage image, File file) {
107  
    this.file = file;
108  
    bufferedImage = image;
109  
    width = image.getWidth();
110  
    height = image.getHeight();
111  
    pixels = new int[width*height];
112  
    PixelGrabber pixelGrabber = new PixelGrabber(image, 0, 0, width, height, pixels, 0, width);
113  
    try {
114  
      if (!pixelGrabber.grabPixels())
115  
        throw new RuntimeException("Could not grab pixels");
116  
      cleanPixels(); // set upper byte to 0
117  
    } catch (InterruptedException e) {
118  
      throw new RuntimeException(e);
119  
    }
120  
  }
121  
122  
  /** We assume it's a file name to load from */
123  
  public RGBImage(String file) throws IOException {
124  
    this(new File(file));
125  
  }
126  
127  
  public RGBImage(Dimension size, Color color) {
128  
    this(size.width, size.height, color);
129  
  }
130  
131  
  public RGBImage(Dimension size, RGB color) {
132  
    this(size.width, size.height, color);
133  
  }
134  
135  
  private void cleanPixels() {
136  
    for (int i = 0; i < pixels.length; i++)
137  
      pixels[i] &= 0xFFFFFF;
138  
  }
139  
140  
  public RGBImage(int width, int height, int[] pixels) {
141  
    this.width = width;
142  
    this.height = height;
143  
    this.pixels = pixels;
144  
  }
145  
146  
  public RGBImage(int w, int h, RGB[] pixels) {
147  
    this.width = w;
148  
    this.height = h;
149  
    this.pixels = asInts(pixels);
150  
  }
151  
152  
  public static int[] asInts(RGB[] pixels) {
153  
    int[] ints = new int[pixels.length];
154  
    for (int i = 0; i < pixels.length; i++)
155  
      ints[i] = pixels[i] == null ? 0 : pixels[i].getColor().getRGB();
156  
    return ints;
157  
  }
158  
159  
  public RGBImage(int w, int h, RGB rgb) {
160  
    this.width = w;
161  
    this.height = h;
162  
    this.pixels = new int[w*h];
163  
    int col = rgb.asInt();
164  
    if (col != 0)
165  
      for (int i = 0; i < pixels.length; i++)
166  
        pixels[i] = col;
167  
  }
168  
169  
  public RGBImage(RGBImage image) {
170  
    this(image.width, image.height, copyPixels(image.pixels));
171  
  }
172  
173  
  public RGBImage(int width, int height, Color color) {
174  
    this(width, height, new RGB(color));
175  
  }
176  
177  
  public RGBImage(File file) throws IOException {
178  
    this(javax.imageio.ImageIO.read(file));
179  
  }
180  
181  
  private static int[] copyPixels(int[] pixels) {
182  
    int[] copy = new int[pixels.length];
183  
    System.arraycopy(pixels, 0, copy, 0, pixels.length);
184  
    return copy;
185  
  }
186  
187  
  public int getIntPixel(int x, int y) {
188  
    if (inRange(x, y))
189  
      return pixels[y * width + x];
190  
    else
191  
      return background;
192  
  }
193  
194  
  public static RGB asRGB(int packed) {
195  
    int r = (packed >> 16) & 0xFF;
196  
    int g = (packed >> 8) & 0xFF;
197  
    int b = packed & 0xFF;
198  
    return new RGB(r / 255f, g / 255f, b / 255f);
199  
  }
200  
201  
  public RGB getRGB(int x, int y) {
202  
    if (inRange(x, y))
203  
      return asRGB(pixels[y * width + x]);
204  
    else
205  
      return new RGB(background);
206  
  }
207  
208  
  /** alias of getRGB - I kept typing getPixel instead of getRGB all the time, so I finally created it */
209  
  public RGB getPixel(int x, int y) {
210  
    return getRGB(x, y);
211  
  }
212  
213  
  public int getWidth() {
214  
    return width;
215  
  }
216  
217  
  public int getHeight() {
218  
    return height;
219  
  }
220  
221  
  /** Attention: cached, i.e. does not change when image itself changes */
222  
  /** @NotNull */
223  
  public BufferedImage getBufferedImage() {
224  
    if (bufferedImage == null) {
225  
      bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
226  
      //bufferedImage.setData(Raster.createRaster(new SampleModel()));
227  
      for (int y = 0; y < height; y++)
228  
        for (int x = 0; x < width; x++)
229  
          bufferedImage.setRGB(x, y, pixels[y*width+x]);
230  
    }
231  
    return bufferedImage;
232  
  }
233  
234  
  public RGBImage clip(Rectangle r) {
235  
    r = fixClipRect(r);
236  
    int[] newPixels;
237  
    try {
238  
      newPixels = new int[r.width*r.height];
239  
    } catch (RuntimeException e) {
240  
      System.out.println(r);
241  
      throw e;
242  
    }
243  
    for (int y = 0; y < r.height; y++) {
244  
      System.arraycopy(pixels, (y+r.y)*width+r.x, newPixels, y*r.width, r.width);
245  
    }
246  
    return new RGBImage(r.width, r.height, newPixels);
247  
  }
248  
249  
  private Rectangle fixClipRect(Rectangle r) {
250  
    r = r.intersection(new Rectangle(0, 0, width, height));
251  
    if (r.isEmpty())
252  
      r = new Rectangle(r.x, r.y, 0, 0);
253  
    return r;
254  
  }
255  
256  
  public File getFile() {
257  
    return file;
258  
  }
259  
260  
  /** can now also do GIF (not just JPEG) */
261  
  public static RGBImage load(String fileName) {
262  
    return load(new File(fileName));
263  
  }
264  
265  
  /** can now also do GIF (not just JPEG) */
266  
  public static RGBImage load(File file) {
267  
    try {
268  
      BufferedImage bufferedImage = javax.imageio.ImageIO.read(file);
269  
      return new RGBImage(bufferedImage);
270  
    } catch (IOException e) {
271  
      throw new RuntimeException(e);
272  
    }
273  
  }
274  
275  
  public int getInt(int x, int y) {
276  
    return pixels[y * width + x];
277  
  }
278  
279  
  public void save(File file) throws IOException {
280  
    String name = file.getName().toLowerCase();
281  
    String type;
282  
    if (name.endsWith(".png")) type = "png";
283  
    else if (name.endsWith(".jpg") || name.endsWith(".jpeg")) type = "jpeg";
284  
    else throw new IOException("Unknown image extension: " + name);
285  
    javax.imageio.ImageIO.write(getBufferedImage(), type, file);
286  
  }
287  
288  
  public static RGBImage dummyImage() {
289  
    return new RGBImage(1, 1, new int[] {0xFFFFFF});
290  
  }
291  
292  
  public int[] getPixels() {
293  
    return pixels;
294  
  }
295  
296  
  public void setPixel(int x, int y, RGB rgb) {
297  
    if (x >= 0 && y >= 0 && x < width && y < height)
298  
      pixels[y*width+x] = rgb.asInt();
299  
  }
300  
301  
  public void setPixel(int x, int y, Color color) {
302  
    setPixel(x, y, new RGB(color));
303  
  }
304  
305  
  public void setPixel(int x, int y, int rgb) {
306  
    if (x >= 0 && y >= 0 && x < width && y < height)
307  
      pixels[y*width+x] = rgb;
308  
  }
309  
310  
  public RGBImage copy() {
311  
    return new RGBImage(this);
312  
  }
313  
314  
  public boolean inRange(int x, int y) {
315  
    return x >= 0 && y >= 0 && x < width && y < height;
316  
  }
317  
318  
  public int getBackground() {
319  
    return background;
320  
  }
321  
322  
  public void setBackground(int background) {
323  
    this.background = background;
324  
  }
325  
326  
  public Dimension getSize() {
327  
    return new Dimension(width, height);
328  
  }
329  
330  
  @Override
331  
  public boolean equals(Object o) {
332  
    if (this == o) return true;
333  
    if (o == null || getClass() != o.getClass()) return false;
334  
335  
    RGBImage rgbImage = (RGBImage) o;
336  
337  
    if (height != rgbImage.height) return false;
338  
    if (width != rgbImage.width) return false;
339  
    if (!Arrays.equals(pixels, rgbImage.pixels)) return false;
340  
341  
    return true;
342  
  }
343  
344  
  @Override
345  
  public int hashCode() {
346  
    int result = width;
347  
    result = 31 * result + height;
348  
    result = 31 * result + Arrays.hashCode(pixels);
349  
    return result;
350  
  }
351  
352  
  public String getHex(int x, int y) {
353  
    return getPixel(x, y).getHexString();
354  
  }
355  
356  
  public RGBImage clip(int x, int y, int width, int height) {
357  
    return clip(new Rectangle(x, y, width, height));
358  
  }
359  
360  
  public RGBImage clipLine(int y) {
361  
    return clip(0, y, width, 1);
362  
  }
363  
364  
  public int numPixels() {
365  
    return width*height;
366  
  }
367  
}
368  
369  
abstract class Surface extends JPanel {
370  
371  
372  
  public Object AntiAlias = RenderingHints.VALUE_ANTIALIAS_ON;
373  
  public Object Rendering = RenderingHints.VALUE_RENDER_SPEED;
374  
  public AlphaComposite composite;
375  
  public Paint texture;
376  
  public BufferedImage bimg;
377  
  public int imageType;
378  
  public String name;
379  
  public boolean clearSurface = true;
380  
  // Demos using animated gif's that implement ImageObserver set dontThread.
381  
  public boolean dontThread;
382  
383  
  protected long sleepAmount = 50; // max20 fps
384  
385  
  private long orig, start, frame;
386  
  private Toolkit toolkit;
387  
  private boolean perfMonitor, outputPerf;
388  
  private int biw, bih;
389  
  private boolean clearOnce;
390  
  private boolean toBeInitialized = true;
391  
392  
393  
  public Surface() {
394  
    setDoubleBuffered(false);
395  
    toolkit = getToolkit();
396  
    name = this.getClass().getName();
397  
    name = name.substring(name.indexOf(".", 7)+1);
398  
    setImageType(0);
399  
400  
    // To launch an individual demo with the performance str output  :
401  
    //    java -Djava2demo.perf= -cp Java2Demo.jar demos.Clipping.ClipAnim
402  
    try {
403  
      if (System.getProperty("java2demo.perf") != null) {
404  
        perfMonitor = outputPerf = true;
405  
      }
406  
    } catch (Exception ex) { }
407  
  }
408  
409  
410  
    /*protected Image getImage(String name) {
411  
        return DemoImages.getImage(name, this);
412  
    }
413  
414  
415  
    protected Font getFont(String name) {
416  
        return DemoFonts.getFont(name);
417  
    }*/
418  
419  
420  
  public int getImageType() {
421  
    return imageType;
422  
  }
423  
424  
425  
  public void setImageType(int imgType) {
426  
    if (imgType == 0) {
427  
      imageType = 1;
428  
    } else {
429  
      imageType = imgType;
430  
    }
431  
    bimg = null;
432  
  }
433  
434  
435  
  public void setAntiAlias(boolean aa) {
436  
    AntiAlias = aa
437  
      ? RenderingHints.VALUE_ANTIALIAS_ON
438  
      : RenderingHints.VALUE_ANTIALIAS_OFF;
439  
  }
440  
441  
442  
  public void setRendering(boolean rd) {
443  
    Rendering = rd
444  
      ? RenderingHints.VALUE_RENDER_QUALITY
445  
      : RenderingHints.VALUE_RENDER_SPEED;
446  
  }
447  
448  
449  
  public void setTexture(Object obj) {
450  
    if (obj instanceof GradientPaint) {
451  
      texture = new GradientPaint(0, 0, Color.white,
452  
        getSize().width*2, 0, Color.green);
453  
    } else {
454  
      texture = (Paint) obj;
455  
    }
456  
  }
457  
458  
459  
  public void setComposite(boolean cp) {
460  
    composite = cp
461  
      ? AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f)
462  
      : null;
463  
  }
464  
465  
466  
  public void setMonitor(boolean pm) {
467  
    perfMonitor = pm;
468  
  }
469  
470  
471  
  public void setSleepAmount(long amount) {
472  
    sleepAmount = amount;
473  
  }
474  
475  
476  
  public long getSleepAmount() {
477  
    return sleepAmount;
478  
  }
479  
480  
481  
  public BufferedImage createBufferedImage(Graphics2D g2,
482  
                                           int w,
483  
                                           int h,
484  
                                           int imgType) {
485  
    BufferedImage bi = null;
486  
    if (imgType == 0) {
487  
      bi = (BufferedImage) g2.getDeviceConfiguration().
488  
        createCompatibleImage(w, h);
489  
    } else if (imgType > 0 && imgType < 14) {
490  
      bi = new BufferedImage(w, h, imgType);
491  
    } else if (imgType == 14) {
492  
      bi = createBinaryImage(w, h, 2);
493  
    } else if (imgType == 15) {
494  
      bi = createBinaryImage(w, h, 4);
495  
    } else if (imgType == 16) {
496  
      bi = createSGISurface(w, h, 32);
497  
    } else if (imgType == 17) {
498  
      bi = createSGISurface(w, h, 16);
499  
    }
500  
    biw = w;
501  
    bih = h;
502  
    return bi;
503  
  }
504  
505  
506  
  // Lookup tables for BYTE_BINARY 1, 2 and 4 bits.
507  
  static byte[] lut1Arr = new byte[] {0, (byte)255 };
508  
  static byte[] lut2Arr = new byte[] {0, (byte)85, (byte)170, (byte)255};
509  
  static byte[] lut4Arr = new byte[] {0, (byte)17, (byte)34, (byte)51,
510  
    (byte)68, (byte)85,(byte) 102, (byte)119,
511  
    (byte)136, (byte)153, (byte)170, (byte)187,
512  
    (byte)204, (byte)221, (byte)238, (byte)255};
513  
514  
515  
  private BufferedImage createBinaryImage(int w, int h, int pixelBits) {
516  
    int bytesPerRow = w * pixelBits / 8;
517  
    if (w * pixelBits % 8 != 0) {
518  
      bytesPerRow++;
519  
    }
520  
    byte[] imageData = new byte[h * bytesPerRow];
521  
    IndexColorModel cm = null;
522  
    switch (pixelBits) {
523  
      case 1:
524  
        cm = new IndexColorModel(pixelBits, lut1Arr.length,
525  
          lut1Arr, lut1Arr, lut1Arr);
526  
        break;
527  
      case 2:
528  
        cm = new IndexColorModel(pixelBits, lut2Arr.length,
529  
          lut2Arr, lut2Arr, lut2Arr);
530  
        break;
531  
      case 4:
532  
        cm = new IndexColorModel(pixelBits, lut4Arr.length,
533  
          lut4Arr, lut4Arr, lut4Arr);
534  
        break;
535  
      default:
536  
      {new Exception("Invalid # of bit per pixel").printStackTrace();}
537  
    }
538  
539  
    DataBuffer db = new DataBufferByte(imageData, imageData.length);
540  
    WritableRaster r = Raster.createPackedRaster(db, w, h, pixelBits, null);
541  
    return new BufferedImage(cm, r, false, null);
542  
  }
543  
544  
  private BufferedImage createSGISurface(int w, int h, int pixelBits) {
545  
    int rMask32 = 0xFF000000;
546  
    int rMask16 = 0xF800;
547  
    int gMask32 = 0x00FF0000;
548  
    int gMask16 = 0x07C0;
549  
    int bMask32 = 0x0000FF00;
550  
    int bMask16 = 0x003E;
551  
552  
    DirectColorModel dcm = null;
553  
    DataBuffer db = null;
554  
    WritableRaster wr = null;
555  
    switch (pixelBits) {
556  
      case 16:
557  
        short[] imageDataUShort = new short[w * h];
558  
        dcm = new DirectColorModel(16, rMask16, gMask16, bMask16);
559  
        db = new DataBufferUShort(imageDataUShort, imageDataUShort.length);
560  
        wr = Raster.createPackedRaster(db, w, h, w,
561  
          new int[] {rMask16, gMask16, bMask16},
562  
          null);
563  
        break;
564  
      case 32:
565  
        int[] imageDataInt = new int[w * h];
566  
        dcm = new DirectColorModel(32, rMask32, gMask32, bMask32);
567  
        db = new DataBufferInt(imageDataInt, imageDataInt.length);
568  
        wr = Raster.createPackedRaster(db, w, h, w,
569  
          new int[] {rMask32, gMask32, bMask32},
570  
          null);
571  
        break;
572  
      default:
573  
      {new Exception("Invalid # of bit per pixel").printStackTrace();}
574  
    }
575  
576  
    return new BufferedImage(dcm, wr, false, null);
577  
  }
578  
579  
  public Graphics2D createGraphics2D(int width,
580  
                                     int height,
581  
                                     BufferedImage bi,
582  
                                     Graphics g) {
583  
584  
    Graphics2D g2 = null;
585  
586  
    if (bi != null) {
587  
      g2 = bi.createGraphics();
588  
    } else {
589  
      g2 = (Graphics2D) g;
590  
    }
591  
592  
    g2.setBackground(getBackground());
593  
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, AntiAlias);
594  
    g2.setRenderingHint(RenderingHints.KEY_RENDERING, Rendering);
595  
596  
    if (clearSurface || clearOnce) {
597  
      g2.clearRect(0, 0, width, height);
598  
      clearOnce = false;
599  
    }
600  
601  
    if (texture != null) {
602  
      // set composite to opaque for texture fills
603  
      g2.setComposite(AlphaComposite.SrcOver);
604  
      g2.setPaint(texture);
605  
      g2.fillRect(0, 0, width, height);
606  
    }
607  
608  
    if (composite != null) {
609  
      g2.setComposite(composite);
610  
    }
611  
612  
    return g2;
613  
  }
614  
615  
  public abstract void render(int w, int h, Graphics2D g);
616  
617  
618  
  /**
619  
   * It's possible to turn off double-buffering for just the repaint
620  
   * calls invoked directly on the non double buffered component.
621  
   * This can be done by overriding paintImmediately() (which is called
622  
   * as a result of repaint) and getting the current RepaintManager and
623  
   * turning off double buffering in the RepaintManager before calling
624  
   * super.paintImmediately(g).
625  
   */
626  
  public void paintImmediately(int x,int y,int w, int h) {
627  
    RepaintManager repaintManager = null;
628  
    boolean save = true;
629  
    if (!isDoubleBuffered()) {
630  
      repaintManager = RepaintManager.currentManager(this);
631  
      save = repaintManager.isDoubleBufferingEnabled();
632  
      repaintManager.setDoubleBufferingEnabled(false);
633  
    }
634  
    super.paintImmediately(x, y, w, h);
635  
636  
    if (repaintManager != null) {
637  
      repaintManager.setDoubleBufferingEnabled(save);
638  
    }
639  
  }
640  
641  
642  
  public void paint(Graphics g) {
643  
644  
    Dimension d = getSize();
645  
646  
    if (imageType == 1)
647  
      bimg = null;
648  
    else if (bimg == null || biw != d.width || bih != d.height) {
649  
      bimg = createBufferedImage((Graphics2D)g,
650  
        d.width, d.height, imageType-2);
651  
      clearOnce = true;
652  
      toBeInitialized = true;
653  
    }
654  
655  
    if (toBeInitialized) {
656  
      toBeInitialized = false;
657  
      startClock();
658  
    }
659  
660  
    Graphics2D g2 = createGraphics2D(d.width, d.height, bimg, g);
661  
    render(d.width, d.height, g2);
662  
    g2.dispose();
663  
664  
    if (bimg != null)  {
665  
      g.drawImage(bimg, 0, 0, null);
666  
      toolkit.sync();
667  
    }
668  
669  
  }
670  
671  
672  
  public void startClock() {
673  
    orig = System.currentTimeMillis();
674  
    start = orig;
675  
    frame = 0;
676  
  }
677  
678  
  private static final int REPORTFRAMES = 30;
679  
680  
681  
  public static void setAlpha(Graphics2D g, float alpha) {
682  
    g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
683  
  }
684  
}
685  
686  
class ImageSurface extends Surface {
687  
  private BufferedImage image;
688  
  private double zoomX = 1, zoomY = 1;
689  
  private Rectangle selection;
690  
691  
  public ImageSurface() {
692  
    this(new RGBImage(1, 1, new int[] { 0xFFFFFF }));
693  
  }
694  
695  
  public ImageSurface(RGBImage image) {
696  
    this(image.getBufferedImage());
697  
  }
698  
699  
  public ImageSurface(BufferedImage image) {
700  
    clearSurface = false;
701  
    this.image = image;
702  
703  
    /*addMouseMotionListener(new MouseAdapter() {
704  
      public void mouseMoved(MouseEvent e) {
705  
        getMousePosition()
706  
707  
      }
708  
    });*/
709  
  }
710  
711  
  public ImageSurface(RGBImage image, double zoom) {
712  
    this(image);
713  
    setZoom(zoom);
714  
  }
715  
716  
  public void render(int w, int h, Graphics2D g) {
717  
    g.setColor(Color.white);
718  
    g.fillRect(0, 0, w, h);
719  
    if (image != null)
720  
      g.drawImage(image, 0, 0, getZoomedWidth(), getZoomedHeight(), null);
721  
722  
    if (selection != null) {
723  
      // drawRect is inclusive, selection is exclusive, so... whatever, tests show it's cool.
724  
      drawSelectionRect(g, selection, Color.green, Color.white);
725  
    }
726  
  }
727  
728  
  public void drawSelectionRect(Graphics2D g, Rectangle selection, Color green, Color white) {
729  
    g.setColor(green);
730  
    int top = (int) (selection.y * zoomY);
731  
    int bottom = (int) ((selection.y+selection.height) * zoomY);
732  
    int left = (int) (selection.x * zoomX);
733  
    int right = (int) ((selection.x+selection.width) * zoomX);
734  
    g.drawRect(left-1, top-1, right-left+1, bottom-top+1);
735  
    g.setColor(white);
736  
    g.drawRect(left - 2, top - 2, right - left + 3, bottom - top + 3);
737  
  }
738  
739  
  public void setZoom(double zoom) {
740  
    setZoom(zoom, zoom);
741  
  }
742  
743  
  public void setZoom(double zoomX, double zoomY) {
744  
    this.zoomX = zoomX;
745  
    this.zoomY = zoomY;
746  
    revalidate();
747  
    repaint();
748  
  }
749  
750  
  public Dimension getMinimumSize() {
751  
    int w = getZoomedWidth();
752  
    int h = getZoomedHeight();
753  
    Dimension min = super.getMinimumSize();
754  
    return new Dimension(Math.max(w, min.width), Math.max(h, min.height));
755  
  }
756  
757  
  private int getZoomedHeight() {
758  
    return (int) (image.getHeight() * zoomY);
759  
  }
760  
761  
  private int getZoomedWidth() {
762  
    return (int) (image.getWidth() * zoomX);
763  
  }
764  
765  
  public void setImage(RGBImage image) {
766  
    setImage(image.getBufferedImage());
767  
  }
768  
769  
  public void setImage(BufferedImage image) {
770  
    this.image = image;
771  
    revalidate();
772  
    repaint();
773  
  }
774  
775  
  public BufferedImage getImage() {
776  
    return image;
777  
  }
778  
779  
  public double getZoomX() {
780  
    return zoomX;
781  
  }
782  
783  
  public double getZoomY() {
784  
    return zoomY;
785  
  }
786  
787  
  public Dimension getPreferredSize() {
788  
    return new Dimension(getZoomedWidth(), getZoomedHeight());
789  
  }
790  
791  
  /** returns a scrollpane with the scroll-mode prevent-garbage-drawing fix applied */
792  
  public JScrollPane makeScrollPane() {
793  
    JScrollPane scrollPane = new JScrollPane(this);
794  
    scrollPane.getViewport().setScrollMode(JViewport.BACKINGSTORE_SCROLL_MODE);
795  
    return scrollPane;
796  
  }
797  
798  
  public void zoomToDisplaySize() {
799  
    if (image == null) return;
800  
    Dimension display = getDisplaySize();
801  
    double xRatio = display.width/(double) image.getWidth();
802  
    double yRatio = display.height/(double) image.getHeight();
803  
    setZoom(Math.min(xRatio, yRatio));
804  
    revalidate();
805  
  }
806  
807  
  /** tricky magic to get parent scroll pane */
808  
  private Dimension getDisplaySize() {
809  
    Container c = getParent();
810  
    while (c != null) {
811  
      if (c instanceof JScrollPane)
812  
        return c.getSize();
813  
      c = c.getParent();
814  
    }
815  
    return getSize();
816  
  }
817  
818  
  public void setSelection(Rectangle r) {
819  
    selection = r;
820  
    repaint();
821  
  }
822  
823  
  public Rectangle getSelection() {
824  
    return selection;
825  
  }
826  
827  
  public RGBImage getRGBImage() {
828  
    return new RGBImage(getImage());
829  
  }
830  
}

Author comment

Began life as a copy of #2000447

download  show line numbers   

Snippet is not live.

Travelled to 12 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt

1 comment(s) hidden. show

Snippet ID: #2000557
Snippet name: Image classes
Eternal ID of this version: #2000557/1
Text MD5: f9f9856d37015d0fd7cb369d22859c20
Author: stefan
Category: javax
Type: New Tinybrain snippet
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2015-09-13 00:39:01
Source code size: 22273 bytes / 830 lines
Pitched / IR pitched: No / Yes
Views / Downloads: 795 / 172
Referenced in: [show references]