aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkColorSpaceXform_A2B.cpp
diff options
context:
space:
mode:
authorGravatar raftias <raftias@google.com>2016-12-01 13:44:07 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2016-12-01 19:42:32 +0000
commit5476128f0a88217414f05e6a7ee518cdb411d026 (patch)
tree6b65531042d9af58a82ba8305a928edec17e0f29 /src/core/SkColorSpaceXform_A2B.cpp
parentb6d4e139b522821933d356ef7d2472816d25340a (diff)
Added CMYK support for ICC profiles.
Changed ICC parsing/SkGammas/SkColorLookUpTable to handle non-3-channel inputs. Parsed CMYK A2B ICC profiles. Integrated this with SkJpegCodec (the only file that supports CMYK) and SkColorSpaceXform_A2B to allow parsing and color xforming of ICC CMYK images. CQ_INCLUDE_TRYBOTS=skia.primary:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD Change-Id: I11e3d17180244281be3eb43fd608609925a7f71e Reviewed-on: https://skia-review.googlesource.com/5444 Reviewed-by: Matt Sarett <msarett@google.com> Commit-Queue: Matt Sarett <msarett@google.com>
Diffstat (limited to 'src/core/SkColorSpaceXform_A2B.cpp')
-rw-r--r--src/core/SkColorSpaceXform_A2B.cpp81
1 files changed, 51 insertions, 30 deletions
diff --git a/src/core/SkColorSpaceXform_A2B.cpp b/src/core/SkColorSpaceXform_A2B.cpp
index f2f694349f..b0495cfef2 100644
--- a/src/core/SkColorSpaceXform_A2B.cpp
+++ b/src/core/SkColorSpaceXform_A2B.cpp
@@ -169,16 +169,33 @@ SkColorSpaceXform_A2B::SkColorSpaceXform_A2B(SkColorSpace_A2B* srcSpace,
"None", "Named", "Value", "Table", "Param"
};
#endif
+ int currentChannels = -1;
+ switch (srcSpace->inputColorFormat()) {
+ case SkColorSpace_Base::InputColorFormat::kRGB:
+ currentChannels = 3;
+ break;
+ case SkColorSpace_Base::InputColorFormat::kCMYK:
+ currentChannels = 4;
+ // CMYK images from JPEGs (the only format that supports it) are actually
+ // inverted CMYK, so we need to invert every channel.
+ // TransferFn is y = -x + 1 for x < 1.f, otherwise 0x + 0, ie y = 1 - x for x in [0,1]
+ this->addTransferFns({1.f, 0.f, 0.f, 0.f, 1.f, -1.f, 1.f}, 4);
+ break;
+ default:
+ SkASSERT(false);
+ }
// add in all input color space -> PCS xforms
for (int i = 0; i < srcSpace->count(); ++i) {
const SkColorSpace_A2B::Element& e = srcSpace->element(i);
+ SkASSERT(e.inputChannels() == currentChannels);
+ currentChannels = e.outputChannels();
switch (e.type()) {
case SkColorSpace_A2B::Element::Type::kGammaNamed:
if (kLinear_SkGammaNamed != e.gammaNamed()) {
SkCSXformPrintf("Gamma stage added: %s\n",
debugGammaNamed[(int)e.gammaNamed()]);
SkColorSpaceTransferFn fn = gammanamed_to_parametric(e.gammaNamed());
- this->addTransferFn(fn, kRGB_Channels);
+ this->addTransferFns(fn, currentChannels);
fElementsPipeline.append(SkRasterPipeline::clamp_0);
fElementsPipeline.append(SkRasterPipeline::clamp_1);
@@ -187,23 +204,23 @@ SkColorSpaceXform_A2B::SkColorSpaceXform_A2B(SkColorSpace_A2B* srcSpace,
case SkColorSpace_A2B::Element::Type::kGammas: {
const SkGammas& gammas = e.gammas();
SkCSXformPrintf("Gamma stage added:");
- for (int channel = 0; channel < 3; ++channel) {
+ for (int channel = 0; channel < gammas.channels(); ++channel) {
SkCSXformPrintf(" %s", debugGammas[(int)gammas.type(channel)]);
}
SkCSXformPrintf("\n");
bool gammaNeedsRef = false;
- for (int channel = 0; channel < 3; ++channel) {
+ for (int channel = 0; channel < gammas.channels(); ++channel) {
if (SkGammas::Type::kTable_Type == gammas.type(channel)) {
SkTableTransferFn table = {
gammas.table(channel),
gammas.data(channel).fTable.fSize,
};
- this->addTableFn(table, static_cast<Channels>(channel));
+ this->addTableFn(table, channel);
gammaNeedsRef = true;
} else {
SkColorSpaceTransferFn fn = gamma_to_parametric(gammas, channel);
- this->addTransferFn(fn, static_cast<Channels>(channel));
+ this->addTransferFn(fn, channel);
}
}
if (gammaNeedsRef) {
@@ -215,8 +232,8 @@ SkColorSpaceXform_A2B::SkColorSpaceXform_A2B(SkColorSpace_A2B* srcSpace,
break;
}
case SkColorSpace_A2B::Element::Type::kCLUT:
- SkCSXformPrintf("CLUT stage added [%d][%d][%d]\n", e.colorLUT().fGridPoints[0],
- e.colorLUT().fGridPoints[1], e.colorLUT().fGridPoints[2]);
+ SkCSXformPrintf("CLUT (%d -> %d) stage added\n", e.colorLUT().inputChannels(),
+ e.colorLUT().outputChannels());
fCLUTs.push_back(sk_ref_sp(&e.colorLUT()));
fElementsPipeline.append(SkRasterPipeline::color_lookup_table,
fCLUTs.back().get());
@@ -230,6 +247,8 @@ SkColorSpaceXform_A2B::SkColorSpaceXform_A2B(SkColorSpace_A2B* srcSpace,
}
}
+ SkASSERT(3 == currentChannels);
+
// Lab PCS -> XYZ PCS
if (SkColorSpace_A2B::PCS::kLAB == srcSpace->pcs()) {
SkCSXformPrintf("Lab -> XYZ element added\n");
@@ -245,7 +264,7 @@ SkColorSpaceXform_A2B::SkColorSpaceXform_A2B(SkColorSpace_A2B* srcSpace,
if (!fLinearDstGamma) {
SkColorSpaceTransferFn fn =
invert_parametric(gammanamed_to_parametric(dstSpace->gammaNamed()));
- this->addTransferFn(fn, kRGB_Channels);
+ this->addTransferFns(fn, 3);
fElementsPipeline.append(SkRasterPipeline::clamp_0);
fElementsPipeline.append(SkRasterPipeline::clamp_1);
}
@@ -261,10 +280,10 @@ SkColorSpaceXform_A2B::SkColorSpaceXform_A2B(SkColorSpace_A2B* srcSpace,
};
fTableStorage.push_front(std::move(storage));
- this->addTableFn(table, static_cast<Channels>(channel));
+ this->addTableFn(table, channel);
} else {
SkColorSpaceTransferFn fn = invert_parametric(gamma_to_parametric(gammas, channel));
- this->addTransferFn(fn, static_cast<Channels>(channel));
+ this->addTransferFn(fn, channel);
}
}
@@ -273,45 +292,47 @@ SkColorSpaceXform_A2B::SkColorSpaceXform_A2B(SkColorSpace_A2B* srcSpace,
}
}
-void SkColorSpaceXform_A2B::addTransferFn(const SkColorSpaceTransferFn& fn, Channels channels) {
+void SkColorSpaceXform_A2B::addTransferFns(const SkColorSpaceTransferFn& fn, int channelCount) {
+ for (int i = 0; i < channelCount; ++i) {
+ this->addTransferFn(fn, i);
+ }
+}
+
+void SkColorSpaceXform_A2B::addTransferFn(const SkColorSpaceTransferFn& fn, int channelIndex) {
fTransferFns.push_front(fn);
- switch (channels) {
- case kRGB_Channels:
- fElementsPipeline.append(SkRasterPipeline::parametric_r, &fTransferFns.front());
- fElementsPipeline.append(SkRasterPipeline::parametric_g, &fTransferFns.front());
- fElementsPipeline.append(SkRasterPipeline::parametric_b, &fTransferFns.front());
- break;
- case kR_Channels:
+ switch (channelIndex) {
+ case 0:
fElementsPipeline.append(SkRasterPipeline::parametric_r, &fTransferFns.front());
break;
- case kG_Channels:
+ case 1:
fElementsPipeline.append(SkRasterPipeline::parametric_g, &fTransferFns.front());
break;
- case kB_Channels:
+ case 2:
fElementsPipeline.append(SkRasterPipeline::parametric_b, &fTransferFns.front());
break;
+ case 3:
+ fElementsPipeline.append(SkRasterPipeline::parametric_a, &fTransferFns.front());
+ break;
default:
SkASSERT(false);
}
}
-void SkColorSpaceXform_A2B::addTableFn(const SkTableTransferFn& fn, Channels channels) {
+void SkColorSpaceXform_A2B::addTableFn(const SkTableTransferFn& fn, int channelIndex) {
fTableTransferFns.push_front(fn);
- switch (channels) {
- case kRGB_Channels:
- fElementsPipeline.append(SkRasterPipeline::table_r, &fTableTransferFns.front());
- fElementsPipeline.append(SkRasterPipeline::table_g, &fTableTransferFns.front());
- fElementsPipeline.append(SkRasterPipeline::table_b, &fTableTransferFns.front());
- break;
- case kR_Channels:
+ switch (channelIndex) {
+ case 0:
fElementsPipeline.append(SkRasterPipeline::table_r, &fTableTransferFns.front());
break;
- case kG_Channels:
+ case 1:
fElementsPipeline.append(SkRasterPipeline::table_g, &fTableTransferFns.front());
break;
- case kB_Channels:
+ case 2:
fElementsPipeline.append(SkRasterPipeline::table_b, &fTableTransferFns.front());
break;
+ case 3:
+ fElementsPipeline.append(SkRasterPipeline::table_a, &fTableTransferFns.front());
+ break;
default:
SkASSERT(false);
}