• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   */
convert_to_8(uint32_t component,uint32_t n)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  
get_comp(uint32_t pixel,uint32_t mask,uint32_t shift,uint32_t size)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   */
getRed(uint32_t pixel)71  uint8_t SkMasks::getRed(uint32_t pixel) {
72      return get_comp(pixel, fRed.mask, fRed.shift, fRed.size);
73  }
getGreen(uint32_t pixel)74  uint8_t SkMasks::getGreen(uint32_t pixel) {
75      return get_comp(pixel, fGreen.mask, fGreen.shift, fGreen.size);
76  }
getBlue(uint32_t pixel)77  uint8_t SkMasks::getBlue(uint32_t pixel) {
78      return get_comp(pixel, fBlue.mask, fBlue.shift, fBlue.size);
79  }
getAlpha(uint32_t pixel)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   */
process_mask(uint32_t mask,uint32_t bpp)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   */
CreateMasks(InputMasks masks,uint32_t bitsPerPixel)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  
SkMasks(const MaskInfo red,const MaskInfo green,const MaskInfo blue,const MaskInfo alpha)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