OLD | NEW |
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 | 8 |
9 #include "SkImageDecoder.h" | 9 #include "SkImageDecoder.h" |
10 #include "SkBitmap.h" | 10 #include "SkBitmap.h" |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
273 SkBitmap::Config pref, Mode mode, Format* format) { | 273 SkBitmap::Config pref, Mode mode, Format* format) { |
274 if (0 == size) { | 274 if (0 == size) { |
275 return false; | 275 return false; |
276 } | 276 } |
277 SkASSERT(buffer); | 277 SkASSERT(buffer); |
278 | 278 |
279 SkMemoryStream stream(buffer, size); | 279 SkMemoryStream stream(buffer, size); |
280 return SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format); | 280 return SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format); |
281 } | 281 } |
282 | 282 |
283 class TargetAllocator : public SkBitmap::Allocator { | 283 /** |
| 284 * Special allocator used by DecodeMemoryToTarget. Uses preallocated memory |
| 285 * provided if the bm is 8888. Otherwise, uses a heap allocator. The same |
| 286 * allocator will be used again for a copy to 8888, when the preallocated |
| 287 * memory will be used. |
| 288 */ |
| 289 class TargetAllocator : public SkBitmap::HeapAllocator { |
284 | 290 |
285 public: | 291 public: |
286 TargetAllocator(void* target) | 292 TargetAllocator(void* target) |
287 : fTarget(target) {} | 293 : fTarget(target) {} |
288 | 294 |
289 virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) SK_OVERRIDE { | 295 virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) SK_OVERRIDE { |
290 // SkColorTable is not supported by Info/Target model. | 296 // If the config is not 8888, allocate a pixelref using the heap. |
| 297 // fTarget will be used to store the final pixels when copied to |
| 298 // 8888. |
| 299 if (bm->config() != SkBitmap::kARGB_8888_Config) { |
| 300 return INHERITED::allocPixelRef(bm, ct); |
| 301 } |
| 302 // In kARGB_8888_Config, there is no colortable. |
291 SkASSERT(NULL == ct); | 303 SkASSERT(NULL == ct); |
292 bm->setPixels(fTarget); | 304 bm->setPixels(fTarget); |
293 return true; | 305 return true; |
294 } | 306 } |
295 | 307 |
296 private: | 308 private: |
297 void* fTarget; | 309 void* fTarget; |
| 310 typedef SkBitmap::HeapAllocator INHERITED; |
298 }; | 311 }; |
299 | 312 |
| 313 /** |
| 314 * Helper function for DecodeMemoryToTarget. DecodeMemoryToTarget wants |
| 315 * 8888, so set the config to it. All parameters must not be null. |
| 316 * @param decoder Decoder appropriate for this stream. |
| 317 * @param stream Rewound stream to the encoded data. |
| 318 * @param bitmap On success, will have its bounds set to the bounds of the |
| 319 * encoded data, and its config set to 8888. |
| 320 * @return True if the bounds were decoded and the bitmap is 8888 or can be |
| 321 * copied to 8888. |
| 322 */ |
| 323 static bool decode_bounds_to_8888(SkImageDecoder* decoder, SkStream* stream, |
| 324 SkBitmap* bitmap) { |
| 325 SkASSERT(decoder != NULL); |
| 326 SkASSERT(stream != NULL); |
| 327 SkASSERT(bitmap != NULL); |
| 328 |
| 329 if (!decoder->decode(stream, bitmap, SkImageDecoder::kDecodeBounds_Mode)) { |
| 330 return false; |
| 331 } |
| 332 |
| 333 if (bitmap->config() == SkBitmap::kARGB_8888_Config) { |
| 334 return true; |
| 335 } |
| 336 |
| 337 if (!bitmap->canCopyTo(SkBitmap::kARGB_8888_Config)) { |
| 338 return false; |
| 339 } |
| 340 |
| 341 bitmap->setConfig(SkBitmap::kARGB_8888_Config, bitmap->width(), bitmap->heig
ht()); |
| 342 return true; |
| 343 } |
| 344 |
| 345 /** |
| 346 * Helper function for DecodeMemoryToTarget. Decodes the stream into bitmap, an
d if |
| 347 * the bitmap is not 8888, then it is copied to 8888. Either way, the end resul
t has |
| 348 * its pixels stored in target. All parameters must not be null. |
| 349 * @param decoder Decoder appropriate for this stream. |
| 350 * @param stream Rewound stream to the encoded data. |
| 351 * @param bitmap On success, will contain the decoded image, with its pixels st
ored |
| 352 * at target. |
| 353 * @param target Preallocated memory for storing pixels. |
| 354 * @return bool Whether the decode (and copy, if necessary) succeeded. |
| 355 */ |
| 356 static bool decode_pixels_to_8888(SkImageDecoder* decoder, SkStream* stream, |
| 357 SkBitmap* bitmap, void* target) { |
| 358 SkASSERT(decoder != NULL); |
| 359 SkASSERT(stream != NULL); |
| 360 SkASSERT(bitmap != NULL); |
| 361 SkASSERT(target != NULL); |
| 362 |
| 363 TargetAllocator allocator(target); |
| 364 decoder->setAllocator(&allocator); |
| 365 |
| 366 bool success = decoder->decode(stream, bitmap, SkImageDecoder::kDecodePixels
_Mode); |
| 367 decoder->setAllocator(NULL); |
| 368 |
| 369 if (!success) { |
| 370 return false; |
| 371 } |
| 372 |
| 373 if (bitmap->config() == SkBitmap::kARGB_8888_Config) { |
| 374 return true; |
| 375 } |
| 376 |
| 377 SkBitmap bm8888; |
| 378 if (!bitmap->copyTo(&bm8888, SkBitmap::kARGB_8888_Config, &allocator)) { |
| 379 return false; |
| 380 } |
| 381 |
| 382 bitmap->swap(bm8888); |
| 383 return true; |
| 384 } |
| 385 |
300 bool SkImageDecoder::DecodeMemoryToTarget(const void* buffer, size_t size, | 386 bool SkImageDecoder::DecodeMemoryToTarget(const void* buffer, size_t size, |
301 SkImage::Info* info, | 387 SkImage::Info* info, |
302 const SkBitmapFactory::Target* target)
{ | 388 const SkBitmapFactory::Target* target)
{ |
303 if (NULL == info) { | 389 if (NULL == info) { |
304 return false; | 390 return false; |
305 } | 391 } |
| 392 |
306 // FIXME: Just to get this working, implement in terms of existing | 393 // FIXME: Just to get this working, implement in terms of existing |
307 // ImageDecoder calls. | 394 // ImageDecoder calls. |
308 SkBitmap bm; | 395 SkBitmap bm; |
309 SkMemoryStream stream(buffer, size); | 396 SkMemoryStream stream(buffer, size); |
310 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(&stream)); | 397 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(&stream)); |
311 if (decoder.get() != NULL && decoder->decode(&stream, &bm, kDecodeBounds_Mod
e)) { | 398 if (NULL == decoder.get()) { |
312 // Now set info properly | 399 return false; |
313 if (!SkBitmapToImageInfo(bm, info)) { | 400 } |
| 401 |
| 402 if (!decode_bounds_to_8888(decoder.get(), &stream, &bm)) { |
| 403 return false; |
| 404 } |
| 405 |
| 406 SkASSERT(bm.config() == SkBitmap::kARGB_8888_Config); |
| 407 |
| 408 // Now set info properly. |
| 409 // Since Config is SkBitmap::kARGB_8888_Config, SkBitmapToImageInfo |
| 410 // will always succeed. |
| 411 SkAssertResult(SkBitmapToImageInfo(bm, info)); |
| 412 |
| 413 if (NULL == target) { |
| 414 return true; |
| 415 } |
| 416 |
| 417 if (target->fRowBytes != SkToU32(bm.rowBytes())) { |
| 418 if (target->fRowBytes < SkImageMinRowBytes(*info)) { |
| 419 SkASSERT(!"Desired row bytes is too small"); |
314 return false; | 420 return false; |
315 } | 421 } |
| 422 bm.setConfig(bm.config(), bm.width(), bm.height(), target->fRowBytes); |
| 423 } |
316 | 424 |
317 // SkBitmapToImageInfo will return false if Index8 is used. kIndex8 | 425 // SkMemoryStream.rewind() will always return true. |
318 // is not supported by the Info/Target model, since kIndex8 requires | 426 SkAssertResult(stream.rewind()); |
319 // an SkColorTable, which this model does not keep track of. | 427 return decode_pixels_to_8888(decoder.get(), &stream, &bm, target->fAddr); |
320 SkASSERT(bm.config() != SkBitmap::kIndex8_Config); | |
321 | |
322 if (NULL == target) { | |
323 return true; | |
324 } | |
325 | |
326 if (target->fRowBytes != SkToU32(bm.rowBytes())) { | |
327 if (target->fRowBytes < SkImageMinRowBytes(*info)) { | |
328 SkASSERT(!"Desired row bytes is too small"); | |
329 return false; | |
330 } | |
331 bm.setConfig(bm.config(), bm.width(), bm.height(), target->fRowBytes
); | |
332 } | |
333 | |
334 TargetAllocator allocator(target->fAddr); | |
335 decoder->setAllocator(&allocator); | |
336 stream.rewind(); | |
337 bool success = decoder->decode(&stream, &bm, kDecodePixels_Mode); | |
338 // Remove the allocator, since it's on the stack. | |
339 decoder->setAllocator(NULL); | |
340 return success; | |
341 } | |
342 return false; | |
343 } | 428 } |
344 | 429 |
345 | 430 |
346 bool SkImageDecoder::DecodeStream(SkStream* stream, SkBitmap* bm, | 431 bool SkImageDecoder::DecodeStream(SkStream* stream, SkBitmap* bm, |
347 SkBitmap::Config pref, Mode mode, Format* format) { | 432 SkBitmap::Config pref, Mode mode, Format* format) { |
348 SkASSERT(stream); | 433 SkASSERT(stream); |
349 SkASSERT(bm); | 434 SkASSERT(bm); |
350 | 435 |
351 bool success = false; | 436 bool success = false; |
352 SkImageDecoder* codec = SkImageDecoder::Factory(stream); | 437 SkImageDecoder* codec = SkImageDecoder::Factory(stream); |
(...skipping 29 matching lines...) Expand all Loading... |
382 CreateICOImageDecoder(); | 467 CreateICOImageDecoder(); |
383 CreateWBMPImageDecoder(); | 468 CreateWBMPImageDecoder(); |
384 // Only link GIF and PNG on platforms that build them. See images.gyp | 469 // Only link GIF and PNG on platforms that build them. See images.gyp |
385 #if !defined(SK_BUILD_FOR_MAC) && !defined(SK_BUILD_FOR_WIN) && !defined(SK_BUIL
D_FOR_NACL) | 470 #if !defined(SK_BUILD_FOR_MAC) && !defined(SK_BUILD_FOR_WIN) && !defined(SK_BUIL
D_FOR_NACL) |
386 CreateGIFImageDecoder(); | 471 CreateGIFImageDecoder(); |
387 #endif | 472 #endif |
388 #if !defined(SK_BUILD_FOR_MAC) && !defined(SK_BUILD_FOR_WIN) | 473 #if !defined(SK_BUILD_FOR_MAC) && !defined(SK_BUILD_FOR_WIN) |
389 CreatePNGImageDecoder(); | 474 CreatePNGImageDecoder(); |
390 #endif | 475 #endif |
391 } | 476 } |
OLD | NEW |