Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6357429

RenderedImage fails to draw if non WR returned from getTile( int, int )

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: P5 P5
    • None
    • 5.0
    • client-libs
    • 2d
    • x86
    • windows_xp

      FULL PRODUCT VERSION :
      java version "1.5.0-beta2"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta2-b51)
      Java HotSpot(TM) Client VM (build 1.5.0-beta2-b51, mixed mode, sharing)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows XP [Version 5.1.2600]
      I believe this bug happens across all OSes

      A DESCRIPTION OF THE PROBLEM :
      When drawing a RenderedImage, if the Raster returned from RenderedImage.getTile( int, int ) is not an instance of WritableRaster, a RasterFormatException is thrown for any Raster not located at (0,0).

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Create a RenderedImage implementation that returns an instance of java.awt.image.Raster from getData( int, int ), then attempt to draw that RenderedImage via java.awt.Graphics2D.drawRenderedImage( java.awt.image.RenderedImage, java.awt.geom.AffineTransform ).

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      RenderedImage is drawn.
      ACTUAL -
      First tile of RenderedImage is drawn, then an exception is thrown.

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      Exception in thread "AWT-EventQueue-0" java.awt.image.RasterFormatException: (parentX + width) is outside raster
              at java.awt.image.WritableRaster.createWritableChild(WritableRaster.java:210)
              at sun.java2d.SunGraphics2D.drawTranslatedRenderedImage(SunGraphics2D.java:2556)
              at sun.java2d.SunGraphics2D.drawRenderedImage(SunGraphics2D.java:2415)
              at RIBug$TestWin.paint(RIBug.java:216)
              at sun.awt.RepaintArea.paintComponent(RepaintArea.java:248)
              at sun.awt.RepaintArea.paint(RepaintArea.java:224)
              at sun.awt.windows.WComponentPeer.handleEvent(WComponentPeer.java:248)
              at java.awt.Component.dispatchEventImpl(Component.java:4009)
              at java.awt.Container.dispatchEventImpl(Container.java:2019)
              at java.awt.Window.dispatchEventImpl(Window.java:1764)
              at java.awt.Component.dispatchEvent(Component.java:3781)
              at java.awt.EventQueue.dispatchEvent(EventQueue.java:463)
              at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:234)
              at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:163)
              at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:157)
              at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:149)
              at java.awt.EventDispatchThread.run(EventDispatchThread.java:110)


      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      public class RIBug {
          
          private RIBug() {}
          
          public static void main( String[] args ) {
              final int imageWidth = 100;
              final int imageHeight = 100;
              final int numTilesX = 2;
              final int numTilesY = 2;
              final int tileWidth = 50;
              final int tileHeight = 50;
              
              final java.awt.image.SampleModel sampleModel =
                      new java.awt.image.ComponentSampleModel(
                              java.awt.image.DataBuffer.TYPE_BYTE, imageWidth,
                              imageHeight, 1, imageWidth, new int[] { 0, 1, 2 },
                              new int[] { 0, 0, 0 } );
                              
              final java.awt.image.ColorModel colorModel =
                          new java.awt.image.ComponentColorModel(
                              java.awt.color.ColorSpace.getInstance(
                                  java.awt.color.ColorSpace.CS_sRGB ),
                              false, false, java.awt.image.ColorModel.OPAQUE,
                              sampleModel.getTransferType() );
              
              final java.awt.image.Raster[][] tiles =
                                  new java.awt.image.Raster[ numTilesX ][ numTilesY ];
              
              byte[][] color = new byte[][] { {(byte)0xFF, 0x00, 0x00},
                                              {0x00, (byte)0xFF, 0x00},
                                              {0x00, 0x00, (byte)0xFF},
                                              {(byte)0xFF, (byte)0xFF, (byte)0xFF} };
                                              
              int colorIndex = 0;
              byte[][] data;
              
              for( int ty = 0; ty < numTilesY; ty++ ) {
                  for( int tx = 0; tx < numTilesX; tx++ ) {
                      data=new byte[sampleModel.getNumBands()][tileWidth*tileHeight];
                      
                      for( int band = 0; band < sampleModel.getNumBands(); band++ )
                          for( int i = 0; i < data[band].length; i ++ )
                              data[band][i] = color[colorIndex][band];
                      
                      tiles[tx][ty] = java.awt.image.Raster.createRaster(
                                          sampleModel.createCompatibleSampleModel(
                                                          tileWidth, tileHeight ),
                                          new java.awt.image.DataBufferByte(data,
                                                              tileWidth*tileHeight ),
                                          new java.awt.Point( tx * tileWidth,
                                                              ty * tileHeight ) );
                      
                      colorIndex++;
                  }
              }
              
              java.awt.image.RenderedImage ri = new java.awt.image.RenderedImage() {
                  public java.awt.image.WritableRaster copyData(
                                                  java.awt.image.WritableRaster wr ) {
                                                      
                      if( wr == null )
                          return (java.awt.image.WritableRaster)getData();
                      
                      for( int ty = this.getMinTileY();
                           ty < (this.getMinTileY()+this.getNumYTiles());
                           ty++ ) {
                               
                          if( (ty * this.getTileHeight()) >
                                              (wr.getMinY()+wr.getHeight()) ||
                              (ty * this.getTileHeight() + this.getTileHeight()) <
                                              wr.getMinY() )
                              
                              continue;
                          
                          for( int tx = this.getMinTileX();
                               tx < (this.getMinTileX()+this.getNumXTiles());
                               tx++ ) {
                                   
                              if( (tx * this.getTileWidth()) >
                                              (wr.getMinX()+wr.getWidth()) ||
                                  (tx * this.getTileWidth() + this.getTileWidth()) <
                                              wr.getMinX() )
                                  
                                  continue;
                              
                              java.awt.Rectangle dataRegion =
                                          tiles[tx][ty].getBounds().intersection(
                                                                  wr.getBounds() );
                              
                              wr.setDataElements(0,0,
                                         tiles[tx][ty].createChild( dataRegion.x,
                                                                    dataRegion.y,
                                                                    dataRegion.width,
                                                                    dataRegion.height,
                                                                    dataRegion.x,
                                                                    dataRegion.y,
                                                                    null ) );
                          }
                      }
                      return wr;
                  }
                  
                  public java.awt.image.Raster getData( java.awt.Rectangle r ) {
                      return copyData( java.awt.image.Raster.createWritableRaster(
                                              sampleModel.createCompatibleSampleModel(
                                                                          r.width,
                                                                          r.height ),
                                              r.getLocation() ) );
                  }
                  
                  public java.awt.image.Raster getData() {
                      return getData( new java.awt.Rectangle( this.getMinX(),
                                                              this.getMinY(),
                                                              this.getWidth(),
                                                              this.getHeight() ) );
                  }
                  
                  public java.awt.image.Raster getTile( int tx, int ty ) {
                      return tiles[tx][ty];
                  }
                  
                  public int getTileGridYOffset() {
                      return 0;
                  }
                  
                  public int getTileGridXOffset() {
                      return 0;
                  }
                  
                  public int getTileHeight() {
                      return tileHeight;
                  }
                  
                  public int getTileWidth() {
                      return tileWidth;
                  }
                  
                  public int getMinTileY() {
                      return 0;
                  }
                  
                  public int getMinTileX() {
                      return 0;
                  }
                  
                  public int getNumYTiles() {
                      return numTilesY;
                  }
                  
                  public int getNumXTiles() {
                      return numTilesX;
                  }
                  
                  public int getMinX() {
                      return tiles[getMinTileX()][getMinTileY()].getMinX();
                  }
                  
                  public int getMinY() {
                      return tiles[getMinTileX()][getMinTileY()].getMinY();
                  }
                  
                  public int getHeight() {
                      return sampleModel.getHeight();
                  }
                  
                  public int getWidth() {
                      return sampleModel.getWidth();
                  }
                  
                  public java.awt.image.SampleModel getSampleModel() {
                      return sampleModel;
                  }
                  
                  public java.awt.image.ColorModel getColorModel() {
                      return colorModel;
                  }
                  
                  public String[] getPropertyNames() {
                      return null;
                  }
                  
                  public Object getProperty( String propertyName ) {
                      return java.awt.Image.UndefinedProperty;
                  }
                  
                  public java.util.Vector<java.awt.image.RenderedImage> getSources() {
                      return new java.util.Vector();
                  }
              };
              
              TestWin win = new TestWin( ri );
              win.setDefaultCloseOperation( TestWin.DISPOSE_ON_CLOSE );
              win.setVisible( true );
          }
          
          private static class TestWin extends javax.swing.JDialog {
              private java.awt.image.RenderedImage image;
              
              public TestWin( java.awt.image.RenderedImage i ) {
                  image = i;
                  
                  setSize( image.getWidth(), image.getHeight() );
              }
              
              public void paint( java.awt.Graphics g ) {
                  super.paint( g );
                  
                  ((java.awt.Graphics2D)g).drawRenderedImage( image,
                                  java.awt.geom.AffineTransform.getTranslateInstance(
                                              image.getMinX(), image.getMinY() ) );
              }
          }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      With access to the source for the implementation of RenderedImage, I can ensure that the returned Raster is an instance of WritableRaster, however, if I cannot modify the source, this exception is unavoidable and unrecoverable with no workaround.

            Unassigned Unassigned
            prr Philip Race
            Votes:
            1 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Imported:
              Indexed: