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

832
LINES

< > BotCompany Repo | #1001447 // Image classes

JavaX fragment (include)

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

Author comment

Began life as a copy of #2000447

download  show line numbers  debug dex  old transpilations   

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

No comments. add comment

Snippet ID: #1001447
Snippet name: Image classes
Eternal ID of this version: #1001447/1
Text MD5: c3a61eaf63c792ea56e904d9041f84b6
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2015-10-16 17:34:51
Source code size: 22233 bytes / 832 lines
Pitched / IR pitched: No / Yes
Views / Downloads: 696 / 1136
Referenced in: [show references]