blob: 6dea27f0a85520e12c8a8c65a1f066fe68717997 [file] [log] [blame]
Dichen Zhang85b37562022-10-11 11:08:28 -07001/*
2 * Copyright 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <jpegrecoverymap/recoverymap.h>
Dichen Zhangdc8452b2022-11-23 17:17:56 +000018#include <jpegrecoverymap/recoverymaputils.h>
Dichen Zhang36c1e732022-11-23 01:25:34 +000019#include <fcntl.h>
20#include <fstream>
21#include <gtest/gtest.h>
22#include <utils/Log.h>
23
24#define RAW_P010_IMAGE "/sdcard/Documents/raw_p010_image.p010"
25#define RAW_P010_IMAGE_WIDTH 1280
26#define RAW_P010_IMAGE_HEIGHT 720
27#define JPEG_IMAGE "/sdcard/Documents/jpeg_image.jpg"
28
29#define SAVE_ENCODING_RESULT true
30#define SAVE_DECODING_RESULT true
Dichen Zhang85b37562022-10-11 11:08:28 -070031
Nick Deakin594a4ca2022-11-16 20:57:42 -050032namespace android::recoverymap {
Dichen Zhang85b37562022-10-11 11:08:28 -070033
Nick Deakin594a4ca2022-11-16 20:57:42 -050034class RecoveryMapTest : public testing::Test {
35public:
36 RecoveryMapTest();
37 ~RecoveryMapTest();
38protected:
39 virtual void SetUp();
40 virtual void TearDown();
Dichen Zhang36c1e732022-11-23 01:25:34 +000041
42 struct jpegr_uncompressed_struct mRawP010Image;
43 struct jpegr_compressed_struct mJpegImage;
Nick Deakin594a4ca2022-11-16 20:57:42 -050044};
45
46RecoveryMapTest::RecoveryMapTest() {}
47RecoveryMapTest::~RecoveryMapTest() {}
48
49void RecoveryMapTest::SetUp() {}
Dichen Zhang36c1e732022-11-23 01:25:34 +000050void RecoveryMapTest::TearDown() {
51 free(mRawP010Image.data);
52 free(mJpegImage.data);
53}
54
55static size_t getFileSize(int fd) {
56 struct stat st;
57 if (fstat(fd, &st) < 0) {
58 ALOGW("%s : fstat failed", __func__);
59 return 0;
60 }
61 return st.st_size; // bytes
62}
63
64static bool loadFile(const char filename[], void*& result, int* fileLength) {
65 int fd = open(filename, O_CLOEXEC);
66 if (fd < 0) {
67 return false;
68 }
69 int length = getFileSize(fd);
70 if (length == 0) {
71 close(fd);
72 return false;
73 }
74 if (fileLength != nullptr) {
75 *fileLength = length;
76 }
77 result = malloc(length);
78 if (read(fd, result, length) != static_cast<ssize_t>(length)) {
79 close(fd);
80 return false;
81 }
82 close(fd);
83 return true;
84}
Nick Deakin594a4ca2022-11-16 20:57:42 -050085
86TEST_F(RecoveryMapTest, build) {
87 // Force all of the recovery map lib to be linked by calling all public functions.
88 RecoveryMap recovery_map;
Dichen Zhang636f5242022-12-07 20:25:44 +000089 recovery_map.encodeJPEGR(nullptr, static_cast<jpegr_transfer_function>(0), nullptr, 0, nullptr);
Nick Deakin6bd90432022-11-20 16:26:37 -050090 recovery_map.encodeJPEGR(nullptr, nullptr, static_cast<jpegr_transfer_function>(0),
91 nullptr, 0, nullptr);
92 recovery_map.encodeJPEGR(nullptr, nullptr, nullptr, static_cast<jpegr_transfer_function>(0),
93 nullptr);
94 recovery_map.encodeJPEGR(nullptr, nullptr, static_cast<jpegr_transfer_function>(0), nullptr);
Nick Deakin594a4ca2022-11-16 20:57:42 -050095 recovery_map.decodeJPEGR(nullptr, nullptr, nullptr, false);
96}
97
Dichen Zhangdc8452b2022-11-23 17:17:56 +000098TEST_F(RecoveryMapTest, writeXmpThenRead) {
99 jpegr_metadata metadata_expected;
100 metadata_expected.transferFunction = JPEGR_TF_HLG;
101 metadata_expected.rangeScalingFactor = 1.25;
102 int length_expected = 1000;
103 std::string xmp = generateXmp(1000, metadata_expected);
104
105 jpegr_metadata metadata_read;
106 EXPECT_TRUE(getMetadataFromXMP(reinterpret_cast<uint8_t*>(xmp[0]), xmp.size(), &metadata_read));
107 ASSERT_EQ(metadata_expected.transferFunction, metadata_read.transferFunction);
108 ASSERT_EQ(metadata_expected.rangeScalingFactor, metadata_read.rangeScalingFactor);
109
110}
Dichen Zhang54444382022-12-07 20:57:49 +0000111TEST_F(RecoveryMapTest, encodeFromP010ThenDecode) {
112 int ret;
113
114 // Load input files.
115 if (!loadFile(RAW_P010_IMAGE, mRawP010Image.data, nullptr)) {
116 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
117 }
118 mRawP010Image.width = RAW_P010_IMAGE_WIDTH;
119 mRawP010Image.height = RAW_P010_IMAGE_HEIGHT;
120 mRawP010Image.colorGamut = jpegr_color_gamut::JPEGR_COLORGAMUT_BT2100;
121
122 RecoveryMap recoveryMap;
123
124 jpegr_compressed_struct jpegR;
125 jpegR.maxLength = RAW_P010_IMAGE_WIDTH * RAW_P010_IMAGE_HEIGHT * sizeof(uint8_t);
126 jpegR.data = malloc(jpegR.maxLength);
127 ret = recoveryMap.encodeJPEGR(
128 &mRawP010Image, jpegr_transfer_function::JPEGR_TF_HLG, &jpegR, 90, nullptr);
129 if (ret != OK) {
130 FAIL() << "Error code is " << ret;
131 }
132 if (SAVE_ENCODING_RESULT) {
133 // Output image data to file
134 std::string filePath = "/sdcard/Documents/encoded_from_jpeg_input.jpgr";
135 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
136 if (!imageFile.is_open()) {
137 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
138 }
139 imageFile.write((const char*)jpegR.data, jpegR.length);
140 }
141
142 jpegr_uncompressed_struct decodedJpegR;
143 int decodedJpegRSize = RAW_P010_IMAGE_WIDTH * RAW_P010_IMAGE_HEIGHT * 4;
144 decodedJpegR.data = malloc(decodedJpegRSize);
145 ret = recoveryMap.decodeJPEGR(&jpegR, &decodedJpegR);
146 if (ret != OK) {
147 FAIL() << "Error code is " << ret;
148 }
149 if (SAVE_DECODING_RESULT) {
150 // Output image data to file
151 std::string filePath = "/sdcard/Documents/decoded_from_jpeg_input.rgb10";
152 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
153 if (!imageFile.is_open()) {
154 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
155 }
156 imageFile.write((const char*)decodedJpegR.data, decodedJpegRSize);
157 }
158
159 free(jpegR.data);
160 free(decodedJpegR.data);
161}
162
Dichen Zhang36c1e732022-11-23 01:25:34 +0000163TEST_F(RecoveryMapTest, encodeFromJpegThenDecode) {
164 int ret;
165
166 // Load input files.
167 if (!loadFile(RAW_P010_IMAGE, mRawP010Image.data, nullptr)) {
168 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
169 }
170 mRawP010Image.width = RAW_P010_IMAGE_WIDTH;
171 mRawP010Image.height = RAW_P010_IMAGE_HEIGHT;
172 mRawP010Image.colorGamut = jpegr_color_gamut::JPEGR_COLORGAMUT_BT2100;
173
174 if (!loadFile(JPEG_IMAGE, mJpegImage.data, &mJpegImage.length)) {
175 FAIL() << "Load file " << JPEG_IMAGE << " failed";
176 }
177 mJpegImage.colorGamut = jpegr_color_gamut::JPEGR_COLORGAMUT_BT709;
178
179 RecoveryMap recoveryMap;
180
181 jpegr_compressed_struct jpegR;
182 jpegR.maxLength = RAW_P010_IMAGE_WIDTH * RAW_P010_IMAGE_HEIGHT * sizeof(uint8_t);
183 jpegR.data = malloc(jpegR.maxLength);
184 ret = recoveryMap.encodeJPEGR(
185 &mRawP010Image, &mJpegImage, jpegr_transfer_function::JPEGR_TF_HLG, &jpegR);
186 if (ret != OK) {
187 FAIL() << "Error code is " << ret;
188 }
189 if (SAVE_ENCODING_RESULT) {
190 // Output image data to file
191 std::string filePath = "/sdcard/Documents/encoded_from_jpeg_input.jpgr";
192 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
193 if (!imageFile.is_open()) {
194 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
195 }
196 imageFile.write((const char*)jpegR.data, jpegR.length);
197 }
198
199 jpegr_uncompressed_struct decodedJpegR;
200 int decodedJpegRSize = RAW_P010_IMAGE_WIDTH * RAW_P010_IMAGE_HEIGHT * 4;
201 decodedJpegR.data = malloc(decodedJpegRSize);
202 ret = recoveryMap.decodeJPEGR(&jpegR, &decodedJpegR);
203 if (ret != OK) {
204 FAIL() << "Error code is " << ret;
205 }
206 if (SAVE_DECODING_RESULT) {
207 // Output image data to file
208 std::string filePath = "/sdcard/Documents/decoded_from_jpeg_input.rgb10";
209 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
210 if (!imageFile.is_open()) {
211 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
212 }
213 imageFile.write((const char*)decodedJpegR.data, decodedJpegRSize);
214 }
215
216 free(jpegR.data);
217 free(decodedJpegR.data);
218}
219
Nick Deakin594a4ca2022-11-16 20:57:42 -0500220} // namespace android::recoverymap