SkCodecPriv.h revision cc2feb161f756c4035a407296567654d86bc7be7
1/*
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
11#include "SkColorTable.h"
12#include "SkImageInfo.h"
13#include "SkSwizzler.h"
14#include "SkTypes.h"
15#include "SkUtils.h"
16
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
33static inline bool valid_alpha(SkAlphaType dstAlpha, SkAlphaType srcAlpha) {
34    // Check for supported alpha types
35    if (srcAlpha != dstAlpha) {
36        if (kOpaque_SkAlphaType == srcAlpha) {
37            // If the source is opaque, we must decode to opaque
38            return false;
39        }
40
41        // The source is not opaque
42        switch (dstAlpha) {
43            case kPremul_SkAlphaType:
44            case kUnpremul_SkAlphaType:
45                // The source is not opaque, so either of these is okay
46                break;
47            default:
48                // We cannot decode a non-opaque image to opaque (or unknown)
49                return false;
50        }
51    }
52    return true;
53}
54
55/*
56 * Most of our codecs support the same conversions:
57 * - profileType must be the same
58 * - opaque only to opaque (and 565 only if opaque)
59 * - premul to unpremul and vice versa
60 * - always support N32
61 * - otherwise match the src color type
62 */
63static bool conversion_possible(const SkImageInfo& dst, const SkImageInfo& src) {
64    if (dst.profileType() != src.profileType()) {
65        return false;
66    }
67
68    // Ensure the alpha type is valid
69    if (!valid_alpha(dst.alphaType(), src.alphaType())) {
70        return false;
71    }
72
73    // Check for supported color types
74    switch (dst.colorType()) {
75        case kN32_SkColorType:
76            return true;
77        case kRGB_565_SkColorType:
78            return src.alphaType() == kOpaque_SkAlphaType;
79        default:
80            return dst.colorType() == src.colorType();
81    }
82}
83
84/*
85 * If there is a color table, get a pointer to the colors, otherwise return NULL
86 */
87static const SkPMColor* get_color_ptr(SkColorTable* colorTable) {
88     return NULL != colorTable ? colorTable->readColors() : NULL;
89}
90
91/*
92 *
93 * Copy the codec color table back to the client when kIndex8 color type is requested
94 */
95static inline void copy_color_table(const SkImageInfo& dstInfo, SkColorTable* colorTable,
96        SkPMColor* inputColorPtr, int* inputColorCount) {
97    if (kIndex_8_SkColorType == dstInfo.colorType()) {
98        SkASSERT(NULL != inputColorPtr);
99        SkASSERT(NULL != inputColorCount);
100        SkASSERT(NULL != colorTable);
101        memcpy(inputColorPtr, colorTable->readColors(), *inputColorCount * 4);
102    }
103}
104
105/*
106 * Compute row bytes for an image using pixels per byte
107 */
108static inline size_t compute_row_bytes_ppb(int width, uint32_t pixelsPerByte) {
109    return (width + pixelsPerByte - 1) / pixelsPerByte;
110}
111
112/*
113 * Compute row bytes for an image using bytes per pixel
114 */
115static inline size_t compute_row_bytes_bpp(int width, uint32_t bytesPerPixel) {
116    return width * bytesPerPixel;
117}
118
119/*
120 * Compute row bytes for an image
121 */
122static inline size_t compute_row_bytes(int width, uint32_t bitsPerPixel) {
123    if (bitsPerPixel < 16) {
124        SkASSERT(0 == 8 % bitsPerPixel);
125        const uint32_t pixelsPerByte = 8 / bitsPerPixel;
126        return compute_row_bytes_ppb(width, pixelsPerByte);
127    } else {
128        SkASSERT(0 == bitsPerPixel % 8);
129        const uint32_t bytesPerPixel = bitsPerPixel / 8;
130        return compute_row_bytes_bpp(width, bytesPerPixel);
131    }
132}
133
134/*
135 * Get a byte from a buffer
136 * This method is unsafe, the caller is responsible for performing a check
137 */
138static inline uint8_t get_byte(uint8_t* buffer, uint32_t i) {
139    return buffer[i];
140}
141
142/*
143 * Get a short from a buffer
144 * This method is unsafe, the caller is responsible for performing a check
145 */
146static inline uint16_t get_short(uint8_t* buffer, uint32_t i) {
147    uint16_t result;
148    memcpy(&result, &(buffer[i]), 2);
149#ifdef SK_CPU_BENDIAN
150    return SkEndianSwap16(result);
151#else
152    return result;
153#endif
154}
155
156/*
157 * Get an int from a buffer
158 * This method is unsafe, the caller is responsible for performing a check
159 */
160static inline uint32_t get_int(uint8_t* buffer, uint32_t i) {
161    uint32_t result;
162    memcpy(&result, &(buffer[i]), 4);
163#ifdef SK_CPU_BENDIAN
164    return SkEndianSwap32(result);
165#else
166    return result;
167#endif
168}
169
170#ifdef SK_PRINT_CODEC_MESSAGES
171    #define SkCodecPrintf SkDebugf
172#else
173    #define SkCodecPrintf(...)
174#endif
175
176#endif // SkCodecPriv_DEFINED
177