• Home
  • 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 "include/core/SkTypes.h"
9 #include "src/codec/SkCodecPriv.h"
10 #include "src/codec/SkMasks.h"
11 
12 /*
13  *
14  * Used to convert 1-7 bit color components into 8-bit color components
15  *
16  */
17 static constexpr 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(uint8_t component,uint32_t n)50 static uint8_t convert_to_8(uint8_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) const71 uint8_t SkMasks::getRed(uint32_t pixel) const {
72     return get_comp(pixel, fRed.mask, fRed.shift, fRed.size);
73 }
getGreen(uint32_t pixel) const74 uint8_t SkMasks::getGreen(uint32_t pixel) const {
75     return get_comp(pixel, fGreen.mask, fGreen.shift, fGreen.size);
76 }
getBlue(uint32_t pixel) const77 uint8_t SkMasks::getBlue(uint32_t pixel) const {
78     return get_comp(pixel, fBlue.mask, fBlue.shift, fBlue.size);
79 }
getAlpha(uint32_t pixel) const80 uint8_t SkMasks::getAlpha(uint32_t pixel) const {
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)89 static const SkMasks::MaskInfo process_mask(uint32_t mask) {
90     // Determine properties of the mask
91     uint32_t tempMask = mask;
92     uint32_t shift = 0;
93     uint32_t size = 0;
94     if (tempMask != 0) {
95         // Count trailing zeros on masks
96         for (; (tempMask & 1) == 0; tempMask >>= 1) {
97             shift++;
98         }
99         // Count the size of the mask
100         for (; tempMask & 1; tempMask >>= 1) {
101             size++;
102         }
103         // Verify that the mask is continuous
104         if (tempMask) {
105             SkCodecPrintf("Warning: Bit mask is not continuous.\n");
106             // Finish processing the mask
107             for (; tempMask; tempMask >>= 1) {
108                 size++;
109             }
110         }
111         // Truncate masks greater than 8 bits
112         if (size > 8) {
113             shift += size - 8;
114             size = 8;
115             mask &= 0xFF << shift;
116         }
117     }
118 
119     return { mask, shift, size };
120 }
121 
122 /*
123  *
124  * Create the masks object
125  *
126  */
CreateMasks(InputMasks masks,int bytesPerPixel)127 SkMasks* SkMasks::CreateMasks(InputMasks masks, int bytesPerPixel) {
128     SkASSERT(0 < bytesPerPixel && bytesPerPixel <= 4);
129 
130     // Trim the input masks to match bytesPerPixel.
131     if (bytesPerPixel < 4) {
132         int bitsPerPixel = 8*bytesPerPixel;
133         masks.red   &= (1 << bitsPerPixel) - 1;
134         masks.green &= (1 << bitsPerPixel) - 1;
135         masks.blue  &= (1 << bitsPerPixel) - 1;
136         masks.alpha &= (1 << bitsPerPixel) - 1;
137     }
138 
139     // Check that masks do not overlap.
140     if (((masks.red   & masks.green) |
141          (masks.red   & masks.blue ) |
142          (masks.red   & masks.alpha) |
143          (masks.green & masks.blue ) |
144          (masks.green & masks.alpha) |
145          (masks.blue  & masks.alpha) ) != 0) {
146         return nullptr;
147     }
148 
149     return new SkMasks(process_mask(masks.red  ),
150                        process_mask(masks.green),
151                        process_mask(masks.blue ),
152                        process_mask(masks.alpha));
153 }
154 
155 
SkMasks(const MaskInfo & red,const MaskInfo & green,const MaskInfo & blue,const MaskInfo & alpha)156 SkMasks::SkMasks(const MaskInfo& red, const MaskInfo& green,
157                  const MaskInfo& blue, const MaskInfo& alpha)
158     : fRed(red)
159     , fGreen(green)
160     , fBlue(blue)
161     , fAlpha(alpha)
162 {}
163