1 /*
   2  * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 import java.awt.image.BufferedImage;
  25 import java.awt.image.RenderedImage;
  26 
  27 /**
  28  * @test
  29  * @author Martin Desruisseaux
  30  */
  31 public final class GetTileGridOffset {
  32     public static void main(final String[] args) {
  33         final BufferedImage image = new BufferedImage(
  34                 20, 20, BufferedImage.TYPE_BYTE_GRAY);
  35         validate(image);
  36 
  37         final BufferedImage subImage = image.getSubimage(5, 5, 10, 10);
  38         verifyConsistency(subImage);
  39         validate(subImage);
  40     }
  41 
  42     /**
  43      * Verifies that the tile grid offsets of given image are consistent with
  44      * other properties (minimum pixel coordinates, minimum tile indices and
  45      * tile size). This method verifies the general contract, ignoring
  46      * simplifications brought by the {@link BufferedImage} specialization.
  47      * The purpose of this method is to demonstrate why tile grid offsets
  48      * need to be zero in the {@link BufferedImage} case.
  49      */
  50     private static void verifyConsistency(final RenderedImage image) {
  51         /*
  52          * This test will convert the coordinates of an arbitrary pixel in
  53          * the first tile to the indices of that tile. The expected result
  54          * is (minTileX, minTileY). We take the pixel in lower-right corner
  55          * of the first tile (the upper-left corner does not demonstrate
  56          * bug 8166038).
  57          */
  58         final int tileWidth  = image.getTileWidth();
  59         final int tileHeight = image.getTileHeight();
  60         final int x = image.getMinX() + tileWidth  - 1;
  61         final int y = image.getMinY() + tileHeight - 1;
  62         /*
  63          * From javax.media.jai.PlanarImage.XToTileX(int)
  64          * (omitting rounding toward negative infinity):
  65          *
  66          *  tileX = (x - tileGridXOffset) / tileWidth
  67          */
  68         int tileX = Math.floorDiv(x - image.getTileGridXOffset(), tileWidth);
  69         int tileY = Math.floorDiv(y - image.getTileGridYOffset(), tileHeight);
  70         int minTileX = image.getMinTileX();                 // Expected value
  71         int minTileY = image.getMinTileY();
  72         if (tileX != minTileX || tileY != minTileY) {
  73             throw new RuntimeException("Tile indices of upper-left tile"
  74                     + " shall be (" + minTileX + ", " + minTileY + ")."
  75                     + " But using the provided tileGridOffsets we got"
  76                     + " (" + tileX + ", " + tileY + ").");
  77         }
  78     }
  79 
  80     /**
  81      * Verifies that tile grid offsets are zero as required by
  82      * {@link BufferedImage} specification.
  83      */
  84     private static void validate(final BufferedImage image) {
  85         final int tileGridXOffset = image.getTileGridXOffset();
  86         final int tileGridYOffset = image.getTileGridYOffset();
  87         if (tileGridXOffset != 0) {
  88             throw new RuntimeException("BufferedImage.getTileGridXOffset()"
  89                     + " shall be zero. Got " + tileGridXOffset);
  90         }
  91         if (tileGridYOffset != 0) {
  92             throw new RuntimeException("BufferedImage.getTileGridTOffset()"
  93                     + " shall be zero. Got " + tileGridYOffset);
  94         }
  95     }
  96 }