blob: 7f3f055de10d36d0ae9eef429df2fb725344e77d [file] [log] [blame]
Mike Klein7af351a2018-07-27 09:54:43 -04001/*
2* Copyright 2018 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 "../third_party/skcms/skcms.h"
9#include "SkColorSpacePriv.h"
10#include "SkData.h"
11#include "SkImage.h"
12#include "SkStream.h"
13
14int main(int argc, char** argv) {
Mike Klein06a215b2018-09-06 14:21:09 -040015 const char* source_path = argc > 1 ? argv[1] : nullptr;
16 if (!source_path) {
17 SkDebugf("Please pass an image or profile to convert"
18 " as the first argument to this program.\n");
Mike Klein7af351a2018-07-27 09:54:43 -040019 return 1;
20 }
21
Mike Klein06a215b2018-09-06 14:21:09 -040022 const char* dst_profile_path = argc > 2 ? argv[2] : nullptr;
23 skcms_ICCProfile dst_profile = *skcms_sRGB_profile();
24 if (dst_profile_path) {
25 sk_sp<SkData> blob = SkData::MakeFromFileName(dst_profile_path);
26 if (!skcms_Parse(blob->data(), blob->size(), &dst_profile)) {
27 SkDebugf("Can't parse %s as an ICC profile.\n", dst_profile_path);
28 return 1;
29 }
30 }
31
32 auto blob = SkData::MakeFromFileName(source_path);
33
34 skcms_ICCProfile src_profile;
35 if (skcms_Parse(blob->data(), blob->size(), &src_profile)) {
36 // Transform white, black, primaries, and primary complements.
37 float src[] = {
38 0,0,0,
39 1,1,1,
40
41 1,0,0,
42 0,1,0,
43 0,0,1,
44
45 0,1,1,
46 1,0,1,
47 1,1,0,
48 };
49 float dst[24] = {0};
50
51 if (!skcms_Transform(
52 src, skcms_PixelFormat_RGB_fff, skcms_AlphaFormat_Unpremul, &src_profile,
53 dst, skcms_PixelFormat_RGB_fff, skcms_AlphaFormat_Unpremul, &dst_profile,
54 8)) {
55 SkDebugf("Cannot transform.\n");
56 return 1;
57 }
58 for (int i = 0; i < 8; i++) {
59 SkDebugf("(%g, %g, %g) --> (%+.4f, %+.4f, %+.4f)\n",
60 src[3*i+0], src[3*i+1], src[3*i+2],
61 dst[3*i+0], dst[3*i+1], dst[3*i+2]);
62 }
63 return 0;
64 }
65
66 sk_sp<SkImage> image = SkImage::MakeFromEncoded(blob);
Mike Klein7af351a2018-07-27 09:54:43 -040067 if (!image) {
Mike Klein06a215b2018-09-06 14:21:09 -040068 SkDebugf("Couldn't decode %s as an SkImage or an ICC profile.\n", source_path);
Mike Klein7af351a2018-07-27 09:54:43 -040069 return 1;
70 }
71
72 image = image->makeRasterImage();
73 if (!image) {
74 SkDebugf("Converting to raster image failed.\n");
75 return 1;
76 }
77
78 SkPixmap pixmap;
79 if (!image->peekPixels(&pixmap)) {
80 SkDebugf("We really should be able to peek raster pixels.\n");
81 return 1;
82 }
83
84 SkColorSpace* src_cs = image->colorSpace() ? image->colorSpace()
85 : sk_srgb_singleton();
Mike Klein7af351a2018-07-27 09:54:43 -040086 src_cs->toProfile(&src_profile);
87
Mike Klein7af351a2018-07-27 09:54:43 -040088 skcms_PixelFormat fmt;
89 switch (pixmap.colorType()) {
90 case kRGBA_8888_SkColorType: fmt = skcms_PixelFormat_RGBA_8888; break;
91 case kBGRA_8888_SkColorType: fmt = skcms_PixelFormat_BGRA_8888; break;
92 default:
93 SkDebugf("color type %d not yet supported, imgcvt.cpp needs an update.\n",
94 pixmap.colorType());
95 return 1;
96 }
97
98 if (pixmap.alphaType() != kPremul_SkAlphaType) {
99 SkDebugf("not premul, that's weird.\n");
100 return 1;
101 }
102 auto alpha = skcms_AlphaFormat_PremulAsEncoded;
103
104 if (pixmap.rowBytes() != (size_t)pixmap.width() * pixmap.info().bytesPerPixel()) {
105 SkDebugf("not a tight pixmap, need a loop here\n");
106 return 1;
107 }
108
109 skcms_Transform(pixmap.addr(), fmt,alpha, &src_profile,
110 pixmap.writable_addr(), fmt,alpha, &dst_profile,
111 pixmap.width() * pixmap.height());
112 pixmap.setColorSpace(SkColorSpace::Make(dst_profile));
113
114 sk_sp<SkImage> transformed = SkImage::MakeRasterCopy(pixmap);
115 sk_sp<SkData> png = transformed->encodeToData();
116
117 SkFILEWStream("transformed.png").write(png->data(), png->size());
118
119 return 0;
120}