OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright 2016 Google Inc. |
| 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 #include "SkExrCodec.h" |
| 9 |
| 10 //#define TINYEXR_IMPLEMENTATION |
| 11 #include "tinyexr.h" |
| 12 |
| 13 bool SkExrCodec::IsExr(const void* buffer, size_t bytes) { |
| 14 static constexpr uint8_t kExrSig[] = { 0x76, 0x2f, 0x31, 0x01, }; |
| 15 return bytes >= 4 && 0 == memcmp(buffer, kExrSig, 4); |
| 16 } |
| 17 |
| 18 SkCodec* SkExrCodec::NewFromStream(SkStream* stream) { |
| 19 sk_sp<SkData> data = ((SkMemoryStream*) stream)->asData(); |
| 20 |
| 21 EXRVersion version; |
| 22 int result = ParseEXRVersionFromMemory(&version, data->bytes(), data->size()
); |
| 23 if (result != TINYEXR_SUCCESS) { |
| 24 return nullptr; |
| 25 } |
| 26 |
| 27 EXRHeader header; |
| 28 InitEXRHeader(&header); |
| 29 result = ParseEXRHeaderFromMemory(&header, &version, data->bytes(), data->si
ze(), nullptr); |
| 30 if (TINYEXR_SUCCESS != result) { |
| 31 return nullptr; |
| 32 } |
| 33 |
| 34 int width = header.data_window[2] - header.data_window[0] + 1; |
| 35 int height = header.data_window[3] - header.data_window[1] + 1; |
| 36 SkEncodedInfo info = SkEncodedInfo::Make(SkEncodedInfo::kRGB_Color, |
| 37 SkEncodedInfo::kOpaque_Alpha, 8); |
| 38 return new SkExrCodec(width, height, info, SkColorSpace::NewNamed(SkColorSpa
ce::kSRGB_Named), |
| 39 stream, data); |
| 40 } |
| 41 |
| 42 SkCodec::Result SkExrCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst, s
ize_t rowBytes, |
| 43 const Options& options, SkPMColor*, int*
, |
| 44 int* rowsDecodedPtr) { |
| 45 EXRVersion exr_version; |
| 46 EXRImage exr_image; |
| 47 EXRHeader exr_header; |
| 48 |
| 49 InitEXRHeader(&exr_header); |
| 50 |
| 51 int ret = ParseEXRVersionFromMemory(&exr_version, fData->bytes(), fData->siz
e()); |
| 52 if (ret != TINYEXR_SUCCESS) { |
| 53 return kInvalidInput; |
| 54 } |
| 55 |
| 56 ret = ParseEXRHeaderFromMemory(&exr_header, &exr_version, fData->bytes(), fD
ata->size(), nullptr); |
| 57 if (ret != TINYEXR_SUCCESS) { |
| 58 return kInvalidInput; |
| 59 } |
| 60 |
| 61 int pixelTypes[] = { |
| 62 TINYEXR_PIXELTYPE_FLOAT, |
| 63 TINYEXR_PIXELTYPE_FLOAT, |
| 64 TINYEXR_PIXELTYPE_FLOAT, |
| 65 TINYEXR_PIXELTYPE_FLOAT, |
| 66 }; |
| 67 exr_header.requested_pixel_types = pixelTypes; |
| 68 |
| 69 InitEXRImage(&exr_image); |
| 70 ret = LoadEXRImageFromMemory(&exr_image, &exr_header, fData->bytes(), nullpt
r); |
| 71 if (ret != TINYEXR_SUCCESS) { |
| 72 return kInvalidInput; |
| 73 } |
| 74 |
| 75 // RGBA |
| 76 int idxR = -1; |
| 77 int idxG = -1; |
| 78 int idxB = -1; |
| 79 for (int c = 0; c < exr_header.num_channels; c++) { |
| 80 if (strcmp(exr_header.channels[c].name, "R") == 0) { |
| 81 idxR = c; |
| 82 } else if (strcmp(exr_header.channels[c].name, "G") == 0) { |
| 83 idxG = c; |
| 84 } else if (strcmp(exr_header.channels[c].name, "B") == 0) { |
| 85 idxB = c; |
| 86 } |
| 87 } |
| 88 |
| 89 if (idxR == -1 || idxG == -1 || idxB == -1) { |
| 90 return kInvalidInput; |
| 91 } |
| 92 |
| 93 // Assume `out_rgba` have enough memory allocated. |
| 94 uint32_t* dst32 = (uint32_t*) dst; |
| 95 for (int i = 0; i < exr_image.width * exr_image.height; i++) { |
| 96 SkColor4f rgba; |
| 97 rgba.fR = reinterpret_cast<float **>(exr_image.images)[idxR][i]; |
| 98 rgba.fG = reinterpret_cast<float **>(exr_image.images)[idxG][i]; |
| 99 rgba.fB = reinterpret_cast<float **>(exr_image.images)[idxB][i]; |
| 100 rgba.fA = 1.0; |
| 101 //SkDebugf("%g %g %g %g\n", rgba.fR, rgba.fG, rgba.fB, rgba.fA); |
| 102 SkColor color = rgba.toSkColor(); |
| 103 dst32[i] = color; |
| 104 } |
| 105 |
| 106 return kSuccess; |
| 107 } |
| 108 |
| 109 SkExrCodec::SkExrCodec(int width, int height, const SkEncodedInfo& info, |
| 110 sk_sp<SkColorSpace> colorSpace, SkStream* stream, sk_sp<S
kData> data) |
| 111 : INHERITED(width, height, info, stream, std::move(colorSpace)) |
| 112 , fData(data) |
| 113 {} |
OLD | NEW |