SkImageInfo.cpp revision 615c369777258231054840a88cdb74c68c382485
1/* 2 * Copyright 2010 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 "SkImageInfo.h" 9#include "SkReadBuffer.h" 10#include "SkWriteBuffer.h" 11 12static bool color_type_supports_sRGB(SkColorType colorType) { 13 switch (colorType) { 14 case kRGBA_8888_SkColorType: 15 case kBGRA_8888_SkColorType: 16 return true; 17 default: 18 return false; 19 } 20} 21 22static bool color_type_supports_gamma(SkColorType colorType) { 23 switch (colorType) { 24 case kRGBA_8888_SkColorType: 25 case kBGRA_8888_SkColorType: 26 // case kLuminance ... 27 return true; 28 default: 29 return false; 30 } 31} 32 33static float pin_gamma_to_legal(float gamma) { 34 if (!SkScalarIsFinite(gamma)) { 35 return 1; 36 } 37 // these limits are just made up -- feel free to change them within reason 38 const float min_gamma = 0.01f; 39 const float max_gamma = 4.0; 40 return SkScalarPin(gamma, min_gamma, max_gamma); 41} 42 43SkImageInfo SkImageInfo::MakeSRGB(int width, int height, SkColorType ct, SkAlphaType at) { 44 Profile p = color_type_supports_sRGB(ct) ? kSRGB_Profile : kUnknown_Profile; 45 return SkImageInfo(width, height, ct, at, p, 0); 46} 47 48SkImageInfo SkImageInfo::MakeWithGamma(int width, int height, SkColorType ct, SkAlphaType at, 49 float gamma) { 50 Profile p; 51 if (color_type_supports_gamma(ct)) { 52 gamma = pin_gamma_to_legal(gamma); 53 p = kExponential_Profile; 54 } else { 55 p = kUnknown_Profile; 56 gamma = 0; 57 } 58 return SkImageInfo(width, height, ct, at, p, gamma); 59} 60 61bool SkColorTypeValidateAlphaType(SkColorType colorType, SkAlphaType alphaType, 62 SkAlphaType* canonical) { 63 switch (colorType) { 64 case kUnknown_SkColorType: 65 alphaType = kIgnore_SkAlphaType; 66 break; 67 case kAlpha_8_SkColorType: 68 if (kUnpremul_SkAlphaType == alphaType) { 69 alphaType = kPremul_SkAlphaType; 70 } 71 // fall-through 72 case kIndex_8_SkColorType: 73 case kARGB_4444_SkColorType: 74 case kRGBA_8888_SkColorType: 75 case kBGRA_8888_SkColorType: 76 if (kIgnore_SkAlphaType == alphaType) { 77 return false; 78 } 79 break; 80 case kRGB_565_SkColorType: 81 alphaType = kOpaque_SkAlphaType; 82 break; 83 default: 84 return false; 85 } 86 if (canonical) { 87 *canonical = alphaType; 88 } 89 return true; 90} 91 92void SkImageInfo::unflatten(SkReadBuffer& buffer) { 93 *this = Unflatten(buffer); 94} 95 96//////////////////////////////////////////////////////////////////////////////////////////// 97 98static bool alpha_type_is_valid(SkAlphaType alphaType) { 99 return (alphaType >= 0) && (alphaType <= kLastEnum_SkAlphaType); 100} 101 102static bool color_type_is_valid(SkColorType colorType) { 103 return (colorType >= 0) && (colorType <= kLastEnum_SkColorType); 104} 105 106static float igamma_to_gamma(int gamma3dot9) { 107 return gamma3dot9 / 512.0f; 108} 109 110static unsigned gamma_to_igamma(float gamma) { 111 SkASSERT(gamma >= 0 && gamma < 8); 112 int igamma = SkScalarRoundToInt(gamma * 512); 113 SkASSERT(igamma >= 0 && igamma <= 0xFFF); 114 return igamma; 115} 116 117SkImageInfo SkImageInfo::Unflatten(SkReadBuffer& buffer) { 118 int width = buffer.read32(); 119 int height = buffer.read32(); 120 uint32_t packed = buffer.read32(); 121 122 SkColorType ct = (SkColorType)((packed >> 0) & 0xFF); // 8 bits for colortype 123 SkAlphaType at = (SkAlphaType)((packed >> 8) & 0xFF); // 8 bits for alphatype 124 if (!alpha_type_is_valid(at) || !color_type_is_valid(ct)) { 125 return MakeUnknown(); 126 } 127 128 // Earlier formats always stored 0 in the upper 16 bits. That corresponds to 129 // days before we had gamma/profile. That happens to correspond to kUnknown_Profile, 130 // which means we can just ignore the gamma value anyways. 131 // 132 int iprofile = ((packed >> 16) & 0xF); // 4 bits for profile 133 134 switch (iprofile) { 135 case kUnknown_Profile: 136 return Make(width, height, ct, at); 137 case kSRGB_Profile: 138 return MakeSRGB(width, height, ct, at); 139 case kExponential_Profile: { 140 int igamma = packed >> 20; // 12 bits for gamma 3.9 141 float gamma = igamma_to_gamma(igamma); 142 return MakeWithGamma(width, height, ct, at, gamma); 143 } 144 default: 145 (void)buffer.validate(false); 146 return MakeUnknown(); 147 } 148} 149 150void SkImageInfo::flatten(SkWriteBuffer& buffer) const { 151 buffer.write32(fWidth); 152 buffer.write32(fHeight); 153 154 SkASSERT(0 == (fColorType & ~0xFF)); // 8 bits for colortype 155 SkASSERT(0 == (fAlphaType & ~0xFF)); // 8 bits for alphatype 156 SkASSERT(0 == (fProfile & ~0xF)); // 4 bits for profile 157 int igamma = gamma_to_igamma(fGamma); // 12 bits for gamma (if needed) 158 159 uint32_t packed = (igamma << 20) | (fProfile << 16) | (fAlphaType << 8) | fColorType; 160 buffer.write32(packed); 161} 162