// Copyright 2016 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef UI_GFX_ICC_PROFILE_H_ #define UI_GFX_ICC_PROFILE_H_ #include #include #include #include "base/gtest_prod_util.h" #include "base/memory/ref_counted.h" #include "ui/gfx/color_space.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); namespace gfx { // Used to represent a full ICC profile, usually retrieved from a monitor. It // can be lossily compressed into a ColorSpace object. This structure should // only be sent from higher-privilege processes to lower-privilege processes, // as parsing this structure is not secure. class COLOR_SPACE_EXPORT ICCProfile { public: ICCProfile(); ICCProfile(ICCProfile&& other); ICCProfile(const ICCProfile& other); ICCProfile& operator=(ICCProfile&& other); ICCProfile& operator=(const ICCProfile& other); ~ICCProfile(); bool operator==(const ICCProfile& other) const; bool operator!=(const ICCProfile& other) const; // Returns true if this profile was successfully parsed by SkICC and will // return a valid ColorSpace. bool IsValid() const; // Create directly from profile data. This function should be called only // in the browser process (and the results from there sent to other // processes). static ICCProfile FromData(const void* icc_profile, size_t size); // Create a profile for a parametric color space. Returns an invalid profile // if the specified space is not parametric. static ICCProfile FromParametricColorSpace( const gfx::ColorSpace& color_space); // Return the ICCProfile that was used to create the specified ColorSpace, if // available. Otherwise, return an invalid profile. This is used on macOS for // power reasons. static ICCProfile FromCacheMac(const gfx::ColorSpace& color_space); // Return a ColorSpace that references this ICCProfile. ColorTransforms // created using this ColorSpace will match this ICCProfile precisely. ColorSpace GetColorSpace() const; // Return a ColorSpace that is the best parametric approximation of this // ICCProfile. The resulting ColorSpace will reference this ICCProfile only // if the parametric approximation is almost exact. ColorSpace GetParametricColorSpace() const; // Return the data for the profile. std::vector GetData() const; // Histogram how we this was approximated by a gfx::ColorSpace. Only // histogram a given profile once per display. void HistogramDisplay(int64_t display_id) const; private: // This method is used to hard-code the |id_| to a specific value. It is used // only when a profile is received via IPC. static ICCProfile FromDataWithId(const void* data, size_t size, uint64_t id); // This method is used by ColorTransform to construct LUT based transforms. static sk_sp GetSkColorSpaceFromId(uint64_t id); class Internals : public base::RefCountedThreadSafe { public: Internals(std::vector, uint64_t id); void HistogramDisplay(int64_t display_id); // This must match ICCProfileAnalyzeResult enum in histograms.xml. enum AnalyzeResult { kICCExtractedMatrixAndAnalyticTrFn = 0, kICCExtractedMatrixAndApproximatedTrFn = 1, kICCFailedToConvergeToApproximateTrFn = 2, kICCFailedToExtractRawTrFn = 3, kICCFailedToExtractMatrix = 4, kICCFailedToParse = 5, kICCFailedToExtractSkColorSpace = 6, kICCFailedToCreateXform = 7, kICCFailedToApproximateTrFnAccurately = 8, kICCExtractedSRGBColorSpace = 9, kICCNoProfile = 10, kICCProfileAnalyzeLast = kICCNoProfile, }; const std::vector data_; // The result of attepting to extract a color space from the color profile. AnalyzeResult analyze_result_ = kICCNoProfile; // True iff we can create a valid ColorSpace (and ColorTransform) from this // object. The transform may be LUT-based (using an SkColorSpaceXform to // compute the lut). bool is_valid_ = false; // True iff |to_XYZD50_| and |transfer_fn_| are accurate representations of // the data in this profile. In this case ColorTransforms created from this // profile will be analytic and not LUT-based. bool is_parametric_ = false; // If |is_valid_| but not |is_parametric_|, then |id_| is assigned a // non-zero value that can be used to look up this ICCProfile from a // ColorSpace for the purpose of creating a LUT based ColorTransform. uint64_t id_ = 0; // Results of Skia parsing the ICC profile data. sk_sp sk_color_space_; // The best-fit parametric primaries and transfer function. SkMatrix44 to_XYZD50_; SkColorSpaceTransferFn transfer_fn_; // The L-infinity error of the parametric color space fit. This is undefined // unless |analyze_result_| is kICCFailedToApproximateTrFnAccurately or // kICCExtractedMatrixAndApproximatedTrFn. float transfer_fn_error_ = 0; // The set of display ids which have have caused this ICC profile to be // recorded in UMA histograms. Only record an ICC profile once per display // id (since the same profile will be re-read repeatedly, e.g, when displays // are resized). std::set histogrammed_display_ids_; protected: friend class base::RefCountedThreadSafe; AnalyzeResult Initialize(); virtual ~Internals(); }; scoped_refptr internals_; FRIEND_TEST_ALL_PREFIXES(SimpleColorSpace, BT709toSRGBICC); FRIEND_TEST_ALL_PREFIXES(SimpleColorSpace, GetColorSpace); friend int ::LLVMFuzzerTestOneInput(const uint8_t*, size_t); friend class ColorSpace; friend class ColorTransformInternal; friend struct IPC::ParamTraits; }; } // namespace gfx #endif // UI_GFX_ICC_PROFILE_H_