1*89a0ef05SAndroid Build Coastguard Worker /*
2*89a0ef05SAndroid Build Coastguard Worker * Copyright 2022 The Android Open Source Project
3*89a0ef05SAndroid Build Coastguard Worker *
4*89a0ef05SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*89a0ef05SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*89a0ef05SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*89a0ef05SAndroid Build Coastguard Worker *
8*89a0ef05SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*89a0ef05SAndroid Build Coastguard Worker *
10*89a0ef05SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*89a0ef05SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*89a0ef05SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*89a0ef05SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*89a0ef05SAndroid Build Coastguard Worker * limitations under the License.
15*89a0ef05SAndroid Build Coastguard Worker */
16*89a0ef05SAndroid Build Coastguard Worker
17*89a0ef05SAndroid Build Coastguard Worker #include <gtest/gtest.h>
18*89a0ef05SAndroid Build Coastguard Worker
19*89a0ef05SAndroid Build Coastguard Worker #include <fstream>
20*89a0ef05SAndroid Build Coastguard Worker #include <iostream>
21*89a0ef05SAndroid Build Coastguard Worker
22*89a0ef05SAndroid Build Coastguard Worker #include "ultrahdr/ultrahdrcommon.h"
23*89a0ef05SAndroid Build Coastguard Worker #include "ultrahdr/jpegencoderhelper.h"
24*89a0ef05SAndroid Build Coastguard Worker
25*89a0ef05SAndroid Build Coastguard Worker namespace ultrahdr {
26*89a0ef05SAndroid Build Coastguard Worker
27*89a0ef05SAndroid Build Coastguard Worker #ifdef __ANDROID__
28*89a0ef05SAndroid Build Coastguard Worker #define ALIGNED_IMAGE "/data/local/tmp/minnie-320x240.yu12"
29*89a0ef05SAndroid Build Coastguard Worker #define SINGLE_CHANNEL_IMAGE "/data/local/tmp/minnie-320x240.y"
30*89a0ef05SAndroid Build Coastguard Worker #define UNALIGNED_IMAGE "/data/local/tmp/minnie-318x240.yu12"
31*89a0ef05SAndroid Build Coastguard Worker #define RGB_IMAGE "/data/local/tmp/minnie-320x240.rgb"
32*89a0ef05SAndroid Build Coastguard Worker #else
33*89a0ef05SAndroid Build Coastguard Worker #define ALIGNED_IMAGE "./data/minnie-320x240.yu12"
34*89a0ef05SAndroid Build Coastguard Worker #define SINGLE_CHANNEL_IMAGE "./data/minnie-320x240.y"
35*89a0ef05SAndroid Build Coastguard Worker #define UNALIGNED_IMAGE "./data/minnie-318x240.yu12"
36*89a0ef05SAndroid Build Coastguard Worker #define RGB_IMAGE "./data/minnie-320x240.rgb"
37*89a0ef05SAndroid Build Coastguard Worker #endif
38*89a0ef05SAndroid Build Coastguard Worker #define ALIGNED_IMAGE_WIDTH 320
39*89a0ef05SAndroid Build Coastguard Worker #define ALIGNED_IMAGE_HEIGHT 240
40*89a0ef05SAndroid Build Coastguard Worker #define SINGLE_CHANNEL_IMAGE_WIDTH ALIGNED_IMAGE_WIDTH
41*89a0ef05SAndroid Build Coastguard Worker #define SINGLE_CHANNEL_IMAGE_HEIGHT ALIGNED_IMAGE_HEIGHT
42*89a0ef05SAndroid Build Coastguard Worker #define UNALIGNED_IMAGE_WIDTH 318
43*89a0ef05SAndroid Build Coastguard Worker #define UNALIGNED_IMAGE_HEIGHT 240
44*89a0ef05SAndroid Build Coastguard Worker #define JPEG_QUALITY 90
45*89a0ef05SAndroid Build Coastguard Worker
46*89a0ef05SAndroid Build Coastguard Worker class JpegEncoderHelperTest : public testing::Test {
47*89a0ef05SAndroid Build Coastguard Worker public:
48*89a0ef05SAndroid Build Coastguard Worker struct Image {
49*89a0ef05SAndroid Build Coastguard Worker std::unique_ptr<uint8_t[]> buffer;
50*89a0ef05SAndroid Build Coastguard Worker unsigned int width;
51*89a0ef05SAndroid Build Coastguard Worker unsigned int height;
52*89a0ef05SAndroid Build Coastguard Worker };
53*89a0ef05SAndroid Build Coastguard Worker JpegEncoderHelperTest();
54*89a0ef05SAndroid Build Coastguard Worker ~JpegEncoderHelperTest();
55*89a0ef05SAndroid Build Coastguard Worker
56*89a0ef05SAndroid Build Coastguard Worker protected:
57*89a0ef05SAndroid Build Coastguard Worker virtual void SetUp();
58*89a0ef05SAndroid Build Coastguard Worker virtual void TearDown();
59*89a0ef05SAndroid Build Coastguard Worker
60*89a0ef05SAndroid Build Coastguard Worker Image mAlignedImage, mUnalignedImage, mSingleChannelImage, mRgbImage;
61*89a0ef05SAndroid Build Coastguard Worker };
62*89a0ef05SAndroid Build Coastguard Worker
JpegEncoderHelperTest()63*89a0ef05SAndroid Build Coastguard Worker JpegEncoderHelperTest::JpegEncoderHelperTest() {}
64*89a0ef05SAndroid Build Coastguard Worker
~JpegEncoderHelperTest()65*89a0ef05SAndroid Build Coastguard Worker JpegEncoderHelperTest::~JpegEncoderHelperTest() {}
66*89a0ef05SAndroid Build Coastguard Worker
loadFile(const char filename[],JpegEncoderHelperTest::Image * result)67*89a0ef05SAndroid Build Coastguard Worker static bool loadFile(const char filename[], JpegEncoderHelperTest::Image* result) {
68*89a0ef05SAndroid Build Coastguard Worker std::ifstream ifd(filename, std::ios::binary | std::ios::ate);
69*89a0ef05SAndroid Build Coastguard Worker if (ifd.good()) {
70*89a0ef05SAndroid Build Coastguard Worker int size = ifd.tellg();
71*89a0ef05SAndroid Build Coastguard Worker ifd.seekg(0, std::ios::beg);
72*89a0ef05SAndroid Build Coastguard Worker result->buffer.reset(new uint8_t[size]);
73*89a0ef05SAndroid Build Coastguard Worker ifd.read(reinterpret_cast<char*>(result->buffer.get()), size);
74*89a0ef05SAndroid Build Coastguard Worker ifd.close();
75*89a0ef05SAndroid Build Coastguard Worker return true;
76*89a0ef05SAndroid Build Coastguard Worker }
77*89a0ef05SAndroid Build Coastguard Worker return false;
78*89a0ef05SAndroid Build Coastguard Worker }
79*89a0ef05SAndroid Build Coastguard Worker
SetUp()80*89a0ef05SAndroid Build Coastguard Worker void JpegEncoderHelperTest::SetUp() {
81*89a0ef05SAndroid Build Coastguard Worker if (!loadFile(ALIGNED_IMAGE, &mAlignedImage)) {
82*89a0ef05SAndroid Build Coastguard Worker FAIL() << "Load file " << ALIGNED_IMAGE << " failed";
83*89a0ef05SAndroid Build Coastguard Worker }
84*89a0ef05SAndroid Build Coastguard Worker mAlignedImage.width = ALIGNED_IMAGE_WIDTH;
85*89a0ef05SAndroid Build Coastguard Worker mAlignedImage.height = ALIGNED_IMAGE_HEIGHT;
86*89a0ef05SAndroid Build Coastguard Worker if (!loadFile(UNALIGNED_IMAGE, &mUnalignedImage)) {
87*89a0ef05SAndroid Build Coastguard Worker FAIL() << "Load file " << UNALIGNED_IMAGE << " failed";
88*89a0ef05SAndroid Build Coastguard Worker }
89*89a0ef05SAndroid Build Coastguard Worker mUnalignedImage.width = UNALIGNED_IMAGE_WIDTH;
90*89a0ef05SAndroid Build Coastguard Worker mUnalignedImage.height = UNALIGNED_IMAGE_HEIGHT;
91*89a0ef05SAndroid Build Coastguard Worker if (!loadFile(SINGLE_CHANNEL_IMAGE, &mSingleChannelImage)) {
92*89a0ef05SAndroid Build Coastguard Worker FAIL() << "Load file " << SINGLE_CHANNEL_IMAGE << " failed";
93*89a0ef05SAndroid Build Coastguard Worker }
94*89a0ef05SAndroid Build Coastguard Worker mSingleChannelImage.width = SINGLE_CHANNEL_IMAGE_WIDTH;
95*89a0ef05SAndroid Build Coastguard Worker mSingleChannelImage.height = SINGLE_CHANNEL_IMAGE_HEIGHT;
96*89a0ef05SAndroid Build Coastguard Worker if (!loadFile(RGB_IMAGE, &mRgbImage)) {
97*89a0ef05SAndroid Build Coastguard Worker FAIL() << "Load file " << RGB_IMAGE << " failed";
98*89a0ef05SAndroid Build Coastguard Worker }
99*89a0ef05SAndroid Build Coastguard Worker mRgbImage.width = ALIGNED_IMAGE_WIDTH;
100*89a0ef05SAndroid Build Coastguard Worker mRgbImage.height = ALIGNED_IMAGE_HEIGHT;
101*89a0ef05SAndroid Build Coastguard Worker }
102*89a0ef05SAndroid Build Coastguard Worker
TearDown()103*89a0ef05SAndroid Build Coastguard Worker void JpegEncoderHelperTest::TearDown() {}
104*89a0ef05SAndroid Build Coastguard Worker
TEST_F(JpegEncoderHelperTest,encodeAlignedImage)105*89a0ef05SAndroid Build Coastguard Worker TEST_F(JpegEncoderHelperTest, encodeAlignedImage) {
106*89a0ef05SAndroid Build Coastguard Worker JpegEncoderHelper encoder;
107*89a0ef05SAndroid Build Coastguard Worker const uint8_t* yPlane = mAlignedImage.buffer.get();
108*89a0ef05SAndroid Build Coastguard Worker const uint8_t* uPlane = yPlane + mAlignedImage.width * mAlignedImage.height;
109*89a0ef05SAndroid Build Coastguard Worker const uint8_t* vPlane = uPlane + mAlignedImage.width * mAlignedImage.height / 4;
110*89a0ef05SAndroid Build Coastguard Worker const uint8_t* planes[3]{yPlane, uPlane, vPlane};
111*89a0ef05SAndroid Build Coastguard Worker const unsigned int strides[3]{mAlignedImage.width, mAlignedImage.width / 2,
112*89a0ef05SAndroid Build Coastguard Worker mAlignedImage.width / 2};
113*89a0ef05SAndroid Build Coastguard Worker EXPECT_EQ(encoder
114*89a0ef05SAndroid Build Coastguard Worker .compressImage(planes, strides, mAlignedImage.width, mAlignedImage.height,
115*89a0ef05SAndroid Build Coastguard Worker UHDR_IMG_FMT_12bppYCbCr420, JPEG_QUALITY, NULL, 0)
116*89a0ef05SAndroid Build Coastguard Worker .error_code,
117*89a0ef05SAndroid Build Coastguard Worker UHDR_CODEC_OK);
118*89a0ef05SAndroid Build Coastguard Worker ASSERT_GT(encoder.getCompressedImageSize(), static_cast<uint32_t>(0));
119*89a0ef05SAndroid Build Coastguard Worker }
120*89a0ef05SAndroid Build Coastguard Worker
TEST_F(JpegEncoderHelperTest,encodeUnalignedImage)121*89a0ef05SAndroid Build Coastguard Worker TEST_F(JpegEncoderHelperTest, encodeUnalignedImage) {
122*89a0ef05SAndroid Build Coastguard Worker JpegEncoderHelper encoder;
123*89a0ef05SAndroid Build Coastguard Worker const uint8_t* yPlane = mUnalignedImage.buffer.get();
124*89a0ef05SAndroid Build Coastguard Worker const uint8_t* uPlane = yPlane + mUnalignedImage.width * mUnalignedImage.height;
125*89a0ef05SAndroid Build Coastguard Worker const uint8_t* vPlane = uPlane + mUnalignedImage.width * mUnalignedImage.height / 4;
126*89a0ef05SAndroid Build Coastguard Worker const uint8_t* planes[3]{yPlane, uPlane, vPlane};
127*89a0ef05SAndroid Build Coastguard Worker const unsigned int strides[3]{mUnalignedImage.width, mUnalignedImage.width / 2,
128*89a0ef05SAndroid Build Coastguard Worker mUnalignedImage.width / 2};
129*89a0ef05SAndroid Build Coastguard Worker EXPECT_EQ(encoder
130*89a0ef05SAndroid Build Coastguard Worker .compressImage(planes, strides, mUnalignedImage.width, mUnalignedImage.height,
131*89a0ef05SAndroid Build Coastguard Worker UHDR_IMG_FMT_12bppYCbCr420, JPEG_QUALITY, NULL, 0)
132*89a0ef05SAndroid Build Coastguard Worker .error_code,
133*89a0ef05SAndroid Build Coastguard Worker UHDR_CODEC_OK);
134*89a0ef05SAndroid Build Coastguard Worker ASSERT_GT(encoder.getCompressedImageSize(), static_cast<uint32_t>(0));
135*89a0ef05SAndroid Build Coastguard Worker }
136*89a0ef05SAndroid Build Coastguard Worker
TEST_F(JpegEncoderHelperTest,encodeSingleChannelImage)137*89a0ef05SAndroid Build Coastguard Worker TEST_F(JpegEncoderHelperTest, encodeSingleChannelImage) {
138*89a0ef05SAndroid Build Coastguard Worker JpegEncoderHelper encoder;
139*89a0ef05SAndroid Build Coastguard Worker const uint8_t* yPlane = mSingleChannelImage.buffer.get();
140*89a0ef05SAndroid Build Coastguard Worker const uint8_t* planes[1]{yPlane};
141*89a0ef05SAndroid Build Coastguard Worker const unsigned int strides[1]{mSingleChannelImage.width};
142*89a0ef05SAndroid Build Coastguard Worker EXPECT_EQ(
143*89a0ef05SAndroid Build Coastguard Worker encoder
144*89a0ef05SAndroid Build Coastguard Worker .compressImage(planes, strides, mSingleChannelImage.width, mSingleChannelImage.height,
145*89a0ef05SAndroid Build Coastguard Worker UHDR_IMG_FMT_8bppYCbCr400, JPEG_QUALITY, NULL, 0)
146*89a0ef05SAndroid Build Coastguard Worker .error_code,
147*89a0ef05SAndroid Build Coastguard Worker UHDR_CODEC_OK);
148*89a0ef05SAndroid Build Coastguard Worker ASSERT_GT(encoder.getCompressedImageSize(), static_cast<uint32_t>(0));
149*89a0ef05SAndroid Build Coastguard Worker }
150*89a0ef05SAndroid Build Coastguard Worker
TEST_F(JpegEncoderHelperTest,encodeRGBImage)151*89a0ef05SAndroid Build Coastguard Worker TEST_F(JpegEncoderHelperTest, encodeRGBImage) {
152*89a0ef05SAndroid Build Coastguard Worker JpegEncoderHelper encoder;
153*89a0ef05SAndroid Build Coastguard Worker const uint8_t* rgbPlane = mRgbImage.buffer.get();
154*89a0ef05SAndroid Build Coastguard Worker const uint8_t* planes[1]{rgbPlane};
155*89a0ef05SAndroid Build Coastguard Worker const unsigned int strides[1]{mRgbImage.width};
156*89a0ef05SAndroid Build Coastguard Worker EXPECT_EQ(encoder
157*89a0ef05SAndroid Build Coastguard Worker .compressImage(planes, strides, mRgbImage.width, mRgbImage.height,
158*89a0ef05SAndroid Build Coastguard Worker UHDR_IMG_FMT_24bppRGB888, JPEG_QUALITY, NULL, 0)
159*89a0ef05SAndroid Build Coastguard Worker .error_code,
160*89a0ef05SAndroid Build Coastguard Worker UHDR_CODEC_OK);
161*89a0ef05SAndroid Build Coastguard Worker ASSERT_GT(encoder.getCompressedImageSize(), static_cast<uint32_t>(0));
162*89a0ef05SAndroid Build Coastguard Worker }
163*89a0ef05SAndroid Build Coastguard Worker
164*89a0ef05SAndroid Build Coastguard Worker } // namespace ultrahdr
165