blob: fa7d146d1afd01ba7c2e3ba3886b48b6367fe999 [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
msarette6dd0042015-10-09 11:07:34 -070011#include "SkColorPriv.h"
msarett9e43cab2015-04-29 07:38:43 -070012#include "SkColorTable.h"
msarett74114382015-03-16 11:55:18 -070013#include "SkImageInfo.h"
msarett74114382015-03-16 11:55:18 -070014#include "SkTypes.h"
msarett9e43cab2015-04-29 07:38:43 -070015#include "SkUtils.h"
msarett74114382015-03-16 11:55:18 -070016
scroggoc5560be2016-02-03 09:42:42 -080017#ifdef SK_PRINT_CODEC_MESSAGES
18 #define SkCodecPrintf SkDebugf
19#else
20 #define SkCodecPrintf(...)
21#endif
22
msarett3d9d7a72015-10-21 10:27:10 -070023// FIXME: Consider sharing with dm, nanbench, and tools.
24inline float get_scale_from_sample_size(int sampleSize) {
25 return 1.0f / ((float) sampleSize);
26}
27
28inline bool is_valid_subset(const SkIRect& subset, const SkISize& imageDims) {
29 return SkIRect::MakeSize(imageDims).contains(subset);
30}
31
msarett5406d6f2015-08-31 06:55:13 -070032/*
msarett10522ff2015-09-07 08:54:01 -070033 * returns a scaled dimension based on the original dimension and the sampleSize
34 * NOTE: we round down here for scaled dimension to match the behavior of SkImageDecoder
msarett3d9d7a72015-10-21 10:27:10 -070035 * FIXME: I think we should call this get_sampled_dimension().
msarett10522ff2015-09-07 08:54:01 -070036 */
msarette6dd0042015-10-09 11:07:34 -070037inline int get_scaled_dimension(int srcDimension, int sampleSize) {
msarett10522ff2015-09-07 08:54:01 -070038 if (sampleSize > srcDimension) {
39 return 1;
40 }
41 return srcDimension / sampleSize;
42}
43
44/*
msarett5406d6f2015-08-31 06:55:13 -070045 * Returns the first coordinate that we will keep during a scaled decode.
46 * The output can be interpreted as an x-coordinate or a y-coordinate.
47 *
48 * This does not need to be called and is not called when sampleFactor == 1.
49 */
msarette6dd0042015-10-09 11:07:34 -070050inline int get_start_coord(int sampleFactor) { return sampleFactor / 2; };
msarett5406d6f2015-08-31 06:55:13 -070051
52/*
53 * Given a coordinate in the original image, this returns the corresponding
54 * coordinate in the scaled image. This function is meaningless if
55 * IsCoordNecessary returns false.
56 * The output can be interpreted as an x-coordinate or a y-coordinate.
57 *
58 * This does not need to be called and is not called when sampleFactor == 1.
59 */
msarette6dd0042015-10-09 11:07:34 -070060inline int get_dst_coord(int srcCoord, int sampleFactor) { return srcCoord / sampleFactor; };
msarett5406d6f2015-08-31 06:55:13 -070061
62/*
63 * When scaling, we will discard certain y-coordinates (rows) and
64 * x-coordinates (columns). This function returns true if we should keep the
65 * coordinate and false otherwise.
66 * The inputs may be x-coordinates or y-coordinates.
67 *
68 * This does not need to be called and is not called when sampleFactor == 1.
69 */
msarette6dd0042015-10-09 11:07:34 -070070inline bool is_coord_necessary(int srcCoord, int sampleFactor, int scaledDim) {
msarett5406d6f2015-08-31 06:55:13 -070071 // Get the first coordinate that we want to keep
72 int startCoord = get_start_coord(sampleFactor);
73
74 // Return false on edge cases
75 if (srcCoord < startCoord || get_dst_coord(srcCoord, sampleFactor) >= scaledDim) {
76 return false;
77 }
78
79 // Every sampleFactor rows are necessary
80 return ((srcCoord - startCoord) % sampleFactor) == 0;
81}
82
msarette6dd0042015-10-09 11:07:34 -070083inline bool valid_alpha(SkAlphaType dstAlpha, SkAlphaType srcAlpha) {
scroggoc5560be2016-02-03 09:42:42 -080084 if (kUnknown_SkAlphaType == dstAlpha) {
85 return false;
86 }
87
msarett4ab9d5f2015-08-06 15:34:42 -070088 if (srcAlpha != dstAlpha) {
89 if (kOpaque_SkAlphaType == srcAlpha) {
scroggoc5560be2016-02-03 09:42:42 -080090 // If the source is opaque, we can support any.
91 SkCodecPrintf("Warning: an opaque image should be decoded as opaque "
92 "- it is being decoded as non-opaque, which will draw slower\n");
93 return true;
msarett4ab9d5f2015-08-06 15:34:42 -070094 }
95
96 // The source is not opaque
97 switch (dstAlpha) {
98 case kPremul_SkAlphaType:
99 case kUnpremul_SkAlphaType:
100 // The source is not opaque, so either of these is okay
101 break;
102 default:
103 // We cannot decode a non-opaque image to opaque (or unknown)
104 return false;
105 }
106 }
107 return true;
108}
109
msarett74114382015-03-16 11:55:18 -0700110/*
scroggocc2feb12015-08-14 08:32:46 -0700111 * Most of our codecs support the same conversions:
112 * - profileType must be the same
scroggoc5560be2016-02-03 09:42:42 -0800113 * - opaque to any alpha type
114 * - 565 only if opaque
scroggocc2feb12015-08-14 08:32:46 -0700115 * - premul to unpremul and vice versa
116 * - always support N32
117 * - otherwise match the src color type
118 */
msarette6dd0042015-10-09 11:07:34 -0700119inline bool conversion_possible(const SkImageInfo& dst, const SkImageInfo& src) {
scroggocc2feb12015-08-14 08:32:46 -0700120 if (dst.profileType() != src.profileType()) {
121 return false;
122 }
123
124 // Ensure the alpha type is valid
125 if (!valid_alpha(dst.alphaType(), src.alphaType())) {
126 return false;
127 }
128
129 // Check for supported color types
130 switch (dst.colorType()) {
131 case kN32_SkColorType:
132 return true;
133 case kRGB_565_SkColorType:
134 return src.alphaType() == kOpaque_SkAlphaType;
135 default:
136 return dst.colorType() == src.colorType();
137 }
138}
139
140/*
halcanary96fcdcc2015-08-27 07:41:13 -0700141 * If there is a color table, get a pointer to the colors, otherwise return nullptr
msarett99f567e2015-08-05 12:58:26 -0700142 */
msarette6dd0042015-10-09 11:07:34 -0700143inline const SkPMColor* get_color_ptr(SkColorTable* colorTable) {
halcanary96fcdcc2015-08-27 07:41:13 -0700144 return nullptr != colorTable ? colorTable->readColors() : nullptr;
msarett99f567e2015-08-05 12:58:26 -0700145}
146
147/*
msarette6dd0042015-10-09 11:07:34 -0700148 * Given that the encoded image uses a color table, return the fill value
149 */
150inline uint32_t get_color_table_fill_value(SkColorType colorType, const SkPMColor* colorPtr,
151 uint8_t fillIndex) {
152 SkASSERT(nullptr != colorPtr);
153 switch (colorType) {
154 case kN32_SkColorType:
155 return colorPtr[fillIndex];
156 case kRGB_565_SkColorType:
157 return SkPixel32ToPixel16(colorPtr[fillIndex]);
158 case kIndex_8_SkColorType:
159 return fillIndex;
160 default:
161 SkASSERT(false);
162 return 0;
163 }
164}
165
166/*
msarett74114382015-03-16 11:55:18 -0700167 *
msarett9e43cab2015-04-29 07:38:43 -0700168 * Copy the codec color table back to the client when kIndex8 color type is requested
msarett9e43cab2015-04-29 07:38:43 -0700169 */
msarette6dd0042015-10-09 11:07:34 -0700170inline void copy_color_table(const SkImageInfo& dstInfo, SkColorTable* colorTable,
msarett9e43cab2015-04-29 07:38:43 -0700171 SkPMColor* inputColorPtr, int* inputColorCount) {
172 if (kIndex_8_SkColorType == dstInfo.colorType()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700173 SkASSERT(nullptr != inputColorPtr);
174 SkASSERT(nullptr != inputColorCount);
175 SkASSERT(nullptr != colorTable);
msarett10522ff2015-09-07 08:54:01 -0700176 memcpy(inputColorPtr, colorTable->readColors(), *inputColorCount * sizeof(SkPMColor));
msarett9e43cab2015-04-29 07:38:43 -0700177 }
178}
179
180/*
msarett74114382015-03-16 11:55:18 -0700181 * Compute row bytes for an image using pixels per byte
msarett74114382015-03-16 11:55:18 -0700182 */
msarette6dd0042015-10-09 11:07:34 -0700183inline size_t compute_row_bytes_ppb(int width, uint32_t pixelsPerByte) {
msarett74114382015-03-16 11:55:18 -0700184 return (width + pixelsPerByte - 1) / pixelsPerByte;
185}
186
187/*
msarett74114382015-03-16 11:55:18 -0700188 * Compute row bytes for an image using bytes per pixel
msarett74114382015-03-16 11:55:18 -0700189 */
msarette6dd0042015-10-09 11:07:34 -0700190inline size_t compute_row_bytes_bpp(int width, uint32_t bytesPerPixel) {
msarett74114382015-03-16 11:55:18 -0700191 return width * bytesPerPixel;
192}
193
194/*
msarett74114382015-03-16 11:55:18 -0700195 * Compute row bytes for an image
msarett74114382015-03-16 11:55:18 -0700196 */
msarette6dd0042015-10-09 11:07:34 -0700197inline size_t compute_row_bytes(int width, uint32_t bitsPerPixel) {
msarett74114382015-03-16 11:55:18 -0700198 if (bitsPerPixel < 16) {
199 SkASSERT(0 == 8 % bitsPerPixel);
200 const uint32_t pixelsPerByte = 8 / bitsPerPixel;
201 return compute_row_bytes_ppb(width, pixelsPerByte);
202 } else {
203 SkASSERT(0 == bitsPerPixel % 8);
204 const uint32_t bytesPerPixel = bitsPerPixel / 8;
205 return compute_row_bytes_bpp(width, bytesPerPixel);
206 }
207}
208
209/*
msarett74114382015-03-16 11:55:18 -0700210 * Get a byte from a buffer
211 * This method is unsafe, the caller is responsible for performing a check
msarett74114382015-03-16 11:55:18 -0700212 */
msarette6dd0042015-10-09 11:07:34 -0700213inline uint8_t get_byte(uint8_t* buffer, uint32_t i) {
msarett74114382015-03-16 11:55:18 -0700214 return buffer[i];
215}
216
217/*
msarett74114382015-03-16 11:55:18 -0700218 * Get a short from a buffer
219 * This method is unsafe, the caller is responsible for performing a check
msarett74114382015-03-16 11:55:18 -0700220 */
msarette6dd0042015-10-09 11:07:34 -0700221inline uint16_t get_short(uint8_t* buffer, uint32_t i) {
msarett74114382015-03-16 11:55:18 -0700222 uint16_t result;
223 memcpy(&result, &(buffer[i]), 2);
224#ifdef SK_CPU_BENDIAN
225 return SkEndianSwap16(result);
226#else
227 return result;
228#endif
229}
230
231/*
msarett74114382015-03-16 11:55:18 -0700232 * Get an int from a buffer
233 * This method is unsafe, the caller is responsible for performing a check
msarett74114382015-03-16 11:55:18 -0700234 */
msarette6dd0042015-10-09 11:07:34 -0700235inline uint32_t get_int(uint8_t* buffer, uint32_t i) {
msarett74114382015-03-16 11:55:18 -0700236 uint32_t result;
237 memcpy(&result, &(buffer[i]), 4);
238#ifdef SK_CPU_BENDIAN
239 return SkEndianSwap32(result);
240#else
241 return result;
242#endif
243}
244
msarett74114382015-03-16 11:55:18 -0700245#endif // SkCodecPriv_DEFINED