1113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry/*
2113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry * Copyright 2016 Google Inc.
3113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry *
4113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry * Use of this source code is governed by a BSD-style license that can be
5113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry * found in the LICENSE file.
6113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry */
7113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry
8113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry#ifndef SkICC_DEFINED
9113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry#define SkICC_DEFINED
10113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry
116f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett#include "SkData.h"
12113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry#include "SkRefCnt.h"
13113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry
14113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistrystruct SkColorSpaceTransferFn;
15113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistryclass SkColorSpace;
16113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistryclass SkData;
17113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistryclass SkMatrix44;
18113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry
19113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistryclass SK_API SkICC : public SkRefCnt {
20113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistrypublic:
21113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry
22113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry    /**
23113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry     *  Parse an ICC profile.
24113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry     *
25113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry     *  Returns nullptr if the data is not a valid ICC profile or if the profile
26113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry     *  input space is not RGB.
27113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry     */
28113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry    static sk_sp<SkICC> Make(const void*, size_t);
29113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry
30113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry    /**
31113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry     *  If the gamut can be represented as transformation into XYZ D50, returns
32113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry     *  true and sets the proper values in |toXYZD50|.
33113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry     *
34113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry     *  If not, returns false.  This indicates that the ICC data is too complex
35113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry     *  to isolate a simple gamut transformation.
36113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry     */
37113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry    bool toXYZD50(SkMatrix44* toXYZD50) const;
38113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry
39113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry    /**
40113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry     *  If the transfer function can be represented as coefficients to the standard
41113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry     *  equation, returns true and sets |fn| to the proper values.
42113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry     *
43113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry     *  If not, returns false.  This indicates one of the following:
44113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry     *  (1) The R, G, and B transfer functions are not the same.
45113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry     *  (2) The transfer function is represented as a table that we have not managed
46113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry     *      to match to a standard curve.
47113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry     *  (3) The ICC data is too complex to isolate a single transfer function.
48113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry     */
49113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry    bool isNumericalTransferFn(SkColorSpaceTransferFn* fn) const;
50113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry
51113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry    /**
526f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett     *  Please do not call this unless isNumericalTransferFn() has been called and it
536f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett     *  fails.  SkColorSpaceTransferFn is the preferred representation.
54113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry     *
556f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett     *  If it is not possible to represent the R, G, and B transfer functions numerically
566f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett     *  and it is still necessary to get the transfer function, this will return the
576f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett     *  transfer functions as three tables (R, G, and B).
586f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett     *
596f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett     *  If possible, this will return tables of the same length as they were specified in
606f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett     *  the ICC profile.  This means that the lengths of the three tables are not
616f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett     *  guaranteed to be the same.  If the ICC representation was not a table, the length
626f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett     *  will be chosen arbitrarily.
636f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett     *
64541b1b08a82c8deec09b2bd258e1841660bd862aMatt Sarett     *  The lengths of the tables are all guaranteed to be at least 2.  Entries in the
65541b1b08a82c8deec09b2bd258e1841660bd862aMatt Sarett     *  tables are guaranteed to be in [0, 1].
666f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett     *
676f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett     *  This API may be deleted in favor of a numerical approximation of the raw data.
686f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett     *
696f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett     *  This function may fail, indicating that the ICC profile does not have transfer
706f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett     *  functions.
71113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry     */
726f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett    struct Channel {
736f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett        // Byte offset of the start of the table in |fStorage|
746f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett        size_t fOffset;
756f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett        int    fCount;
766f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett    };
776f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett    struct Tables {
786f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett        Channel fRed;
796f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett        Channel fGreen;
806f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett        Channel fBlue;
816f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett
826f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett        const float* red() {
836f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett            return (const float*) (fStorage->bytes() + fRed.fOffset);
846f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett        }
856f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett        const float* green() {
866f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett            return (const float*) (fStorage->bytes() + fGreen.fOffset);
876f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett        }
886f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett        const float* blue() {
896f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett            return (const float*) (fStorage->bytes() + fBlue.fOffset);
906f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett        }
916f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett
926f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett        sk_sp<SkData> fStorage;
936f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett    };
946f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett    bool rawTransferFnData(Tables* tables) const;
95113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry
96113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry    /**
97113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry     *  Write an ICC profile with transfer function |fn| and gamut |toXYZD50|.
98113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry     */
99113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry    static sk_sp<SkData> WriteToICC(const SkColorSpaceTransferFn& fn, const SkMatrix44& toXYZD50);
100113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry
101113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistryprivate:
102113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry    SkICC(sk_sp<SkColorSpace> colorSpace);
103113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry
104113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry    sk_sp<SkColorSpace> fColorSpace;
1056f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett
1066f67fc29eddfb6f415f7e6a86197db5d8c8539edMatt Sarett    friend class ICCTest;
107113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry};
108113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry
109113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry#endif
110