Added A2B support to colorspaceinfo tool
Tool now parses A2B images/profiles.
Tool can now display a cross-section based visualization for the color
look-up tables in A2B profiles.
BUG=skia:
Change-Id: I68abb3e947b080c533e283783d7859feea8d35d6
Reviewed-on: https://skia-review.googlesource.com/6119
Commit-Queue: Matt Sarett <msarett@google.com>
Reviewed-by: Matt Sarett <msarett@google.com>
diff --git a/src/core/SkColorLookUpTable.h b/src/core/SkColorLookUpTable.h
index 0cde767..cc5415b 100644
--- a/src/core/SkColorLookUpTable.h
+++ b/src/core/SkColorLookUpTable.h
@@ -36,7 +36,7 @@
int inputChannels() const { return fInputChannels; }
int outputChannels() const { return kOutputChannels; }
-
+
int gridPoints(int dimension) const {
SkASSERT(dimension >= 0 && dimension < inputChannels());
return fGridPoints[dimension];
diff --git a/src/core/SkColorSpace_Base.h b/src/core/SkColorSpace_Base.h
index 61f65a5..9055cce 100644
--- a/src/core/SkColorSpace_Base.h
+++ b/src/core/SkColorSpace_Base.h
@@ -110,7 +110,7 @@
SkASSERT(i >= 0 && i < fChannels);
return fType[i];
}
-
+
uint8_t channels() const { return fChannels; }
SkGammas(uint8_t channels)
diff --git a/tools/colorspaceinfo.cpp b/tools/colorspaceinfo.cpp
index d605d50..91445db 100644
--- a/tools/colorspaceinfo.cpp
+++ b/tools/colorspaceinfo.cpp
@@ -20,22 +20,59 @@
#include "sk_tool_utils.h"
+#include <sstream>
+#include <string>
+#include <vector>
+
DEFINE_string(input, "input.png", "A path to the input image or icc profile.");
-DEFINE_string(gamut_output, "gamut_output.png", "A path to the output gamut image.");
-DEFINE_string(gamma_output, "gamma_output.png", "A path to the output gamma image.");
+DEFINE_string(output, ".", "A path to the output image directory.");
DEFINE_bool(sRGB_gamut, false, "Draws the sRGB gamut on the gamut visualization.");
DEFINE_bool(adobeRGB, false, "Draws the Adobe RGB gamut on the gamut visualization.");
DEFINE_bool(sRGB_gamma, false, "Draws the sRGB gamma on all gamma output images.");
DEFINE_string(uncorrected, "", "A path to reencode the uncorrected input image.");
+
+//-------------------------------------------------------------------------------------------------
+//------------------------------------ Gamma visualizations ---------------------------------------
+
static const char* kRGBChannelNames[3] = {
- "Red ", "Green", "Blue "
+ "Red ",
+ "Green",
+ "Blue "
+};
+static const SkColor kRGBChannelColors[3] = {
+ SkColorSetARGB(128, 255, 0, 0),
+ SkColorSetARGB(128, 0, 255, 0),
+ SkColorSetARGB(128, 0, 0, 255)
};
-static const SkColor kRGBChannelColors[3] = {
- SkColorSetARGB(164, 255, 32, 32),
- SkColorSetARGB(164, 32, 255, 32),
- SkColorSetARGB(164, 32, 32, 255)
+static const char* kGrayChannelNames[1] = { "Gray"};
+static const SkColor kGrayChannelColors[1] = { SkColorSetRGB(128, 128, 128) };
+
+static const char* kCMYKChannelNames[4] = {
+ "Cyan ",
+ "Magenta",
+ "Yellow ",
+ "Black "
+};
+static const SkColor kCMYKChannelColors[4] = {
+ SkColorSetARGB(128, 0, 255, 255),
+ SkColorSetARGB(128, 255, 0, 255),
+ SkColorSetARGB(128, 255, 255, 0),
+ SkColorSetARGB(128, 16, 16, 16)
+};
+
+static const char*const*const kChannelNames[4] = {
+ kGrayChannelNames,
+ kRGBChannelNames,
+ kRGBChannelNames,
+ kCMYKChannelNames
+};
+static const SkColor*const kChannelColors[4] = {
+ kGrayChannelColors,
+ kRGBChannelColors,
+ kRGBChannelColors,
+ kCMYKChannelColors
};
static void dump_transfer_fn(SkGammaNamed gammaNamed) {
@@ -55,35 +92,38 @@
}
+static constexpr int kGammaImageWidth = 500;
+static constexpr int kGammaImageHeight = 500;
+
static void dump_transfer_fn(const SkGammas& gammas) {
- SkASSERT(gammas.channels() == 3);
+ SkASSERT(gammas.channels() <= 4);
+ const char*const*const channels = kChannelNames[gammas.channels() - 1];
for (int i = 0; i < gammas.channels(); i++) {
if (gammas.isNamed(i)) {
switch (gammas.data(i).fNamed) {
case kSRGB_SkGammaNamed:
- SkDebugf("%s Transfer Function: sRGB\n", kRGBChannelNames[i]);
+ SkDebugf("%s Transfer Function: sRGB\n", channels[i]);
return;
case k2Dot2Curve_SkGammaNamed:
- SkDebugf("%s Transfer Function: Exponent 2.2\n", kRGBChannelNames[i]);
+ SkDebugf("%s Transfer Function: Exponent 2.2\n", channels[i]);
return;
case kLinear_SkGammaNamed:
- SkDebugf("%s Transfer Function: Linear\n", kRGBChannelNames[i]);
+ SkDebugf("%s Transfer Function: Linear\n", channels[i]);
return;
default:
SkASSERT(false);
continue;
}
} else if (gammas.isValue(i)) {
- SkDebugf("%s Transfer Function: Exponent %.3f\n", kRGBChannelNames[i],
- gammas.data(i).fValue);
+ SkDebugf("%s Transfer Function: Exponent %.3f\n", channels[i], gammas.data(i).fValue);
} else if (gammas.isParametric(i)) {
const SkColorSpaceTransferFn& fn = gammas.data(i).params(&gammas);
SkDebugf("%s Transfer Function: Parametric A = %.3f, B = %.3f, C = %.3f, D = %.3f, "
- "E = %.3f, F = %.3f, G = %.3f\n", kRGBChannelNames[i], fn.fA, fn.fB, fn.fC,
- fn.fD, fn.fE, fn.fF, fn.fG);
+ "E = %.3f, F = %.3f, G = %.3f\n", channels[i], fn.fA, fn.fB, fn.fC, fn.fD,
+ fn.fE, fn.fF, fn.fG);
} else {
SkASSERT(gammas.isTable(i));
- SkDebugf("%s Transfer Function: Table (%d entries)\n", kRGBChannelNames[i],
+ SkDebugf("%s Transfer Function: Table (%d entries)\n", channels[i],
gammas.data(i).fTable.fSize);
}
}
@@ -95,7 +135,7 @@
}
static void draw_transfer_fn(SkCanvas* canvas, SkGammaNamed gammaNamed, const SkGammas* gammas,
- SkColor color, int col) {
+ SkColor color) {
SkColorSpaceTransferFn fn[4];
struct TableInfo {
const float* fTable;
@@ -142,16 +182,14 @@
// note: gamma has positive values going up in this image so this origin is
// the bottom left and we must subtract y instead of adding.
const float gap = 16.0f;
- const float cellWidth = 500.0f;
- const float cellHeight = 500.0f;
- const float gammaWidth = cellWidth - 2 * gap;
- const float gammaHeight = cellHeight - 2 * gap;
+ const float gammaWidth = kGammaImageWidth - 2 * gap;
+ const float gammaHeight = kGammaImageHeight - 2 * gap;
// gamma origin point
- const float ox = gap + cellWidth * col;
+ const float ox = gap;
const float oy = gap + gammaHeight;
for (int i = 0; i < channels; ++i) {
if (kNonStandard_SkGammaNamed == gammaNamed) {
- paint.setColor(kRGBChannelColors[i]);
+ paint.setColor(kChannelColors[channels - 1][i]);
} else {
paint.setColor(color);
}
@@ -183,6 +221,98 @@
canvas->drawRect({ ox, oy - gammaHeight, ox + gammaWidth, oy }, paint);
}
+//-------------------------------------------------------------------------------------------------
+//------------------------------------ CLUT visualizations ----------------------------------------
+static void dump_clut(const SkColorLookUpTable& clut) {
+ SkDebugf("CLUT: ");
+ for (int i = 0; i < clut.inputChannels(); ++i) {
+ SkDebugf("[%d]", clut.gridPoints(i));
+ }
+ SkDebugf(" -> [%d]\n", clut.outputChannels());
+}
+
+constexpr int kClutGap = 8;
+constexpr float kClutCanvasSize = 2000;
+
+static inline int usedGridPoints(const SkColorLookUpTable& clut, int dimension) {
+ const int gp = clut.gridPoints(dimension);
+ return gp <= 16 ? gp : 16;
+}
+
+// how many rows of cross-section cuts to display
+static inline int cut_rows(const SkColorLookUpTable& clut, int dimOrder[4]) {
+ // and vertical ones for the 4th dimension (if applicable)
+ return clut.inputChannels() >= 4 ? usedGridPoints(clut, dimOrder[3]) : 1;
+}
+
+// how many columns of cross-section cuts to display
+static inline int cut_cols(const SkColorLookUpTable& clut, int dimOrder[4]) {
+ // do horizontal cuts for the 3rd dimension (if applicable)
+ return clut.inputChannels() >= 3 ? usedGridPoints(clut, dimOrder[2]) : 1;
+}
+
+// gets the width/height to use for cross-sections of a CLUT
+static int cut_size(const SkColorLookUpTable& clut, int dimOrder[4]) {
+ const int rows = cut_rows(clut, dimOrder);
+ const int cols = cut_cols(clut, dimOrder);
+ // make sure the cross-section CLUT cuts are square still by using the
+ // smallest of the width/height, then adjust the gaps between accordingly
+ const int cutWidth = (kClutCanvasSize - kClutGap * (1 + cols)) / cols;
+ const int cutHeight = (kClutCanvasSize - kClutGap * (1 + rows)) / rows;
+ return cutWidth < cutHeight ? cutWidth : cutHeight;
+}
+
+static void draw_clut(SkCanvas* canvas, const SkColorLookUpTable& clut, int dimOrder[4]) {
+ dump_clut(clut);
+
+ const int cutSize = cut_size(clut, dimOrder);
+ const int rows = cut_rows(clut, dimOrder);
+ const int cols = cut_cols(clut, dimOrder);
+ const int cutHorizGap = (kClutCanvasSize - cutSize * cols) / (1 + cols);
+ const int cutVertGap = (kClutCanvasSize - cutSize * rows) / (1 + rows);
+
+ SkPaint paint;
+ for (int row = 0; row < rows; ++row) {
+ for (int col = 0; col < cols; ++col) {
+ // make sure to move at least one pixel, but otherwise move per-gridpoint
+ const float xStep = 1.0f / (SkTMin(cutSize, clut.gridPoints(dimOrder[0])) - 1);
+ const float yStep = 1.0f / (SkTMin(cutSize, clut.gridPoints(dimOrder[1])) - 1);
+ const float ox = clut.inputChannels() >= 3 ? (1 + col) * cutHorizGap + col * cutSize
+ : kClutGap;
+ const float oy = clut.inputChannels() >= 4 ? (1 + row) * cutVertGap + row * cutSize
+ : kClutGap;
+ // for each cross-section cut, draw a bunch of squares whose colour is the top-left's
+ // colour in the CLUT (usually this will just draw the gridpoints)
+ for (float x = 0.0f; x < 1.0f; x += xStep) {
+ for (float y = 0.0f; y < 1.0f; y += yStep) {
+ const float z = col / (cols - 1.0f);
+ const float w = row / (rows - 1.0f);
+ const float input[4] = {x, y, z, w};
+ float output[3];
+ clut.interp(output, input);
+ paint.setColor(SkColorSetRGB(255*output[0], 255*output[1], 255*output[2]));
+ canvas->drawRect(SkRect::MakeLTRB(ox + cutSize * x, oy + cutSize * y,
+ ox + cutSize * (x + xStep),
+ oy + cutSize * (y + yStep)), paint);
+ }
+ }
+ }
+ }
+}
+
+
+//-------------------------------------------------------------------------------------------------
+//------------------------------------ Gamut visualizations ---------------------------------------
+static void dump_matrix(const SkMatrix44& m) {
+ for (int r = 0; r < 4; ++r) {
+ SkDebugf("|");
+ for (int c = 0; c < 4; ++c) {
+ SkDebugf(" %f ", m.get(r, c));
+ }
+ SkDebugf("|\n");
+ }
+}
+
/**
* Loads the triangular gamut as a set of three points.
*/
@@ -258,22 +388,63 @@
}
}
+
+//-------------------------------------------------------------------------------------------------
+//----------------------------------------- Main code ---------------------------------------------
+static SkBitmap transparentBitmap(int width, int height) {
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(width, height);
+ bitmap.eraseColor(SkColorSetARGB(0, 0, 0, 0));
+ return bitmap;
+}
+
+class OutputCanvas {
+public:
+ OutputCanvas(SkBitmap&& bitmap)
+ :fBitmap(bitmap)
+ ,fCanvas(fBitmap)
+ {}
+
+ bool save(std::vector<std::string>* output, const std::string& filename) {
+ // Finally, encode the result to the output file.
+ sk_sp<SkData> out = sk_tool_utils::EncodeImageToData(fBitmap, SkEncodedImageFormat::kPNG,
+ 100);
+ if (!out) {
+ SkDebugf("Failed to encode %s output.\n", filename.c_str());
+ return false;
+ }
+ SkFILEWStream stream(filename.c_str());
+ if (!stream.write(out->data(), out->size())) {
+ SkDebugf("Failed to write %s output.\n", filename.c_str());
+ return false;
+ }
+ // record name of canvas
+ output->push_back(filename);
+ return true;
+ }
+
+ SkCanvas* canvas() { return &fCanvas; }
+
+private:
+ SkBitmap fBitmap;
+ SkCanvas fCanvas;
+};
+
int main(int argc, char** argv) {
SkCommandLineFlags::SetUsage(
"Usage: colorspaceinfo --input <path to input image or icc profile> "
- "--gamma_output <path to output gamma image> "
- "--gamut_output <path to output gamut image>"
- "--sRGB <draw canonical sRGB gamut> "
+ "--output <directory to output images> "
+ "--sRGB_gamut <draw canonical sRGB gamut> "
"--adobeRGB <draw canonical Adobe RGB gamut> "
+ "--sRGB_gamma <draw sRGB gamma> "
"--uncorrected <path to reencoded, uncorrected input image>\n"
"Description: Writes visualizations of the color space to the output image(s) ."
"Also, if a path is provided, writes uncorrected bytes to an unmarked "
"png, for comparison with the input image.\n");
SkCommandLineFlags::Parse(argc, argv);
const char* input = FLAGS_input[0];
- const char* gamut_output = FLAGS_gamut_output[0];
- const char* gamma_output = FLAGS_gamma_output[0];
- if (!input || !gamut_output || !gamma_output) {
+ const char* output = FLAGS_output[0];
+ if (!input || !output) {
SkCommandLineFlags::PrintUsage();
return -1;
}
@@ -297,81 +468,149 @@
return -1;
}
- // Load a graph of the CIE XYZ color gamut.
- SkBitmap gamutCanvasBitmap;
- if (!GetResourceAsBitmap("gamut.png", &gamutCanvasBitmap)) {
- SkDebugf("Program failure.\n");
- return -1;
- }
- SkCanvas gamutCanvas(gamutCanvasBitmap);
+ // TODO: command line tweaking of this order
+ int dimOrder[4] = {0, 1, 2, 3};
- SkBitmap gammaCanvasBitmap;
- gammaCanvasBitmap.allocN32Pixels(500, 500);
- SkCanvas gammaCanvas(gammaCanvasBitmap);
+ std::vector<std::string> outputFilenames;
- // Draw the sRGB gamut if requested.
- if (FLAGS_sRGB_gamut) {
- sk_sp<SkColorSpace> sRGBSpace = SkColorSpace::MakeSRGB();
- const SkMatrix44* mat = as_CSB(sRGBSpace)->toXYZD50();
- SkASSERT(mat);
- draw_gamut(&gamutCanvas, *mat, "sRGB", 0xFFFF9394, false);
- }
+ auto createOutputFilename = [output](const char* category, int index) -> std::string {
+ std::stringstream ss;
+ ss << output << '/' << category << '_' << index << ".png";
+ return ss.str();
+ };
- // Draw the Adobe RGB gamut if requested.
- if (FLAGS_adobeRGB) {
- sk_sp<SkColorSpace> adobeRGBSpace =
- SkColorSpace_Base::MakeNamed(SkColorSpace_Base::kAdobeRGB_Named);
- const SkMatrix44* mat = as_CSB(adobeRGBSpace)->toXYZD50();
- SkASSERT(mat);
- draw_gamut(&gamutCanvas, *mat, "Adobe RGB", 0xFF31a9e1, false);
- }
-
- int gammaCol = 0;
if (SkColorSpace_Base::Type::kXYZ == as_CSB(colorSpace)->type()) {
+ SkDebugf("XYZ/TRC color space\n");
+
+ // Load a graph of the CIE XYZ color gamut.
+ SkBitmap gamutCanvasBitmap;
+ if (!GetResourceAsBitmap("gamut.png", &gamutCanvasBitmap)) {
+ SkDebugf("Program failure (could not load gamut.png).\n");
+ return -1;
+ }
+ OutputCanvas gamutCanvas(std::move(gamutCanvasBitmap));
+ // Draw the sRGB gamut if requested.
+ if (FLAGS_sRGB_gamut) {
+ sk_sp<SkColorSpace> sRGBSpace = SkColorSpace::MakeSRGB();
+ const SkMatrix44* mat = as_CSB(sRGBSpace)->toXYZD50();
+ SkASSERT(mat);
+ draw_gamut(gamutCanvas.canvas(), *mat, "sRGB", 0xFFFF9394, false);
+ }
+
+ // Draw the Adobe RGB gamut if requested.
+ if (FLAGS_adobeRGB) {
+ sk_sp<SkColorSpace> adobeRGBSpace = SkColorSpace::MakeRGB(
+ SkColorSpace::kSRGB_RenderTargetGamma, SkColorSpace::kAdobeRGB_Gamut);
+ const SkMatrix44* mat = as_CSB(adobeRGBSpace)->toXYZD50();
+ SkASSERT(mat);
+ draw_gamut(gamutCanvas.canvas(), *mat, "Adobe RGB", 0xFF31a9e1, false);
+ }
const SkMatrix44* mat = as_CSB(colorSpace)->toXYZD50();
SkASSERT(mat);
auto xyz = static_cast<SkColorSpace_XYZ*>(colorSpace.get());
- draw_gamut(&gamutCanvas, *mat, input, 0xFF000000, true);
- if (FLAGS_sRGB_gamma) {
- draw_transfer_fn(&gammaCanvas, kSRGB_SkGammaNamed, nullptr, 0xFFFF9394, gammaCol);
+ draw_gamut(gamutCanvas.canvas(), *mat, input, 0xFF000000, true);
+ if (!gamutCanvas.save(&outputFilenames, createOutputFilename("gamut", 0))) {
+ return -1;
}
- draw_transfer_fn(&gammaCanvas, xyz->gammaNamed(), xyz->gammas(), 0xFF000000, gammaCol++);
+
+ OutputCanvas gammaCanvas(transparentBitmap(kGammaImageWidth, kGammaImageHeight));
+ if (FLAGS_sRGB_gamma) {
+ draw_transfer_fn(gammaCanvas.canvas(), kSRGB_SkGammaNamed, nullptr, 0xFFFF9394);
+ }
+ draw_transfer_fn(gammaCanvas.canvas(), xyz->gammaNamed(), xyz->gammas(), 0xFF000000);
+ if (!gammaCanvas.save(&outputFilenames, createOutputFilename("gamma", 0))) {
+ return -1;
+ }
} else {
- SkDebugf("Color space is defined using an A2B tag. It cannot be represented by "
- "a transfer function and to D50 matrix.\n");
- return -1;
+ SkDebugf("A2B color space");
+ SkColorSpace_A2B* a2b = static_cast<SkColorSpace_A2B*>(colorSpace.get());
+ SkDebugf("Conversion type: ");
+ switch (a2b->iccType()) {
+ case SkColorSpace_Base::kRGB_ICCTypeFlag:
+ SkDebugf("RGB");
+ break;
+ case SkColorSpace_Base::kCMYK_ICCTypeFlag:
+ SkDebugf("CMYK");
+ break;
+ case SkColorSpace_Base::kGray_ICCTypeFlag:
+ SkDebugf("Gray");
+ break;
+ default:
+ SkASSERT(false);
+ break;
+
+ }
+ SkDebugf(" -> ");
+ switch (a2b->pcs()) {
+ case SkColorSpace_A2B::PCS::kXYZ:
+ SkDebugf("XYZ\n");
+ break;
+ case SkColorSpace_A2B::PCS::kLAB:
+ SkDebugf("LAB\n");
+ break;
+ }
+ int clutCount = 0;
+ int gammaCount = 0;
+ for (int i = 0; i < a2b->count(); ++i) {
+ const SkColorSpace_A2B::Element& e = a2b->element(i);
+ switch (e.type()) {
+ case SkColorSpace_A2B::Element::Type::kGammaNamed: {
+ OutputCanvas gammaCanvas(transparentBitmap(kGammaImageWidth,
+ kGammaImageHeight));
+ if (FLAGS_sRGB_gamma) {
+ draw_transfer_fn(gammaCanvas.canvas(), kSRGB_SkGammaNamed, nullptr,
+ 0xFFFF9394);
+ }
+ draw_transfer_fn(gammaCanvas.canvas(), e.gammaNamed(), nullptr,
+ 0xFF000000);
+ if (!gammaCanvas.save(&outputFilenames,
+ createOutputFilename("gamma", gammaCount++))) {
+ return -1;
+ }
+ }
+ break;
+ case SkColorSpace_A2B::Element::Type::kGammas: {
+ OutputCanvas gammaCanvas(transparentBitmap(kGammaImageWidth,
+ kGammaImageHeight));
+ if (FLAGS_sRGB_gamma) {
+ draw_transfer_fn(gammaCanvas.canvas(), kSRGB_SkGammaNamed, nullptr,
+ 0xFFFF9394);
+ }
+ draw_transfer_fn(gammaCanvas.canvas(), kNonStandard_SkGammaNamed,
+ &e.gammas(), 0xFF000000);
+ if (!gammaCanvas.save(&outputFilenames,
+ createOutputFilename("gamma", gammaCount++))) {
+ return -1;
+ }
+ }
+ break;
+ case SkColorSpace_A2B::Element::Type::kCLUT: {
+ const SkColorLookUpTable& clut = e.colorLUT();
+ const int cutSize = cut_size(clut, dimOrder);
+ const int clutWidth = clut.inputChannels() >= 3 ? kClutCanvasSize
+ : 2 * kClutGap + cutSize;
+ const int clutHeight = clut.inputChannels() >= 4 ? kClutCanvasSize
+ : 2 * kClutGap + cutSize;
+ OutputCanvas clutCanvas(transparentBitmap(clutWidth, clutHeight));
+ draw_clut(clutCanvas.canvas(), e.colorLUT(), dimOrder);
+ if (!clutCanvas.save(&outputFilenames,
+ createOutputFilename("clut", clutCount++))) {
+ return -1;
+ }
+ }
+ break;
+ case SkColorSpace_A2B::Element::Type::kMatrix:
+ dump_matrix(e.matrix());
+ break;
+ }
+ }
}
// marker to tell the web-tool the names of all images output
SkDebugf("=========\n");
- auto saveCanvasBitmap = [](const SkBitmap& bitmap, const char *fname) {
- // Finally, encode the result to the output file.
- sk_sp<SkData> out = sk_tool_utils::EncodeImageToData(bitmap, SkEncodedImageFormat::kPNG,
- 100);
- if (!out) {
- SkDebugf("Failed to encode %s output.\n", fname);
- return false;
- }
- SkFILEWStream stream(fname);
- if (!stream.write(out->data(), out->size())) {
- SkDebugf("Failed to write %s output.\n", fname);
- return false;
- }
- // record name of canvas
- SkDebugf("%s\n", fname);
- return true;
- };
-
- // only XYZ images have a gamut visualization since the matrix in A2B is not
- // a gamut adjustment from RGB->XYZ always (or ever)
- if (SkColorSpace_Base::Type::kXYZ == as_CSB(colorSpace)->type() &&
- !saveCanvasBitmap(gamutCanvasBitmap, gamut_output)) {
- return -1;
+ for (const std::string& filename : outputFilenames) {
+ SkDebugf("%s\n", filename.c_str());
}
- if (gammaCol > 0 && !saveCanvasBitmap(gammaCanvasBitmap, gamma_output)) {
- return -1;
- }
-
if (isImage) {
SkDebugf("%s\n", input);
}