Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: src/images/SkImageDecoder_libico.cpp

Issue 1018953003: Add SkEncodedFormat, used by SkCodec. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Use a common enum for SkImageEncoder and SkImageDecoder and SkCodec Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2006 The Android Open Source Project 2 * Copyright 2006 The Android Open Source Project
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkColorPriv.h" 8 #include "SkColorPriv.h"
9 #include "SkImageDecoder.h" 9 #include "SkImageDecoder.h"
10 #include "SkStream.h" 10 #include "SkStream.h"
11 #include "SkStreamPriv.h" 11 #include "SkStreamPriv.h"
12 #include "SkTypes.h" 12 #include "SkTypes.h"
13 13
14 class SkICOImageDecoder : public SkImageDecoder { 14 class SkICOImageDecoder : public SkImageDecoder {
15 public: 15 public:
16 SkICOImageDecoder(); 16 SkICOImageDecoder();
17 17
18 Format getFormat() const SK_OVERRIDE { 18 SkEncodedFormat getFormat() const SK_OVERRIDE {
19 return kICO_Format; 19 return kICO_SkEncodedFormat;
20 } 20 }
21 21
22 protected: 22 protected:
23 Result onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; 23 Result onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE;
24 24
25 private: 25 private:
26 typedef SkImageDecoder INHERITED; 26 typedef SkImageDecoder INHERITED;
27 }; 27 };
28 28
29 //////////////////////////////////////////////////////////////////////////////// ///////// 29 //////////////////////////////////////////////////////////////////////////////// /////////
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 return (w + 1) << 2; 69 return (w + 1) << 2;
70 } 70 }
71 // Otherwise return 0, which will allow it to be calculated automatically. 71 // Otherwise return 0, which will allow it to be calculated automatically.
72 return 0; 72 return 0;
73 } 73 }
74 74
75 SkImageDecoder::Result SkICOImageDecoder::onDecode(SkStream* stream, SkBitmap* b m, Mode mode) 75 SkImageDecoder::Result SkICOImageDecoder::onDecode(SkStream* stream, SkBitmap* b m, Mode mode)
76 { 76 {
77 SkAutoMalloc autoMal; 77 SkAutoMalloc autoMal;
78 const size_t length = SkCopyStreamToStorage(&autoMal, stream); 78 const size_t length = SkCopyStreamToStorage(&autoMal, stream);
79 // Check that the buffer is large enough to read the directory header 79 if (0 == length) {
80 if (length < 6) {
81 return kFailure; 80 return kFailure;
82 } 81 }
83 82
84 unsigned char* buf = (unsigned char*)autoMal.get(); 83 unsigned char* buf = (unsigned char*)autoMal.get();
85 84
86 //these should always be the same - should i use for error checking? - what about files that have some 85 //these should always be the same - should i use for error checking? - what about files that have some
87 //incorrect values, but still decode properly? 86 //incorrect values, but still decode properly?
88 int reserved = read2Bytes(buf, 0); // 0 87 int reserved = read2Bytes(buf, 0); // 0
89 int type = read2Bytes(buf, 2); // 1 88 int type = read2Bytes(buf, 2); // 1
90 if (reserved != 0 || type != 1) { 89 if (reserved != 0 || type != 1) {
91 return kFailure; 90 return kFailure;
92 } 91 }
93 92
94 int count = read2Bytes(buf, 4); 93 int count = read2Bytes(buf, 4);
95 // Check that there are directory entries
96 if (count < 1) {
97 return kFailure;
98 }
99 94
100 // Check that buffer is large enough to read directory entries. 95 //need to at least have enough space to hold the initial table of info
101 // We are guaranteed that count is at least 1. We might as well assume
102 // count is 1 because this deprecated decoder only looks at the first
103 // directory entry.
104 if (length < (size_t)(6 + count*16)) { 96 if (length < (size_t)(6 + count*16)) {
105 return kFailure; 97 return kFailure;
106 } 98 }
107 99
108 //skip ahead to the correct header 100 //skip ahead to the correct header
109 //commented out lines are not used, but if i switch to other read method, ne ed to know how many to skip 101 //commented out lines are not used, but if i switch to other read method, ne ed to know how many to skip
110 //otherwise, they could be used for error checking 102 //otherwise, they could be used for error checking
111 int w = readByte(buf, 6); 103 int w = readByte(buf, 6);
112 int h = readByte(buf, 7); 104 int h = readByte(buf, 7);
113 SkASSERT(w >= 0 && h >= 0);
114 int colorCount = readByte(buf, 8); 105 int colorCount = readByte(buf, 8);
115 //int reservedToo = readByte(buf, 9 + choice*16); //0 106 //int reservedToo = readByte(buf, 9 + choice*16); //0
116 //int planes = read2Bytes(buf, 10 + choice*16); //1 - but often 0 107 //int planes = read2Bytes(buf, 10 + choice*16); //1 - but often 0
117 //int fakeBitCount = read2Bytes(buf, 12 + choice*16); //should be real - usu ally 0 108 //int fakeBitCount = read2Bytes(buf, 12 + choice*16); //should be real - usu ally 0
118 const size_t size = read4Bytes(buf, 14); //matters? 109 const size_t size = read4Bytes(buf, 14); //matters?
119 const size_t offset = read4Bytes(buf, 18); 110 const size_t offset = read4Bytes(buf, 18);
120 // promote the sum to 64-bits to avoid overflow 111 // promote the sum to 64-bits to avoid overflow
121 // Check that buffer is large enough to read image data
122 if (offset > length || size > length || ((uint64_t)offset + size) > length) { 112 if (offset > length || size > length || ((uint64_t)offset + size) > length) {
123 return kFailure; 113 return kFailure;
124 } 114 }
125 115
126 // Check to see if this is a PNG image inside the ICO 116 // Check to see if this is a PNG image inside the ICO
127 { 117 {
128 SkMemoryStream subStream(buf + offset, size, false); 118 SkMemoryStream subStream(buf + offset, size, false);
129 SkAutoTDelete<SkImageDecoder> otherDecoder(SkImageDecoder::Factory(&subS tream)); 119 SkAutoTDelete<SkImageDecoder> otherDecoder(SkImageDecoder::Factory(&subS tream));
130 if (otherDecoder.get() != NULL) { 120 if (otherDecoder.get() != NULL) {
131 // Disallow nesting ICO files within one another 121 // Disallow nesting ICO files within one another
132 // FIXME: Can ICO files contain other formats besides PNG? 122 // FIXME: Can ICO files contain other formats besides PNG?
133 if (otherDecoder->getFormat() == SkImageDecoder::kICO_Format) { 123 if (otherDecoder->getFormat() == kICO_SkEncodedFormat) {
134 return kFailure; 124 return kFailure;
135 } 125 }
136 // Set fields on the other decoder to be the same as this one. 126 // Set fields on the other decoder to be the same as this one.
137 this->copyFieldsToOther(otherDecoder.get()); 127 this->copyFieldsToOther(otherDecoder.get());
138 const Result result = otherDecoder->decode(&subStream, bm, this->get DefaultPref(), 128 const Result result = otherDecoder->decode(&subStream, bm, this->get DefaultPref(),
139 mode); 129 mode);
140 // FIXME: Should we just return result here? Is it possible that dat a that looked like 130 // FIXME: Should we just return result here? Is it possible that dat a that looked like
141 // a subimage was not, but was actually a valid ICO? 131 // a subimage was not, but was actually a valid ICO?
142 if (result != kFailure) { 132 if (result != kFailure) {
143 return result; 133 return result;
144 } 134 }
145 } 135 }
146 } 136 }
147 137
148 //int infoSize = read4Bytes(buf, offset); //40 138 //int infoSize = read4Bytes(buf, offset); //40
149 //int width = read4Bytes(buf, offset+4); //should == w 139 //int width = read4Bytes(buf, offset+4); //should == w
150 //int height = read4Bytes(buf, offset+8); //should == 2*h 140 //int height = read4Bytes(buf, offset+8); //should == 2*h
151 //int planesToo = read2Bytes(buf, offset+12); //should == 1 (does it ?) 141 //int planesToo = read2Bytes(buf, offset+12); //should == 1 (does it ?)
152
153 // For ico images, only a byte is used to store each dimension
154 // 0 is used to represent 256
155 if (w == 0) {
156 w = 256;
157 }
158 if (h == 0) {
159 h = 256;
160 }
161
162 // Check that buffer is large enough to read the bit depth
163 if (length < offset + 16) {
164 return kFailure;
165 }
166 int bitCount = read2Bytes(buf, offset+14); 142 int bitCount = read2Bytes(buf, offset+14);
167 143
168 void (*placePixel)(const int pixelNo, const unsigned char* buf, 144 void (*placePixel)(const int pixelNo, const unsigned char* buf,
169 const int xorOffset, int& x, int y, const int w, 145 const int xorOffset, int& x, int y, const int w,
170 SkBitmap* bm, int alphaByte, int m, int shift, SkPMColor* colors) = NULL ; 146 SkBitmap* bm, int alphaByte, int m, int shift, SkPMColor* colors) = NULL ;
171 switch (bitCount) 147 switch (bitCount)
172 { 148 {
173 case 1: 149 case 1:
174 placePixel = &editPixelBit1; 150 placePixel = &editPixelBit1;
175 colorCount = 2; 151 colorCount = 2;
(...skipping 21 matching lines...) Expand all
197 173
198 //these should all be zero, but perhaps are not - need to check 174 //these should all be zero, but perhaps are not - need to check
199 //int compression = read4Bytes(buf, offset+16); //0 175 //int compression = read4Bytes(buf, offset+16); //0
200 //int imageSize = read4Bytes(buf, offset+20); //0 - sometimes has a value 176 //int imageSize = read4Bytes(buf, offset+20); //0 - sometimes has a value
201 //int xPixels = read4Bytes(buf, offset+24); //0 177 //int xPixels = read4Bytes(buf, offset+24); //0
202 //int yPixels = read4Bytes(buf, offset+28); //0 178 //int yPixels = read4Bytes(buf, offset+28); //0
203 //int colorsUsed = read4Bytes(buf, offset+32) //0 - might have an ac tual value though 179 //int colorsUsed = read4Bytes(buf, offset+32) //0 - might have an ac tual value though
204 //int colorsImportant = read4Bytes(buf, offset+36); //0 180 //int colorsImportant = read4Bytes(buf, offset+36); //0
205 181
206 int begin = SkToInt(offset + 40); 182 int begin = SkToInt(offset + 40);
207 // Check that the buffer is large enough to read the color table
208 // For bmp-in-icos, there should be 4 bytes per color
209 if (length < (size_t) (begin + 4*colorCount)) {
210 return kFailure;
211 }
212
213 //this array represents the colortable 183 //this array represents the colortable
214 //if i allow other types of bitmaps, it may actually be used as a part of th e bitmap 184 //if i allow other types of bitmaps, it may actually be used as a part of th e bitmap
215 SkPMColor* colors = NULL; 185 SkPMColor* colors = NULL;
216 int blue, green, red; 186 int blue, green, red;
217 if (colorCount) 187 if (colorCount)
218 { 188 {
219 colors = new SkPMColor[colorCount]; 189 colors = new SkPMColor[colorCount];
220 for (int j = 0; j < colorCount; j++) 190 for (int j = 0; j < colorCount; j++)
221 { 191 {
222 //should this be a function - maybe a #define? 192 //should this be a function - maybe a #define?
(...skipping 28 matching lines...) Expand all
251 delete[] colors; 221 delete[] colors;
252 return kSuccess; 222 return kSuccess;
253 } 223 }
254 224
255 if (!this->allocPixelRef(bm, NULL)) 225 if (!this->allocPixelRef(bm, NULL))
256 { 226 {
257 delete[] colors; 227 delete[] colors;
258 return kFailure; 228 return kFailure;
259 } 229 }
260 230
261 // The AND mask is a 1-bit alpha mask for each pixel that comes after the
262 // XOR mask in the bmp. If we check that the largest AND offset is safe,
263 // it should mean all other buffer accesses will be at smaller indices and
264 // will therefore be safe.
265 size_t maxAndOffset = andOffset + ((andLineWidth*(h-1)+(w-1)) >> 3);
266 if (length <= maxAndOffset) {
267 return kFailure;
268 }
269
270 // Here we assert that all reads from the buffer using the XOR offset are
271 // less than the AND offset. This should be guaranteed based on the above
272 // calculations.
273 #ifdef SK_DEBUG
274 int maxPixelNum = lineWidth*(h-1)+w-1;
275 int maxByte;
276 switch (bitCount) {
277 case 1:
278 maxByte = maxPixelNum >> 3;
279 break;
280 case 4:
281 maxByte = maxPixelNum >> 1;
282 break;
283 case 8:
284 maxByte = maxPixelNum;
285 break;
286 case 24:
287 maxByte = maxPixelNum * 3 + 2;
288 break;
289 case 32:
290 maxByte = maxPixelNum * 4 + 3;
291 break;
292 default:
293 SkASSERT(false);
294 return kFailure;
295 }
296 int maxXOROffset = xorOffset + maxByte;
297 SkASSERT(maxXOROffset < andOffset);
298 #endif
299
300 SkAutoLockPixels alp(*bm); 231 SkAutoLockPixels alp(*bm);
301 232
302 for (int y = 0; y < h; y++) 233 for (int y = 0; y < h; y++)
303 { 234 {
304 for (int x = 0; x < w; x++) 235 for (int x = 0; x < w; x++)
305 { 236 {
306 //U32* address = bm->getAddr32(x, y); 237 //U32* address = bm->getAddr32(x, y);
307 238
308 //check the alpha bit first, but pass it along to the function to fi gure out how to deal with it 239 //check the alpha bit first, but pass it along to the function to fi gure out how to deal with it
309 int andPixelNo = andLineWidth*(h-y-1)+x; 240 int andPixelNo = andLineWidth*(h-y-1)+x;
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
435 366
436 static SkImageDecoder* sk_libico_dfactory(SkStreamRewindable* stream) { 367 static SkImageDecoder* sk_libico_dfactory(SkStreamRewindable* stream) {
437 if (is_ico(stream)) { 368 if (is_ico(stream)) {
438 return SkNEW(SkICOImageDecoder); 369 return SkNEW(SkICOImageDecoder);
439 } 370 }
440 return NULL; 371 return NULL;
441 } 372 }
442 373
443 static SkImageDecoder_DecodeReg gReg(sk_libico_dfactory); 374 static SkImageDecoder_DecodeReg gReg(sk_libico_dfactory);
444 375
445 static SkImageDecoder::Format get_format_ico(SkStreamRewindable* stream) { 376 SkEncodedFormat get_format_ico(SkStreamRewindable* stream) {
446 if (is_ico(stream)) { 377 if (is_ico(stream)) {
447 return SkImageDecoder::kICO_Format; 378 return kICO_SkEncodedFormat;
448 } 379 }
449 return SkImageDecoder::kUnknown_Format; 380 return kUnknown_SkEncodedFormat;
450 } 381 }
451 382
452 static SkImageDecoder_FormatReg gFormatReg(get_format_ico); 383 static SkImageDecoder_FormatReg gFormatReg(get_format_ico);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698