Home | History | Annotate | Download | only in codec
      1 /*
      2  * Copyright 2015 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 "SkCodecPriv.h"
      9 #include "SkMasks.h"
     10 #include "SkTypes.h"
     11 
     12 /*
     13  *
     14  * Used to convert 1-7 bit color components into 8-bit color components
     15  *
     16  */
     17 const static uint8_t n_bit_to_8_bit_lookup_table[] = {
     18     // 1 bit
     19     0, 255,
     20     // 2 bits
     21     0, 85, 170, 255,
     22     // 3 bits
     23     0, 36, 73, 109, 146, 182, 219, 255,
     24     // 4 bits
     25     0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255,
     26     // 5 bits
     27     0, 8, 16, 25, 33, 41, 49, 58, 66, 74, 82, 90, 99, 107, 115, 123, 132, 140,
     28     148, 156, 165, 173, 181, 189, 197, 206, 214, 222, 230, 239, 247, 255,
     29     // 6 bits
     30     0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 45, 49, 53, 57, 61, 65, 69, 73,
     31     77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 130, 134, 138,
     32     142, 146, 150, 154, 158, 162, 166, 170, 174, 178, 182, 186, 190, 194, 198,
     33     202, 206, 210, 215, 219, 223, 227, 231, 235, 239, 243, 247, 251, 255,
     34     // 7 bits
     35     0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38,
     36     40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76,
     37     78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110,
     38     112, 114, 116, 118, 120, 122, 124, 126, 129, 131, 133, 135, 137, 139, 141,
     39     143, 145, 147, 149, 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171,
     40     173, 175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201,
     41     203, 205, 207, 209, 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231,
     42     233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255
     43 };
     44 
     45 /*
     46  *
     47  * Convert an n bit component to an 8-bit component
     48  *
     49  */
     50 static uint8_t convert_to_8(uint32_t component, uint32_t n) {
     51     if (0 == n) {
     52         return 0;
     53     } else if (8 > n) {
     54         return n_bit_to_8_bit_lookup_table[(1 << n) - 2 + component];
     55     } else {
     56         SkASSERT(8 == n);
     57         return component;
     58     }
     59 }
     60 
     61 static uint8_t get_comp(uint32_t pixel, uint32_t mask, uint32_t shift,
     62                         uint32_t size) {
     63     return convert_to_8((pixel & mask) >> shift, size);
     64 }
     65 
     66 /*
     67  *
     68  * Get a color component
     69  *
     70  */
     71 uint8_t SkMasks::getRed(uint32_t pixel) {
     72     return get_comp(pixel, fRed.mask, fRed.shift, fRed.size);
     73 }
     74 uint8_t SkMasks::getGreen(uint32_t pixel) {
     75     return get_comp(pixel, fGreen.mask, fGreen.shift, fGreen.size);
     76 }
     77 uint8_t SkMasks::getBlue(uint32_t pixel) {
     78     return get_comp(pixel, fBlue.mask, fBlue.shift, fBlue.size);
     79 }
     80 uint8_t SkMasks::getAlpha(uint32_t pixel) {
     81     return get_comp(pixel, fAlpha.mask, fAlpha.shift, fAlpha.size);
     82 }
     83 
     84 /*
     85  *
     86  * Process an input mask to obtain the necessary information
     87  *
     88  */
     89 const SkMasks::MaskInfo process_mask(uint32_t mask, uint32_t bpp) {
     90     // Trim the masks to the allowed number of bits
     91     if (bpp < 32) {
     92         mask &= (1 << bpp) - 1;
     93     }
     94 
     95     // Determine properties of the mask
     96     uint32_t tempMask = mask;
     97     uint32_t shift = 0;
     98     uint32_t size = 0;
     99     if (tempMask != 0) {
    100         // Count trailing zeros on masks
    101         for (; (tempMask & 1) == 0; tempMask >>= 1) {
    102             shift++;
    103         }
    104         // Count the size of the mask
    105         for (; tempMask & 1; tempMask >>= 1) {
    106             size++;
    107         }
    108         // Check that the mask is continuous
    109         if (tempMask != 0) {
    110             SkCodecPrintf("Warning: Bit masks is not continuous.\n");
    111         }
    112         // Truncate masks greater than 8 bits
    113         if (size > 8) {
    114             shift += size - 8;
    115             size = 8;
    116         }
    117     }
    118 
    119     // Save the calculated values
    120     const SkMasks::MaskInfo info = { mask, shift, size };
    121     return info;
    122 }
    123 
    124 /*
    125  *
    126  * Create the masks object
    127  *
    128  */
    129 SkMasks* SkMasks::CreateMasks(InputMasks masks, uint32_t bitsPerPixel) {
    130     // Trim the input masks according to bitsPerPixel
    131     if (bitsPerPixel < 32) {
    132         masks.red &= (1 << bitsPerPixel) - 1;
    133         masks.green &= (1 << bitsPerPixel) - 1;
    134         masks.blue &= (1 << bitsPerPixel) - 1;
    135         masks.alpha &= (1 << bitsPerPixel) - 1;
    136     }
    137 
    138     // Check that masks do not overlap
    139     if (((masks.red & masks.green) | (masks.red & masks.blue) |
    140             (masks.red & masks.alpha) | (masks.green & masks.blue) |
    141             (masks.green & masks.alpha) | (masks.blue & masks.alpha)) != 0) {
    142         return NULL;
    143     }
    144 
    145     // Collect information about the masks
    146     const MaskInfo red = process_mask(masks.red, bitsPerPixel);
    147     const MaskInfo green = process_mask(masks.green, bitsPerPixel);
    148     const MaskInfo blue = process_mask(masks.blue, bitsPerPixel);
    149     const MaskInfo alpha = process_mask(masks.alpha, bitsPerPixel);
    150 
    151     return SkNEW_ARGS(SkMasks, (red, green, blue, alpha));
    152 }
    153 
    154 
    155 SkMasks::SkMasks(const MaskInfo red, const MaskInfo green,
    156                  const MaskInfo blue, const MaskInfo alpha)
    157     : fRed(red)
    158     , fGreen(green)
    159     , fBlue(blue)
    160     , fAlpha(alpha)
    161 {}
    162