Home | History | Annotate | Download | only in images
      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(const SkBitmap::Config& config) {
     75     switch (config) {
     76         case SkBitmap::kARGB_8888_Config:
     77             return ARGB_8888_To_ARGB;
     78         case SkBitmap::kRGB_565_Config:
     79             return RGB_565_To_ARGB;
     80         case SkBitmap::kARGB_4444_Config:
     81             return ARGB_4444_To_ARGB;
     82         case SkBitmap::kIndex8_Config:
     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 SkBitmap::Config config = bitmap.getConfig();
     91     const ScanlineImporter scanline_import = ChooseImporter(config);
     92     if (NULL == scanline_import) {
     93         return false;
     94     }
     95 
     96     SkAutoLockPixels alp(bitmap);
     97     const uint8_t* src = (uint8_t*)bitmap.getPixels();
     98     if (NULL == bitmap.getPixels()) {
     99         return false;
    100     }
    101 
    102     SkAutoLockColors ctLocker;
    103     const SkPMColor* colors = ctLocker.lockColors(bitmap);
    104 
    105     const int argbStride = bitmap.width() * 4;
    106     SkAutoTDeleteArray<uint8_t> ada(new uint8_t[argbStride]);
    107     uint8_t* argb = ada.get();
    108     for (int y = 0; y < bitmap.height(); ++y) {
    109         scanline_import(src + y * bitmap.rowBytes(), argb, bitmap.width(), colors);
    110         stream->write(argb, argbStride);
    111     }
    112 
    113     return true;
    114 }
    115 
    116 
    117 ///////////////////////////////////////////////////////////////////////////////
    118 DEFINE_ENCODER_CREATOR(ARGBImageEncoder);
    119 ///////////////////////////////////////////////////////////////////////////////
    120