1 /* 2 * Copyright 2013 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkImageEncoder.h" 9 #include "SkBitmap.h" 10 #include "SkColorPriv.h" 11 #include "SkStream.h" 12 #include "SkTemplates.h" 13 14 class SkARGBImageEncoder : public SkImageEncoder { 15 protected: 16 virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) SK_OVERRIDE; 17 18 private: 19 typedef SkImageEncoder INHERITED; 20 }; 21 22 typedef void (*ScanlineImporter)(const uint8_t* in, uint8_t* argb, int width, 23 const SkPMColor* SK_RESTRICT ctable); 24 25 static void ARGB_8888_To_ARGB(const uint8_t* in, uint8_t* argb, int width, const SkPMColor*) { 26 const uint32_t* SK_RESTRICT src = (const uint32_t*)in; 27 for (int i = 0; i < width; ++i) { 28 const uint32_t c = *src++; 29 argb[0] = SkGetPackedA32(c); 30 argb[1] = SkGetPackedR32(c); 31 argb[2] = SkGetPackedG32(c); 32 argb[3] = SkGetPackedB32(c); 33 argb += 4; 34 } 35 } 36 37 static void RGB_565_To_ARGB(const uint8_t* in, uint8_t* argb, int width, const SkPMColor*) { 38 const uint16_t* SK_RESTRICT src = (const uint16_t*)in; 39 for (int i = 0; i < width; ++i) { 40 const uint16_t c = *src++; 41 argb[0] = 0xFF; 42 argb[1] = SkPacked16ToR32(c); 43 argb[2] = SkPacked16ToG32(c); 44 argb[3] = SkPacked16ToB32(c); 45 argb += 4; 46 } 47 } 48 49 static void ARGB_4444_To_ARGB(const uint8_t* in, uint8_t* argb, int width, const SkPMColor*) { 50 const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)in; 51 for (int i = 0; i < width; ++i) { 52 const SkPMColor16 c = *src++; 53 argb[0] = SkPacked4444ToA32(c); 54 argb[1] = SkPacked4444ToR32(c); 55 argb[2] = SkPacked4444ToG32(c); 56 argb[3] = SkPacked4444ToB32(c); 57 argb += 4; 58 } 59 } 60 61 static void Index8_To_ARGB(const uint8_t* in, uint8_t* argb, int width, 62 const SkPMColor* SK_RESTRICT ctable) { 63 const uint8_t* SK_RESTRICT src = (const uint8_t*)in; 64 for (int i = 0; i < width; ++i) { 65 const uint32_t c = ctable[*src++]; 66 argb[0] = SkGetPackedA32(c); 67 argb[1] = SkGetPackedR32(c); 68 argb[2] = SkGetPackedG32(c); 69 argb[3] = SkGetPackedB32(c); 70 argb += 4; 71 } 72 } 73 74 static ScanlineImporter ChooseImporter(SkColorType ct) { 75 switch (ct) { 76 case kN32_SkColorType: 77 return ARGB_8888_To_ARGB; 78 case kRGB_565_SkColorType: 79 return RGB_565_To_ARGB; 80 case kARGB_4444_SkColorType: 81 return ARGB_4444_To_ARGB; 82 case kIndex_8_SkColorType: 83 return Index8_To_ARGB; 84 default: 85 return NULL; 86 } 87 } 88 89 bool SkARGBImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bitmap, int) { 90 const ScanlineImporter scanline_import = ChooseImporter(bitmap.colorType()); 91 if (NULL == scanline_import) { 92 return false; 93 } 94 95 SkAutoLockPixels alp(bitmap); 96 const uint8_t* src = (uint8_t*)bitmap.getPixels(); 97 if (NULL == bitmap.getPixels()) { 98 return false; 99 } 100 101 SkAutoLockColors ctLocker; 102 const SkPMColor* colors = ctLocker.lockColors(bitmap); 103 104 const int argbStride = bitmap.width() * 4; 105 SkAutoTDeleteArray<uint8_t> ada(new uint8_t[argbStride]); 106 uint8_t* argb = ada.get(); 107 for (int y = 0; y < bitmap.height(); ++y) { 108 scanline_import(src + y * bitmap.rowBytes(), argb, bitmap.width(), colors); 109 stream->write(argb, argbStride); 110 } 111 112 return true; 113 } 114 115 116 /////////////////////////////////////////////////////////////////////////////// 117 DEFINE_ENCODER_CREATOR(ARGBImageEncoder); 118 /////////////////////////////////////////////////////////////////////////////// 119