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 "SkBitmap.h" |
| 9 #include "SkImageEncoder.h" |
| 10 #include "SkHalf.h" |
| 11 #include "SkStream.h" |
| 12 #include "SkTemplates.h" |
| 13 |
| 14 #define TINYEXR_IMPLEMENTATION |
| 15 #include "tinyexr.h" |
| 16 |
| 17 class SkEXRImageEncoder : public SkImageEncoder { |
| 18 protected: |
| 19 bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) override; |
| 20 private: |
| 21 typedef SkImageEncoder INHERITED; |
| 22 }; |
| 23 |
| 24 static inline bool encode_f16(SkWStream* stream, const SkBitmap& bitmap) { |
| 25 bool isOpaque = bitmap.isOpaque(); |
| 26 |
| 27 EXRHeader header; |
| 28 InitEXRHeader(&header); |
| 29 header.compression_type = TINYEXR_COMPRESSIONTYPE_PIZ; |
| 30 |
| 31 EXRChannelInfo channels[4]; |
| 32 sk_bzero(channels, 4 * sizeof(EXRChannelInfo)); |
| 33 header.channels = channels; |
| 34 |
| 35 // EXR viewers expect BGR(A). |
| 36 if (isOpaque) { |
| 37 header.num_channels = 3; |
| 38 header.channels[0].name[0] = 'B'; |
| 39 header.channels[1].name[0] = 'G'; |
| 40 header.channels[2].name[0] = 'R'; |
| 41 } else { |
| 42 header.num_channels = 4; |
| 43 header.channels[0].name[0] = 'B'; |
| 44 header.channels[1].name[0] = 'G'; |
| 45 header.channels[2].name[0] = 'R'; |
| 46 header.channels[3].name[0] = 'A'; |
| 47 } |
| 48 |
| 49 int pixelTypes[] = { |
| 50 TINYEXR_PIXELTYPE_HALF, |
| 51 TINYEXR_PIXELTYPE_HALF, |
| 52 TINYEXR_PIXELTYPE_HALF, |
| 53 TINYEXR_PIXELTYPE_HALF, |
| 54 }; |
| 55 |
| 56 header.pixel_types = pixelTypes; |
| 57 header.requested_pixel_types = pixelTypes; |
| 58 |
| 59 EXRImage image; |
| 60 InitEXRImage(&image); |
| 61 |
| 62 image.num_channels = header.num_channels; |
| 63 |
| 64 int width = bitmap.width(); |
| 65 int height = bitmap.height(); |
| 66 SkAutoTMalloc<SkHalf> storage(image.num_channels * width * height); |
| 67 SkHalf* planes[4]; |
| 68 for (int i = 0; i < image.num_channels; i++) { |
| 69 planes[i] = storage.get() + i * width * height; |
| 70 } |
| 71 |
| 72 for (int y = 0; y < height; y++) { |
| 73 for (int x = 0; x < width; x++) { |
| 74 uint64_t pixel = *((uint64_t*) bitmap.getAddr(x, y)); |
| 75 planes[0][y * width + x] = (pixel >> 32) & 0xFFFF; |
| 76 planes[1][y * width + x] = (pixel >> 16) & 0xFFFF; |
| 77 planes[2][y * width + x] = (pixel >> 0) & 0xFFFF; |
| 78 if (4 == image.num_channels) { |
| 79 planes[3][y * width + x] = (pixel >> 48) & 0xFFFF; |
| 80 } |
| 81 } |
| 82 } |
| 83 |
| 84 image.images = (uint8_t**) planes; |
| 85 image.width = width; |
| 86 image.height = height; |
| 87 |
| 88 const char* error; |
| 89 uint8_t* memory; |
| 90 size_t bytes = SaveEXRImageToMemory(&image, &header, &memory, &error); |
| 91 if (0 == bytes) { |
| 92 SkDebugf("EXR Error: %s\n", error); |
| 93 return false; |
| 94 } |
| 95 |
| 96 stream->write(memory, bytes); |
| 97 free(memory); |
| 98 return true; |
| 99 } |
| 100 |
| 101 bool SkEXRImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bitmap, int)
{ |
| 102 const SkColorType colorType = bitmap.colorType(); |
| 103 const SkAlphaType alphaType = bitmap.alphaType(); |
| 104 switch (colorType) { |
| 105 case kAlpha_8_SkColorType: |
| 106 if (kPremul_SkAlphaType != alphaType && kUnpremul_SkAlphaType != alp
haType) { |
| 107 return false; |
| 108 } |
| 109 break; |
| 110 case kRGBA_F16_SkColorType: |
| 111 if (kUnpremul_SkAlphaType == alphaType) { |
| 112 // OpenEXR expect premultiplied alpha. |
| 113 // FIXME (msarett): |
| 114 // Do the premultiply, then encode. |
| 115 return false; |
| 116 } |
| 117 |
| 118 return encode_f16(stream, bitmap); |
| 119 default: |
| 120 return false; |
| 121 } |
| 122 |
| 123 return true; |
| 124 } |
| 125 |
| 126 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
| 127 |
| 128 DEFINE_ENCODER_CREATOR(EXRImageEncoder); |
| 129 |
| 130 SkImageEncoder* sk_exr_efactory(SkImageEncoder::Type t) { |
| 131 return (SkImageEncoder::kEXR_Type == t) ? new SkEXRImageEncoder : nullptr; |
| 132 } |
| 133 |
| 134 static SkImageEncoder_EncodeReg gEReg(sk_exr_efactory); |
OLD | NEW |