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