Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(374)

Unified Diff: src/images/SkEXRImageEncoder.cpp

Issue 2344523002: Experimental: EXR
Patch Set: Now we have a decoder Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/codec/SkExrCodec.cpp ('k') | src/images/SkForceLinking.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/images/SkEXRImageEncoder.cpp
diff --git a/src/images/SkEXRImageEncoder.cpp b/src/images/SkEXRImageEncoder.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..416e1322fd7c5683bf35b2ce23e4e05f20dd37d8
--- /dev/null
+++ b/src/images/SkEXRImageEncoder.cpp
@@ -0,0 +1,134 @@
+/*
+ * 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 "SkBitmap.h"
+#include "SkImageEncoder.h"
+#include "SkHalf.h"
+#include "SkStream.h"
+#include "SkTemplates.h"
+
+#define TINYEXR_IMPLEMENTATION
+#include "tinyexr.h"
+
+class SkEXRImageEncoder : public SkImageEncoder {
+protected:
+ bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) override;
+private:
+ typedef SkImageEncoder INHERITED;
+};
+
+static inline bool encode_f16(SkWStream* stream, const SkBitmap& bitmap) {
+ bool isOpaque = bitmap.isOpaque();
+
+ EXRHeader header;
+ InitEXRHeader(&header);
+ header.compression_type = TINYEXR_COMPRESSIONTYPE_PIZ;
+
+ EXRChannelInfo channels[4];
+ sk_bzero(channels, 4 * sizeof(EXRChannelInfo));
+ header.channels = channels;
+
+ // EXR viewers expect BGR(A).
+ if (isOpaque) {
+ header.num_channels = 3;
+ header.channels[0].name[0] = 'B';
+ header.channels[1].name[0] = 'G';
+ header.channels[2].name[0] = 'R';
+ } else {
+ header.num_channels = 4;
+ header.channels[0].name[0] = 'B';
+ header.channels[1].name[0] = 'G';
+ header.channels[2].name[0] = 'R';
+ header.channels[3].name[0] = 'A';
+ }
+
+ int pixelTypes[] = {
+ TINYEXR_PIXELTYPE_HALF,
+ TINYEXR_PIXELTYPE_HALF,
+ TINYEXR_PIXELTYPE_HALF,
+ TINYEXR_PIXELTYPE_HALF,
+ };
+
+ header.pixel_types = pixelTypes;
+ header.requested_pixel_types = pixelTypes;
+
+ EXRImage image;
+ InitEXRImage(&image);
+
+ image.num_channels = header.num_channels;
+
+ int width = bitmap.width();
+ int height = bitmap.height();
+ SkAutoTMalloc<SkHalf> storage(image.num_channels * width * height);
+ SkHalf* planes[4];
+ for (int i = 0; i < image.num_channels; i++) {
+ planes[i] = storage.get() + i * width * height;
+ }
+
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ uint64_t pixel = *((uint64_t*) bitmap.getAddr(x, y));
+ planes[0][y * width + x] = (pixel >> 32) & 0xFFFF;
+ planes[1][y * width + x] = (pixel >> 16) & 0xFFFF;
+ planes[2][y * width + x] = (pixel >> 0) & 0xFFFF;
+ if (4 == image.num_channels) {
+ planes[3][y * width + x] = (pixel >> 48) & 0xFFFF;
+ }
+ }
+ }
+
+ image.images = (uint8_t**) planes;
+ image.width = width;
+ image.height = height;
+
+ const char* error;
+ uint8_t* memory;
+ size_t bytes = SaveEXRImageToMemory(&image, &header, &memory, &error);
+ if (0 == bytes) {
+ SkDebugf("EXR Error: %s\n", error);
+ return false;
+ }
+
+ stream->write(memory, bytes);
+ free(memory);
+ return true;
+}
+
+bool SkEXRImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bitmap, int) {
+ const SkColorType colorType = bitmap.colorType();
+ const SkAlphaType alphaType = bitmap.alphaType();
+ switch (colorType) {
+ case kAlpha_8_SkColorType:
+ if (kPremul_SkAlphaType != alphaType && kUnpremul_SkAlphaType != alphaType) {
+ return false;
+ }
+ break;
+ case kRGBA_F16_SkColorType:
+ if (kUnpremul_SkAlphaType == alphaType) {
+ // OpenEXR expect premultiplied alpha.
+ // FIXME (msarett):
+ // Do the premultiply, then encode.
+ return false;
+ }
+
+ return encode_f16(stream, bitmap);
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+DEFINE_ENCODER_CREATOR(EXRImageEncoder);
+
+SkImageEncoder* sk_exr_efactory(SkImageEncoder::Type t) {
+ return (SkImageEncoder::kEXR_Type == t) ? new SkEXRImageEncoder : nullptr;
+}
+
+static SkImageEncoder_EncodeReg gEReg(sk_exr_efactory);
« no previous file with comments | « src/codec/SkExrCodec.cpp ('k') | src/images/SkForceLinking.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698