Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6438a192 authored by Dichen Zhang's avatar Dichen Zhang
Browse files

jpegr: encode ICC

bug: b/264715926, b/263609305
test: recoverymap_test.cpp, check the ICC package in the encoded jpeg/r
image in a hex editor

Change-Id: I099eb9201c26fce046b7ca8ea4b5e7e8443adcb3
parent dff1554c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -41,6 +41,8 @@ cc_library {
        "libjpegdecoder",
        "liblog",
    ],

    static_libs: ["libskia"],
}

cc_library {
+1 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ typedef enum {
  JPEGR_TF_LINEAR = 0,
  JPEGR_TF_HLG = 1,
  JPEGR_TF_PQ = 2,
  JPEGR_TF_SRGB = 3,
} jpegr_transfer_function;

struct jpegr_info_struct {
+0 −7
Original line number Diff line number Diff line
@@ -28,13 +28,6 @@ namespace android::recoverymap {

struct jpegr_metadata;

// If the EXIF package doesn't exist in the input JPEG, we'll create one with one entry
// where the length is represented by this value.
const size_t PSEUDO_EXIF_PACKAGE_LENGTH = 28;
// If the EXIF package exists in the input JPEG, we'll add an "JR" entry where the length is
// represented by this value.
const size_t EXIF_J_R_ENTRY_LENGTH = 12;

/*
 * Helper function used for writing data to destination.
 *
+31 −6
Original line number Diff line number Diff line
@@ -26,7 +26,10 @@
#include <image_io/jpeg/jpeg_info_builder.h>
#include <image_io/base/data_segment_data_source.h>
#include <utils/Log.h>
#include "SkColorSpace.h"
#include "SkICC.h"

#include <map>
#include <memory>
#include <sstream>
#include <string>
@@ -93,6 +96,20 @@ int GetCPUCoreCount() {
  return cpuCoreCount;
}

static const map<recoverymap::jpegr_color_gamut, skcms_Matrix3x3> jrGamut_to_skGamut {
    {JPEGR_COLORGAMUT_BT709,     SkNamedGamut::kSRGB},
    {JPEGR_COLORGAMUT_P3,        SkNamedGamut::kDisplayP3},
    {JPEGR_COLORGAMUT_BT2100,    SkNamedGamut::kRec2020},
};

static const map<
        recoverymap::jpegr_transfer_function, skcms_TransferFunction> jrTransFunc_to_skTransFunc {
    {JPEGR_TF_SRGB,        SkNamedTransferFn::kSRGB},
    {JPEGR_TF_LINEAR,      SkNamedTransferFn::kLinear},
    {JPEGR_TF_HLG,         SkNamedTransferFn::kHLG},
    {JPEGR_TF_PQ,          SkNamedTransferFn::kPQ},
};

/*
 * Helper function copies the JPEG image from without EXIF.
 *
@@ -164,11 +181,15 @@ status_t RecoveryMap::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image,
  compressed_map.data = compressed_map_data.get();
  JPEGR_CHECK(compressRecoveryMap(&map, &compressed_map));

  sk_sp<SkData> icc = SkWriteICCProfile(
          jrTransFunc_to_skTransFunc.at(JPEGR_TF_SRGB),
          jrGamut_to_skGamut.at(uncompressed_yuv_420_image.colorGamut));

  JpegEncoder jpeg_encoder;
  // TODO: determine ICC data based on color gamut information
  if (!jpeg_encoder.compressImage(uncompressed_yuv_420_image.data,
                                  uncompressed_yuv_420_image.width,
                                  uncompressed_yuv_420_image.height, quality, nullptr, 0)) {
                                  uncompressed_yuv_420_image.height, quality,
                                  icc.get()->data(), icc.get()->size())) {
    return ERROR_JPEGR_ENCODE_ERROR;
  }
  jpegr_compressed_struct jpeg;
@@ -228,11 +249,15 @@ status_t RecoveryMap::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image,
  compressed_map.data = compressed_map_data.get();
  JPEGR_CHECK(compressRecoveryMap(&map, &compressed_map));

  sk_sp<SkData> icc = SkWriteICCProfile(
          jrTransFunc_to_skTransFunc.at(JPEGR_TF_SRGB),
          jrGamut_to_skGamut.at(uncompressed_yuv_420_image->colorGamut));

  JpegEncoder jpeg_encoder;
  // TODO: determine ICC data based on color gamut information
  if (!jpeg_encoder.compressImage(uncompressed_yuv_420_image->data,
                                  uncompressed_yuv_420_image->width,
                                  uncompressed_yuv_420_image->height, quality, nullptr, 0)) {
                                  uncompressed_yuv_420_image->height, quality,
                                  icc.get()->data(), icc.get()->size())) {
    return ERROR_JPEGR_ENCODE_ERROR;
  }
  jpegr_compressed_struct jpeg;
@@ -574,7 +599,7 @@ status_t RecoveryMap::generateRecoveryMap(jr_uncompressed_ptr uncompressed_yuv_4
#endif
      hdr_white_nits = kPqMaxNits;
      break;
    case JPEGR_TF_UNSPECIFIED:
    default:
      // Should be impossible to hit after input validation.
      return ERROR_JPEGR_INVALID_TRANS_FUNC;
  }
@@ -750,7 +775,7 @@ status_t RecoveryMap::applyRecoveryMap(jr_uncompressed_ptr uncompressed_yuv_420_
        hdrOetf = pqOetf;
#endif
        break;
      case JPEGR_TF_UNSPECIFIED:
      default:
        // Should be impossible to hit after input validation.
        hdrOetf = identityConversion;
    }
+3 −5
Original line number Diff line number Diff line
@@ -30,15 +30,13 @@ cc_test {
    ],
    shared_libs: [
        "libjpeg",
        "libjpegrecoverymap",
        "libimage_io",
        "liblog",
    ],
    static_libs: [
        "libgmock",
        "libgtest",
        "libjpegdecoder",
        "libjpegencoder",
        "libjpegrecoverymap",
    ],
}

@@ -50,10 +48,10 @@ cc_test {
    ],
    shared_libs: [
        "libjpeg",
        "libjpegencoder",
        "liblog",
    ],
    static_libs: [
        "libjpegencoder",
        "libgtest",
    ],
}
@@ -66,10 +64,10 @@ cc_test {
    ],
    shared_libs: [
        "libjpeg",
        "libjpegdecoder",
        "liblog",
    ],
    static_libs: [
        "libjpegdecoder",
        "libgtest",
    ],
}