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 */ 17static 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 */ 50static 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 61static 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 */ 71uint8_t SkMasks::getRed(uint32_t pixel) const { 72 return get_comp(pixel, fRed.mask, fRed.shift, fRed.size); 73} 74uint8_t SkMasks::getGreen(uint32_t pixel) const { 75 return get_comp(pixel, fGreen.mask, fGreen.shift, fGreen.size); 76} 77uint8_t SkMasks::getBlue(uint32_t pixel) const { 78 return get_comp(pixel, fBlue.mask, fBlue.shift, fBlue.size); 79} 80uint8_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 */ 89static 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 */ 127SkMasks* 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