| Index: src/codec/SkExrCodec.cpp
|
| diff --git a/src/codec/SkExrCodec.cpp b/src/codec/SkExrCodec.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..bea9a63d274216c4afe2443510a2ac40e7727684
|
| --- /dev/null
|
| +++ b/src/codec/SkExrCodec.cpp
|
| @@ -0,0 +1,113 @@
|
| +/*
|
| + * Copyright 2016 Google Inc.
|
| + *
|
| + * Use of this source code is governed by a BSD-style license that can be
|
| + * found in the LICENSE file.
|
| + */
|
| +
|
| +#include "SkExrCodec.h"
|
| +
|
| +//#define TINYEXR_IMPLEMENTATION
|
| +#include "tinyexr.h"
|
| +
|
| +bool SkExrCodec::IsExr(const void* buffer, size_t bytes) {
|
| + static constexpr uint8_t kExrSig[] = { 0x76, 0x2f, 0x31, 0x01, };
|
| + return bytes >= 4 && 0 == memcmp(buffer, kExrSig, 4);
|
| +}
|
| +
|
| +SkCodec* SkExrCodec::NewFromStream(SkStream* stream) {
|
| + sk_sp<SkData> data = ((SkMemoryStream*) stream)->asData();
|
| +
|
| + EXRVersion version;
|
| + int result = ParseEXRVersionFromMemory(&version, data->bytes(), data->size());
|
| + if (result != TINYEXR_SUCCESS) {
|
| + return nullptr;
|
| + }
|
| +
|
| + EXRHeader header;
|
| + InitEXRHeader(&header);
|
| + result = ParseEXRHeaderFromMemory(&header, &version, data->bytes(), data->size(), nullptr);
|
| + if (TINYEXR_SUCCESS != result) {
|
| + return nullptr;
|
| + }
|
| +
|
| + int width = header.data_window[2] - header.data_window[0] + 1;
|
| + int height = header.data_window[3] - header.data_window[1] + 1;
|
| + SkEncodedInfo info = SkEncodedInfo::Make(SkEncodedInfo::kRGB_Color,
|
| + SkEncodedInfo::kOpaque_Alpha, 8);
|
| + return new SkExrCodec(width, height, info, SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named),
|
| + stream, data);
|
| +}
|
| +
|
| +SkCodec::Result SkExrCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
|
| + const Options& options, SkPMColor*, int*,
|
| + int* rowsDecodedPtr) {
|
| + EXRVersion exr_version;
|
| + EXRImage exr_image;
|
| + EXRHeader exr_header;
|
| +
|
| + InitEXRHeader(&exr_header);
|
| +
|
| + int ret = ParseEXRVersionFromMemory(&exr_version, fData->bytes(), fData->size());
|
| + if (ret != TINYEXR_SUCCESS) {
|
| + return kInvalidInput;
|
| + }
|
| +
|
| + ret = ParseEXRHeaderFromMemory(&exr_header, &exr_version, fData->bytes(), fData->size(), nullptr);
|
| + if (ret != TINYEXR_SUCCESS) {
|
| + return kInvalidInput;
|
| + }
|
| +
|
| + int pixelTypes[] = {
|
| + TINYEXR_PIXELTYPE_FLOAT,
|
| + TINYEXR_PIXELTYPE_FLOAT,
|
| + TINYEXR_PIXELTYPE_FLOAT,
|
| + TINYEXR_PIXELTYPE_FLOAT,
|
| + };
|
| + exr_header.requested_pixel_types = pixelTypes;
|
| +
|
| + InitEXRImage(&exr_image);
|
| + ret = LoadEXRImageFromMemory(&exr_image, &exr_header, fData->bytes(), nullptr);
|
| + if (ret != TINYEXR_SUCCESS) {
|
| + return kInvalidInput;
|
| + }
|
| +
|
| + // RGBA
|
| + int idxR = -1;
|
| + int idxG = -1;
|
| + int idxB = -1;
|
| + for (int c = 0; c < exr_header.num_channels; c++) {
|
| + if (strcmp(exr_header.channels[c].name, "R") == 0) {
|
| + idxR = c;
|
| + } else if (strcmp(exr_header.channels[c].name, "G") == 0) {
|
| + idxG = c;
|
| + } else if (strcmp(exr_header.channels[c].name, "B") == 0) {
|
| + idxB = c;
|
| + }
|
| + }
|
| +
|
| + if (idxR == -1 || idxG == -1 || idxB == -1) {
|
| + return kInvalidInput;
|
| + }
|
| +
|
| + // Assume `out_rgba` have enough memory allocated.
|
| + uint32_t* dst32 = (uint32_t*) dst;
|
| + for (int i = 0; i < exr_image.width * exr_image.height; i++) {
|
| + SkColor4f rgba;
|
| + rgba.fR = reinterpret_cast<float **>(exr_image.images)[idxR][i];
|
| + rgba.fG = reinterpret_cast<float **>(exr_image.images)[idxG][i];
|
| + rgba.fB = reinterpret_cast<float **>(exr_image.images)[idxB][i];
|
| + rgba.fA = 1.0;
|
| + //SkDebugf("%g %g %g %g\n", rgba.fR, rgba.fG, rgba.fB, rgba.fA);
|
| + SkColor color = rgba.toSkColor();
|
| + dst32[i] = color;
|
| + }
|
| +
|
| + return kSuccess;
|
| +}
|
| +
|
| +SkExrCodec::SkExrCodec(int width, int height, const SkEncodedInfo& info,
|
| + sk_sp<SkColorSpace> colorSpace, SkStream* stream, sk_sp<SkData> data)
|
| + : INHERITED(width, height, info, stream, std::move(colorSpace))
|
| + , fData(data)
|
| +{}
|
|
|