OLD | NEW |
---|---|
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ | 1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 /* ***** BEGIN LICENSE BLOCK ***** | 2 /* ***** BEGIN LICENSE BLOCK ***** |
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | 3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
4 * | 4 * |
5 * The contents of this file are subject to the Mozilla Public License Version | 5 * The contents of this file are subject to the Mozilla Public License Version |
6 * 1.1 (the "License"); you may not use this file except in compliance with | 6 * 1.1 (the "License"); you may not use this file except in compliance with |
7 * the License. You may obtain a copy of the License at | 7 * the License. You may obtain a copy of the License at |
8 * http://www.mozilla.org/MPL/ | 8 * http://www.mozilla.org/MPL/ |
9 * | 9 * |
10 * Software distributed under the License is distributed on an "AS IS" basis, | 10 * Software distributed under the License is distributed on an "AS IS" basis, |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
91 #define GETN(n, s) \ | 91 #define GETN(n, s) \ |
92 do { \ | 92 do { \ |
93 m_bytesToConsume = (n); \ | 93 m_bytesToConsume = (n); \ |
94 m_state = (s); \ | 94 m_state = (s); \ |
95 } while (0) | 95 } while (0) |
96 | 96 |
97 // Get a 16-bit value stored in little-endian format. | 97 // Get a 16-bit value stored in little-endian format. |
98 #define GETINT16(p) ((p)[1]<<8|(p)[0]) | 98 #define GETINT16(p) ((p)[1]<<8|(p)[0]) |
99 | 99 |
100 // Send the data to the display front-end. | 100 // Send the data to the display front-end. |
101 bool GIFLZWContext::outputRow() | 101 bool GIFLZWContext::outputRow(GIFRow::const_iterator rowBegin) |
102 { | 102 { |
103 int drowStart = irow; | 103 int drowStart = irow; |
104 int drowEnd = irow; | 104 int drowEnd = irow; |
105 | 105 |
106 // Haeberli-inspired hack for interlaced GIFs: Replicate lines while | 106 // Haeberli-inspired hack for interlaced GIFs: Replicate lines while |
107 // displaying to diminish the "venetian-blind" effect as the image is | 107 // displaying to diminish the "venetian-blind" effect as the image is |
108 // loaded. Adjust pixel vertical positions to avoid the appearance of the | 108 // loaded. Adjust pixel vertical positions to avoid the appearance of the |
109 // image crawling up the screen as successive passes are drawn. | 109 // image crawling up the screen as successive passes are drawn. |
110 if (m_frameContext->progressiveDisplay() && m_frameContext->interlaced() && ipass < 4) { | 110 if (m_frameContext->progressiveDisplay() && m_frameContext->interlaced() && ipass < 4) { |
111 unsigned rowDup = 0; | 111 unsigned rowDup = 0; |
(...skipping 29 matching lines...) Expand all Loading... | |
141 | 141 |
142 if ((unsigned)drowEnd >= m_frameContext->height()) | 142 if ((unsigned)drowEnd >= m_frameContext->height()) |
143 drowEnd = m_frameContext->height() - 1; | 143 drowEnd = m_frameContext->height() - 1; |
144 } | 144 } |
145 | 145 |
146 // Protect against too much image data. | 146 // Protect against too much image data. |
147 if ((unsigned)drowStart >= m_frameContext->height()) | 147 if ((unsigned)drowStart >= m_frameContext->height()) |
148 return true; | 148 return true; |
149 | 149 |
150 // CALLBACK: Let the client know we have decoded a row. | 150 // CALLBACK: Let the client know we have decoded a row. |
151 if (!m_client->haveDecodedRow(m_frameContext->frameId(), rowBuffer, m_frameC ontext->width(), | 151 if (!m_client->haveDecodedRow(m_frameContext->frameId(), rowBegin, m_frameCo ntext->width(), |
152 drowStart, drowEnd - drowStart + 1, m_frameContext->progressiveDisplay() && m_frameContext->interlaced() && ipass > 1)) | 152 drowStart, drowEnd - drowStart + 1, m_frameContext->progressiveDisplay() && m_frameContext->interlaced() && ipass > 1)) |
153 return false; | 153 return false; |
154 | 154 |
155 if (!m_frameContext->interlaced()) | 155 if (!m_frameContext->interlaced()) |
156 irow++; | 156 irow++; |
157 else { | 157 else { |
158 do { | 158 do { |
159 switch (ipass) { | 159 switch (ipass) { |
160 case 1: | 160 case 1: |
161 irow += 8; | 161 irow += 8; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
195 } while (irow > (m_frameContext->height() - 1)); | 195 } while (irow > (m_frameContext->height() - 1)); |
196 } | 196 } |
197 return true; | 197 return true; |
198 } | 198 } |
199 | 199 |
200 // Perform Lempel-Ziv-Welch decoding. | 200 // Perform Lempel-Ziv-Welch decoding. |
201 // Returns true if decoding was successful. In this case the block will have bee n completely consumed and/or rowsRemaining will be 0. | 201 // Returns true if decoding was successful. In this case the block will have bee n completely consumed and/or rowsRemaining will be 0. |
202 // Otherwise, decoding failed; returns false in this case, which will always cau se the GIFImageReader to set the "decode failed" flag. | 202 // Otherwise, decoding failed; returns false in this case, which will always cau se the GIFImageReader to set the "decode failed" flag. |
203 bool GIFLZWContext::doLZW(const unsigned char* block, size_t bytesInBlock) | 203 bool GIFLZWContext::doLZW(const unsigned char* block, size_t bytesInBlock) |
204 { | 204 { |
205 int code; | 205 int code; |
Peter Kasting
2013/08/29 23:46:25
Nit: Declare these first three where they are firs
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
206 int incode; | 206 int incode; |
207 const unsigned char *ch; | 207 const unsigned char *ch; |
208 size_t width = m_frameContext->width(); | |
208 | 209 |
209 if (rowIter == rowBuffer.end()) | 210 if (rowIter == rowBuffer.end()) |
210 return true; | 211 return true; |
211 | 212 |
212 #define OUTPUT_ROW \ | |
213 do { \ | |
214 if (!outputRow()) \ | |
215 return false; \ | |
216 rowsRemaining--; \ | |
217 rowIter = rowBuffer.begin(); \ | |
218 if (!rowsRemaining) \ | |
219 return true; \ | |
220 } while (0) | |
221 | |
222 for (ch = block; bytesInBlock-- > 0; ch++) { | 213 for (ch = block; bytesInBlock-- > 0; ch++) { |
223 // Feed the next byte into the decoder's 32-bit input buffer. | 214 // Feed the next byte into the decoder's 32-bit input buffer. |
224 datum += ((int) *ch) << bits; | 215 datum += ((int) *ch) << bits; |
225 bits += 8; | 216 bits += 8; |
226 | 217 |
227 // Check for underflow of decoder's 32-bit input buffer. | 218 // Check for underflow of decoder's 32-bit input buffer. |
228 while (bits >= codesize) { | 219 while (bits >= codesize) { |
229 // Get the leading variable-length symbol from the data stream. | 220 // Get the leading variable-length symbol from the data stream. |
230 code = datum & codemask; | 221 code = datum & codemask; |
231 datum >>= codesize; | 222 datum >>= codesize; |
(...skipping 10 matching lines...) Expand all Loading... | |
242 | 233 |
243 // Check for explicit end-of-stream code. | 234 // Check for explicit end-of-stream code. |
244 if (code == (clearCode + 1)) { | 235 if (code == (clearCode + 1)) { |
245 // end-of-stream should only appear after all image data. | 236 // end-of-stream should only appear after all image data. |
246 if (!rowsRemaining) | 237 if (!rowsRemaining) |
247 return true; | 238 return true; |
248 return false; | 239 return false; |
249 } | 240 } |
250 | 241 |
251 if (oldcode == -1) { | 242 if (oldcode == -1) { |
243 // The previous code is not available either because this is the first | |
Peter Kasting
2013/08/29 23:46:25
Tiny nit: It seems like your comments in this sect
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
244 // code in the stream or the dictionary was reset. We'll write t he | |
245 // current code to stream. The code will have only one character . | |
Peter Kasting
2013/08/29 23:46:25
Nit: Maybe better second sentence:
This code must
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
246 firstchar = oldcode = code; | |
247 if (rowIter >= rowBuffer.end()) | |
248 return false; | |
252 *rowIter++ = suffix[code]; | 249 *rowIter++ = suffix[code]; |
253 if (rowIter == rowBuffer.end()) | 250 } else { |
254 OUTPUT_ROW; | 251 incode = code; |
252 unsigned short codeLength = 0; | |
253 if (code < avail) { | |
254 // This is a complete code. Code length and code content are known. | |
Peter Kasting
2013/08/29 23:46:25
Nit: How about just:
This is a pre-existing code,
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
255 codeLength = suffixLength[code]; | |
256 rowIter += codeLength; | |
257 if (rowIter >= rowBuffer.end()) | |
Peter Kasting
2013/08/29 23:46:25
Shouldn't this be '>', not ">=", since the row ite
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
258 return false; | |
259 } else if (code == avail) { | |
260 // This is an incomplete code. Code length is the length of previous | |
261 // code plus one. Code content is that of previous code conc atenated | |
262 // by the first character of previous code. | |
Peter Kasting
2013/08/29 23:46:25
Nit: How about:
This is a new code just being add
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
263 codeLength = suffixLength[oldcode] + 1; | |
264 rowIter += codeLength; | |
265 if (rowIter >= rowBuffer.end()) | |
266 return false; | |
255 | 267 |
256 firstchar = oldcode = code; | 268 // The last character of this code is the first character of the |
257 continue; | 269 // previous code. Write it to output and then write the prev ious code. |
Peter Kasting
2013/08/29 23:46:25
Nit: This comment seems unnecessary given the abov
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
270 *--rowIter = firstchar; | |
271 code = oldcode; | |
272 } else { | |
273 // Bad code received. Complete and incomplete codes are defi ned up | |
274 // to |avail|. | |
Peter Kasting
2013/08/29 23:46:25
Nit: How about just:
This is an invalid code.
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
275 return false; | |
276 } | |
277 | |
278 while (code >= clearCode) { | |
279 if (code >= MAX_BYTES || code == prefix[code]) | |
Peter Kasting
2013/08/29 23:46:25
|code| must be less than MAX_BYTES, given how it w
Alpha Left Google
2013/08/30 23:25:36
I removed this block of comments entirely. Having
| |
280 return false; | |
281 | |
282 // Even though suffix[] only holds characters through suffix [avail - 1], | |
283 // allowing code >= avail here lets us be more tolerant of m alformed | |
284 // data. As long as code < MAX_BYTES, the only risk is a gar bled image, | |
285 // which is no worse than refusing to display it. | |
286 *--rowIter = suffix[code]; | |
287 code = prefix[code]; | |
288 } | |
289 | |
290 *--rowIter = firstchar = suffix[code]; | |
291 | |
292 // Define a new codeword in the dictionary. | |
293 if (avail < 4096) { | |
Peter Kasting
2013/08/29 23:46:25
Nit: Use MAX_DICTIONARY_ENTRIES here in place of 4
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
294 prefix[avail] = oldcode; | |
295 suffix[avail] = firstchar; | |
296 suffixLength[avail] = suffixLength[oldcode] + 1; | |
297 avail++; | |
Peter Kasting
2013/08/29 23:46:25
Nit: I suggest using preincrement form wherever po
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
298 | |
299 // If we've used up all the codewords of a given length | |
300 // increase the length of codewords by one bit, but don't | |
301 // exceed the specified maximum codeword size of 12 bits. | |
Peter Kasting
2013/08/29 23:46:25
Nit: Remove "of 12 bits". Here and elsewhere, I'd
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
302 if ((!(avail & codemask)) && (avail < 4096)) { | |
Peter Kasting
2013/08/29 23:46:25
Nit: Instead of "(avail < 4096)", the equivalent "
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
303 codesize++; | |
304 codemask += avail; | |
305 } | |
306 } | |
307 oldcode = incode; | |
308 rowIter += codeLength; | |
258 } | 309 } |
259 | 310 |
260 incode = code; | 311 // Not enough bytes to output row. |
261 if (code >= avail) { | 312 if (rowIter < rowBuffer.begin() + width) |
262 stack[stackp++] = firstchar; | 313 continue; |
Peter Kasting
2013/08/29 23:46:25
Nit: It seems slightly clearer to me to skip this,
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
263 code = oldcode; | |
264 | 314 |
265 if (stackp == MAX_BYTES) | 315 // There's enough data to output. Output as many rows as possible. |
316 GIFRow::iterator rowBegin = rowBuffer.begin(); | |
317 for (;rowBegin + width <= rowIter; rowBegin += width) { | |
Peter Kasting
2013/08/29 23:46:25
Nit: Space after first semicolon.
If you don't ta
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
318 if (!outputRow(rowBegin)) | |
266 return false; | 319 return false; |
320 rowsRemaining--; | |
321 if (!rowsRemaining) | |
322 return true; | |
267 } | 323 } |
268 | 324 |
269 while (code >= clearCode) { | 325 // These bytes cannot make up a full row. Move them to the beginning |
270 if (code >= MAX_BYTES || code == prefix[code]) | 326 // of buffer. |
Peter Kasting
2013/08/29 23:46:25
Nit: How about just:
Move the remaining bytes to
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
271 return false; | 327 size_t bytesToCopy = rowIter - rowBegin; |
272 | 328 memcpy(rowBuffer.begin(), rowBegin, bytesToCopy); |
273 // Even though suffix[] only holds characters through suffix[ava il - 1], | 329 rowIter = rowBuffer.begin() + bytesToCopy; |
274 // allowing code >= avail here lets us be more tolerant of malfo rmed | |
275 // data. As long as code < MAX_BYTES, the only risk is a garbled image, | |
276 // which is no worse than refusing to display it. | |
277 stack[stackp++] = suffix[code]; | |
278 code = prefix[code]; | |
279 | |
280 if (stackp == MAX_BYTES) | |
281 return false; | |
282 } | |
283 | |
284 stack[stackp++] = firstchar = suffix[code]; | |
285 | |
286 // Define a new codeword in the dictionary. | |
287 if (avail < 4096) { | |
288 prefix[avail] = oldcode; | |
289 suffix[avail] = firstchar; | |
290 avail++; | |
291 | |
292 // If we've used up all the codewords of a given length | |
293 // increase the length of codewords by one bit, but don't | |
294 // exceed the specified maximum codeword size of 12 bits. | |
295 if ((!(avail & codemask)) && (avail < 4096)) { | |
296 codesize++; | |
297 codemask += avail; | |
298 } | |
299 } | |
300 oldcode = incode; | |
301 | |
302 // Copy the decoded data out to the scanline buffer. | |
303 do { | |
304 *rowIter++ = stack[--stackp]; | |
305 if (rowIter == rowBuffer.end()) | |
306 OUTPUT_ROW; | |
307 } while (stackp > 0); | |
308 } | 330 } |
309 } | 331 } |
310 | |
311 return true; | 332 return true; |
312 } | 333 } |
313 | 334 |
314 void GIFColorMap::buildTable(const unsigned char* data, size_t length) | 335 void GIFColorMap::buildTable(const unsigned char* data, size_t length) |
315 { | 336 { |
316 if (!m_isDefined || !m_table.isEmpty()) | 337 if (!m_isDefined || !m_table.isEmpty()) |
317 return; | 338 return; |
318 | 339 |
319 RELEASE_ASSERT(m_position + m_colors * GIF_COLORS <= length); | 340 RELEASE_ASSERT(m_position + m_colors * GIF_COLORS <= length); |
320 const unsigned char* srcColormap = data + m_position; | 341 const unsigned char* srcColormap = data + m_position; |
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
752 m_frames.append(adoptPtr(new GIFFrameContext(m_frames.size()))); | 773 m_frames.append(adoptPtr(new GIFFrameContext(m_frames.size()))); |
753 } | 774 } |
754 | 775 |
755 // FIXME: Move this method to close to doLZW(). | 776 // FIXME: Move this method to close to doLZW(). |
756 bool GIFLZWContext::prepareToDecode() | 777 bool GIFLZWContext::prepareToDecode() |
757 { | 778 { |
758 ASSERT(m_frameContext->isDataSizeDefined() && m_frameContext->isHeaderDefine d()); | 779 ASSERT(m_frameContext->isDataSizeDefined() && m_frameContext->isHeaderDefine d()); |
759 | 780 |
760 // Since we use a codesize of 1 more than the datasize, we need to ensure | 781 // Since we use a codesize of 1 more than the datasize, we need to ensure |
761 // that our datasize is strictly less than the MAX_LZW_BITS value (12). | 782 // that our datasize is strictly less than the MAX_LZW_BITS value (12). |
762 // This sets the largest possible codemask correctly at 4095. | 783 // This sets the largest possible codemask correctly at 4095. |
Peter Kasting
2013/08/29 23:46:25
Nit: Remove last sentence, and remove "(12)" from
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
763 if (m_frameContext->dataSize() >= MAX_LZW_BITS) | 784 if (m_frameContext->dataSize() >= MAX_LZW_BITS) |
764 return false; | 785 return false; |
765 clearCode = 1 << m_frameContext->dataSize(); | 786 clearCode = 1 << m_frameContext->dataSize(); |
766 if (clearCode >= MAX_BYTES) | 787 if (clearCode >= MAX_BYTES) |
Peter Kasting
2013/08/29 23:46:25
This conditional cannot fail given the previous co
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
767 return false; | 788 return false; |
768 | 789 |
769 avail = clearCode + 2; | 790 avail = clearCode + 2; |
770 oldcode = -1; | 791 oldcode = -1; |
771 codesize = m_frameContext->dataSize() + 1; | 792 codesize = m_frameContext->dataSize() + 1; |
772 codemask = (1 << codesize) - 1; | 793 codemask = (1 << codesize) - 1; |
773 datum = bits = 0; | 794 datum = bits = 0; |
774 ipass = m_frameContext->interlaced() ? 1 : 0; | 795 ipass = m_frameContext->interlaced() ? 1 : 0; |
775 irow = 0; | 796 irow = 0; |
776 | 797 |
777 // Initialize output row buffer. | 798 // Initialize output row buffer. |
778 rowBuffer.resize(m_frameContext->width()); | 799 rowBuffer.resize(m_frameContext->width() + MAX_BYTES); |
Peter Kasting
2013/08/29 23:46:25
(See my comment atop GIFImageReader.h as to why I
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
779 rowIter = rowBuffer.begin(); | 800 rowIter = rowBuffer.begin(); |
780 rowsRemaining = m_frameContext->height(); | 801 rowsRemaining = m_frameContext->height(); |
781 | 802 |
782 // Clearing the whole suffix table lets us be more tolerant of bad data. | 803 // Clearing the whole suffix table lets us be more tolerant of bad data. |
783 memset(suffix, 0, sizeof(suffix)); | 804 memset(suffix, 0, sizeof(suffix)); |
Peter Kasting
2013/08/29 23:46:25
Nit: Seems like we could save a little time on the
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
805 for (int i = 0; i < clearCode; ++i) | |
806 suffix[i] = i; | |
807 for (int i = 0; i < MAX_BYTES; i++) | |
808 suffixLength[i] = 1; | |
784 | 809 |
785 // Clearing the whole prefix table to prevent uninitialized access. | 810 // Clearing the whole prefix table to prevent uninitialized access. |
786 memset(prefix, 0, sizeof(prefix)); | 811 memset(prefix, 0, sizeof(prefix)); |
787 for (int i = 0; i < clearCode; i++) | |
788 suffix[i] = i; | |
789 stackp = 0; | |
790 return true; | 812 return true; |
791 } | 813 } |
OLD | NEW |