blob: 0f96723189edc1fd0d529efc69cac087af5b1323 [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 Zhang36c1e732022-11-23 01:25:34 +000018#include <fcntl.h>
19#include <fstream>
20#include <gtest/gtest.h>
21#include <utils/Log.h>
22
23#define RAW_P010_IMAGE "/sdcard/Documents/raw_p010_image.p010"
24#define RAW_P010_IMAGE_WIDTH 1280
25#define RAW_P010_IMAGE_HEIGHT 720
26#define JPEG_IMAGE "/sdcard/Documents/jpeg_image.jpg"
27
28#define SAVE_ENCODING_RESULT true
29#define SAVE_DECODING_RESULT true
Dichen Zhang85b37562022-10-11 11:08:28 -070030
Nick Deakin594a4ca2022-11-16 20:57:42 -050031namespace android::recoverymap {
Dichen Zhang85b37562022-10-11 11:08:28 -070032
Nick Deakin594a4ca2022-11-16 20:57:42 -050033class RecoveryMapTest : public testing::Test {
34public:
35 RecoveryMapTest();
36 ~RecoveryMapTest();
37protected:
38 virtual void SetUp();
39 virtual void TearDown();
Dichen Zhang36c1e732022-11-23 01:25:34 +000040
41 struct jpegr_uncompressed_struct mRawP010Image;
42 struct jpegr_compressed_struct mJpegImage;
Nick Deakin594a4ca2022-11-16 20:57:42 -050043};
44
45RecoveryMapTest::RecoveryMapTest() {}
46RecoveryMapTest::~RecoveryMapTest() {}
47
48void RecoveryMapTest::SetUp() {}
Dichen Zhang36c1e732022-11-23 01:25:34 +000049void RecoveryMapTest::TearDown() {
50 free(mRawP010Image.data);
51 free(mJpegImage.data);
52}
53
54static size_t getFileSize(int fd) {
55 struct stat st;
56 if (fstat(fd, &st) < 0) {
57 ALOGW("%s : fstat failed", __func__);
58 return 0;
59 }
60 return st.st_size; // bytes
61}
62
63static bool loadFile(const char filename[], void*& result, int* fileLength) {
64 int fd = open(filename, O_CLOEXEC);
65 if (fd < 0) {
66 return false;
67 }
68 int length = getFileSize(fd);
69 if (length == 0) {
70 close(fd);
71 return false;
72 }
73 if (fileLength != nullptr) {
74 *fileLength = length;
75 }
76 result = malloc(length);
77 if (read(fd, result, length) != static_cast<ssize_t>(length)) {
78 close(fd);
79 return false;
80 }
81 close(fd);
82 return true;
83}
Nick Deakin594a4ca2022-11-16 20:57:42 -050084
85TEST_F(RecoveryMapTest, build) {
86 // Force all of the recovery map lib to be linked by calling all public functions.
87 RecoveryMap recovery_map;
Dichen Zhang636f5242022-12-07 20:25:44 +000088 recovery_map.encodeJPEGR(nullptr, static_cast<jpegr_transfer_function>(0), nullptr, 0, nullptr);
Nick Deakin6bd90432022-11-20 16:26:37 -050089 recovery_map.encodeJPEGR(nullptr, nullptr, static_cast<jpegr_transfer_function>(0),
90 nullptr, 0, nullptr);
91 recovery_map.encodeJPEGR(nullptr, nullptr, nullptr, static_cast<jpegr_transfer_function>(0),
92 nullptr);
93 recovery_map.encodeJPEGR(nullptr, nullptr, static_cast<jpegr_transfer_function>(0), nullptr);
Nick Deakin594a4ca2022-11-16 20:57:42 -050094 recovery_map.decodeJPEGR(nullptr, nullptr, nullptr, false);
95}
96
Dichen Zhang54444382022-12-07 20:57:49 +000097TEST_F(RecoveryMapTest, encodeFromP010ThenDecode) {
98 int ret;
99
100 // Load input files.
101 if (!loadFile(RAW_P010_IMAGE, mRawP010Image.data, nullptr)) {
102 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
103 }
104 mRawP010Image.width = RAW_P010_IMAGE_WIDTH;
105 mRawP010Image.height = RAW_P010_IMAGE_HEIGHT;
106 mRawP010Image.colorGamut = jpegr_color_gamut::JPEGR_COLORGAMUT_BT2100;
107
108 RecoveryMap recoveryMap;
109
110 jpegr_compressed_struct jpegR;
111 jpegR.maxLength = RAW_P010_IMAGE_WIDTH * RAW_P010_IMAGE_HEIGHT * sizeof(uint8_t);
112 jpegR.data = malloc(jpegR.maxLength);
113 ret = recoveryMap.encodeJPEGR(
114 &mRawP010Image, jpegr_transfer_function::JPEGR_TF_HLG, &jpegR, 90, nullptr);
115 if (ret != OK) {
116 FAIL() << "Error code is " << ret;
117 }
118 if (SAVE_ENCODING_RESULT) {
119 // Output image data to file
120 std::string filePath = "/sdcard/Documents/encoded_from_jpeg_input.jpgr";
121 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
122 if (!imageFile.is_open()) {
123 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
124 }
125 imageFile.write((const char*)jpegR.data, jpegR.length);
126 }
127
128 jpegr_uncompressed_struct decodedJpegR;
129 int decodedJpegRSize = RAW_P010_IMAGE_WIDTH * RAW_P010_IMAGE_HEIGHT * 4;
130 decodedJpegR.data = malloc(decodedJpegRSize);
131 ret = recoveryMap.decodeJPEGR(&jpegR, &decodedJpegR);
132 if (ret != OK) {
133 FAIL() << "Error code is " << ret;
134 }
135 if (SAVE_DECODING_RESULT) {
136 // Output image data to file
137 std::string filePath = "/sdcard/Documents/decoded_from_jpeg_input.rgb10";
138 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
139 if (!imageFile.is_open()) {
140 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
141 }
142 imageFile.write((const char*)decodedJpegR.data, decodedJpegRSize);
143 }
144
145 free(jpegR.data);
146 free(decodedJpegR.data);
147}
148
Dichen Zhang36c1e732022-11-23 01:25:34 +0000149TEST_F(RecoveryMapTest, encodeFromJpegThenDecode) {
150 int ret;
151
152 // Load input files.
153 if (!loadFile(RAW_P010_IMAGE, mRawP010Image.data, nullptr)) {
154 FAIL() << "Load file " << RAW_P010_IMAGE << " failed";
155 }
156 mRawP010Image.width = RAW_P010_IMAGE_WIDTH;
157 mRawP010Image.height = RAW_P010_IMAGE_HEIGHT;
158 mRawP010Image.colorGamut = jpegr_color_gamut::JPEGR_COLORGAMUT_BT2100;
159
160 if (!loadFile(JPEG_IMAGE, mJpegImage.data, &mJpegImage.length)) {
161 FAIL() << "Load file " << JPEG_IMAGE << " failed";
162 }
163 mJpegImage.colorGamut = jpegr_color_gamut::JPEGR_COLORGAMUT_BT709;
164
165 RecoveryMap recoveryMap;
166
167 jpegr_compressed_struct jpegR;
168 jpegR.maxLength = RAW_P010_IMAGE_WIDTH * RAW_P010_IMAGE_HEIGHT * sizeof(uint8_t);
169 jpegR.data = malloc(jpegR.maxLength);
170 ret = recoveryMap.encodeJPEGR(
171 &mRawP010Image, &mJpegImage, jpegr_transfer_function::JPEGR_TF_HLG, &jpegR);
172 if (ret != OK) {
173 FAIL() << "Error code is " << ret;
174 }
175 if (SAVE_ENCODING_RESULT) {
176 // Output image data to file
177 std::string filePath = "/sdcard/Documents/encoded_from_jpeg_input.jpgr";
178 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
179 if (!imageFile.is_open()) {
180 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
181 }
182 imageFile.write((const char*)jpegR.data, jpegR.length);
183 }
184
185 jpegr_uncompressed_struct decodedJpegR;
186 int decodedJpegRSize = RAW_P010_IMAGE_WIDTH * RAW_P010_IMAGE_HEIGHT * 4;
187 decodedJpegR.data = malloc(decodedJpegRSize);
188 ret = recoveryMap.decodeJPEGR(&jpegR, &decodedJpegR);
189 if (ret != OK) {
190 FAIL() << "Error code is " << ret;
191 }
192 if (SAVE_DECODING_RESULT) {
193 // Output image data to file
194 std::string filePath = "/sdcard/Documents/decoded_from_jpeg_input.rgb10";
195 std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
196 if (!imageFile.is_open()) {
197 ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
198 }
199 imageFile.write((const char*)decodedJpegR.data, decodedJpegRSize);
200 }
201
202 free(jpegR.data);
203 free(decodedJpegR.data);
204}
205
Nick Deakin594a4ca2022-11-16 20:57:42 -0500206} // namespace android::recoverymap