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