}
const uint32_t kExifHeaderSize = 14;
+const uint32_t kICCHeaderSize = 14;
const uint32_t kExifMarker = JPEG_APP0 + 1;
+const uint32_t kICCMarker = JPEG_APP0 + 2;
static bool is_orientation_marker(jpeg_marker_struct* marker, SkCodec::Origin* orientation) {
if (kExifMarker != marker->marker || marker->data_length < kExifHeaderSize) {
}
static bool is_icc_marker(jpeg_marker_struct* marker) {
- if (kICCMarker != marker->marker || marker->data_length < kICCMarkerHeaderSize) {
+ if (kICCMarker != marker->marker || marker->data_length < kICCHeaderSize) {
return false;
}
+ static const uint8_t kICCSig[] { 'I', 'C', 'C', '_', 'P', 'R', 'O', 'F', 'I', 'L', 'E', '\0' };
return !memcmp(marker->data, kICCSig, sizeof(kICCSig));
}
return nullptr;
}
markerSequence[markerIndex] = marker;
- SkASSERT(marker->data_length >= kICCMarkerHeaderSize);
- totalBytes += marker->data_length - kICCMarkerHeaderSize;
+ SkASSERT(marker->data_length >= kICCHeaderSize);
+ totalBytes += marker->data_length - kICCHeaderSize;
}
}
return nullptr;
}
- void* src = SkTAddOffset<void>(marker->data, kICCMarkerHeaderSize);
- size_t bytes = marker->data_length - kICCMarkerHeaderSize;
+ void* src = SkTAddOffset<void>(marker->data, kICCHeaderSize);
+ size_t bytes = marker->data_length - kICCHeaderSize;
memcpy(dst, src, bytes);
dst = SkTAddOffset<void>(dst, bytes);
}
#include "jerror.h"
}
-static constexpr uint32_t kICCMarker = JPEG_APP0 + 2;
-static constexpr uint32_t kICCMarkerHeaderSize = 14;
-static constexpr uint8_t kICCSig[] = {
- 'I', 'C', 'C', '_', 'P', 'R', 'O', 'F', 'I', 'L', 'E', '\0',
-};
-
/*
* Error handling struct
*/
#ifdef SK_HAS_JPEG_LIBRARY
#include "SkColorPriv.h"
-#include "SkImageEncoderFns.h"
-#include "SkJpegUtility.h"
#include "SkJPEGWriteUtility.h"
#include "SkStream.h"
#include "SkTemplates.h"
+#include "transform_scanline.h"
#include <stdio.h>
SkAutoTMalloc<uint8_t> storage;
cinfo.err = jpeg_std_error(&sk_err);
- sk_err.error_exit = skjpeg_write_error_exit;
+ sk_err.error_exit = skjpeg_error_exit;
if (setjmp(sk_err.fJmpBuf)) {
return false;
}
jpeg_start_compress(&cinfo, TRUE);
- if (pixmap.colorSpace()) {
- sk_sp<SkData> icc = icc_from_color_space(*pixmap.colorSpace());
- if (icc) {
- // Create a contiguous block of memory with the icc signature followed by the profile.
- sk_sp<SkData> markerData =
- SkData::MakeUninitialized(kICCMarkerHeaderSize + icc->size());
- uint8_t* ptr = (uint8_t*) markerData->writable_data();
- memcpy(ptr, kICCSig, sizeof(kICCSig));
- ptr += sizeof(kICCSig);
- *ptr++ = 1; // This is the first marker.
- *ptr++ = 1; // Out of one total markers.
- memcpy(ptr, icc->data(), icc->size());
-
- jpeg_write_marker(&cinfo, kICCMarker, markerData->bytes(), markerData->size());
- }
- }
-
if (proc) {
storage.reset(numComponents * pixmap.width());
}
* found in the LICENSE file.
*/
-#include "SkJpegUtility.h"
+
#include "SkJPEGWriteUtility.h"
///////////////////////////////////////////////////////////////////////////////
this->term_destination = sk_term_destination;
}
-void skjpeg_write_error_exit(j_common_ptr cinfo) {
+void skjpeg_error_exit(j_common_ptr cinfo) {
skjpeg_error_mgr* error = (skjpeg_error_mgr*)cinfo->err;
(*error->output_message) (cinfo);
#include <setjmp.h>
-void skjpeg_write_error_exit(j_common_ptr cinfo);
+/* Our error-handling struct.
+ *
+*/
+struct skjpeg_error_mgr : jpeg_error_mgr {
+ jmp_buf fJmpBuf;
+};
+
+
+void skjpeg_error_exit(j_common_ptr cinfo);
/////////////////////////////////////////////////////////////////////////////
/* Our destination struct for directing decompressed pixels to our stream
#include "SkColor.h"
#include "SkColorPriv.h"
#include "SkDither.h"
-#include "SkImageEncoderFns.h"
+#include "SkICC.h"
#include "SkMath.h"
#include "SkStream.h"
#include "SkString.h"
#include "SkTemplates.h"
#include "SkUnPreMultiply.h"
#include "SkUtils.h"
+#include "transform_scanline.h"
#include "png.h"
}
}
-static void set_icc(png_structp png_ptr, png_infop info_ptr, sk_sp<SkData> icc) {
+static void set_icc(png_structp png_ptr, png_infop info_ptr, const SkColorSpaceTransferFn& fn,
+ const SkMatrix44& toXYZD50) {
+ sk_sp<SkData> icc = SkICC::WriteToICC(fn, toXYZD50);
#if PNG_LIBPNG_VER_MAJOR > 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR >= 5)
const char* name = "Skia";
png_const_bytep iccPtr = icc->bytes();
}
if (pixmap.colorSpace()) {
+ SkColorSpaceTransferFn fn;
+ SkMatrix44 toXYZD50(SkMatrix44::kUninitialized_Constructor);
if (pixmap.colorSpace()->isSRGB()) {
png_set_sRGB(png_ptr, info_ptr, PNG_sRGB_INTENT_PERCEPTUAL);
- } else {
- sk_sp<SkData> icc = icc_from_color_space(*pixmap.colorSpace());
- if (icc) {
- set_icc(png_ptr, info_ptr, std::move(icc));
- }
+ } else if (pixmap.colorSpace()->isNumericalTransferFn(&fn) &&
+ pixmap.colorSpace()->toXYZD50(&toXYZD50))
+ {
+ set_icc(png_ptr, info_ptr, fn, toXYZD50);
}
+
+ // TODO: Should we support writing ICC profiles for additional color spaces?
}
png_set_sBIT(png_ptr, info_ptr, &sig_bit);
#include "SkBitmap.h"
#include "SkColorPriv.h"
-#include "SkImageEncoderFns.h"
#include "SkStream.h"
#include "SkTemplates.h"
#include "SkUnPreMultiply.h"
#include "SkUtils.h"
+#include "transform_scanline.h"
// A WebP decoder only, on top of (subset of) libwebp
// For more information on WebP image format, and libwebp library, see:
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
-
-#ifndef SkImageEncoderFns_DEFINED
-#define SkImageEncoderFns_DEFINED
+#ifndef transform_scanline_DEFINED
+#define transform_scanline_DEFINED
/**
* Functions to transform scanlines between packed-pixel formats.
#include "SkBitmap.h"
#include "SkColor.h"
#include "SkColorPriv.h"
-#include "SkICC.h"
#include "SkPreConfig.h"
#include "SkRasterPipeline.h"
#include "SkUnPreMultiply.h"
p.append(SkRasterPipeline::store_8888, (void**) &dst);
p.run(0, width);
}
-
-static inline sk_sp<SkData> icc_from_color_space(const SkColorSpace& cs) {
- SkColorSpaceTransferFn fn;
- SkMatrix44 toXYZD50(SkMatrix44::kUninitialized_Constructor);
- if (cs.isNumericalTransferFn(&fn) && cs.toXYZD50(&toXYZD50)) {
- return SkICC::WriteToICC(fn, toXYZD50);
- }
-
- // TODO: Should we support writing ICC profiles for additional color spaces?
- return nullptr;
-}
-
-#endif // SkImageEncoderFns_DEFINED
+#endif // transform_scanline_DEFINED
}
}
-static void encode_format(SkDynamicMemoryWStream* stream, const SkPixmap& pixmap,
- const SkEncodeOptions& opts, SkEncodedImageFormat format) {
- switch (format) {
- case SkEncodedImageFormat::kPNG:
- SkEncodeImageAsPNG(stream, pixmap, opts);
- break;
- case SkEncodedImageFormat::kJPEG:
- SkEncodeImageAsJPEG(stream, pixmap, opts);
- break;
- default:
- SkASSERT(false);
- break;
- }
-}
-
-static void test_encode_icc(skiatest::Reporter* r, SkEncodedImageFormat format) {
+DEF_TEST(Codec_EncodeICC, r) {
// Test with sRGB color space.
SkBitmap srgbBitmap;
SkImageInfo srgbInfo = SkImageInfo::MakeS32(1, 1, kOpaque_SkAlphaType);
SkDynamicMemoryWStream srgbBuf;
SkEncodeOptions opts;
opts.fColorBehavior = SkEncodeOptions::ColorBehavior::kCorrect;
- encode_format(&srgbBuf, pixmap, opts, format);
+ SkEncodeImageAsPNG(&srgbBuf, pixmap, opts);
sk_sp<SkData> srgbData = srgbBuf.detachAsData();
std::unique_ptr<SkCodec> srgbCodec(SkCodec::NewFromData(srgbData));
REPORTER_ASSERT(r, srgbCodec->getInfo().colorSpace() == SkColorSpace::MakeSRGB().get());
sk_sp<SkColorSpace> p3 = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
SkColorSpace::kDCIP3_D65_Gamut);
pixmap.setColorSpace(p3);
- encode_format(&p3Buf, pixmap, opts, format);
+ SkEncodeImageAsPNG(&p3Buf, pixmap, opts);
sk_sp<SkData> p3Data = p3Buf.detachAsData();
std::unique_ptr<SkCodec> p3Codec(SkCodec::NewFromData(p3Data));
REPORTER_ASSERT(r, p3Codec->getInfo().colorSpace()->gammaCloseToSRGB());
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
- REPORTER_ASSERT(r, color_space_almost_equal(mat0.get(i, j), mat1.get(i, j)));
+ REPORTER_ASSERT(r, color_space_almost_equal(mat0.get(0, 0), mat1.get(0, 0)));
}
}
}
-
-DEF_TEST(Codec_EncodeICC, r) {
- test_encode_icc(r, SkEncodedImageFormat::kPNG);
- test_encode_icc(r, SkEncodedImageFormat::kJPEG);
-}