4924727: reader.abort() method does not work when called inside imageStarted for PNG
authorjdv
Mon, 12 Sep 2016 12:07:56 +0530
changeset 41010 9824689edeb1
parent 41009 4ac943a81e95
child 41011 45626938f66a
4924727: reader.abort() method does not work when called inside imageStarted for PNG Reviewed-by: prr, serb, bpb
jdk/make/mapfiles/libjpeg/mapfile-vers
jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java
jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java
jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java
jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java
jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java
jdk/src/java.desktop/share/native/libjavajpeg/imageioJPEG.c
jdk/test/javax/imageio/ReadAbortTest.java
--- a/jdk/make/mapfiles/libjpeg/mapfile-vers	Sat Sep 10 14:50:35 2016 +0530
+++ b/jdk/make/mapfiles/libjpeg/mapfile-vers	Mon Sep 12 12:07:56 2016 +0530
@@ -42,6 +42,7 @@
         Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_resetReader;
         Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_disposeReader;
         Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_resetLibraryState;
+        Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_clearNativeReadAbortFlag;
         Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_initWriterIDs;
         Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_initJPEGImageWriter;
         Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_setDest;
--- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java	Sat Sep 10 14:50:35 2016 +0530
+++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java	Mon Sep 12 12:07:56 2016 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -749,6 +749,10 @@
         checkIndex(imageIndex);
         clearAbortRequest();
         processImageStarted(imageIndex);
+        if (abortRequested()) {
+            processReadAborted();
+            return bi;
+        }
 
         if (param == null)
             param = getDefaultReadParam();
@@ -1005,9 +1009,6 @@
             int j = isBottomUp ? (height -1)*bytesPerScanline : 0;
 
             for (int i=0; i<height; i++) {
-                if (abortRequested()) {
-                    break;
-                }
                 iis.readFully(bdata, j, bytesPerScanline);
                 iis.skipBytes(padding);
                 j += isBottomUp ? -bytesPerScanline : bytesPerScanline;
@@ -1015,6 +1016,9 @@
                                    destinationRegion.width, 1, 1, 1,
                                    new int[]{0});
                 processImageProgress(100.0F * i/destinationRegion.height);
+                if (abortRequested()) {
+                    break;
+                }
             }
         } else {
             byte[] buf = new byte[lineLength];
@@ -1051,9 +1055,6 @@
 
             for (int j = 0, y = sourceRegion.y;
                  j < destinationRegion.height; j++, y+=scaleY) {
-
-                if (abortRequested())
-                    break;
                 iis.read(buf, 0, lineLength);
                 for (int i = 0; i < destinationRegion.width; i++) {
                     //get the bit and assign to the data buffer of the raster
@@ -1067,6 +1068,9 @@
                                    destinationRegion.width, 1, 1, 1,
                                    new int[]{0});
                 processImageProgress(100.0F*j/destinationRegion.height);
+                if (abortRequested()) {
+                    break;
+                }
             }
         }
     }
@@ -1087,9 +1091,6 @@
             int j = isBottomUp ? (height -1) * bytesPerScanline : 0;
 
             for (int i=0; i<height; i++) {
-                if (abortRequested()) {
-                    break;
-                }
                 iis.readFully(bdata, j, bytesPerScanline);
                 iis.skipBytes(padding);
                 j += isBottomUp ? -bytesPerScanline : bytesPerScanline;
@@ -1097,6 +1098,9 @@
                                    destinationRegion.width, 1, 1, 1,
                                    new int[]{0});
                 processImageProgress(100.0F * i/destinationRegion.height);
+                if (abortRequested()) {
+                    break;
+                }
             }
         } else {
             byte[] buf = new byte[lineLength];
@@ -1133,9 +1137,6 @@
 
             for (int j = 0, y = sourceRegion.y;
                  j < destinationRegion.height; j++, y+=scaleY) {
-
-                if (abortRequested())
-                    break;
                 iis.read(buf, 0, lineLength);
                 for (int i = 0; i < destinationRegion.width; i++) {
                     //get the bit and assign to the data buffer of the raster
@@ -1149,6 +1150,9 @@
                                    destinationRegion.width, 1, 1, 1,
                                    new int[]{0});
                 processImageProgress(100.0F*j/destinationRegion.height);
+                if (abortRequested()) {
+                    break;
+                }
             }
         }
     }
@@ -1168,9 +1172,6 @@
             int j = isBottomUp ? (height -1) * width : 0;
 
             for (int i=0; i<height; i++) {
-                if (abortRequested()) {
-                    break;
-                }
                 iis.readFully(bdata, j, width);
                 iis.skipBytes(padding);
                 j += isBottomUp ? -width : width;
@@ -1178,6 +1179,9 @@
                                    destinationRegion.width, 1, 1, 1,
                                    new int[]{0});
                 processImageProgress(100.0F * i/destinationRegion.height);
+                if (abortRequested()) {
+                    break;
+                }
             }
         } else {
             byte[] buf = new byte[lineLength];
@@ -1200,9 +1204,6 @@
 
             for (int j = 0, y = sourceRegion.y;
                  j < destinationRegion.height; j++, y+=scaleY) {
-
-                if (abortRequested())
-                    break;
                 iis.read(buf, 0, lineLength);
                 for (int i = 0, m = sourceRegion.x;
                      i < destinationRegion.width; i++, m += scaleX) {
@@ -1216,6 +1217,9 @@
                                    destinationRegion.width, 1, 1, 1,
                                    new int[]{0});
                 processImageProgress(100.0F*j/destinationRegion.height);
+                if (abortRequested()) {
+                    break;
+                }
             }
         }
     }
@@ -1235,9 +1239,6 @@
             int j = isBottomUp ? (height -1) * width * 3 : 0;
 
             for (int i=0; i<height; i++) {
-                if (abortRequested()) {
-                    break;
-                }
                 iis.readFully(bdata, j, lineStride);
                 iis.skipBytes(padding);
                 j += isBottomUp ? -lineStride : lineStride;
@@ -1245,6 +1246,9 @@
                                    destinationRegion.width, 1, 1, 1,
                                    new int[]{0});
                 processImageProgress(100.0F * i/destinationRegion.height);
+                if (abortRequested()) {
+                    break;
+                }
             }
         } else {
             byte[] buf = new byte[lineLength];
@@ -1267,9 +1271,6 @@
 
             for (int j = 0, y = sourceRegion.y;
                  j < destinationRegion.height; j++, y+=scaleY) {
-
-                if (abortRequested())
-                    break;
                 iis.read(buf, 0, lineLength);
                 for (int i = 0, m = 3 * sourceRegion.x;
                      i < destinationRegion.width; i++, m += 3 * scaleX) {
@@ -1285,6 +1286,9 @@
                                    destinationRegion.width, 1, 1, 1,
                                    new int[]{0});
                 processImageProgress(100.0F*j/destinationRegion.height);
+                if (abortRequested()) {
+                    break;
+                }
             }
         }
     }
@@ -1302,10 +1306,6 @@
         if (noTransform) {
             int j = isBottomUp ? (height -1) * width : 0;
             for (int i=0; i<height; i++) {
-                if (abortRequested()) {
-                    break;
-                }
-
                 iis.readFully(sdata, j, width);
                 iis.skipBytes(padding);
 
@@ -1314,6 +1314,9 @@
                                    destinationRegion.width, 1, 1, 1,
                                    new int[]{0});
                 processImageProgress(100.0F * i/destinationRegion.height);
+                if (abortRequested()) {
+                    break;
+                }
             }
         } else {
             short[] buf = new short[lineLength];
@@ -1336,9 +1339,6 @@
 
             for (int j = 0, y = sourceRegion.y;
                  j < destinationRegion.height; j++, y+=scaleY) {
-
-                if (abortRequested())
-                    break;
                 iis.readFully(buf, 0, lineLength);
                 for (int i = 0, m = sourceRegion.x;
                      i < destinationRegion.width; i++, m += scaleX) {
@@ -1352,6 +1352,9 @@
                                    destinationRegion.width, 1, 1, 1,
                                    new int[]{0});
                 processImageProgress(100.0F*j/destinationRegion.height);
+                if (abortRequested()) {
+                    break;
+                }
             }
         }
     }
@@ -1361,15 +1364,15 @@
             int j = isBottomUp ? (height -1) * width : 0;
 
             for (int i=0; i<height; i++) {
-                if (abortRequested()) {
-                    break;
-                }
                 iis.readFully(idata, j, width);
                 j += isBottomUp ? -width : width;
                 processImageUpdate(bi, 0, i,
                                    destinationRegion.width, 1, 1, 1,
                                    new int[]{0});
                 processImageProgress(100.0F * i/destinationRegion.height);
+                if (abortRequested()) {
+                    break;
+                }
             }
         } else {
             int[] buf = new int[width];
@@ -1392,9 +1395,6 @@
 
             for (int j = 0, y = sourceRegion.y;
                  j < destinationRegion.height; j++, y+=scaleY) {
-
-                if (abortRequested())
-                    break;
                 iis.readFully(buf, 0, width);
                 for (int i = 0, m = sourceRegion.x;
                      i < destinationRegion.width; i++, m += scaleX) {
@@ -1408,6 +1408,9 @@
                                    destinationRegion.width, 1, 1, 1,
                                    new int[]{0});
                 processImageProgress(100.0F*j/destinationRegion.height);
+                if (abortRequested()) {
+                    break;
+                }
             }
         }
     }
--- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java	Sat Sep 10 14:50:35 2016 +0530
+++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java	Mon Sep 12 12:07:56 2016 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -456,6 +456,9 @@
                 // Update IIOReadProgressListeners
                 ++rowsDone;
                 processImageProgress(100.0F*rowsDone/height);
+                if (abortRequested()) {
+                    return;
+                }
 
                 if (decodeThisRow) {
                     outputRow();
@@ -860,7 +863,6 @@
             throw new IndexOutOfBoundsException("imageIndex out of bounds!");
         }
 
-        clearAbortRequest();
         readMetadata();
 
         // A null ImageReadParam means we use the default
@@ -903,8 +905,13 @@
             (streamY - sourceRegion.y)/sourceYSubsampling;
         computeDecodeThisRow();
 
+        clearAbortRequest();
         // Inform IIOReadProgressListeners of start of image
         processImageStarted(imageIndex);
+        if (abortRequested()) {
+            processReadAborted();
+            return theImage;
+        }
         startPass(0);
 
         this.rowBuf = new byte[width];
@@ -947,7 +954,7 @@
             int codeSize = initCodeSize + 1;
             int codeMask = (1 << codeSize) - 1;
 
-            while (!abortRequested()) {
+            do {
                 code = getCode(codeSize, codeMask);
 
                 if (code == clearCode) {
@@ -1005,7 +1012,7 @@
 
                 outputPixels(string, len);
                 oldCode = code;
-            }
+            } while (!abortRequested());
 
             processReadAborted();
             return theImage;
--- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java	Sat Sep 10 14:50:35 2016 +0530
+++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java	Mon Sep 12 12:07:56 2016 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1327,28 +1327,32 @@
             System.out.println("callbackUpdates is " + callbackUpdates);
         }
 
-        // Finally, we are ready to read
-
+        /*
+         * All the Jpeg processing happens in native, we should clear
+         * abortFlag of imageIODataStruct in imageioJPEG.c. And we need to
+         * clear abortFlag because if in previous read() if we had called
+         * reader.abort() that will continue to be valid for present call also.
+         */
+        clearNativeReadAbortFlag(structPointer);
         processImageStarted(currentImage);
-
-        boolean aborted = false;
-
-        // Note that getData disables acceleration on buffer, but it is
-        // just a 1-line intermediate data transfer buffer that will not
-        // affect the acceleration of the resulting image.
-        aborted = readImage(structPointer,
-                            buffer.getData(),
-                            numRasterBands,
-                            srcBands,
-                            bandSizes,
-                            srcROI.x, srcROI.y,
-                            srcROI.width, srcROI.height,
-                            periodX, periodY,
-                            abbrevQTables,
-                            abbrevDCHuffmanTables,
-                            abbrevACHuffmanTables,
-                            minProgressivePass, maxProgressivePass,
-                            callbackUpdates);
+        /*
+         * Note that getData disables acceleration on buffer, but it is
+         * just a 1-line intermediate data transfer buffer that will not
+         * affect the acceleration of the resulting image.
+         */
+        boolean aborted = readImage(structPointer,
+                                    buffer.getData(),
+                                    numRasterBands,
+                                    srcBands,
+                                    bandSizes,
+                                    srcROI.x, srcROI.y,
+                                    srcROI.width, srcROI.height,
+                                    periodX, periodY,
+                                    abbrevQTables,
+                                    abbrevDCHuffmanTables,
+                                    abbrevACHuffmanTables,
+                                    minProgressivePass, maxProgressivePass,
+                                    callbackUpdates);
 
         if (aborted) {
             processReadAborted();
@@ -1513,6 +1517,12 @@
                                      int maxProgressivePass,
                                      boolean wantUpdates);
 
+    /*
+     * We should call clearNativeReadAbortFlag() before we start reading
+     * jpeg image as image processing happens at native side.
+     */
+    private native void clearNativeReadAbortFlag(long structPointer);
+
     public void abort() {
         setThreadLock();
         try {
--- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java	Sat Sep 10 14:50:35 2016 +0530
+++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java	Mon Sep 12 12:07:56 2016 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -937,12 +937,6 @@
         for (int srcY = 0; srcY < passHeight; srcY++) {
             // Skip filter byte and the remaining row bytes
             pixelStream.skipBytes(1 + bytesPerRow);
-
-            // If read has been aborted, just return
-            // processReadAborted will be called later
-            if (abortRequested()) {
-                return;
-            }
         }
     }
 
@@ -996,6 +990,13 @@
             for (int srcY = 0; srcY < passHeight; srcY++) {
                 // Update count of pixels read
                 updateImageProgress(passWidth);
+                /*
+                 * If read has been aborted, just return
+                 * processReadAborted will be called later
+                 */
+                if (abortRequested()) {
+                    return;
+                }
                 // Skip filter byte and the remaining row bytes
                 pixelStream.skipBytes(1 + bytesPerRow);
             }
@@ -1105,7 +1106,13 @@
         for (int srcY = 0; srcY < passHeight; srcY++) {
             // Update count of pixels read
             updateImageProgress(passWidth);
-
+            /*
+             * If read has been aborted, just return
+             * processReadAborted will be called later
+             */
+            if (abortRequested()) {
+                return;
+            }
             // Read the filter type byte and a row of data
             int filter = pixelStream.read();
             try {
@@ -1195,12 +1202,6 @@
                                    updateWidth, 1,
                                    updateXStep, updateYStep,
                                    destinationBands);
-
-                // If read has been aborted, just return
-                // processReadAborted will be called later
-                if (abortRequested()) {
-                    return;
-                }
             }
         }
 
@@ -1215,8 +1216,6 @@
         this.pixelsDone = 0;
         this.totalPixels = width*height;
 
-        clearAbortRequest();
-
         if (metadata.IHDR_interlaceMethod == 0) {
             decodePass(0, 0, 0, 1, 1, width, height);
         } else {
@@ -1241,8 +1240,10 @@
                              (height + ybump)/YSubsampling);
                 }
 
-                // If read has been aborted, just return
-                // processReadAborted will be called later
+                /*
+                 * If read has been aborted, just return
+                 * processReadAborted will be called later
+                 */
                 if (abortRequested()) {
                     return;
                 }
@@ -1332,13 +1333,19 @@
                                        inputBandsForColorType[colorType],
                                       theImage.getSampleModel().getNumBands());
 
+            clearAbortRequest();
             processImageStarted(0);
-            decodeImage();
             if (abortRequested()) {
                 processReadAborted();
             } else {
-                processImageComplete();
+                decodeImage();
+                if (abortRequested()) {
+                    processReadAborted();
+                } else {
+                    processImageComplete();
+                }
             }
+
         } catch (IOException e) {
             throw new IIOException("Error reading PNG image data", e);
         } finally {
--- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java	Sat Sep 10 14:50:35 2016 +0530
+++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java	Mon Sep 12 12:07:56 2016 +0530
@@ -1131,8 +1131,12 @@
         pixelsToRead = destRegion.width * destRegion.height;
         pixelsRead = 0;
 
+        clearAbortRequest();
         processImageStarted(imageIndex);
-        processImageProgress(0.0f);
+        if (abortRequested()) {
+            processReadAborted();
+            return theImage;
+        }
 
         tilesAcross = (width + tileOrStripWidth - 1) / tileOrStripWidth;
         tilesDown = (height + tileOrStripHeight - 1) / tileOrStripHeight;
@@ -1286,6 +1290,10 @@
                     }
 
                     reportProgress();
+                    if (abortRequested()) {
+                        processReadAborted();
+                        return theImage;
+                    }
                 }
             }
         } else {
@@ -1294,16 +1302,14 @@
                     decodeTile(ti, tj, -1);
 
                     reportProgress();
+                    if (abortRequested()) {
+                        processReadAborted();
+                        return theImage;
+                    }
                 }
             }
         }
-
-        if (abortRequested()) {
-            processReadAborted();
-        } else {
-            processImageComplete();
-        }
-
+        processImageComplete();
         return theImage;
     }
 
--- a/jdk/src/java.desktop/share/native/libjavajpeg/imageioJPEG.c	Sat Sep 10 14:50:35 2016 +0530
+++ b/jdk/src/java.desktop/share/native/libjavajpeg/imageioJPEG.c	Mon Sep 12 12:07:56 2016 +0530
@@ -2162,6 +2162,25 @@
 }
 
 JNIEXPORT void JNICALL
+Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_clearNativeReadAbortFlag
+    (JNIEnv *env,
+    jobject this,
+    jlong ptr) {
+
+    imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr);
+
+    if (data == NULL) {
+        JNU_ThrowByName(env,
+            "java/lang/IllegalStateException",
+            "Attempting to use reader after dispose()");
+        return;
+    }
+
+    data->abortFlag = JNI_FALSE;
+
+}
+
+JNIEXPORT void JNICALL
 Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_abortRead
     (JNIEnv *env,
      jobject this,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/ReadAbortTest.java	Mon Sep 12 12:07:56 2016 +0530
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+ /*
+ * @test
+ * @bug     4924727
+ * @summary Test verifies that if we call ImageReader.abort() in
+ *          IIOReadProgressListener.imageStarted() or
+ *          IIOReadProgressListener.imageProgress() are we
+ *          calling IIOReadProgressListener.readAborted() for all readers.
+ * @run     main ReadAbortTest
+ */
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.util.Iterator;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.event.IIOReadProgressListener;
+import javax.imageio.stream.ImageInputStream;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.nio.file.Files;
+
+public class ReadAbortTest implements IIOReadProgressListener {
+
+    ImageReader reader = null;
+    ImageInputStream iis = null;
+    BufferedImage bimg = null;
+    File file;
+    boolean startAbort = false;
+    boolean startAborted = false;
+    boolean progressAbort = false;
+    boolean progressAborted = false;
+    Color srccolor = Color.red;
+    int width = 100;
+    int heght = 100;
+
+    public ReadAbortTest(String format) throws Exception {
+        try {
+            System.out.println("Test for format " + format);
+            bimg = new BufferedImage(width, heght,
+                    BufferedImage.TYPE_INT_RGB);
+
+            Graphics2D g = bimg.createGraphics();
+            g.setColor(srccolor);
+            g.fillRect(0, 0, width, heght);
+            g.dispose();
+
+            file = File.createTempFile("src_", "." + format, new File("."));
+            ImageIO.write(bimg, format, file);
+            ImageInputStream iis = ImageIO.createImageInputStream(file);
+
+            Iterator iter = ImageIO.getImageReaders(iis);
+            while (iter.hasNext()) {
+                reader = (ImageReader) iter.next();
+                break;
+            }
+            reader.setInput(iis);
+            reader.addIIOReadProgressListener(this);
+
+            // Abort reading in IIOReadProgressListener.imageStarted().
+            startAbort = true;
+            bimg = reader.read(0);
+            startAbort = false;
+
+            // Abort reading in IIOReadProgressListener.imageProgress().
+            progressAbort = true;
+            bimg = reader.read(0);
+            progressAbort = false;
+
+            iis.close();
+            /*
+             * All abort requests from imageStarted,imageProgress and
+             * imageComplete from IIOReadProgressListener should be reached
+             * otherwise throw RuntimeException.
+             */
+            if (!(startAborted
+                    && progressAborted)) {
+                throw new RuntimeException("All IIOReadProgressListener abort"
+                        + " requests are not processed for format "
+                        + format);
+            }
+        } catch (Exception e) {
+            throw e;
+        } finally {
+            Files.delete(file.toPath());
+        }
+    }
+
+    /*
+     * Abstract methods that we need to implement from
+     * IIOReadProgressListener, and relevant for this test case.
+     */
+    @Override
+    public void imageStarted(ImageReader source, int imageIndex) {
+        System.out.println("imageStarted called");
+        if (startAbort) {
+            source.abort();
+        }
+    }
+
+    @Override
+    public void imageProgress(ImageReader source, float percentageDone) {
+        System.out.println("imageProgress called");
+        if (progressAbort) {
+            source.abort();
+        }
+    }
+
+    @Override
+    public void readAborted(ImageReader source) {
+        System.out.println("readAborted called");
+        // Verify IIOReadProgressListener.imageStarted() abort request.
+        if (startAbort) {
+            System.out.println("imageStarted aborted ");
+            startAborted = true;
+        }
+
+        // Verify IIOReadProgressListener.imageProgress() abort request.
+        if (progressAbort) {
+            System.out.println("imageProgress aborted ");
+            progressAborted = true;
+        }
+    }
+
+    public static void main(String args[]) throws Exception {
+        final String[] formats = {"bmp", "png", "gif", "jpg", "tif"};
+        for (String format : formats) {
+            new ReadAbortTest(format);
+        }
+    }
+
+    /*
+     * Remaining abstract methods that we need to implement from
+     * IIOReadProgressListener, but not relevant for this test case.
+     */
+    @Override
+    public void imageComplete(ImageReader source) {
+    }
+
+    @Override
+    public void sequenceStarted(ImageReader reader, int i) {
+    }
+
+    @Override
+    public void sequenceComplete(ImageReader reader) {
+    }
+
+    @Override
+    public void thumbnailStarted(ImageReader reader, int i, int i1) {
+    }
+
+    @Override
+    public void thumbnailProgress(ImageReader reader, float f) {
+    }
+
+    @Override
+    public void thumbnailComplete(ImageReader reader) {
+    }
+}
+