blob: 726074195daf23d787c0187520baa9a4a97e1e86 [file] [log] [blame]
msarett74114382015-03-16 11:55:18 -07001/*
2 * Copyright 2015 The Android Open Source Project
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#ifndef SkCodecPriv_DEFINED
9#define SkCodecPriv_DEFINED
10
msarett9e43cab2015-04-29 07:38:43 -070011#include "SkColorTable.h"
msarett74114382015-03-16 11:55:18 -070012#include "SkImageInfo.h"
13#include "SkSwizzler.h"
14#include "SkTypes.h"
msarett9e43cab2015-04-29 07:38:43 -070015#include "SkUtils.h"
msarett74114382015-03-16 11:55:18 -070016
17/*
18 *
19 * Helper routine for alpha result codes
20 *
21 */
22#define INIT_RESULT_ALPHA \
23 uint8_t zeroAlpha = 0; \
24 uint8_t maxAlpha = 0xFF;
25
26#define UPDATE_RESULT_ALPHA(alpha) \
27 zeroAlpha |= (alpha); \
28 maxAlpha &= (alpha);
29
30#define COMPUTE_RESULT_ALPHA \
31 SkSwizzler::GetResult(zeroAlpha, maxAlpha);
32
msarett5406d6f2015-08-31 06:55:13 -070033/*
34 * Returns the first coordinate that we will keep during a scaled decode.
35 * The output can be interpreted as an x-coordinate or a y-coordinate.
36 *
37 * This does not need to be called and is not called when sampleFactor == 1.
38 */
39static int get_start_coord(int sampleFactor) { return sampleFactor / 2; };
40
41/*
42 * Given a coordinate in the original image, this returns the corresponding
43 * coordinate in the scaled image. This function is meaningless if
44 * IsCoordNecessary returns false.
45 * The output can be interpreted as an x-coordinate or a y-coordinate.
46 *
47 * This does not need to be called and is not called when sampleFactor == 1.
48 */
49static int get_dst_coord(int srcCoord, int sampleFactor) { return srcCoord / sampleFactor; };
50
51/*
52 * When scaling, we will discard certain y-coordinates (rows) and
53 * x-coordinates (columns). This function returns true if we should keep the
54 * coordinate and false otherwise.
55 * The inputs may be x-coordinates or y-coordinates.
56 *
57 * This does not need to be called and is not called when sampleFactor == 1.
58 */
59static bool is_coord_necessary(int srcCoord, int sampleFactor, int scaledDim) {
60 // Get the first coordinate that we want to keep
61 int startCoord = get_start_coord(sampleFactor);
62
63 // Return false on edge cases
64 if (srcCoord < startCoord || get_dst_coord(srcCoord, sampleFactor) >= scaledDim) {
65 return false;
66 }
67
68 // Every sampleFactor rows are necessary
69 return ((srcCoord - startCoord) % sampleFactor) == 0;
70}
71
msarett4ab9d5f2015-08-06 15:34:42 -070072static inline bool valid_alpha(SkAlphaType dstAlpha, SkAlphaType srcAlpha) {
73 // Check for supported alpha types
74 if (srcAlpha != dstAlpha) {
75 if (kOpaque_SkAlphaType == srcAlpha) {
76 // If the source is opaque, we must decode to opaque
77 return false;
78 }
79
80 // The source is not opaque
81 switch (dstAlpha) {
82 case kPremul_SkAlphaType:
83 case kUnpremul_SkAlphaType:
84 // The source is not opaque, so either of these is okay
85 break;
86 default:
87 // We cannot decode a non-opaque image to opaque (or unknown)
88 return false;
89 }
90 }
91 return true;
92}
93
msarett74114382015-03-16 11:55:18 -070094/*
scroggocc2feb12015-08-14 08:32:46 -070095 * Most of our codecs support the same conversions:
96 * - profileType must be the same
97 * - opaque only to opaque (and 565 only if opaque)
98 * - premul to unpremul and vice versa
99 * - always support N32
100 * - otherwise match the src color type
101 */
102static bool conversion_possible(const SkImageInfo& dst, const SkImageInfo& src) {
103 if (dst.profileType() != src.profileType()) {
104 return false;
105 }
106
107 // Ensure the alpha type is valid
108 if (!valid_alpha(dst.alphaType(), src.alphaType())) {
109 return false;
110 }
111
112 // Check for supported color types
113 switch (dst.colorType()) {
114 case kN32_SkColorType:
115 return true;
116 case kRGB_565_SkColorType:
117 return src.alphaType() == kOpaque_SkAlphaType;
118 default:
119 return dst.colorType() == src.colorType();
120 }
121}
122
123/*
halcanary96fcdcc2015-08-27 07:41:13 -0700124 * If there is a color table, get a pointer to the colors, otherwise return nullptr
msarett99f567e2015-08-05 12:58:26 -0700125 */
126static const SkPMColor* get_color_ptr(SkColorTable* colorTable) {
halcanary96fcdcc2015-08-27 07:41:13 -0700127 return nullptr != colorTable ? colorTable->readColors() : nullptr;
msarett99f567e2015-08-05 12:58:26 -0700128}
129
130/*
msarett74114382015-03-16 11:55:18 -0700131 *
msarett9e43cab2015-04-29 07:38:43 -0700132 * Copy the codec color table back to the client when kIndex8 color type is requested
msarett9e43cab2015-04-29 07:38:43 -0700133 */
134static inline void copy_color_table(const SkImageInfo& dstInfo, SkColorTable* colorTable,
135 SkPMColor* inputColorPtr, int* inputColorCount) {
136 if (kIndex_8_SkColorType == dstInfo.colorType()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700137 SkASSERT(nullptr != inputColorPtr);
138 SkASSERT(nullptr != inputColorCount);
139 SkASSERT(nullptr != colorTable);
mtklein58fd2c82015-07-27 11:08:28 -0700140 memcpy(inputColorPtr, colorTable->readColors(), *inputColorCount * 4);
msarett9e43cab2015-04-29 07:38:43 -0700141 }
142}
143
144/*
msarett74114382015-03-16 11:55:18 -0700145 * Compute row bytes for an image using pixels per byte
msarett74114382015-03-16 11:55:18 -0700146 */
147static inline size_t compute_row_bytes_ppb(int width, uint32_t pixelsPerByte) {
148 return (width + pixelsPerByte - 1) / pixelsPerByte;
149}
150
151/*
msarett74114382015-03-16 11:55:18 -0700152 * Compute row bytes for an image using bytes per pixel
msarett74114382015-03-16 11:55:18 -0700153 */
154static inline size_t compute_row_bytes_bpp(int width, uint32_t bytesPerPixel) {
155 return width * bytesPerPixel;
156}
157
158/*
msarett74114382015-03-16 11:55:18 -0700159 * Compute row bytes for an image
msarett74114382015-03-16 11:55:18 -0700160 */
161static inline size_t compute_row_bytes(int width, uint32_t bitsPerPixel) {
162 if (bitsPerPixel < 16) {
163 SkASSERT(0 == 8 % bitsPerPixel);
164 const uint32_t pixelsPerByte = 8 / bitsPerPixel;
165 return compute_row_bytes_ppb(width, pixelsPerByte);
166 } else {
167 SkASSERT(0 == bitsPerPixel % 8);
168 const uint32_t bytesPerPixel = bitsPerPixel / 8;
169 return compute_row_bytes_bpp(width, bytesPerPixel);
170 }
171}
172
173/*
msarett5406d6f2015-08-31 06:55:13 -0700174 * On incomplete images, get the color to fill with
175 */
176static inline SkPMColor get_fill_color_or_index(SkAlphaType alphaType) {
177 // This condition works properly for all supported output color types.
178 // kIndex8: The low 8-bits of both possible return values is 0, which is
179 // our desired default index.
180 // kGray8: The low 8-bits of both possible return values is 0, which is
181 // black, our desired fill value.
182 // kRGB565: The low 16-bits of both possible return values is 0, which is
183 // black, our desired fill value.
184 // kN32: Return black for opaque images and transparent for non-opaque
185 // images.
186 return kOpaque_SkAlphaType == alphaType ?
187 SK_ColorBLACK : SK_ColorTRANSPARENT;
188}
189
190/*
msarett74114382015-03-16 11:55:18 -0700191 * Get a byte from a buffer
192 * This method is unsafe, the caller is responsible for performing a check
msarett74114382015-03-16 11:55:18 -0700193 */
194static inline uint8_t get_byte(uint8_t* buffer, uint32_t i) {
195 return buffer[i];
196}
197
198/*
msarett74114382015-03-16 11:55:18 -0700199 * Get a short from a buffer
200 * This method is unsafe, the caller is responsible for performing a check
msarett74114382015-03-16 11:55:18 -0700201 */
202static inline uint16_t get_short(uint8_t* buffer, uint32_t i) {
203 uint16_t result;
204 memcpy(&result, &(buffer[i]), 2);
205#ifdef SK_CPU_BENDIAN
206 return SkEndianSwap16(result);
207#else
208 return result;
209#endif
210}
211
212/*
msarett74114382015-03-16 11:55:18 -0700213 * Get an int from a buffer
214 * This method is unsafe, the caller is responsible for performing a check
msarett74114382015-03-16 11:55:18 -0700215 */
216static inline uint32_t get_int(uint8_t* buffer, uint32_t i) {
217 uint32_t result;
218 memcpy(&result, &(buffer[i]), 4);
219#ifdef SK_CPU_BENDIAN
220 return SkEndianSwap32(result);
221#else
222 return result;
223#endif
224}
225
scroggo230d4ac2015-03-26 07:15:55 -0700226#ifdef SK_PRINT_CODEC_MESSAGES
227 #define SkCodecPrintf SkDebugf
228#else
229 #define SkCodecPrintf(...)
230#endif
231
msarett74114382015-03-16 11:55:18 -0700232#endif // SkCodecPriv_DEFINED