xref: /aosp_15_r20/external/libultrahdr/tests/editorhelper_test.cpp (revision 89a0ef05262152531a00a15832a2d3b1e3990773)
1 /*
2  * Copyright 2024 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 <gtest/gtest.h>
18 
19 #include <fstream>
20 #include <iostream>
21 
22 #include "ultrahdr/editorhelper.h"
23 
24 // #define DUMP_OUTPUT
25 
26 #ifdef __ANDROID__
27 #define INPUT_IMAGE "/data/local/tmp/raw_p010_image.p010"
28 #else
29 #define INPUT_IMAGE "./data/raw_p010_image.p010"
30 #endif
31 
32 #define OUTPUT_P010_IMAGE "output.p010"
33 #define OUTPUT_YUV_IMAGE "output.yuv"
34 #define OUTPUT_RGBA_IMAGE "output.rgb"
35 
36 #ifdef DUMP_OUTPUT
writeFile(std::string prefixName,uhdr_raw_image_t * img)37 static bool writeFile(std::string prefixName, uhdr_raw_image_t* img) {
38   char filename[50];
39 
40   if (img->fmt == UHDR_IMG_FMT_24bppYCbCrP010) {
41     snprintf(filename, sizeof filename, "%s_%d_%s", prefixName.c_str(), img->fmt,
42              OUTPUT_P010_IMAGE);
43   } else if (img->fmt == UHDR_IMG_FMT_12bppYCbCr420 || img->fmt == UHDR_IMG_FMT_8bppYCbCr400) {
44     snprintf(filename, sizeof filename, "%s_%d_%s", prefixName.c_str(), img->fmt, OUTPUT_YUV_IMAGE);
45   } else if (img->fmt == UHDR_IMG_FMT_32bppRGBA1010102 || img->fmt == UHDR_IMG_FMT_32bppRGBA8888 ||
46              img->fmt == UHDR_IMG_FMT_64bppRGBAHalfFloat) {
47     snprintf(filename, sizeof filename, "%s_%d_%s", prefixName.c_str(), img->fmt,
48              OUTPUT_RGBA_IMAGE);
49   } else {
50     return false;
51   }
52 
53   std::ofstream ofd(filename, std::ios::binary);
54   if (ofd.is_open()) {
55     int bpp = 1;
56 
57     if (img->fmt == UHDR_IMG_FMT_24bppYCbCrP010) {
58       bpp = 2;
59     } else if (img->fmt == UHDR_IMG_FMT_32bppRGBA8888 ||
60                img->fmt == UHDR_IMG_FMT_32bppRGBA1010102) {
61       bpp = 4;
62     } else if (img->fmt == UHDR_IMG_FMT_64bppRGBAHalfFloat) {
63       bpp = 8;
64     }
65 
66     const char* data = static_cast<char*>(img->planes[UHDR_PLANE_Y]);
67     size_t stride = img->stride[UHDR_PLANE_Y] * bpp;
68     size_t length = img->w * bpp;
69     for (unsigned i = 0; i < img->h; i++, data += stride) {
70       ofd.write(data, length);
71     }
72 
73     if (img->fmt == UHDR_IMG_FMT_24bppYCbCrP010) {
74       data = static_cast<char*>(img->planes[UHDR_PLANE_UV]);
75       stride = img->stride[UHDR_PLANE_UV] * bpp;
76       length = img->w * bpp;
77       for (unsigned i = 0; i < img->h / 2; i++, data += stride) {
78         ofd.write(data, length);
79       }
80     } else if (img->fmt == UHDR_IMG_FMT_12bppYCbCr420) {
81       data = static_cast<char*>(img->planes[UHDR_PLANE_U]);
82       stride = img->stride[UHDR_PLANE_U] * bpp;
83       length = (img->w / 2) * bpp;
84       for (unsigned i = 0; i < img->h / 2; i++, data += stride) {
85         ofd.write(data, length);
86       }
87       data = static_cast<char*>(img->planes[UHDR_PLANE_V]);
88       stride = img->stride[UHDR_PLANE_V] * bpp;
89       length = (img->w / 2) * bpp;
90       for (unsigned i = 0; i < img->h / 2; i++, data += stride) {
91         ofd.write(data, length);
92       }
93     }
94     return true;
95   }
96   std::cerr << "unable to write to file : " << filename << std::endl;
97   return false;
98 }
99 #endif
100 
101 namespace ultrahdr {
102 
loadFile(const char * filename,uhdr_raw_image_t * handle)103 static bool loadFile(const char* filename, uhdr_raw_image_t* handle) {
104   std::ifstream ifd(filename, std::ios::binary);
105   if (ifd.good()) {
106     if (handle->fmt == UHDR_IMG_FMT_24bppYCbCrP010) {
107       const int bpp = 2;
108       ifd.read(static_cast<char*>(handle->planes[UHDR_PLANE_Y]), handle->w * handle->h * bpp);
109       ifd.read(static_cast<char*>(handle->planes[UHDR_PLANE_UV]),
110                (handle->w / 2) * (handle->h / 2) * bpp * 2);
111       return true;
112     } else if (handle->fmt == UHDR_IMG_FMT_12bppYCbCr420) {
113       ifd.read(static_cast<char*>(handle->planes[UHDR_PLANE_Y]), handle->w * handle->h);
114       ifd.read(static_cast<char*>(handle->planes[UHDR_PLANE_U]), (handle->w / 2) * (handle->h / 2));
115       ifd.read(static_cast<char*>(handle->planes[UHDR_PLANE_V]), (handle->w / 2) * (handle->h / 2));
116       return true;
117     } else if (handle->fmt == UHDR_IMG_FMT_32bppRGBA8888 ||
118                handle->fmt == UHDR_IMG_FMT_64bppRGBAHalfFloat ||
119                handle->fmt == UHDR_IMG_FMT_32bppRGBA1010102) {
120       int bpp = handle->fmt == UHDR_IMG_FMT_64bppRGBAHalfFloat ? 8 : 4;
121       ifd.read(static_cast<char*>(handle->planes[UHDR_PLANE_PACKED]), handle->w * handle->h * bpp);
122       return true;
123     } else if (handle->fmt == UHDR_IMG_FMT_8bppYCbCr400) {
124       ifd.read(static_cast<char*>(handle->planes[UHDR_PLANE_Y]), handle->w * handle->h);
125       return true;
126     }
127     return false;
128   }
129   std::cerr << "unable to open file : " << filename << std::endl;
130   return false;
131 }
132 
initImageHandle(uhdr_raw_image_t * handle,int width,int height,uhdr_img_fmt_t format)133 void initImageHandle(uhdr_raw_image_t* handle, int width, int height, uhdr_img_fmt_t format) {
134   handle->fmt = format;
135   handle->cg = UHDR_CG_DISPLAY_P3;
136   handle->ct = UHDR_CT_SRGB;
137   handle->range = UHDR_CR_UNSPECIFIED;
138   handle->w = width;
139   handle->h = height;
140   if (handle->fmt == UHDR_IMG_FMT_24bppYCbCrP010) {
141     handle->planes[UHDR_PLANE_Y] = malloc(width * height * 2);
142     handle->planes[UHDR_PLANE_UV] = malloc((width / 2) * (height / 2) * 2 * 2);
143     handle->planes[UHDR_PLANE_V] = nullptr;
144     handle->stride[UHDR_PLANE_Y] = width;
145     handle->stride[UHDR_PLANE_UV] = width;
146     handle->stride[UHDR_PLANE_V] = 0;
147   } else if (handle->fmt == UHDR_IMG_FMT_12bppYCbCr420) {
148     handle->planes[UHDR_PLANE_Y] = malloc(width * height);
149     handle->planes[UHDR_PLANE_U] = malloc((width / 2) * (height / 2));
150     handle->planes[UHDR_PLANE_V] = malloc((width / 2) * (height / 2));
151     handle->stride[UHDR_PLANE_Y] = width;
152     handle->stride[UHDR_PLANE_U] = width / 2;
153     handle->stride[UHDR_PLANE_V] = width / 2;
154   } else if (handle->fmt == UHDR_IMG_FMT_32bppRGBA8888 ||
155              handle->fmt == UHDR_IMG_FMT_64bppRGBAHalfFloat ||
156              handle->fmt == UHDR_IMG_FMT_32bppRGBA1010102) {
157     int bpp = handle->fmt == UHDR_IMG_FMT_64bppRGBAHalfFloat ? 8 : 4;
158     handle->planes[UHDR_PLANE_PACKED] = malloc(width * height * bpp);
159     handle->planes[UHDR_PLANE_U] = nullptr;
160     handle->planes[UHDR_PLANE_V] = nullptr;
161     handle->stride[UHDR_PLANE_PACKED] = width;
162     handle->stride[UHDR_PLANE_U] = 0;
163     handle->stride[UHDR_PLANE_V] = 0;
164   } else if (handle->fmt == UHDR_IMG_FMT_8bppYCbCr400) {
165     handle->planes[UHDR_PLANE_Y] = malloc(width * height);
166     handle->planes[UHDR_PLANE_U] = nullptr;
167     handle->planes[UHDR_PLANE_V] = nullptr;
168     handle->stride[UHDR_PLANE_Y] = width;
169     handle->stride[UHDR_PLANE_U] = 0;
170     handle->stride[UHDR_PLANE_V] = 0;
171   }
172 }
173 
compare_planes(void * ref_plane,void * test_plane,int ref_stride,int test_stride,int width,int height,int bpp)174 void compare_planes(void* ref_plane, void* test_plane, int ref_stride, int test_stride, int width,
175                     int height, int bpp) {
176   uint8_t* ref = (uint8_t*)ref_plane;
177   uint8_t* test = (uint8_t*)test_plane;
178   const size_t length = width * bpp;
179 
180   for (int i = 0; i < height; i++, ref += (ref_stride * bpp), test += (test_stride * bpp)) {
181     ASSERT_EQ(0, memcmp(ref, test, length));
182   }
183 }
184 
compareImg(uhdr_raw_image_t * ref,uhdr_raw_image_t * test)185 void compareImg(uhdr_raw_image_t* ref, uhdr_raw_image_t* test) {
186   ASSERT_EQ(ref->fmt, test->fmt);
187   ASSERT_EQ(ref->cg, test->cg);
188   ASSERT_EQ(ref->ct, test->ct);
189   ASSERT_EQ(ref->range, test->range);
190   ASSERT_EQ(ref->w, test->w);
191   ASSERT_EQ(ref->h, test->h);
192   int bpp = 1;
193   if (ref->fmt == UHDR_IMG_FMT_24bppYCbCrP010) {
194     bpp = 2;
195     compare_planes(ref->planes[UHDR_PLANE_Y], test->planes[UHDR_PLANE_Y], ref->stride[UHDR_PLANE_Y],
196                    test->stride[UHDR_PLANE_Y], ref->w, ref->h, bpp);
197     compare_planes(ref->planes[UHDR_PLANE_UV], test->planes[UHDR_PLANE_UV],
198                    ref->stride[UHDR_PLANE_UV], test->stride[UHDR_PLANE_UV], ref->w, ref->h / 2,
199                    bpp);
200   } else if (ref->fmt == UHDR_IMG_FMT_12bppYCbCr420) {
201     compare_planes(ref->planes[UHDR_PLANE_Y], test->planes[UHDR_PLANE_Y], ref->stride[UHDR_PLANE_Y],
202                    test->stride[UHDR_PLANE_Y], ref->w, ref->h, bpp);
203     compare_planes(ref->planes[UHDR_PLANE_U], test->planes[UHDR_PLANE_U], ref->stride[UHDR_PLANE_U],
204                    test->stride[UHDR_PLANE_U], ref->w / 2, ref->h / 2, bpp);
205     compare_planes(ref->planes[UHDR_PLANE_V], test->planes[UHDR_PLANE_V], ref->stride[UHDR_PLANE_V],
206                    test->stride[UHDR_PLANE_V], ref->w / 2, ref->h / 2, bpp);
207   } else if (ref->fmt == UHDR_IMG_FMT_32bppRGBA8888 || ref->fmt == UHDR_IMG_FMT_32bppRGBA1010102 ||
208              ref->fmt == UHDR_IMG_FMT_64bppRGBAHalfFloat) {
209     bpp = ref->fmt == UHDR_IMG_FMT_64bppRGBAHalfFloat ? 8 : 4;
210     compare_planes(ref->planes[UHDR_PLANE_PACKED], test->planes[UHDR_PLANE_PACKED],
211                    ref->stride[UHDR_PLANE_PACKED], test->stride[UHDR_PLANE_PACKED], ref->w, ref->h,
212                    bpp);
213   } else if (ref->fmt == UHDR_IMG_FMT_8bppYCbCr400) {
214     compare_planes(ref->planes[UHDR_PLANE_Y], test->planes[UHDR_PLANE_Y], ref->stride[UHDR_PLANE_Y],
215                    test->stride[UHDR_PLANE_Y], ref->w, ref->h, bpp);
216   }
217 }
218 
219 class EditorHelperTest
220     : public ::testing::TestWithParam<std::tuple<std::string, int, int, uhdr_img_fmt_t>> {
221  public:
EditorHelperTest()222   EditorHelperTest()
223       : filename(std::get<0>(GetParam())),
224         width(std::get<1>(GetParam())),
225         height(std::get<2>(GetParam())),
226         fmt(std::get<3>(GetParam())) {
227 #ifdef UHDR_ENABLE_GLES
228     gl_ctxt = new uhdr_opengl_ctxt();
229     opengl_ctxt = static_cast<uhdr_opengl_ctxt*>(gl_ctxt);
230     opengl_ctxt->init_opengl_ctxt();
231     if (opengl_ctxt->mErrorStatus.error_code != UHDR_CODEC_OK) {
232       opengl_ctxt->delete_opengl_ctxt();
233       delete opengl_ctxt;
234       gl_ctxt = nullptr;
235     }
236 #endif
237   };
238 
~EditorHelperTest()239   ~EditorHelperTest() {
240     int count = sizeof img_a.planes / sizeof img_a.planes[0];
241     for (int i = 0; i < count; i++) {
242       if (img_a.planes[i]) {
243         free(img_a.planes[i]);
244         img_a.planes[i] = nullptr;
245       }
246     }
247 #ifdef UHDR_ENABLE_GLES
248     if (gl_ctxt) {
249       uhdr_opengl_ctxt* opengl_ctxt = static_cast<uhdr_opengl_ctxt*>(gl_ctxt);
250       opengl_ctxt->delete_opengl_ctxt();
251       delete opengl_ctxt;
252     }
253     if (Texture) glDeleteTextures(1, &Texture);
254 #endif
255   }
256 
257   std::string filename;
258   int width;
259   int height;
260   uhdr_img_fmt_t fmt;
261   uhdr_raw_image_t img_a{};
262   void* gl_ctxt = nullptr;
263   void* texture = nullptr;
264 #ifdef UHDR_ENABLE_GLES
265   GLuint Texture = 0;
266   uhdr_opengl_ctxt* opengl_ctxt = nullptr;
267 #endif
268 };
269 
TEST_P(EditorHelperTest,Rotate)270 TEST_P(EditorHelperTest, Rotate) {
271   initImageHandle(&img_a, width, height, fmt);
272   ASSERT_TRUE(loadFile(filename.c_str(), &img_a)) << "unable to load file " << filename;
273   ultrahdr::uhdr_rotate_effect_t r90(90), r180(180), r270(270);
274 #ifdef UHDR_ENABLE_GLES
275   if (gl_ctxt != nullptr) {
276     Texture = opengl_ctxt->create_texture(img_a.fmt, img_a.w, img_a.h, img_a.planes[0]);
277     texture = static_cast<void*>(&Texture);
278   }
279 #endif
280   auto dst = apply_rotate(&r90, &img_a, gl_ctxt, texture);
281   dst = apply_rotate(&r90, dst.get(), gl_ctxt, texture);
282   dst = apply_rotate(&r180, dst.get(), gl_ctxt, texture);
283   dst = apply_rotate(&r270, dst.get(), gl_ctxt, texture);
284   dst = apply_rotate(&r90, dst.get(), gl_ctxt, texture);
285   dst = apply_rotate(&r90, dst.get(), gl_ctxt, texture);
286   dst = apply_rotate(&r270, dst.get(), gl_ctxt, texture);
287 #ifdef UHDR_ENABLE_GLES
288   if (gl_ctxt != nullptr) {
289     opengl_ctxt->read_texture(static_cast<GLuint*>(texture), dst->fmt, dst->w, dst->h,
290                               dst->planes[0]);
291   }
292 #endif
293   ASSERT_NO_FATAL_FAILURE(compareImg(&img_a, dst.get()))
294       << "failed for resolution " << width << " x " << height << " format: " << fmt;
295 }
296 
TEST_P(EditorHelperTest,Mirror)297 TEST_P(EditorHelperTest, Mirror) {
298   initImageHandle(&img_a, width, height, fmt);
299   ASSERT_TRUE(loadFile(filename.c_str(), &img_a)) << "unable to load file " << filename;
300   ultrahdr::uhdr_mirror_effect_t mhorz(UHDR_MIRROR_HORIZONTAL), mvert(UHDR_MIRROR_VERTICAL);
301 #ifdef UHDR_ENABLE_GLES
302   if (gl_ctxt != nullptr) {
303     Texture = opengl_ctxt->create_texture(img_a.fmt, img_a.w, img_a.h, img_a.planes[0]);
304     texture = static_cast<void*>(&Texture);
305   }
306 #endif
307   auto dst = apply_mirror(&mhorz, &img_a, gl_ctxt, texture);
308   dst = apply_mirror(&mvert, dst.get(), gl_ctxt, texture);
309   dst = apply_mirror(&mhorz, dst.get(), gl_ctxt, texture);
310   dst = apply_mirror(&mvert, dst.get(), gl_ctxt, texture);
311 #ifdef UHDR_ENABLE_GLES
312   if (gl_ctxt != nullptr) {
313     opengl_ctxt->read_texture(static_cast<GLuint*>(texture), dst->fmt, dst->w, dst->h,
314                               dst->planes[0]);
315   }
316 #endif
317   ASSERT_NO_FATAL_FAILURE(compareImg(&img_a, dst.get()))
318       << "failed for resolution " << width << " x " << height << " format: " << fmt;
319 }
320 
TEST_P(EditorHelperTest,Crop)321 TEST_P(EditorHelperTest, Crop) {
322   const int left = 16;
323   const int top = 16;
324   const int crop_wd = 32;
325   const int crop_ht = 32;
326 
327   if (width < (left + crop_wd) || height <= (top + crop_ht)) {
328     GTEST_SKIP() << "Test skipped as crop attributes are too large for resolution " +
329                         std::to_string(width) + " x " + std::to_string(height) +
330                         " format: " + std::to_string(fmt);
331   }
332   std::string msg = "failed for resolution " + std::to_string(width) + " x " +
333                     std::to_string(height) + " format: " + std::to_string(fmt);
334   initImageHandle(&img_a, width, height, fmt);
335   ASSERT_TRUE(loadFile(filename.c_str(), &img_a)) << "unable to load file " << filename;
336   ultrahdr::uhdr_crop_effect_t crop(left, left + crop_wd, top, top + crop_ht);
337 #ifdef UHDR_ENABLE_GLES
338   if (gl_ctxt != nullptr) {
339     Texture = opengl_ctxt->create_texture(img_a.fmt, img_a.w, img_a.h, img_a.planes[0]);
340     texture = static_cast<void*>(&Texture);
341   }
342 #endif
343   auto dst = apply_crop(&crop, &img_a, left, top, crop_wd, crop_ht, gl_ctxt, texture);
344 #ifdef UHDR_ENABLE_GLES
345   if (gl_ctxt != nullptr) {
346     opengl_ctxt->read_texture(static_cast<GLuint*>(texture), dst->fmt, dst->w, dst->h,
347                               dst->planes[0]);
348   }
349 #endif
350   ASSERT_EQ(img_a.fmt, dst->fmt) << msg;
351   ASSERT_EQ(img_a.cg, dst->cg) << msg;
352   ASSERT_EQ(img_a.ct, dst->ct) << msg;
353   ASSERT_EQ(img_a.range, dst->range) << msg;
354   ASSERT_EQ(dst->w, crop_wd) << msg;
355   ASSERT_EQ(dst->h, crop_ht) << msg;
356 #ifdef DUMP_OUTPUT
357   if (!writeFile("cropped", dst.get())) {
358     std::cerr << "unable to write output file" << std::endl;
359   }
360 #endif
361 }
362 
TEST_P(EditorHelperTest,Resize)363 TEST_P(EditorHelperTest, Resize) {
364   if ((fmt == UHDR_IMG_FMT_12bppYCbCr420 || UHDR_IMG_FMT_24bppYCbCrP010) &&
365       (((width / 2) % 2 != 0) || ((height / 2) % 2 != 0))) {
366     GTEST_SKIP() << "Test skipped for resolution " + std::to_string(width) + " x " +
367                         std::to_string(height) + " format: " + std::to_string(fmt);
368   }
369   std::string msg = "failed for resolution " + std::to_string(width) + " x " +
370                     std::to_string(height) + " format: " + std::to_string(fmt);
371   initImageHandle(&img_a, width, height, fmt);
372   ASSERT_TRUE(loadFile(filename.c_str(), &img_a)) << "unable to load file " << filename;
373   ultrahdr::uhdr_resize_effect_t resize(width / 2, height / 2);
374 #ifdef UHDR_ENABLE_GLES
375   if (gl_ctxt != nullptr) {
376     Texture = opengl_ctxt->create_texture(img_a.fmt, img_a.w, img_a.h, img_a.planes[0]);
377     texture = static_cast<void*>(&Texture);
378   }
379 #endif
380   auto dst = apply_resize(&resize, &img_a, width / 2, height / 2, gl_ctxt, texture);
381 #ifdef UHDR_ENABLE_GLES
382   if (gl_ctxt != nullptr) {
383     opengl_ctxt->read_texture(static_cast<GLuint*>(texture), dst->fmt, dst->w, dst->h,
384                               dst->planes[0]);
385   }
386 #endif
387   ASSERT_EQ(img_a.fmt, dst->fmt) << msg;
388   ASSERT_EQ(img_a.cg, dst->cg) << msg;
389   ASSERT_EQ(img_a.ct, dst->ct) << msg;
390   ASSERT_EQ(img_a.range, dst->range) << msg;
391   ASSERT_EQ(dst->w, width / 2) << msg;
392   ASSERT_EQ(dst->h, height / 2) << msg;
393 #ifdef DUMP_OUTPUT
394   if (!writeFile("resize", dst.get())) {
395     std::cerr << "unable to write output file" << std::endl;
396   }
397 #endif
398 }
399 
TEST_P(EditorHelperTest,MultipleEffects)400 TEST_P(EditorHelperTest, MultipleEffects) {
401   std::string msg = "failed for resolution " + std::to_string(width) + " x " +
402                     std::to_string(height) + " format: " + std::to_string(fmt);
403   initImageHandle(&img_a, width, height, fmt);
404   ASSERT_TRUE(loadFile(filename.c_str(), &img_a)) << "unable to load file " << filename;
405   ultrahdr::uhdr_rotate_effect_t r90(90), r180(180), r270(270);
406   ultrahdr::uhdr_mirror_effect_t mhorz(UHDR_MIRROR_HORIZONTAL), mvert(UHDR_MIRROR_VERTICAL);
407   ultrahdr::uhdr_resize_effect_t resize(width / 2, height / 2);
408 #ifdef UHDR_ENABLE_GLES
409   if (gl_ctxt != nullptr) {
410     Texture = opengl_ctxt->create_texture(img_a.fmt, img_a.w, img_a.h, img_a.planes[0]);
411     texture = static_cast<void*>(&Texture);
412   }
413 #endif
414   auto dst = apply_mirror(&mhorz, &img_a, gl_ctxt, texture);
415   dst = apply_rotate(&r180, dst.get(), gl_ctxt, texture);
416   dst = apply_mirror(&mhorz, dst.get(), gl_ctxt, texture);
417   dst = apply_rotate(&r180, dst.get(), gl_ctxt, texture);
418 #ifdef UHDR_ENABLE_GLES
419   if (gl_ctxt != nullptr) {
420     opengl_ctxt->read_texture(static_cast<GLuint*>(texture), dst->fmt, dst->w, dst->h,
421                               dst->planes[0]);
422   }
423 #endif
424   ASSERT_NO_FATAL_FAILURE(compareImg(&img_a, dst.get())) << msg;
425 
426   dst = apply_mirror(&mhorz, dst.get(), gl_ctxt, texture);
427   dst = apply_rotate(&r90, dst.get(), gl_ctxt, texture);
428   dst = apply_rotate(&r90, dst.get(), gl_ctxt, texture);
429   dst = apply_mirror(&mvert, dst.get(), gl_ctxt, texture);
430 #ifdef UHDR_ENABLE_GLES
431   if (gl_ctxt != nullptr) {
432     opengl_ctxt->read_texture(static_cast<GLuint*>(texture), dst->fmt, dst->w, dst->h,
433                               dst->planes[0]);
434   }
435 #endif
436   ASSERT_NO_FATAL_FAILURE(compareImg(&img_a, dst.get())) << msg;
437 
438   dst = apply_rotate(&r270, dst.get(), gl_ctxt, texture);
439   dst = apply_mirror(&mvert, dst.get(), gl_ctxt, texture);
440   dst = apply_rotate(&r90, dst.get(), gl_ctxt, texture);
441   dst = apply_mirror(&mhorz, dst.get(), gl_ctxt, texture);
442 #ifdef UHDR_ENABLE_GLES
443   if (gl_ctxt != nullptr) {
444     opengl_ctxt->read_texture(static_cast<GLuint*>(texture), dst->fmt, dst->w, dst->h,
445                               dst->planes[0]);
446   }
447 #endif
448   ASSERT_NO_FATAL_FAILURE(compareImg(&img_a, dst.get())) << msg;
449 
450   dst = apply_resize(&resize, dst.get(), width * 2, height * 2, gl_ctxt, texture);
451 #ifdef UHDR_ENABLE_GLES
452   if (gl_ctxt != nullptr) {
453     opengl_ctxt->read_texture(static_cast<GLuint*>(texture), dst->fmt, dst->w, dst->h,
454                               dst->planes[0]);
455   }
456 #endif
457   ASSERT_EQ(img_a.fmt, dst->fmt) << msg;
458   ASSERT_EQ(img_a.cg, dst->cg) << msg;
459   ASSERT_EQ(img_a.ct, dst->ct) << msg;
460   ASSERT_EQ(img_a.range, dst->range) << msg;
461   ASSERT_EQ(dst->w, width * 2) << msg;
462   ASSERT_EQ(dst->h, height * 2) << msg;
463 
464   const int left = 16;
465   const int top = 16;
466   const int crop_wd = 32;
467   const int crop_ht = 32;
468   if (dst->w < (left + crop_wd) || dst->h <= (top + crop_ht)) {
469     GTEST_SKIP() << "Test skipped as crop attributes are too large for resolution " +
470                         std::to_string(dst->w) + " x " + std::to_string(dst->h) +
471                         " format: " + std::to_string(fmt);
472   }
473   ultrahdr::uhdr_crop_effect_t crop(left, left + crop_wd, top, top + crop_ht);
474   dst = apply_crop(&crop, dst.get(), left, top, crop_wd, crop_ht, gl_ctxt, texture);
475 #ifdef UHDR_ENABLE_GLES
476   if (gl_ctxt != nullptr) {
477     opengl_ctxt->read_texture(static_cast<GLuint*>(texture), dst->fmt, dst->w, dst->h,
478                               dst->planes[0]);
479   }
480 #endif
481   ASSERT_EQ(img_a.fmt, dst->fmt) << msg;
482   ASSERT_EQ(img_a.cg, dst->cg) << msg;
483   ASSERT_EQ(img_a.ct, dst->ct) << msg;
484   ASSERT_EQ(img_a.range, dst->range) << msg;
485   ASSERT_EQ(crop_wd, dst->w) << msg;
486   ASSERT_EQ(crop_ht, dst->h) << msg;
487 }
488 
489 INSTANTIATE_TEST_SUITE_P(
490     EditorAPIParameterizedTests, EditorHelperTest,
491     ::testing::Combine(::testing::Values(INPUT_IMAGE), ::testing::Range(2, 80, 2),
492                        ::testing::Values(64),
493                        ::testing::Values(UHDR_IMG_FMT_24bppYCbCrP010, UHDR_IMG_FMT_12bppYCbCr420,
494                                          UHDR_IMG_FMT_8bppYCbCr400, UHDR_IMG_FMT_32bppRGBA1010102,
495                                          UHDR_IMG_FMT_64bppRGBAHalfFloat,
496                                          UHDR_IMG_FMT_32bppRGBA8888)));
497 
498 }  // namespace ultrahdr
499