diff --git a/ij/gui/ImageCanvas.java b/ij/gui/ImageCanvas.java index 747915ea9..896a00692 100644 --- a/ij/gui/ImageCanvas.java +++ b/ij/gui/ImageCanvas.java @@ -78,6 +78,7 @@ public class ImageCanvas extends Canvas implements MouseListener, MouseMotionLis private Image offScreenImage; private int offScreenWidth = 0; private int offScreenHeight = 0; + private boolean offScreenDeviceBuffer; private boolean mouseExited = true; private boolean customRoi; private boolean drawNames; @@ -538,10 +539,36 @@ void drawZoomIndicator(Graphics g) { void paintDoubleBuffered(Graphics g) { final int srcRectWidthMag = (int)(srcRect.width*magnification+0.5); final int srcRectHeightMag = (int)(srcRect.height*magnification+0.5); - if (offScreenImage==null || offScreenWidth!=srcRectWidthMag || offScreenHeight!=srcRectHeightMag) { - offScreenImage = createImage(srcRectWidthMag, srcRectHeightMag); - offScreenWidth = srcRectWidthMag; - offScreenHeight = srcRectHeightMag; + AffineTransform transform = ((Graphics2D)g).getTransform(); + boolean deviceBuffer = transform.getScaleX()!=1.0 || transform.getScaleY()!=1.0 + || transform.getShearX()!=0.0 || transform.getShearY()!=0.0 + || transform.getTranslateX()!=Math.floor(transform.getTranslateX()) + || transform.getTranslateY()!=Math.floor(transform.getTranslateY()); + Rectangle bufferBounds = deviceBuffer + ? transform.createTransformedShape(new Rectangle(0, 0, srcRectWidthMag, srcRectHeightMag)).getBounds() + : new Rectangle(0, 0, srcRectWidthMag, srcRectHeightMag); + final int bufferWidth = bufferBounds.width; + final int bufferHeight = bufferBounds.height; + if (bufferWidth<=0 || bufferHeight<=0) + return; + AffineTransform imageTransform = null; + if (deviceBuffer) { + try { + imageTransform = transform.createInverse(); + imageTransform.translate(bufferBounds.x, bufferBounds.y); + } catch (NoninvertibleTransformException e) { return; } + } + if (offScreenImage==null || offScreenWidth!=bufferWidth || offScreenHeight!=bufferHeight + || offScreenDeviceBuffer!=deviceBuffer) { + if (offScreenImage!=null) + offScreenImage.flush(); + // Explicit raster dimensions avoid depending on a platform Image's backing scale. + offScreenImage = !deviceBuffer + ? createImage(bufferWidth, bufferHeight) + : new BufferedImage(bufferWidth, bufferHeight, BufferedImage.TYPE_INT_ARGB); + offScreenWidth = bufferWidth; + offScreenHeight = bufferHeight; + offScreenDeviceBuffer = deviceBuffer; } Roi roi = imp.getRoi(); try { @@ -550,22 +577,42 @@ void paintDoubleBuffered(Graphics g) { imp.updateImage(); } Graphics offScreenGraphics = offScreenImage.getGraphics(); - setInterpolation(offScreenGraphics, Prefs.interpolateScaledImages); - Image img = imp.getImage(); - if (img!=null) - offScreenGraphics.drawImage(img, 0, 0, srcRectWidthMag, srcRectHeightMag, - srcRect.x, srcRect.y, srcRect.x+srcRect.width, srcRect.y+srcRect.height, null); - Overlay overlay = imp.getOverlay(); - if (overlay!=null) - drawOverlay(overlay, offScreenGraphics); - if (showAllOverlay!=null) - drawOverlay(showAllOverlay, offScreenGraphics); - if (roi!=null) - drawRoi(roi, offScreenGraphics); - if (srcRect.width