root/dwt/internal/image/PngDecodingDataStream.d

Revision 213:36f5cb12e1a2, 3.8 kB (checked in by Frank Benoit <benoit@tionex.de>, 8 months ago)

Update to SWT 3.4M7

Line 
1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  * Port to the D programming language:
11  *     Frank Benoit <benoit@tionex.de>
12  *******************************************************************************/
13 module dwt.internal.image.PngDecodingDataStream;
14
15
16 import dwt.dwthelper.InputStream;
17
18 import dwt.DWT;
19 import dwt.internal.image.PngLzBlockReader;
20
21 public class PngDecodingDataStream : InputStream {
22
23     alias InputStream.read read;
24
25     InputStream stream;
26     byte currentByte;
27     int nextBitIndex;
28
29     PngLzBlockReader lzBlockReader;
30     int adlerValue;
31
32     static final int PRIME = 65521;
33     static final int MAX_BIT = 7;
34
35 this(InputStream stream) {
36     super();
37     this.stream = stream;
38     nextBitIndex = MAX_BIT + 1;
39     adlerValue = 1;
40     lzBlockReader = new PngLzBlockReader(this);
41     readCompressedDataHeader();
42     lzBlockReader.readNextBlockHeader();
43 }
44
45 /**
46  * This method should be called when the image decoder thinks
47  * that all of the compressed image data has been read. This
48  * method will ensure that the next data value is an end of
49  * block marker. If there are more blocks after this one,
50  * the method will read them and ensure that they are empty.
51  */
52 void assertImageDataAtEnd() {
53     lzBlockReader.assertCompressedDataAtEnd();
54 }
55
56 public override void close() {
57     assertImageDataAtEnd();
58     checkAdler();
59 }
60
61 int getNextIdatBits(int length) {
62     int value = 0;
63     for (int i = 0; i < length; i++) {
64         value |= (getNextIdatBit() << i);
65     }
66     return value;
67 }
68
69 int getNextIdatBit() {
70     if (nextBitIndex > MAX_BIT) {
71         currentByte = getNextIdatByte();
72         nextBitIndex = 0;
73     }
74     return (currentByte & (1 << nextBitIndex)) >> nextBitIndex++;
75 }
76
77 byte getNextIdatByte() {
78     byte nextByte = cast(byte)stream.read();
79     nextBitIndex = MAX_BIT + 1;
80     return nextByte;
81 }
82
83 void updateAdler(byte value) {
84     int low = adlerValue & 0xFFFF;
85     int high = (adlerValue >> 16) & 0xFFFF;
86     int valueInt = value & 0xFF;
87     low = (low + valueInt) % PRIME;
88     high = (low + high) % PRIME;
89     adlerValue = (high << 16) | low;
90 }
91
92 public override int read() {
93     byte nextDecodedByte = lzBlockReader.getNextByte();
94     updateAdler(nextDecodedByte);
95     return nextDecodedByte & 0xFF;
96 }
97
98 public override int read(byte[] buffer, int off, int len) {
99     for (int i = 0; i < len; i++) {
100         int b = read();
101         if (b is -1) return i;
102         buffer[off + i] = cast(byte)b;
103     }
104     return len;
105 }
106
107 void error() {
108     DWT.error(DWT.ERROR_INVALID_IMAGE);
109 }
110
111 private void readCompressedDataHeader() {
112     byte headerByte1 = getNextIdatByte();
113     byte headerByte2 = getNextIdatByte();
114
115     int number = ((headerByte1 & 0xFF) << 8) | (headerByte2 & 0xFF);
116     if (number % 31 !is 0) error();
117
118     int compressionMethod = headerByte1 & 0x0F;
119     if (compressionMethod !is 8) error();
120
121     int windowSizeHint = (headerByte1 & 0xF0) >> 4;
122     if (windowSizeHint > 7) error();
123     int windowSize = (1 << (windowSizeHint + 8));
124     lzBlockReader.setWindowSize(windowSize);
125
126     int dictionary = (headerByte2 & (1 << 5));
127     if (dictionary !is 0) error();
128
129 //  int compressionLevel = (headerByte2 & 0xC0) >> 6;
130 }
131
132 void checkAdler() {
133     int storedAdler = 0;
134     storedAdler |= ((getNextIdatByte() & 0xFF) << 24);
135     storedAdler |= ((getNextIdatByte() & 0xFF) << 16);
136     storedAdler |= ((getNextIdatByte() & 0xFF) << 8);
137     storedAdler |=  (getNextIdatByte() & 0xFF);
138     if (storedAdler !is adlerValue) error();
139 }
140
141 }
Note: See TracBrowser for help on using the browser.