1 /*
2 * Copyright (c) 2000, 2013, 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
439 (((streamY - sourceRegion.y) % sourceYSubsampling) == 0);
440 }
441
442 private void outputPixels(byte[] string, int len) {
443 if (interlacePass < sourceMinProgressivePass ||
444 interlacePass > sourceMaxProgressivePass) {
445 return;
446 }
447
448 for (int i = 0; i < len; i++) {
449 if (streamX >= sourceRegion.x) {
450 rowBuf[streamX - sourceRegion.x] = string[i];
451 }
452
453 // Process end-of-row
454 ++streamX;
455 if (streamX == width) {
456 // Update IIOReadProgressListeners
457 ++rowsDone;
458 processImageProgress(100.0F*rowsDone/height);
459
460 if (decodeThisRow) {
461 outputRow();
462 }
463
464 streamX = 0;
465 if (imageMetadata.interlaceFlag) {
466 streamY += interlaceIncrement[interlacePass];
467 if (streamY >= height) {
468 // Inform IIOReadUpdateListeners of end of pass
469 if (updateListeners != null) {
470 processPassComplete(theImage);
471 }
472
473 ++interlacePass;
474 if (interlacePass > sourceMaxProgressivePass) {
475 return;
476 }
477 streamY = interlaceOffset[interlacePass];
478 startPass(interlacePass);
843 sourceMaxProgressivePass,
844 0,
845 updateMinY,
846 1,
847 updateYStep,
848 bands);
849 }
850
851 public BufferedImage read(int imageIndex, ImageReadParam param)
852 throws IIOException {
853 if (stream == null) {
854 throw new IllegalStateException("Input not set!");
855 }
856 checkIndex(imageIndex);
857
858 int index = locateImage(imageIndex);
859 if (index != imageIndex) {
860 throw new IndexOutOfBoundsException("imageIndex out of bounds!");
861 }
862
863 clearAbortRequest();
864 readMetadata();
865
866 // A null ImageReadParam means we use the default
867 if (param == null) {
868 param = getDefaultReadParam();
869 }
870
871 // Initialize the destination image
872 Iterator<ImageTypeSpecifier> imageTypes = getImageTypes(imageIndex);
873 this.theImage = getDestination(param,
874 imageTypes,
875 imageMetadata.imageWidth,
876 imageMetadata.imageHeight);
877 this.theTile = theImage.getWritableTile(0, 0);
878 this.width = imageMetadata.imageWidth;
879 this.height = imageMetadata.imageHeight;
880 this.streamX = 0;
881 this.streamY = 0;
882 this.rowsDone = 0;
883 this.interlacePass = 0;
886 // and clipping against the true source bounds
887
888 this.sourceRegion = new Rectangle(0, 0, 0, 0);
889 this.destinationRegion = new Rectangle(0, 0, 0, 0);
890 computeRegions(param, width, height, theImage,
891 sourceRegion, destinationRegion);
892 this.destinationOffset = new Point(destinationRegion.x,
893 destinationRegion.y);
894
895 this.sourceXSubsampling = param.getSourceXSubsampling();
896 this.sourceYSubsampling = param.getSourceYSubsampling();
897 this.sourceMinProgressivePass =
898 Math.max(param.getSourceMinProgressivePass(), 0);
899 this.sourceMaxProgressivePass =
900 Math.min(param.getSourceMaxProgressivePass(), 3);
901
902 this.destY = destinationRegion.y +
903 (streamY - sourceRegion.y)/sourceYSubsampling;
904 computeDecodeThisRow();
905
906 // Inform IIOReadProgressListeners of start of image
907 processImageStarted(imageIndex);
908 startPass(0);
909
910 this.rowBuf = new byte[width];
911
912 try {
913 // Read and decode the image data, fill in theImage
914 this.initCodeSize = stream.readUnsignedByte();
915
916 // Read first data block
917 this.blockLength = stream.readUnsignedByte();
918 int left = blockLength;
919 int off = 0;
920 while (left > 0) {
921 int nbytes = stream.read(block, off, left);
922 left -= nbytes;
923 off += nbytes;
924 }
925
926 this.bitPos = 0;
927 this.nextByte = 0;
930
931 // Init 32-bit buffer
932 initNext32Bits();
933
934 this.clearCode = 1 << initCodeSize;
935 this.eofCode = clearCode + 1;
936
937 int code, oldCode = 0;
938
939 int[] prefix = new int[4096];
940 byte[] suffix = new byte[4096];
941 byte[] initial = new byte[4096];
942 int[] length = new int[4096];
943 byte[] string = new byte[4096];
944
945 initializeStringTable(prefix, suffix, initial, length);
946 int tableIndex = (1 << initCodeSize) + 2;
947 int codeSize = initCodeSize + 1;
948 int codeMask = (1 << codeSize) - 1;
949
950 while (!abortRequested()) {
951 code = getCode(codeSize, codeMask);
952
953 if (code == clearCode) {
954 initializeStringTable(prefix, suffix, initial, length);
955 tableIndex = (1 << initCodeSize) + 2;
956 codeSize = initCodeSize + 1;
957 codeMask = (1 << codeSize) - 1;
958
959 code = getCode(codeSize, codeMask);
960 if (code == eofCode) {
961 // Inform IIOReadProgressListeners of end of image
962 processImageComplete();
963 return theImage;
964 }
965 } else if (code == eofCode) {
966 // Inform IIOReadProgressListeners of end of image
967 processImageComplete();
968 return theImage;
969 } else {
970 int newSuffixIndex;
988 length[ti] = length[oc] + 1;
989
990 ++tableIndex;
991 if ((tableIndex == (1 << codeSize)) &&
992 (tableIndex < 4096)) {
993 ++codeSize;
994 codeMask = (1 << codeSize) - 1;
995 }
996 }
997
998 // Reverse code
999 int c = code;
1000 int len = length[c];
1001 for (int i = len - 1; i >= 0; i--) {
1002 string[i] = suffix[c];
1003 c = prefix[c];
1004 }
1005
1006 outputPixels(string, len);
1007 oldCode = code;
1008 }
1009
1010 processReadAborted();
1011 return theImage;
1012 } catch (IOException e) {
1013 e.printStackTrace();
1014 throw new IIOException("I/O error reading image!", e);
1015 }
1016 }
1017
1018 /**
1019 * Remove all settings including global settings such as
1020 * {@code Locale}s and listeners, as well as stream settings.
1021 */
1022 public void reset() {
1023 super.reset();
1024 resetStreamSettings();
1025 }
1026
1027 /**
1028 * Remove local settings based on parsing of a stream.
|
1 /*
2 * Copyright (c) 2000, 2016, 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
439 (((streamY - sourceRegion.y) % sourceYSubsampling) == 0);
440 }
441
442 private void outputPixels(byte[] string, int len) {
443 if (interlacePass < sourceMinProgressivePass ||
444 interlacePass > sourceMaxProgressivePass) {
445 return;
446 }
447
448 for (int i = 0; i < len; i++) {
449 if (streamX >= sourceRegion.x) {
450 rowBuf[streamX - sourceRegion.x] = string[i];
451 }
452
453 // Process end-of-row
454 ++streamX;
455 if (streamX == width) {
456 // Update IIOReadProgressListeners
457 ++rowsDone;
458 processImageProgress(100.0F*rowsDone/height);
459 if (abortRequested()) {
460 return;
461 }
462
463 if (decodeThisRow) {
464 outputRow();
465 }
466
467 streamX = 0;
468 if (imageMetadata.interlaceFlag) {
469 streamY += interlaceIncrement[interlacePass];
470 if (streamY >= height) {
471 // Inform IIOReadUpdateListeners of end of pass
472 if (updateListeners != null) {
473 processPassComplete(theImage);
474 }
475
476 ++interlacePass;
477 if (interlacePass > sourceMaxProgressivePass) {
478 return;
479 }
480 streamY = interlaceOffset[interlacePass];
481 startPass(interlacePass);
846 sourceMaxProgressivePass,
847 0,
848 updateMinY,
849 1,
850 updateYStep,
851 bands);
852 }
853
854 public BufferedImage read(int imageIndex, ImageReadParam param)
855 throws IIOException {
856 if (stream == null) {
857 throw new IllegalStateException("Input not set!");
858 }
859 checkIndex(imageIndex);
860
861 int index = locateImage(imageIndex);
862 if (index != imageIndex) {
863 throw new IndexOutOfBoundsException("imageIndex out of bounds!");
864 }
865
866 readMetadata();
867
868 // A null ImageReadParam means we use the default
869 if (param == null) {
870 param = getDefaultReadParam();
871 }
872
873 // Initialize the destination image
874 Iterator<ImageTypeSpecifier> imageTypes = getImageTypes(imageIndex);
875 this.theImage = getDestination(param,
876 imageTypes,
877 imageMetadata.imageWidth,
878 imageMetadata.imageHeight);
879 this.theTile = theImage.getWritableTile(0, 0);
880 this.width = imageMetadata.imageWidth;
881 this.height = imageMetadata.imageHeight;
882 this.streamX = 0;
883 this.streamY = 0;
884 this.rowsDone = 0;
885 this.interlacePass = 0;
888 // and clipping against the true source bounds
889
890 this.sourceRegion = new Rectangle(0, 0, 0, 0);
891 this.destinationRegion = new Rectangle(0, 0, 0, 0);
892 computeRegions(param, width, height, theImage,
893 sourceRegion, destinationRegion);
894 this.destinationOffset = new Point(destinationRegion.x,
895 destinationRegion.y);
896
897 this.sourceXSubsampling = param.getSourceXSubsampling();
898 this.sourceYSubsampling = param.getSourceYSubsampling();
899 this.sourceMinProgressivePass =
900 Math.max(param.getSourceMinProgressivePass(), 0);
901 this.sourceMaxProgressivePass =
902 Math.min(param.getSourceMaxProgressivePass(), 3);
903
904 this.destY = destinationRegion.y +
905 (streamY - sourceRegion.y)/sourceYSubsampling;
906 computeDecodeThisRow();
907
908 clearAbortRequest();
909 // Inform IIOReadProgressListeners of start of image
910 processImageStarted(imageIndex);
911 if (abortRequested()) {
912 processReadAborted();
913 return theImage;
914 }
915 startPass(0);
916
917 this.rowBuf = new byte[width];
918
919 try {
920 // Read and decode the image data, fill in theImage
921 this.initCodeSize = stream.readUnsignedByte();
922
923 // Read first data block
924 this.blockLength = stream.readUnsignedByte();
925 int left = blockLength;
926 int off = 0;
927 while (left > 0) {
928 int nbytes = stream.read(block, off, left);
929 left -= nbytes;
930 off += nbytes;
931 }
932
933 this.bitPos = 0;
934 this.nextByte = 0;
937
938 // Init 32-bit buffer
939 initNext32Bits();
940
941 this.clearCode = 1 << initCodeSize;
942 this.eofCode = clearCode + 1;
943
944 int code, oldCode = 0;
945
946 int[] prefix = new int[4096];
947 byte[] suffix = new byte[4096];
948 byte[] initial = new byte[4096];
949 int[] length = new int[4096];
950 byte[] string = new byte[4096];
951
952 initializeStringTable(prefix, suffix, initial, length);
953 int tableIndex = (1 << initCodeSize) + 2;
954 int codeSize = initCodeSize + 1;
955 int codeMask = (1 << codeSize) - 1;
956
957 do {
958 code = getCode(codeSize, codeMask);
959
960 if (code == clearCode) {
961 initializeStringTable(prefix, suffix, initial, length);
962 tableIndex = (1 << initCodeSize) + 2;
963 codeSize = initCodeSize + 1;
964 codeMask = (1 << codeSize) - 1;
965
966 code = getCode(codeSize, codeMask);
967 if (code == eofCode) {
968 // Inform IIOReadProgressListeners of end of image
969 processImageComplete();
970 return theImage;
971 }
972 } else if (code == eofCode) {
973 // Inform IIOReadProgressListeners of end of image
974 processImageComplete();
975 return theImage;
976 } else {
977 int newSuffixIndex;
995 length[ti] = length[oc] + 1;
996
997 ++tableIndex;
998 if ((tableIndex == (1 << codeSize)) &&
999 (tableIndex < 4096)) {
1000 ++codeSize;
1001 codeMask = (1 << codeSize) - 1;
1002 }
1003 }
1004
1005 // Reverse code
1006 int c = code;
1007 int len = length[c];
1008 for (int i = len - 1; i >= 0; i--) {
1009 string[i] = suffix[c];
1010 c = prefix[c];
1011 }
1012
1013 outputPixels(string, len);
1014 oldCode = code;
1015 } while (!abortRequested());
1016
1017 processReadAborted();
1018 return theImage;
1019 } catch (IOException e) {
1020 e.printStackTrace();
1021 throw new IIOException("I/O error reading image!", e);
1022 }
1023 }
1024
1025 /**
1026 * Remove all settings including global settings such as
1027 * {@code Locale}s and listeners, as well as stream settings.
1028 */
1029 public void reset() {
1030 super.reset();
1031 resetStreamSettings();
1032 }
1033
1034 /**
1035 * Remove local settings based on parsing of a stream.
|