Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Namespaces | Typedefs | Functions
SkJpegCodec.cpp File Reference
#include "src/codec/SkJpegCodec.h"
#include "include/codec/SkCodec.h"
#include "include/codec/SkJpegDecoder.h"
#include "include/core/SkAlphaType.h"
#include "include/core/SkColorType.h"
#include "include/core/SkData.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkPixmap.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkStream.h"
#include "include/core/SkTypes.h"
#include "include/core/SkYUVAInfo.h"
#include "include/private/SkJpegMetadataDecoder.h"
#include "include/private/base/SkAlign.h"
#include "include/private/base/SkMalloc.h"
#include "include/private/base/SkTemplates.h"
#include "modules/skcms/skcms.h"
#include "src/codec/SkCodecPriv.h"
#include "src/codec/SkJpegConstants.h"
#include "src/codec/SkJpegDecoderMgr.h"
#include "src/codec/SkJpegPriv.h"
#include "src/codec/SkParseEncodedOrigin.h"
#include "src/codec/SkSwizzler.h"
#include <array>
#include <csetjmp>
#include <cstring>
#include <utility>
#include <vector>
#include "jpeglib.h"

Go to the source code of this file.

Classes

class  SkJpegMetadataDecoderImpl
 

Namespaces

namespace  SkJpegDecoder
 

Typedefs

using SkJpegMarker = SkJpegMetadataDecoder::Segment
 
using SkJpegMarkerList = std::vector< SkJpegMarker >
 

Functions

SkJpegMarkerList get_sk_marker_list (jpeg_decompress_struct *dinfo)
 
static bool marker_has_signature (const SkJpegMarker &marker, const uint32_t targetMarker, const uint8_t *signature, size_t signatureSize)
 
static sk_sp< SkDataread_metadata (const SkJpegMarkerList &markerList, const uint32_t targetMarker, const uint8_t *signature, size_t signatureSize, size_t signaturePadding, size_t bytesInIndex, bool alwaysCopyData)
 
static SkEncodedOrigin get_exif_orientation (sk_sp< SkData > exifData)
 
static size_t get_row_bytes (const j_decompress_ptr dinfo)
 
void calc_output_dimensions (jpeg_decompress_struct *dinfo, unsigned int num, unsigned int denom)
 
static bool needs_swizzler_to_convert_from_cmyk (J_COLOR_SPACE jpegColorType, const skcms_ICCProfile *srcProfile, bool hasColorSpaceXform)
 
static bool is_yuv_supported (const jpeg_decompress_struct *dinfo, const SkJpegCodec &codec, const SkYUVAPixmapInfo::SupportedDataTypes *supportedDataTypes, SkYUVAPixmapInfo *yuvaPixmapInfo)
 
SK_API bool SkJpegDecoder::IsJpeg (const void *, size_t)
 
SK_API std::unique_ptr< SkCodecSkJpegDecoder::Decode (std::unique_ptr< SkStream >, SkCodec::Result *, SkCodecs::DecodeContext=nullptr)
 
SK_API std::unique_ptr< SkCodecSkJpegDecoder::Decode (sk_sp< SkData >, SkCodec::Result *, SkCodecs::DecodeContext=nullptr)
 

Typedef Documentation

◆ SkJpegMarker

Definition at line 65 of file SkJpegCodec.cpp.

◆ SkJpegMarkerList

using SkJpegMarkerList = std::vector<SkJpegMarker>

Definition at line 66 of file SkJpegCodec.cpp.

Function Documentation

◆ calc_output_dimensions()

void calc_output_dimensions ( jpeg_decompress_struct *  dinfo,
unsigned int  num,
unsigned int  denom 
)

Definition at line 397 of file SkJpegCodec.cpp.

397 {
398 dinfo->num_components = 0;
399 dinfo->scale_num = num;
400 dinfo->scale_denom = denom;
401 jpeg_calc_output_dimensions(dinfo);
402}

◆ get_exif_orientation()

static SkEncodedOrigin get_exif_orientation ( sk_sp< SkData exifData)
static

Definition at line 244 of file SkJpegCodec.cpp.

244 {
246 if (exifData && SkParseEncodedOrigin(exifData->bytes(), exifData->size(), &origin)) {
247 return origin;
248 }
250}
SkEncodedOrigin
@ kDefault_SkEncodedOrigin
bool SkParseEncodedOrigin(const void *data, size_t data_length, SkEncodedOrigin *orientation)
const uint8_t * bytes() const
Definition SkData.h:43
size_t size() const
Definition SkData.h:30

◆ get_row_bytes()

static size_t get_row_bytes ( const j_decompress_ptr  dinfo)
static

Definition at line 384 of file SkJpegCodec.cpp.

384 {
385 const size_t colorBytes = (dinfo->out_color_space == JCS_RGB565) ? 2 :
386 dinfo->out_color_components;
387 return dinfo->output_width * colorBytes;
388
389}

◆ get_sk_marker_list()

SkJpegMarkerList get_sk_marker_list ( jpeg_decompress_struct *  dinfo)

Definition at line 68 of file SkJpegCodec.cpp.

68 {
69 SkJpegMarkerList markerList;
70 for (auto* marker = dinfo->marker_list; marker; marker = marker->next) {
71 markerList.emplace_back(marker->marker,
72 SkData::MakeWithoutCopy(marker->data, marker->data_length));
73 }
74 return markerList;
75}
static const char marker[]
std::vector< SkJpegMarker > SkJpegMarkerList
static sk_sp< SkData > MakeWithoutCopy(const void *data, size_t length)
Definition SkData.h:116

◆ is_yuv_supported()

static bool is_yuv_supported ( const jpeg_decompress_struct *  dinfo,
const SkJpegCodec codec,
const SkYUVAPixmapInfo::SupportedDataTypes supportedDataTypes,
SkYUVAPixmapInfo yuvaPixmapInfo 
)
static

Definition at line 868 of file SkJpegCodec.cpp.

871 {
872 // Scaling is not supported in raw data mode.
873 SkASSERT(dinfo->scale_num == dinfo->scale_denom);
874
875 // I can't imagine that this would ever change, but we do depend on it.
876 static_assert(8 == DCTSIZE, "DCTSIZE (defined in jpeg library) should always be 8.");
877
878 if (JCS_YCbCr != dinfo->jpeg_color_space) {
879 return false;
880 }
881
882 SkASSERT(3 == dinfo->num_components);
883 SkASSERT(dinfo->comp_info);
884
885 // It is possible to perform a YUV decode for any combination of
886 // horizontal and vertical sampling that is supported by
887 // libjpeg/libjpeg-turbo. However, we will start by supporting only the
888 // common cases (where U and V have samp_factors of one).
889 //
890 // The definition of samp_factor is kind of the opposite of what SkCodec
891 // thinks of as a sampling factor. samp_factor is essentially a
892 // multiplier, and the larger the samp_factor is, the more samples that
893 // there will be. Ex:
894 // U_plane_width = image_width * (U_h_samp_factor / max_h_samp_factor)
895 //
896 // Supporting cases where the samp_factors for U or V were larger than
897 // that of Y would be an extremely difficult change, given that clients
898 // allocate memory as if the size of the Y plane is always the size of the
899 // image. However, this case is very, very rare.
900 if ((1 != dinfo->comp_info[1].h_samp_factor) ||
901 (1 != dinfo->comp_info[1].v_samp_factor) ||
902 (1 != dinfo->comp_info[2].h_samp_factor) ||
903 (1 != dinfo->comp_info[2].v_samp_factor))
904 {
905 return false;
906 }
907
908 // Support all common cases of Y samp_factors.
909 // TODO (msarett): As mentioned above, it would be possible to support
910 // more combinations of samp_factors. The issues are:
911 // (1) Are there actually any images that are not covered
912 // by these cases?
913 // (2) How much complexity would be added to the
914 // implementation in order to support these rare
915 // cases?
916 int hSampY = dinfo->comp_info[0].h_samp_factor;
917 int vSampY = dinfo->comp_info[0].v_samp_factor;
918 SkASSERT(hSampY == dinfo->max_h_samp_factor);
919 SkASSERT(vSampY == dinfo->max_v_samp_factor);
920
921 SkYUVAInfo::Subsampling tempSubsampling;
922 if (1 == hSampY && 1 == vSampY) {
923 tempSubsampling = SkYUVAInfo::Subsampling::k444;
924 } else if (2 == hSampY && 1 == vSampY) {
925 tempSubsampling = SkYUVAInfo::Subsampling::k422;
926 } else if (2 == hSampY && 2 == vSampY) {
927 tempSubsampling = SkYUVAInfo::Subsampling::k420;
928 } else if (1 == hSampY && 2 == vSampY) {
929 tempSubsampling = SkYUVAInfo::Subsampling::k440;
930 } else if (4 == hSampY && 1 == vSampY) {
931 tempSubsampling = SkYUVAInfo::Subsampling::k411;
932 } else if (4 == hSampY && 2 == vSampY) {
933 tempSubsampling = SkYUVAInfo::Subsampling::k410;
934 } else {
935 return false;
936 }
937 if (supportedDataTypes &&
938 !supportedDataTypes->supported(SkYUVAInfo::PlaneConfig::kY_U_V,
940 return false;
941 }
942 if (yuvaPixmapInfo) {
944 size_t rowBytes[SkYUVAPixmapInfo::kMaxPlanes];
945 for (int i = 0; i < 3; ++i) {
946 colorTypes[i] = kAlpha_8_SkColorType;
947 rowBytes[i] = dinfo->comp_info[i].width_in_blocks * DCTSIZE;
948 }
949 SkYUVAInfo yuvaInfo(codec.dimensions(),
951 tempSubsampling,
953 codec.getOrigin(),
956 *yuvaPixmapInfo = SkYUVAPixmapInfo(yuvaInfo, colorTypes, rowBytes);
957 }
958 return true;
959}
#define SkASSERT(cond)
Definition SkAssert.h:116
SkColorType
Definition SkColorType.h:19
@ kAlpha_8_SkColorType
pixel with alpha in 8-bit byte
Definition SkColorType.h:21
@ kJPEG_Full_SkYUVColorSpace
describes full range
Definition SkImageInfo.h:69
SkISize dimensions() const
Definition SkCodec.h:230
SkEncodedOrigin getOrigin() const
Definition SkCodec.h:246
@ kY_U_V
Plane 0: Y, Plane 1: U, Plane 2: V.
@ k440
1 set of UV values for each 1x2 block of Y values.
@ k420
1 set of UV values for each 2x2 block of Y values.
@ k410
1 set of UV values for each 4x2 block of Y values.
@ k411
1 set of UV values for each 4x1 block of Y values.
@ k422
1 set of UV values for each 2x1 block of Y values.
@ k444
No subsampling. UV values for each Y.
constexpr bool supported(PlaneConfig, DataType) const
@ kUnorm8
8 bit unsigned normalized
static constexpr auto kMaxPlanes

◆ marker_has_signature()

static bool marker_has_signature ( const SkJpegMarker marker,
const uint32_t  targetMarker,
const uint8_t *  signature,
size_t  signatureSize 
)
static

Return true if the specified SkJpegMarker has marker |targetMarker| and begins with the specified signature.

Definition at line 81 of file SkJpegCodec.cpp.

84 {
85 if (targetMarker != marker.fMarker) {
86 return false;
87 }
88 if (marker.fData->size() <= signatureSize) {
89 return false;
90 }
91 if (memcmp(marker.fData->bytes(), signature, signatureSize) != 0) {
92 return false;
93 }
94 return true;
95}

◆ needs_swizzler_to_convert_from_cmyk()

static bool needs_swizzler_to_convert_from_cmyk ( J_COLOR_SPACE  jpegColorType,
const skcms_ICCProfile srcProfile,
bool  hasColorSpaceXform 
)
inlinestatic

Definition at line 633 of file SkJpegCodec.cpp.

635 {
636 if (JCS_CMYK != jpegColorType) {
637 return false;
638 }
639
640 bool hasCMYKColorSpace = srcProfile && srcProfile->data_color_space == skcms_Signature_CMYK;
641 return !hasCMYKColorSpace || !hasColorSpaceXform;
642}
@ skcms_Signature_CMYK
uint32_t data_color_space

◆ read_metadata()

static sk_sp< SkData > read_metadata ( const SkJpegMarkerList markerList,
const uint32_t  targetMarker,
const uint8_t *  signature,
size_t  signatureSize,
size_t  signaturePadding,
size_t  bytesInIndex,
bool  alwaysCopyData 
)
static

Definition at line 120 of file SkJpegCodec.cpp.

126 {
127 // Compute the total size of the entire header (signature plus padding plus index plus count),
128 // since we'll use it often.
129 const size_t headerSize = signatureSize + signaturePadding + 2 * bytesInIndex;
130
131 // A map from part index to the data in each part.
132 std::vector<sk_sp<SkData>> parts;
133
134 // Running total of number of data in all parts.
135 size_t partsTotalSize = 0;
136
137 // Running total number of parts found.
138 uint32_t foundPartCount = 0;
139
140 // The expected number of parts (initialized at the first part we encounter).
141 uint32_t expectedPartCount = 0;
142
143 // Iterate through the image's segments.
144 for (const auto& marker : markerList) {
145 // Skip segments that don't have the right marker or signature.
146 if (!marker_has_signature(marker, targetMarker, signature, signatureSize)) {
147 continue;
148 }
149
150 // Skip segments that are too small to include the index and count.
151 const size_t dataLength = marker.fData->size();
152 if (dataLength <= headerSize) {
153 continue;
154 }
155
156 // Read this part's index and count as big-endian (if they are present, otherwise hard-code
157 // them to 1).
158 const uint8_t* data = marker.fData->bytes();
159 uint32_t partIndex = 0;
160 uint32_t partCount = 0;
161 if (bytesInIndex == 0) {
162 partIndex = 1;
163 partCount = 1;
164 } else {
165 for (size_t i = 0; i < bytesInIndex; ++i) {
166 const size_t offset = signatureSize + signaturePadding;
167 partIndex = (partIndex << 8) + data[offset + i];
168 partCount = (partCount << 8) + data[offset + bytesInIndex + i];
169 }
170 }
171
172 // A part count of 0 is invalid.
173 if (!partCount) {
174 SkCodecPrintf("Invalid marker part count zero\n");
175 return nullptr;
176 }
177
178 // The indices must in the range 1, ..., count.
179 if (partIndex <= 0 || partIndex > partCount) {
180 SkCodecPrintf("Invalid marker index %u for count %u\n", partIndex, partCount);
181 return nullptr;
182 }
183
184 // If this is the first marker we've encountered set the expected part count to its count.
185 if (expectedPartCount == 0) {
186 expectedPartCount = partCount;
187 parts.resize(expectedPartCount);
188 }
189
190 // If this does not match the expected part count, then fail.
191 if (partCount != expectedPartCount) {
192 SkCodecPrintf("Conflicting marker counts %u vs %u\n", partCount, expectedPartCount);
193 return nullptr;
194 }
195
196 // Make an SkData directly referencing the decoder's data for this part.
197 auto partData = SkData::MakeWithoutCopy(data + headerSize, dataLength - headerSize);
198
199 // Fail if duplicates are found.
200 if (parts[partIndex-1]) {
201 SkCodecPrintf("Duplicate parts for index %u of %u\n", partIndex, expectedPartCount);
202 return nullptr;
203 }
204
205 // Save part in the map.
206 partsTotalSize += partData->size();
207 parts[partIndex-1] = std::move(partData);
208 foundPartCount += 1;
209
210 // Stop as soon as we find all of the parts.
211 if (foundPartCount == expectedPartCount) {
212 break;
213 }
214 }
215
216 // Return nullptr if we don't find the data (this is not an error).
217 if (expectedPartCount == 0) {
218 return nullptr;
219 }
220
221 // Fail if we don't have all of the parts.
222 if (foundPartCount != expectedPartCount) {
223 SkCodecPrintf("Incomplete set of markers (expected %u got %u)\n",
224 expectedPartCount,
225 foundPartCount);
226 return nullptr;
227 }
228
229 // Return a direct reference to the data if there is only one part and we're allowed to.
230 if (!alwaysCopyData && expectedPartCount == 1) {
231 return std::move(parts[0]);
232 }
233
234 // Copy all of the markers and stitch them together.
235 auto result = SkData::MakeUninitialized(partsTotalSize);
236 void* copyDest = result->writable_data();
237 for (const auto& part : parts) {
238 memcpy(copyDest, part->data(), part->size());
239 copyDest = SkTAddOffset<void>(copyDest, part->size());
240 }
241 return result;
242}
#define SkCodecPrintf(...)
Definition SkCodecPriv.h:23
static bool marker_has_signature(const SkJpegMarker &marker, const uint32_t targetMarker, const uint8_t *signature, size_t signatureSize)
static sk_sp< SkData > MakeUninitialized(size_t length)
Definition SkData.cpp:116
GAsyncResult * result
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switches.h:41
Point offset