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

Commit 4ccd3f11 authored by Dichen Zhang's avatar Dichen Zhang Committed by Automerger Merge Worker
Browse files

Merge "JPEG/R: lift the checking criteria for width 8-alignment" into udc-dev...

Merge "JPEG/R: lift the checking criteria for width 8-alignment" into udc-dev am: 5c0b78a0 am: db90666c

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/native/+/22685453



Change-Id: I9831c71b42b38f0af2e4be95956ec7230710e771
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 47c45802 db90666c
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -61,6 +61,11 @@ public:
     */
    size_t getCompressedImageSize();

    /*
     * Process 16 lines of Y and 16 lines of U/V each time.
     * We must pass at least 16 scanlines according to libjpeg documentation.
     */
    static const int kCompressBatchSize = 16;
private:
    // initDestination(), emptyOutputBuffer() and emptyOutputBuffer() are callback functions to be
    // passed into jpeg library.
@@ -82,9 +87,6 @@ private:

    // The block size for encoded jpeg image buffer.
    static const int kBlockSize = 16384;
    // Process 16 lines of Y and 16 lines of U/V each time.
    // We must pass at least 16 scanlines according to libjpeg documentation.
    static const int kCompressBatchSize = 16;

    // The buffer that holds the compressed result.
    std::vector<JOCTET> mResultBuffer;
+0 −5
Original line number Diff line number Diff line
@@ -38,11 +38,6 @@ JpegEncoderHelper::~JpegEncoderHelper() {
bool JpegEncoderHelper::compressImage(const void* image, int width, int height, int quality,
                                   const void* iccBuffer, unsigned int iccSize,
                                   bool isSingleChannel) {
    if (width % 8 != 0 || height % 2 != 0) {
        ALOGE("Image size can not be handled: %dx%d", width, height);
        return false;
    }

    mResultBuffer.clear();
    if (!encode(image, width, height, quality, iccBuffer, iccSize, isSingleChannel)) {
        return false;
+13 −12
Original line number Diff line number Diff line
@@ -66,9 +66,12 @@ static const uint32_t kJpegrVersion = 1;
// Map is quarter res / sixteenth size
static const size_t kMapDimensionScaleFactor = 4;
// JPEG block size.
// JPEG encoding / decoding will require 8 x 8 DCT transform.
// Width must be 8 dividable, and height must be 2 dividable.
static const size_t kJpegBlock = 8;
// JPEG encoding / decoding will require block based DCT transform 16 x 16 for luma,
// and 8 x 8 for chroma.
// Width must be 16 dividable for luma, and 8 dividable for chroma.
// If this criteria is not ficilitated, we will pad zeros based on the required block size.
static const size_t kJpegBlock = JpegEncoderHelper::kCompressBatchSize;
static const size_t kJpegBlockSquare = kJpegBlock * kJpegBlock;
// JPEG compress quality (0 ~ 100) for gain map
static const int kMapCompressQuality = 85;

@@ -92,13 +95,6 @@ status_t JpegR::areInputImagesValid(jr_uncompressed_ptr uncompressed_p010_image,
    return ERROR_JPEGR_INVALID_NULL_PTR;
  }

  if (uncompressed_p010_image->width % kJpegBlock != 0
          || uncompressed_p010_image->height % 2 != 0) {
    ALOGE("Image size can not be handled: %dx%d.",
            uncompressed_p010_image->width, uncompressed_p010_image->height);
    return ERROR_JPEGR_INVALID_INPUT_TYPE;
  }

  if (uncompressed_p010_image->luma_stride != 0
          && uncompressed_p010_image->luma_stride < uncompressed_p010_image->width) {
    ALOGE("Image stride can not be smaller than width, stride=%d, width=%d",
@@ -157,8 +153,13 @@ status_t JpegR::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image,
  metadata.version = kJpegrVersion;

  jpegr_uncompressed_struct uncompressed_yuv_420_image;
  unique_ptr<uint8_t[]> uncompressed_yuv_420_image_data = make_unique<uint8_t[]>(
      uncompressed_p010_image->width * uncompressed_p010_image->height * 3 / 2);
  size_t gain_map_length = uncompressed_p010_image->width * uncompressed_p010_image->height * 3 / 2;
  // Pad a pseudo chroma block (kJpegBlock / 2) x (kJpegBlock / 2)
  // if width is not kJpegBlock aligned.
  if (uncompressed_p010_image->width % kJpegBlock != 0) {
    gain_map_length += kJpegBlockSquare / 4;
  }
  unique_ptr<uint8_t[]> uncompressed_yuv_420_image_data = make_unique<uint8_t[]>(gain_map_length);
  uncompressed_yuv_420_image.data = uncompressed_yuv_420_image_data.get();
  JPEGR_CHECK(toneMap(uncompressed_p010_image, &uncompressed_yuv_420_image));

+34 −24
Original line number Diff line number Diff line
@@ -22,15 +22,15 @@

namespace android::ultrahdr {

#define VALID_IMAGE "/sdcard/Documents/minnie-320x240.yu12"
#define VALID_IMAGE_WIDTH 320
#define VALID_IMAGE_HEIGHT 240
#define ALIGNED_IMAGE "/sdcard/Documents/minnie-320x240.yu12"
#define ALIGNED_IMAGE_WIDTH 320
#define ALIGNED_IMAGE_HEIGHT 240
#define SINGLE_CHANNEL_IMAGE "/sdcard/Documents/minnie-320x240.y"
#define SINGLE_CHANNEL_IMAGE_WIDTH VALID_IMAGE_WIDTH
#define SINGLE_CHANNEL_IMAGE_HEIGHT VALID_IMAGE_HEIGHT
#define INVALID_SIZE_IMAGE "/sdcard/Documents/minnie-318x240.yu12"
#define INVALID_SIZE_IMAGE_WIDTH 318
#define INVALID_SIZE_IMAGE_HEIGHT 240
#define SINGLE_CHANNEL_IMAGE_WIDTH ALIGNED_IMAGE_WIDTH
#define SINGLE_CHANNEL_IMAGE_HEIGHT ALIGNED_IMAGE_HEIGHT
#define UNALIGNED_IMAGE "/sdcard/Documents/minnie-318x240.yu12"
#define UNALIGNED_IMAGE_WIDTH 318
#define UNALIGNED_IMAGE_HEIGHT 240
#define JPEG_QUALITY 90

class JpegEncoderHelperTest : public testing::Test {
@@ -46,7 +46,7 @@ protected:
    virtual void SetUp();
    virtual void TearDown();

    Image mValidImage, mInvalidSizeImage, mSingleChannelImage;
    Image mAlignedImage, mUnalignedImage, mSingleChannelImage;
};

JpegEncoderHelperTest::JpegEncoderHelperTest() {}
@@ -82,16 +82,16 @@ static bool loadFile(const char filename[], JpegEncoderHelperTest::Image* result
}

void JpegEncoderHelperTest::SetUp() {
    if (!loadFile(VALID_IMAGE, &mValidImage)) {
        FAIL() << "Load file " << VALID_IMAGE << " failed";
    if (!loadFile(ALIGNED_IMAGE, &mAlignedImage)) {
        FAIL() << "Load file " << ALIGNED_IMAGE << " failed";
    }
    mValidImage.width = VALID_IMAGE_WIDTH;
    mValidImage.height = VALID_IMAGE_HEIGHT;
    if (!loadFile(INVALID_SIZE_IMAGE, &mInvalidSizeImage)) {
        FAIL() << "Load file " << INVALID_SIZE_IMAGE << " failed";
    mAlignedImage.width = ALIGNED_IMAGE_WIDTH;
    mAlignedImage.height = ALIGNED_IMAGE_HEIGHT;
    if (!loadFile(UNALIGNED_IMAGE, &mUnalignedImage)) {
        FAIL() << "Load file " << UNALIGNED_IMAGE << " failed";
    }
    mInvalidSizeImage.width = INVALID_SIZE_IMAGE_WIDTH;
    mInvalidSizeImage.height = INVALID_SIZE_IMAGE_HEIGHT;
    mUnalignedImage.width = UNALIGNED_IMAGE_WIDTH;
    mUnalignedImage.height = UNALIGNED_IMAGE_HEIGHT;
    if (!loadFile(SINGLE_CHANNEL_IMAGE, &mSingleChannelImage)) {
        FAIL() << "Load file " << SINGLE_CHANNEL_IMAGE << " failed";
    }
@@ -101,20 +101,30 @@ void JpegEncoderHelperTest::SetUp() {

void JpegEncoderHelperTest::TearDown() {}

TEST_F(JpegEncoderHelperTest, validImage) {
TEST_F(JpegEncoderHelperTest, encodeAlignedImage) {
    JpegEncoderHelper encoder;
    EXPECT_TRUE(encoder.compressImage(mValidImage.buffer.get(), mValidImage.width,
                                         mValidImage.height, JPEG_QUALITY, NULL, 0));
    EXPECT_TRUE(encoder.compressImage(mAlignedImage.buffer.get(), mAlignedImage.width,
                                      mAlignedImage.height, JPEG_QUALITY, NULL, 0));
    ASSERT_GT(encoder.getCompressedImageSize(), static_cast<uint32_t>(0));
}

TEST_F(JpegEncoderHelperTest, invalidSizeImage) {
// The width of the "unaligned" image is not 16-aligned, and will fail if encoded directly.
// Should pass with the padding zero method.
TEST_F(JpegEncoderHelperTest, encodeUnalignedImage) {
    JpegEncoderHelper encoder;
    EXPECT_FALSE(encoder.compressImage(mInvalidSizeImage.buffer.get(), mInvalidSizeImage.width,
                                          mInvalidSizeImage.height, JPEG_QUALITY, NULL, 0));
    const size_t paddingZeroLength = JpegEncoderHelper::kCompressBatchSize
            * JpegEncoderHelper::kCompressBatchSize / 4;
    std::unique_ptr<uint8_t[]> imageWithPaddingZeros(
            new uint8_t[UNALIGNED_IMAGE_WIDTH * UNALIGNED_IMAGE_HEIGHT * 3 / 2
            + paddingZeroLength]);
    memcpy(imageWithPaddingZeros.get(), mUnalignedImage.buffer.get(),
            UNALIGNED_IMAGE_WIDTH * UNALIGNED_IMAGE_HEIGHT * 3 / 2);
    EXPECT_TRUE(encoder.compressImage(imageWithPaddingZeros.get(), mUnalignedImage.width,
                                      mUnalignedImage.height, JPEG_QUALITY, NULL, 0));
    ASSERT_GT(encoder.getCompressedImageSize(), static_cast<uint32_t>(0));
}

TEST_F(JpegEncoderHelperTest, singleChannelImage) {
TEST_F(JpegEncoderHelperTest, encodeSingleChannelImage) {
    JpegEncoderHelper encoder;
    EXPECT_TRUE(encoder.compressImage(mSingleChannelImage.buffer.get(), mSingleChannelImage.width,
                                         mSingleChannelImage.height, JPEG_QUALITY, NULL, 0, true));