OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
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 "SkBmpRLECodec.h" | 8 #include "SkBmpRLECodec.h" |
9 #include "SkCodecPriv.h" | 9 #include "SkCodecPriv.h" |
10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 *rowsDecoded = dstInfo.height(); | 63 *rowsDecoded = dstInfo.height(); |
64 return kIncompleteInput; | 64 return kIncompleteInput; |
65 } | 65 } |
66 | 66 |
67 return kSuccess; | 67 return kSuccess; |
68 } | 68 } |
69 | 69 |
70 /* | 70 /* |
71 * Process the color table for the bmp input | 71 * Process the color table for the bmp input |
72 */ | 72 */ |
73 bool SkBmpRLECodec::createColorTable(int* numColors) { | 73 bool SkBmpRLECodec::createColorTable(SkColorType dstColorType, int* numColors)
{ |
74 // Allocate memory for color table | 74 // Allocate memory for color table |
75 uint32_t colorBytes = 0; | 75 uint32_t colorBytes = 0; |
76 SkPMColor colorTable[256]; | 76 SkPMColor colorTable[256]; |
77 if (this->bitsPerPixel() <= 8) { | 77 if (this->bitsPerPixel() <= 8) { |
78 // Inform the caller of the number of colors | 78 // Inform the caller of the number of colors |
79 uint32_t maxColors = 1 << this->bitsPerPixel(); | 79 uint32_t maxColors = 1 << this->bitsPerPixel(); |
80 if (nullptr != numColors) { | 80 if (nullptr != numColors) { |
81 // We set the number of colors to maxColors in order to ensure | 81 // We set the number of colors to maxColors in order to ensure |
82 // safe memory accesses. Otherwise, an invalid pixel could | 82 // safe memory accesses. Otherwise, an invalid pixel could |
83 // access memory outside of our color table array. | 83 // access memory outside of our color table array. |
84 *numColors = maxColors; | 84 *numColors = maxColors; |
85 } | 85 } |
86 // Don't bother reading more than maxColors. | 86 // Don't bother reading more than maxColors. |
87 const uint32_t numColorsToRead = | 87 const uint32_t numColorsToRead = |
88 fNumColors == 0 ? maxColors : SkTMin(fNumColors, maxColors); | 88 fNumColors == 0 ? maxColors : SkTMin(fNumColors, maxColors); |
89 | 89 |
90 // Read the color table from the stream | 90 // Read the color table from the stream |
91 colorBytes = numColorsToRead * fBytesPerColor; | 91 colorBytes = numColorsToRead * fBytesPerColor; |
92 SkAutoTDeleteArray<uint8_t> cBuffer(new uint8_t[colorBytes]); | 92 SkAutoTDeleteArray<uint8_t> cBuffer(new uint8_t[colorBytes]); |
93 if (stream()->read(cBuffer.get(), colorBytes) != colorBytes) { | 93 if (stream()->read(cBuffer.get(), colorBytes) != colorBytes) { |
94 SkCodecPrintf("Error: unable to read color table.\n"); | 94 SkCodecPrintf("Error: unable to read color table.\n"); |
95 return false; | 95 return false; |
96 } | 96 } |
97 | 97 |
98 // Fill in the color table | 98 // Fill in the color table |
| 99 PackColorProc packARGB = choose_pack_color_proc(false, dstColorType); |
99 uint32_t i = 0; | 100 uint32_t i = 0; |
100 for (; i < numColorsToRead; i++) { | 101 for (; i < numColorsToRead; i++) { |
101 uint8_t blue = get_byte(cBuffer.get(), i*fBytesPerColor); | 102 uint8_t blue = get_byte(cBuffer.get(), i*fBytesPerColor); |
102 uint8_t green = get_byte(cBuffer.get(), i*fBytesPerColor + 1); | 103 uint8_t green = get_byte(cBuffer.get(), i*fBytesPerColor + 1); |
103 uint8_t red = get_byte(cBuffer.get(), i*fBytesPerColor + 2); | 104 uint8_t red = get_byte(cBuffer.get(), i*fBytesPerColor + 2); |
104 colorTable[i] = SkPackARGB32NoCheck(0xFF, red, green, blue); | 105 colorTable[i] = packARGB(0xFF, red, green, blue); |
105 } | 106 } |
106 | 107 |
107 // To avoid segmentation faults on bad pixel data, fill the end of the | 108 // To avoid segmentation faults on bad pixel data, fill the end of the |
108 // color table with black. This is the same the behavior as the | 109 // color table with black. This is the same the behavior as the |
109 // chromium decoder. | 110 // chromium decoder. |
110 for (; i < maxColors; i++) { | 111 for (; i < maxColors; i++) { |
111 colorTable[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0); | 112 colorTable[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0); |
112 } | 113 } |
113 | 114 |
114 // Set the color table | 115 // Set the color table |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 void SkBmpRLECodec::setPixel(void* dst, size_t dstRowBytes, | 202 void SkBmpRLECodec::setPixel(void* dst, size_t dstRowBytes, |
202 const SkImageInfo& dstInfo, uint32_t x, uint32_t y, | 203 const SkImageInfo& dstInfo, uint32_t x, uint32_t y, |
203 uint8_t index) { | 204 uint8_t index) { |
204 if (dst && is_coord_necessary(x, fSampleX, dstInfo.width())) { | 205 if (dst && is_coord_necessary(x, fSampleX, dstInfo.width())) { |
205 // Set the row | 206 // Set the row |
206 uint32_t row = this->getDstRow(y, dstInfo.height()); | 207 uint32_t row = this->getDstRow(y, dstInfo.height()); |
207 | 208 |
208 // Set the pixel based on destination color type | 209 // Set the pixel based on destination color type |
209 const int dstX = get_dst_coord(x, fSampleX); | 210 const int dstX = get_dst_coord(x, fSampleX); |
210 switch (dstInfo.colorType()) { | 211 switch (dstInfo.colorType()) { |
211 case kN32_SkColorType: { | 212 case kRGBA_8888_SkColorType: |
| 213 case kBGRA_8888_SkColorType: { |
212 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, row * (int) dst
RowBytes); | 214 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, row * (int) dst
RowBytes); |
213 dstRow[dstX] = fColorTable->operator[](index); | 215 dstRow[dstX] = fColorTable->operator[](index); |
214 break; | 216 break; |
215 } | 217 } |
216 case kRGB_565_SkColorType: { | 218 case kRGB_565_SkColorType: { |
217 uint16_t* dstRow = SkTAddOffset<uint16_t>(dst, row * (int) dstRo
wBytes); | 219 uint16_t* dstRow = SkTAddOffset<uint16_t>(dst, row * (int) dstRo
wBytes); |
218 dstRow[dstX] = SkPixel32ToPixel16(fColorTable->operator[](index)
); | 220 dstRow[dstX] = SkPixel32ToPixel16(fColorTable->operator[](index)
); |
219 break; | 221 break; |
220 } | 222 } |
221 default: | 223 default: |
(...skipping 12 matching lines...) Expand all Loading... |
234 const SkImageInfo& dstInfo, uint32_t x, | 236 const SkImageInfo& dstInfo, uint32_t x, |
235 uint32_t y, uint8_t red, uint8_t green, | 237 uint32_t y, uint8_t red, uint8_t green, |
236 uint8_t blue) { | 238 uint8_t blue) { |
237 if (dst && is_coord_necessary(x, fSampleX, dstInfo.width())) { | 239 if (dst && is_coord_necessary(x, fSampleX, dstInfo.width())) { |
238 // Set the row | 240 // Set the row |
239 uint32_t row = this->getDstRow(y, dstInfo.height()); | 241 uint32_t row = this->getDstRow(y, dstInfo.height()); |
240 | 242 |
241 // Set the pixel based on destination color type | 243 // Set the pixel based on destination color type |
242 const int dstX = get_dst_coord(x, fSampleX); | 244 const int dstX = get_dst_coord(x, fSampleX); |
243 switch (dstInfo.colorType()) { | 245 switch (dstInfo.colorType()) { |
244 case kN32_SkColorType: { | 246 case kRGBA_8888_SkColorType: { |
245 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, row * (int) dst
RowBytes); | 247 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, row * (int) dst
RowBytes); |
246 dstRow[dstX] = SkPackARGB32NoCheck(0xFF, red, green, blue); | 248 dstRow[dstX] = SkPackARGB_as_RGBA(0xFF, red, green, blue); |
| 249 break; |
| 250 } |
| 251 case kBGRA_8888_SkColorType: { |
| 252 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, row * (int) dst
RowBytes); |
| 253 dstRow[dstX] = SkPackARGB_as_BGRA(0xFF, red, green, blue); |
247 break; | 254 break; |
248 } | 255 } |
249 case kRGB_565_SkColorType: { | 256 case kRGB_565_SkColorType: { |
250 uint16_t* dstRow = SkTAddOffset<uint16_t>(dst, row * (int) dstRo
wBytes); | 257 uint16_t* dstRow = SkTAddOffset<uint16_t>(dst, row * (int) dstRo
wBytes); |
251 dstRow[dstX] = SkPack888ToRGB16(red, green, blue); | 258 dstRow[dstX] = SkPack888ToRGB16(red, green, blue); |
252 break; | 259 break; |
253 } | 260 } |
254 default: | 261 default: |
255 // This case should not be reached. We should catch an invalid | 262 // This case should not be reached. We should catch an invalid |
256 // color type when we check that the conversion is possible. | 263 // color type when we check that the conversion is possible. |
(...skipping 11 matching lines...) Expand all Loading... |
268 return kUnimplemented; | 275 return kUnimplemented; |
269 } | 276 } |
270 | 277 |
271 // Reset fSampleX. If it needs to be a value other than 1, it will get modif
ied by | 278 // Reset fSampleX. If it needs to be a value other than 1, it will get modif
ied by |
272 // the sampler. | 279 // the sampler. |
273 fSampleX = 1; | 280 fSampleX = 1; |
274 fLinesToSkip = 0; | 281 fLinesToSkip = 0; |
275 | 282 |
276 // Create the color table if necessary and prepare the stream for decode | 283 // Create the color table if necessary and prepare the stream for decode |
277 // Note that if it is non-NULL, inputColorCount will be modified | 284 // Note that if it is non-NULL, inputColorCount will be modified |
278 if (!this->createColorTable(inputColorCount)) { | 285 if (!this->createColorTable(dstInfo.colorType(), inputColorCount)) { |
279 SkCodecPrintf("Error: could not create color table.\n"); | 286 SkCodecPrintf("Error: could not create color table.\n"); |
280 return SkCodec::kInvalidInput; | 287 return SkCodec::kInvalidInput; |
281 } | 288 } |
282 | 289 |
283 // Copy the color table to the client if necessary | 290 // Copy the color table to the client if necessary |
284 copy_color_table(dstInfo, this->fColorTable, inputColorPtr, inputColorCount)
; | 291 copy_color_table(dstInfo, this->fColorTable, inputColorPtr, inputColorCount)
; |
285 | 292 |
286 // Initialize a buffer for encoded RLE data | 293 // Initialize a buffer for encoded RLE data |
287 fRLEBytes = fOrigRLEBytes; | 294 fRLEBytes = fOrigRLEBytes; |
288 if (!this->initializeStreamBuffer()) { | 295 if (!this->initializeStreamBuffer()) { |
(...skipping 19 matching lines...) Expand all Loading... |
308 const int width = this->getInfo().width(); | 315 const int width = this->getInfo().width(); |
309 int height = info.height(); | 316 int height = info.height(); |
310 | 317 |
311 // Account for sampling. | 318 // Account for sampling. |
312 SkImageInfo dstInfo = info.makeWH(get_scaled_dimension(width, fSampleX), hei
ght); | 319 SkImageInfo dstInfo = info.makeWH(get_scaled_dimension(width, fSampleX), hei
ght); |
313 | 320 |
314 // Set the background as transparent. Then, if the RLE code skips pixels, | 321 // Set the background as transparent. Then, if the RLE code skips pixels, |
315 // the skipped pixels will be transparent. | 322 // the skipped pixels will be transparent. |
316 // Because of the need for transparent pixels, kN32 is the only color | 323 // Because of the need for transparent pixels, kN32 is the only color |
317 // type that makes sense for the destination format. | 324 // type that makes sense for the destination format. |
318 SkASSERT(kN32_SkColorType == dstInfo.colorType()); | 325 SkASSERT(kRGBA_8888_SkColorType == dstInfo.colorType() || |
| 326 kBGRA_8888_SkColorType == dstInfo.colorType()); |
319 if (dst) { | 327 if (dst) { |
320 SkSampler::Fill(dstInfo, dst, dstRowBytes, SK_ColorTRANSPARENT, opts.fZe
roInitialized); | 328 SkSampler::Fill(dstInfo, dst, dstRowBytes, SK_ColorTRANSPARENT, opts.fZe
roInitialized); |
321 } | 329 } |
322 | 330 |
323 // Adjust the height and the dst if the previous call to decodeRows() left u
s | 331 // Adjust the height and the dst if the previous call to decodeRows() left u
s |
324 // with lines that need to be skipped. | 332 // with lines that need to be skipped. |
325 if (height > fLinesToSkip) { | 333 if (height > fLinesToSkip) { |
326 height -= fLinesToSkip; | 334 height -= fLinesToSkip; |
327 dst = SkTAddOffset<void>(dst, fLinesToSkip * dstRowBytes); | 335 dst = SkTAddOffset<void>(dst, fLinesToSkip * dstRowBytes); |
328 fLinesToSkip = 0; | 336 fLinesToSkip = 0; |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
539 fSampler.reset(new SkBmpRLESampler(this)); | 547 fSampler.reset(new SkBmpRLESampler(this)); |
540 } | 548 } |
541 | 549 |
542 return fSampler; | 550 return fSampler; |
543 } | 551 } |
544 | 552 |
545 int SkBmpRLECodec::setSampleX(int sampleX){ | 553 int SkBmpRLECodec::setSampleX(int sampleX){ |
546 fSampleX = sampleX; | 554 fSampleX = sampleX; |
547 return get_scaled_dimension(this->getInfo().width(), sampleX); | 555 return get_scaled_dimension(this->getInfo().width(), sampleX); |
548 } | 556 } |
OLD | NEW |