1 /*
2 * Copyright (c) 2000, 2012, 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
61
62 public class JPEGImageReader extends ImageReader {
63
64 private boolean debug = false;
65
66 /**
67 * The following variable contains a pointer to the IJG library
68 * structure for this reader. It is assigned in the constructor
69 * and then is passed in to every native call. It is set to 0
70 * by dispose to avoid disposing twice.
71 */
72 private long structPointer = 0;
73
74 /** The input stream we read from */
75 private ImageInputStream iis = null;
76
77 /**
78 * List of stream positions for images, reinitialized every time
79 * a new input source is set.
80 */
81 private List imagePositions = null;
82
83 /**
84 * The number of images in the stream, or 0.
85 */
86 private int numImages = 0;
87
88 static {
89 java.security.AccessController.doPrivileged(
90 new java.security.PrivilegedAction<Void>() {
91 public Void run() {
92 System.loadLibrary("jpeg");
93 return null;
94 }
95 });
96 initReaderIDs(ImageInputStream.class,
97 JPEGQTable.class,
98 JPEGHuffmanTable.class);
99 }
100
101 // The following warnings are converted to strings when used
206 private static final int UNKNOWN = -1; // Number of passes
207 private static final int MIN_ESTIMATED_PASSES = 10; // IJG default
208 private int knownPassCount = UNKNOWN;
209 private int pass = 0;
210 private float percentToDate = 0.0F;
211 private float previousPassPercentage = 0.0F;
212 private int progInterval = 0;
213
214 /**
215 * Set to true once stream has been checked for stream metadata
216 */
217 private boolean tablesOnlyChecked = false;
218
219 /** The referent to be registered with the Disposer. */
220 private Object disposerReferent = new Object();
221
222 /** The DisposerRecord that handles the actual disposal of this reader. */
223 private DisposerRecord disposerRecord;
224
225 /** Sets up static C structures. */
226 private static native void initReaderIDs(Class iisClass,
227 Class qTableClass,
228 Class huffClass);
229
230 public JPEGImageReader(ImageReaderSpi originator) {
231 super(originator);
232 structPointer = initJPEGImageReader();
233 disposerRecord = new JPEGReaderDisposerRecord(structPointer);
234 Disposer.addRecord(disposerReferent, disposerRecord);
235 }
236
237 /** Sets up per-reader C structure and returns a pointer to it. */
238 private native long initJPEGImageReader();
239
240 /**
241 * Called by the native code or other classes to signal a warning.
242 * The code is used to lookup a localized message to be used when
243 * sending warnings to listeners.
244 */
245 protected void warningOccurred(int code) {
246 cbLock.lock();
247 try {
248 if ((code < 0) || (code > MAX_WARNING)){
358 haveSeeked = true;
359 streamMetadata = new JPEGMetadata(true, false,
360 iis, this);
361 long pos = iis.getStreamPosition();
362 if (debug) {
363 System.out.println
364 ("pos after constructing stream metadata is " + pos);
365 }
366 }
367 // Now we are at the first image if there are any, so add it
368 // to the list
369 if (hasNextImage()) {
370 imagePositions.add(new Long(iis.getStreamPosition()));
371 }
372 } else { // Not tables only, so add original pos to the list
373 imagePositions.add(new Long(savePos));
374 // And set current image since we've read it now
375 currentImage = 0;
376 }
377 if (seekForwardOnly) {
378 Long pos = (Long) imagePositions.get(imagePositions.size()-1);
379 iis.flushBefore(pos.longValue());
380 }
381 tablesOnlyChecked = true;
382 }
383
384 public int getNumImages(boolean allowSearch) throws IOException {
385 setThreadLock();
386 try { // locked thread
387 cbLock.check();
388
389 return getNumImagesOnThread(allowSearch);
390 } finally {
391 clearThreadLock();
392 }
393 }
394
395 private int getNumImagesOnThread(boolean allowSearch)
396 throws IOException {
397 if (numImages != 0) {
398 return numImages;
399 }
400 if (iis == null) {
401 throw new IllegalStateException("Input not set");
402 }
403 if (allowSearch == true) {
404 if (seekForwardOnly) {
405 throw new IllegalStateException(
406 "seekForwardOnly and allowSearch can't both be true!");
407 }
408 // Otherwise we have to read the entire stream
409
410 if (!tablesOnlyChecked) {
411 checkTablesOnly();
412 }
413
414 iis.mark();
464 /**
465 * Sets the input stream to the start of the requested image.
466 * <pre>
467 * @exception IllegalStateException if the input source has not been
468 * set.
469 * @exception IndexOutOfBoundsException if the supplied index is
470 * out of bounds.
471 * </pre>
472 */
473 private void gotoImage(int imageIndex) throws IOException {
474 if (iis == null) {
475 throw new IllegalStateException("Input not set");
476 }
477 if (imageIndex < minIndex) {
478 throw new IndexOutOfBoundsException();
479 }
480 if (!tablesOnlyChecked) {
481 checkTablesOnly();
482 }
483 if (imageIndex < imagePositions.size()) {
484 iis.seek(((Long)(imagePositions.get(imageIndex))).longValue());
485 } else {
486 // read to start of image, saving positions
487 // First seek to the last position we already have, and skip the
488 // entire image
489 Long pos = (Long) imagePositions.get(imagePositions.size()-1);
490 iis.seek(pos.longValue());
491 skipImage();
492 // Now add all intervening positions, skipping images
493 for (int index = imagePositions.size();
494 index <= imageIndex;
495 index++) {
496 // Is there an image?
497 if (!hasNextImage()) {
498 throw new IndexOutOfBoundsException();
499 }
500 pos = new Long(iis.getStreamPosition());
501 imagePositions.add(pos);
502 if (seekForwardOnly) {
503 iis.flushBefore(pos.longValue());
504 }
505 if (index < imageIndex) {
506 skipImage();
507 } // Otherwise we are where we want to be
508 }
509 }
749 return ret;
750 }
751
752 public ImageTypeSpecifier getRawImageType(int imageIndex)
753 throws IOException {
754 setThreadLock();
755 try {
756 if (currentImage != imageIndex) {
757 cbLock.check();
758
759 readHeader(imageIndex, true);
760 }
761
762 // Returns null if it can't be represented
763 return getImageType(colorSpaceCode).getType();
764 } finally {
765 clearThreadLock();
766 }
767 }
768
769 public Iterator getImageTypes(int imageIndex)
770 throws IOException {
771 setThreadLock();
772 try {
773 return getImageTypesOnThread(imageIndex);
774 } finally {
775 clearThreadLock();
776 }
777 }
778
779 private Iterator getImageTypesOnThread(int imageIndex)
780 throws IOException {
781 if (currentImage != imageIndex) {
782 cbLock.check();
783 readHeader(imageIndex, true);
784 }
785
786 // We return an iterator containing the default, any
787 // conversions that the library provides, and
788 // all the other default types with the same number
789 // of components, as we can do these as a post-process.
790 // As we convert Rasters rather than images, images
791 // with alpha cannot be converted in a post-process.
792
793 // If this image can't be interpreted, this method
794 // returns an empty Iterator.
795
796 // Get the raw ITS, if there is one. Note that this
797 // won't always be the same as the default.
798 ImageTypeProducer raw = getImageType(colorSpaceCode);
799
1046 }
1047
1048 BufferedImage ret = image;
1049 image = null; // don't keep a reference here
1050 return ret;
1051 } finally {
1052 clearThreadLock();
1053 }
1054 }
1055
1056 private Raster readInternal(int imageIndex,
1057 ImageReadParam param,
1058 boolean wantRaster) throws IOException {
1059 readHeader(imageIndex, false);
1060
1061 WritableRaster imRas = null;
1062 int numImageBands = 0;
1063
1064 if (!wantRaster){
1065 // Can we read this image?
1066 Iterator imageTypes = getImageTypes(imageIndex);
1067 if (imageTypes.hasNext() == false) {
1068 throw new IIOException("Unsupported Image Type");
1069 }
1070
1071 image = getDestination(param, imageTypes, width, height);
1072 imRas = image.getRaster();
1073
1074 // The destination may still be incompatible.
1075
1076 numImageBands = image.getSampleModel().getNumBands();
1077
1078 // Check whether we can handle any implied color conversion
1079
1080 // Throws IIOException if the stream and the image are
1081 // incompatible, and sets convert if a java conversion
1082 // is necessary
1083 checkColorConversion(image, param);
1084
1085 // Check the source and destination bands in the param
1086 checkReadParamBandSettings(param, numComponents, numImageBands);
1170 throw new IIOException("Illegal band size: should be 0 < size <= 8");
1171 }
1172 }
1173
1174 /*
1175 * If the process is sequential, and we have restart markers,
1176 * we could skip to the correct restart marker, if the library
1177 * lets us. That's an optimization to investigate later.
1178 */
1179
1180 // Check for update listeners (don't call back if none)
1181 boolean callbackUpdates = ((updateListeners != null)
1182 || (progressListeners != null));
1183
1184 // Set up progression data
1185 initProgressData();
1186 // if we have a metadata object, we can count the scans
1187 // and set knownPassCount
1188 if (imageIndex == imageMetadataIndex) { // We have metadata
1189 knownPassCount = 0;
1190 for (Iterator iter = imageMetadata.markerSequence.iterator();
1191 iter.hasNext();) {
1192 if (iter.next() instanceof SOSMarkerSegment) {
1193 knownPassCount++;
1194 }
1195 }
1196 }
1197 progInterval = Math.max((target.getHeight()-1) / 20, 1);
1198 if (knownPassCount > 0) {
1199 progInterval *= knownPassCount;
1200 } else if (maxProgressivePass != Integer.MAX_VALUE) {
1201 progInterval *= (maxProgressivePass - minProgressivePass + 1);
1202 }
1203
1204 if (debug) {
1205 System.out.println("**** Read Data *****");
1206 System.out.println("numRasterBands is " + numRasterBands);
1207 System.out.print("srcBands:");
1208 for (int i = 0; i<srcBands.length;i++)
1209 System.out.print(" " + srcBands[i]);
1210 System.out.println();
1211 System.out.println("destination bands is " + destinationBands);
1548 if ((thumbnailIndex < 0)
1549 || (thumbnailIndex >= getNumThumbnails(imageIndex))) {
1550 throw new IndexOutOfBoundsException("No such thumbnail");
1551 }
1552 // Now we know that there is a jfif segment and that iis is good
1553 JFIFMarkerSegment jfif =
1554 (JFIFMarkerSegment) imageMetadata.findMarkerSegment
1555 (JFIFMarkerSegment.class, true);
1556 return jfif.getThumbnail(iis, thumbnailIndex, this);
1557 } finally {
1558 clearThreadLock();
1559 }
1560 }
1561
1562 private void resetInternalState() {
1563 // reset C structures
1564 resetReader(structPointer);
1565
1566 // reset local Java structures
1567 numImages = 0;
1568 imagePositions = new ArrayList();
1569 currentImage = -1;
1570 image = null;
1571 raster = null;
1572 target = null;
1573 buffer = null;
1574 destROI = null;
1575 destinationBands = null;
1576 streamMetadata = null;
1577 imageMetadata = null;
1578 imageMetadataIndex = -1;
1579 haveSeeked = false;
1580 tablesOnlyChecked = false;
1581 iccCS = null;
1582 initProgressData();
1583 }
1584
1585 public void reset() {
1586 setThreadLock();
1587 try {
1588 cbLock.check();
|
1 /*
2 * Copyright (c) 2000, 2014, 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
61
62 public class JPEGImageReader extends ImageReader {
63
64 private boolean debug = false;
65
66 /**
67 * The following variable contains a pointer to the IJG library
68 * structure for this reader. It is assigned in the constructor
69 * and then is passed in to every native call. It is set to 0
70 * by dispose to avoid disposing twice.
71 */
72 private long structPointer = 0;
73
74 /** The input stream we read from */
75 private ImageInputStream iis = null;
76
77 /**
78 * List of stream positions for images, reinitialized every time
79 * a new input source is set.
80 */
81 private List<Long> imagePositions = null;
82
83 /**
84 * The number of images in the stream, or 0.
85 */
86 private int numImages = 0;
87
88 static {
89 java.security.AccessController.doPrivileged(
90 new java.security.PrivilegedAction<Void>() {
91 public Void run() {
92 System.loadLibrary("jpeg");
93 return null;
94 }
95 });
96 initReaderIDs(ImageInputStream.class,
97 JPEGQTable.class,
98 JPEGHuffmanTable.class);
99 }
100
101 // The following warnings are converted to strings when used
206 private static final int UNKNOWN = -1; // Number of passes
207 private static final int MIN_ESTIMATED_PASSES = 10; // IJG default
208 private int knownPassCount = UNKNOWN;
209 private int pass = 0;
210 private float percentToDate = 0.0F;
211 private float previousPassPercentage = 0.0F;
212 private int progInterval = 0;
213
214 /**
215 * Set to true once stream has been checked for stream metadata
216 */
217 private boolean tablesOnlyChecked = false;
218
219 /** The referent to be registered with the Disposer. */
220 private Object disposerReferent = new Object();
221
222 /** The DisposerRecord that handles the actual disposal of this reader. */
223 private DisposerRecord disposerRecord;
224
225 /** Sets up static C structures. */
226 private static native void initReaderIDs(Class<?> iisClass,
227 Class<?> qTableClass,
228 Class<?> huffClass);
229
230 public JPEGImageReader(ImageReaderSpi originator) {
231 super(originator);
232 structPointer = initJPEGImageReader();
233 disposerRecord = new JPEGReaderDisposerRecord(structPointer);
234 Disposer.addRecord(disposerReferent, disposerRecord);
235 }
236
237 /** Sets up per-reader C structure and returns a pointer to it. */
238 private native long initJPEGImageReader();
239
240 /**
241 * Called by the native code or other classes to signal a warning.
242 * The code is used to lookup a localized message to be used when
243 * sending warnings to listeners.
244 */
245 protected void warningOccurred(int code) {
246 cbLock.lock();
247 try {
248 if ((code < 0) || (code > MAX_WARNING)){
358 haveSeeked = true;
359 streamMetadata = new JPEGMetadata(true, false,
360 iis, this);
361 long pos = iis.getStreamPosition();
362 if (debug) {
363 System.out.println
364 ("pos after constructing stream metadata is " + pos);
365 }
366 }
367 // Now we are at the first image if there are any, so add it
368 // to the list
369 if (hasNextImage()) {
370 imagePositions.add(new Long(iis.getStreamPosition()));
371 }
372 } else { // Not tables only, so add original pos to the list
373 imagePositions.add(new Long(savePos));
374 // And set current image since we've read it now
375 currentImage = 0;
376 }
377 if (seekForwardOnly) {
378 Long pos = imagePositions.get(imagePositions.size()-1);
379 iis.flushBefore(pos.longValue());
380 }
381 tablesOnlyChecked = true;
382 }
383
384 public int getNumImages(boolean allowSearch) throws IOException {
385 setThreadLock();
386 try { // locked thread
387 cbLock.check();
388
389 return getNumImagesOnThread(allowSearch);
390 } finally {
391 clearThreadLock();
392 }
393 }
394
395 @SuppressWarnings("fallthrough")
396 private int getNumImagesOnThread(boolean allowSearch)
397 throws IOException {
398 if (numImages != 0) {
399 return numImages;
400 }
401 if (iis == null) {
402 throw new IllegalStateException("Input not set");
403 }
404 if (allowSearch == true) {
405 if (seekForwardOnly) {
406 throw new IllegalStateException(
407 "seekForwardOnly and allowSearch can't both be true!");
408 }
409 // Otherwise we have to read the entire stream
410
411 if (!tablesOnlyChecked) {
412 checkTablesOnly();
413 }
414
415 iis.mark();
465 /**
466 * Sets the input stream to the start of the requested image.
467 * <pre>
468 * @exception IllegalStateException if the input source has not been
469 * set.
470 * @exception IndexOutOfBoundsException if the supplied index is
471 * out of bounds.
472 * </pre>
473 */
474 private void gotoImage(int imageIndex) throws IOException {
475 if (iis == null) {
476 throw new IllegalStateException("Input not set");
477 }
478 if (imageIndex < minIndex) {
479 throw new IndexOutOfBoundsException();
480 }
481 if (!tablesOnlyChecked) {
482 checkTablesOnly();
483 }
484 if (imageIndex < imagePositions.size()) {
485 iis.seek(imagePositions.get(imageIndex).longValue());
486 } else {
487 // read to start of image, saving positions
488 // First seek to the last position we already have, and skip the
489 // entire image
490 Long pos = imagePositions.get(imagePositions.size()-1);
491 iis.seek(pos.longValue());
492 skipImage();
493 // Now add all intervening positions, skipping images
494 for (int index = imagePositions.size();
495 index <= imageIndex;
496 index++) {
497 // Is there an image?
498 if (!hasNextImage()) {
499 throw new IndexOutOfBoundsException();
500 }
501 pos = new Long(iis.getStreamPosition());
502 imagePositions.add(pos);
503 if (seekForwardOnly) {
504 iis.flushBefore(pos.longValue());
505 }
506 if (index < imageIndex) {
507 skipImage();
508 } // Otherwise we are where we want to be
509 }
510 }
750 return ret;
751 }
752
753 public ImageTypeSpecifier getRawImageType(int imageIndex)
754 throws IOException {
755 setThreadLock();
756 try {
757 if (currentImage != imageIndex) {
758 cbLock.check();
759
760 readHeader(imageIndex, true);
761 }
762
763 // Returns null if it can't be represented
764 return getImageType(colorSpaceCode).getType();
765 } finally {
766 clearThreadLock();
767 }
768 }
769
770 public Iterator<ImageTypeSpecifier> getImageTypes(int imageIndex)
771 throws IOException {
772 setThreadLock();
773 try {
774 return getImageTypesOnThread(imageIndex);
775 } finally {
776 clearThreadLock();
777 }
778 }
779
780 private Iterator<ImageTypeSpecifier> getImageTypesOnThread(int imageIndex)
781 throws IOException {
782 if (currentImage != imageIndex) {
783 cbLock.check();
784 readHeader(imageIndex, true);
785 }
786
787 // We return an iterator containing the default, any
788 // conversions that the library provides, and
789 // all the other default types with the same number
790 // of components, as we can do these as a post-process.
791 // As we convert Rasters rather than images, images
792 // with alpha cannot be converted in a post-process.
793
794 // If this image can't be interpreted, this method
795 // returns an empty Iterator.
796
797 // Get the raw ITS, if there is one. Note that this
798 // won't always be the same as the default.
799 ImageTypeProducer raw = getImageType(colorSpaceCode);
800
1047 }
1048
1049 BufferedImage ret = image;
1050 image = null; // don't keep a reference here
1051 return ret;
1052 } finally {
1053 clearThreadLock();
1054 }
1055 }
1056
1057 private Raster readInternal(int imageIndex,
1058 ImageReadParam param,
1059 boolean wantRaster) throws IOException {
1060 readHeader(imageIndex, false);
1061
1062 WritableRaster imRas = null;
1063 int numImageBands = 0;
1064
1065 if (!wantRaster){
1066 // Can we read this image?
1067 Iterator<ImageTypeSpecifier> imageTypes = getImageTypes(imageIndex);
1068 if (imageTypes.hasNext() == false) {
1069 throw new IIOException("Unsupported Image Type");
1070 }
1071
1072 image = getDestination(param, imageTypes, width, height);
1073 imRas = image.getRaster();
1074
1075 // The destination may still be incompatible.
1076
1077 numImageBands = image.getSampleModel().getNumBands();
1078
1079 // Check whether we can handle any implied color conversion
1080
1081 // Throws IIOException if the stream and the image are
1082 // incompatible, and sets convert if a java conversion
1083 // is necessary
1084 checkColorConversion(image, param);
1085
1086 // Check the source and destination bands in the param
1087 checkReadParamBandSettings(param, numComponents, numImageBands);
1171 throw new IIOException("Illegal band size: should be 0 < size <= 8");
1172 }
1173 }
1174
1175 /*
1176 * If the process is sequential, and we have restart markers,
1177 * we could skip to the correct restart marker, if the library
1178 * lets us. That's an optimization to investigate later.
1179 */
1180
1181 // Check for update listeners (don't call back if none)
1182 boolean callbackUpdates = ((updateListeners != null)
1183 || (progressListeners != null));
1184
1185 // Set up progression data
1186 initProgressData();
1187 // if we have a metadata object, we can count the scans
1188 // and set knownPassCount
1189 if (imageIndex == imageMetadataIndex) { // We have metadata
1190 knownPassCount = 0;
1191 for (Iterator<MarkerSegment> iter =
1192 imageMetadata.markerSequence.iterator(); iter.hasNext();) {
1193 if (iter.next() instanceof SOSMarkerSegment) {
1194 knownPassCount++;
1195 }
1196 }
1197 }
1198 progInterval = Math.max((target.getHeight()-1) / 20, 1);
1199 if (knownPassCount > 0) {
1200 progInterval *= knownPassCount;
1201 } else if (maxProgressivePass != Integer.MAX_VALUE) {
1202 progInterval *= (maxProgressivePass - minProgressivePass + 1);
1203 }
1204
1205 if (debug) {
1206 System.out.println("**** Read Data *****");
1207 System.out.println("numRasterBands is " + numRasterBands);
1208 System.out.print("srcBands:");
1209 for (int i = 0; i<srcBands.length;i++)
1210 System.out.print(" " + srcBands[i]);
1211 System.out.println();
1212 System.out.println("destination bands is " + destinationBands);
1549 if ((thumbnailIndex < 0)
1550 || (thumbnailIndex >= getNumThumbnails(imageIndex))) {
1551 throw new IndexOutOfBoundsException("No such thumbnail");
1552 }
1553 // Now we know that there is a jfif segment and that iis is good
1554 JFIFMarkerSegment jfif =
1555 (JFIFMarkerSegment) imageMetadata.findMarkerSegment
1556 (JFIFMarkerSegment.class, true);
1557 return jfif.getThumbnail(iis, thumbnailIndex, this);
1558 } finally {
1559 clearThreadLock();
1560 }
1561 }
1562
1563 private void resetInternalState() {
1564 // reset C structures
1565 resetReader(structPointer);
1566
1567 // reset local Java structures
1568 numImages = 0;
1569 imagePositions = new ArrayList<>();
1570 currentImage = -1;
1571 image = null;
1572 raster = null;
1573 target = null;
1574 buffer = null;
1575 destROI = null;
1576 destinationBands = null;
1577 streamMetadata = null;
1578 imageMetadata = null;
1579 imageMetadataIndex = -1;
1580 haveSeeked = false;
1581 tablesOnlyChecked = false;
1582 iccCS = null;
1583 initProgressData();
1584 }
1585
1586 public void reset() {
1587 setThreadLock();
1588 try {
1589 cbLock.check();
|