xref: /aosp_15_r20/external/libultrahdr/lib/src/editorhelper.cpp (revision 89a0ef05262152531a00a15832a2d3b1e3990773)
1*89a0ef05SAndroid Build Coastguard Worker /*
2*89a0ef05SAndroid Build Coastguard Worker  * Copyright 2024 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 <cstring>
18*89a0ef05SAndroid Build Coastguard Worker #include <cstdint>
19*89a0ef05SAndroid Build Coastguard Worker #include <cmath>
20*89a0ef05SAndroid Build Coastguard Worker 
21*89a0ef05SAndroid Build Coastguard Worker #include "ultrahdr/editorhelper.h"
22*89a0ef05SAndroid Build Coastguard Worker #include "ultrahdr/gainmapmath.h"
23*89a0ef05SAndroid Build Coastguard Worker 
24*89a0ef05SAndroid Build Coastguard Worker namespace ultrahdr {
25*89a0ef05SAndroid Build Coastguard Worker 
26*89a0ef05SAndroid Build Coastguard Worker template <typename T>
rotate_buffer_clockwise(T * src_buffer,T * dst_buffer,int src_w,int src_h,int src_stride,int dst_stride,int degree)27*89a0ef05SAndroid Build Coastguard Worker void rotate_buffer_clockwise(T* src_buffer, T* dst_buffer, int src_w, int src_h, int src_stride,
28*89a0ef05SAndroid Build Coastguard Worker                              int dst_stride, int degree) {
29*89a0ef05SAndroid Build Coastguard Worker   if (degree == 90) {
30*89a0ef05SAndroid Build Coastguard Worker     int dst_w = src_h;
31*89a0ef05SAndroid Build Coastguard Worker     int dst_h = src_w;
32*89a0ef05SAndroid Build Coastguard Worker     for (int i = 0; i < dst_h; i++) {
33*89a0ef05SAndroid Build Coastguard Worker       for (int j = 0; j < dst_w; j++) {
34*89a0ef05SAndroid Build Coastguard Worker         dst_buffer[i * dst_stride + j] = src_buffer[(src_h - j - 1) * src_stride + i];
35*89a0ef05SAndroid Build Coastguard Worker       }
36*89a0ef05SAndroid Build Coastguard Worker     }
37*89a0ef05SAndroid Build Coastguard Worker   } else if (degree == 180) {
38*89a0ef05SAndroid Build Coastguard Worker     int dst_w = src_w;
39*89a0ef05SAndroid Build Coastguard Worker     int dst_h = src_h;
40*89a0ef05SAndroid Build Coastguard Worker     for (int i = 0; i < dst_h; i++) {
41*89a0ef05SAndroid Build Coastguard Worker       for (int j = 0; j < dst_w; j++) {
42*89a0ef05SAndroid Build Coastguard Worker         dst_buffer[i * dst_stride + j] = src_buffer[(src_h - i - 1) * src_stride + (src_w - j - 1)];
43*89a0ef05SAndroid Build Coastguard Worker       }
44*89a0ef05SAndroid Build Coastguard Worker     }
45*89a0ef05SAndroid Build Coastguard Worker   } else if (degree == 270) {
46*89a0ef05SAndroid Build Coastguard Worker     int dst_w = src_h;
47*89a0ef05SAndroid Build Coastguard Worker     int dst_h = src_w;
48*89a0ef05SAndroid Build Coastguard Worker     for (int i = 0; i < dst_h; i++) {
49*89a0ef05SAndroid Build Coastguard Worker       for (int j = 0; j < dst_w; j++) {
50*89a0ef05SAndroid Build Coastguard Worker         dst_buffer[i * dst_stride + j] = src_buffer[j * src_stride + (src_w - i - 1)];
51*89a0ef05SAndroid Build Coastguard Worker       }
52*89a0ef05SAndroid Build Coastguard Worker     }
53*89a0ef05SAndroid Build Coastguard Worker   }
54*89a0ef05SAndroid Build Coastguard Worker }
55*89a0ef05SAndroid Build Coastguard Worker 
56*89a0ef05SAndroid Build Coastguard Worker template <typename T>
mirror_buffer(T * src_buffer,T * dst_buffer,int src_w,int src_h,int src_stride,int dst_stride,uhdr_mirror_direction_t direction)57*89a0ef05SAndroid Build Coastguard Worker void mirror_buffer(T* src_buffer, T* dst_buffer, int src_w, int src_h, int src_stride,
58*89a0ef05SAndroid Build Coastguard Worker                    int dst_stride, uhdr_mirror_direction_t direction) {
59*89a0ef05SAndroid Build Coastguard Worker   if (direction == UHDR_MIRROR_VERTICAL) {
60*89a0ef05SAndroid Build Coastguard Worker     for (int i = 0; i < src_h; i++) {
61*89a0ef05SAndroid Build Coastguard Worker       memcpy(&dst_buffer[(src_h - i - 1) * dst_stride], &src_buffer[i * src_stride],
62*89a0ef05SAndroid Build Coastguard Worker              src_w * sizeof(T));
63*89a0ef05SAndroid Build Coastguard Worker     }
64*89a0ef05SAndroid Build Coastguard Worker   } else if (direction == UHDR_MIRROR_HORIZONTAL) {
65*89a0ef05SAndroid Build Coastguard Worker     for (int i = 0; i < src_h; i++) {
66*89a0ef05SAndroid Build Coastguard Worker       for (int j = 0; j < src_w; j++) {
67*89a0ef05SAndroid Build Coastguard Worker         dst_buffer[i * dst_stride + j] = src_buffer[i * src_stride + (src_w - j - 1)];
68*89a0ef05SAndroid Build Coastguard Worker       }
69*89a0ef05SAndroid Build Coastguard Worker     }
70*89a0ef05SAndroid Build Coastguard Worker   }
71*89a0ef05SAndroid Build Coastguard Worker }
72*89a0ef05SAndroid Build Coastguard Worker 
73*89a0ef05SAndroid Build Coastguard Worker template <typename T>
crop_buffer(T * src_buffer,T * dst_buffer,int src_stride,int dst_stride,int left,int top,int wd,int ht)74*89a0ef05SAndroid Build Coastguard Worker void crop_buffer(T* src_buffer, T* dst_buffer, int src_stride, int dst_stride, int left, int top,
75*89a0ef05SAndroid Build Coastguard Worker                  int wd, int ht) {
76*89a0ef05SAndroid Build Coastguard Worker   for (int row = 0; row < ht; row++) {
77*89a0ef05SAndroid Build Coastguard Worker     memcpy(&dst_buffer[row * dst_stride], &src_buffer[(top + row) * src_stride + left],
78*89a0ef05SAndroid Build Coastguard Worker            wd * sizeof(T));
79*89a0ef05SAndroid Build Coastguard Worker   }
80*89a0ef05SAndroid Build Coastguard Worker }
81*89a0ef05SAndroid Build Coastguard Worker 
82*89a0ef05SAndroid Build Coastguard Worker // TODO (dichenzhang): legacy method, need to be removed
83*89a0ef05SAndroid Build Coastguard Worker template <typename T>
resize_buffer(T * src_buffer,T * dst_buffer,int src_w,int src_h,int dst_w,int dst_h,int src_stride,int dst_stride)84*89a0ef05SAndroid Build Coastguard Worker void resize_buffer(T* src_buffer, T* dst_buffer, int src_w, int src_h, int dst_w, int dst_h,
85*89a0ef05SAndroid Build Coastguard Worker                    int src_stride, int dst_stride) {
86*89a0ef05SAndroid Build Coastguard Worker   for (int i = 0; i < dst_h; i++) {
87*89a0ef05SAndroid Build Coastguard Worker     for (int j = 0; j < dst_w; j++) {
88*89a0ef05SAndroid Build Coastguard Worker       dst_buffer[i * dst_stride + j] =
89*89a0ef05SAndroid Build Coastguard Worker           src_buffer[i * (src_h / dst_h) * src_stride + j * (src_w / dst_w)];
90*89a0ef05SAndroid Build Coastguard Worker     }
91*89a0ef05SAndroid Build Coastguard Worker   }
92*89a0ef05SAndroid Build Coastguard Worker }
93*89a0ef05SAndroid Build Coastguard Worker 
94*89a0ef05SAndroid Build Coastguard Worker // This function performs bicubic interpolation on a 1D signal.
bicubic_interpolate(double p0,double p1,double p2,double p3,double x)95*89a0ef05SAndroid Build Coastguard Worker double bicubic_interpolate(double p0, double p1, double p2, double p3, double x) {
96*89a0ef05SAndroid Build Coastguard Worker   // Calculate the weights for the four neighboring points.
97*89a0ef05SAndroid Build Coastguard Worker   double w0 = (1 - x) * (1 - x) * (1 - x);
98*89a0ef05SAndroid Build Coastguard Worker   double w1 = 3 * x * (1 - x) * (1 - x);
99*89a0ef05SAndroid Build Coastguard Worker   double w2 = 3 * x * x * (1 - x);
100*89a0ef05SAndroid Build Coastguard Worker   double w3 = x * x * x;
101*89a0ef05SAndroid Build Coastguard Worker 
102*89a0ef05SAndroid Build Coastguard Worker   // Calculate the interpolated value.
103*89a0ef05SAndroid Build Coastguard Worker   return w0 * p0 + w1 * p1 + w2 * p2 + w3 * p3;
104*89a0ef05SAndroid Build Coastguard Worker }
105*89a0ef05SAndroid Build Coastguard Worker 
resize_image(uhdr_raw_image_t * src,int dst_w,int dst_h)106*89a0ef05SAndroid Build Coastguard Worker std::unique_ptr<uhdr_raw_image_ext_t> resize_image(uhdr_raw_image_t* src, int dst_w, int dst_h) {
107*89a0ef05SAndroid Build Coastguard Worker   GetPixelFn get_pixel_fn = getPixelFn(src->fmt);
108*89a0ef05SAndroid Build Coastguard Worker   if (get_pixel_fn == nullptr) {
109*89a0ef05SAndroid Build Coastguard Worker     return nullptr;
110*89a0ef05SAndroid Build Coastguard Worker   }
111*89a0ef05SAndroid Build Coastguard Worker 
112*89a0ef05SAndroid Build Coastguard Worker   PutPixelFn put_pixel_fn = putPixelFn(src->fmt);
113*89a0ef05SAndroid Build Coastguard Worker   if (put_pixel_fn == nullptr) {
114*89a0ef05SAndroid Build Coastguard Worker     return nullptr;
115*89a0ef05SAndroid Build Coastguard Worker   }
116*89a0ef05SAndroid Build Coastguard Worker 
117*89a0ef05SAndroid Build Coastguard Worker   std::unique_ptr<uhdr_raw_image_ext_t> dst = std::make_unique<uhdr_raw_image_ext_t>(
118*89a0ef05SAndroid Build Coastguard Worker       src->fmt, src->cg, src->ct, src->range, dst_w, dst_h, 64);
119*89a0ef05SAndroid Build Coastguard Worker 
120*89a0ef05SAndroid Build Coastguard Worker   int src_w = src->w;
121*89a0ef05SAndroid Build Coastguard Worker   int src_h = src->h;
122*89a0ef05SAndroid Build Coastguard Worker   double scale_x = (double)src_w / dst_w;
123*89a0ef05SAndroid Build Coastguard Worker   double scale_y = (double)src_h / dst_h;
124*89a0ef05SAndroid Build Coastguard Worker   for (int y = 0; y < dst_h; y++) {
125*89a0ef05SAndroid Build Coastguard Worker     for (int x = 0; x < dst_w; x++) {
126*89a0ef05SAndroid Build Coastguard Worker       double ori_x = x * scale_x;
127*89a0ef05SAndroid Build Coastguard Worker       double ori_y = y * scale_y;
128*89a0ef05SAndroid Build Coastguard Worker       int p0_x = CLIP3((int)floor(ori_x), 0, src_w - 1);
129*89a0ef05SAndroid Build Coastguard Worker       int p0_y = CLIP3((int)floor(ori_y), 0, src_h - 1);
130*89a0ef05SAndroid Build Coastguard Worker       int p1_x = CLIP3((p0_x + 1), 0, src_w - 1);
131*89a0ef05SAndroid Build Coastguard Worker       int p1_y = p0_y;
132*89a0ef05SAndroid Build Coastguard Worker       int p2_x = p0_x;
133*89a0ef05SAndroid Build Coastguard Worker       int p2_y = CLIP3((p0_y + 1), 0, src_h - 1);
134*89a0ef05SAndroid Build Coastguard Worker       int p3_x = CLIP3((p0_x + 1), 0, src_w - 1);
135*89a0ef05SAndroid Build Coastguard Worker       int p3_y = CLIP3((p0_y + 1), 0, src_h - 1);
136*89a0ef05SAndroid Build Coastguard Worker 
137*89a0ef05SAndroid Build Coastguard Worker       Color p0 = get_pixel_fn(src, p0_x, p0_y);
138*89a0ef05SAndroid Build Coastguard Worker       Color p1 = get_pixel_fn(src, p1_x, p1_y);
139*89a0ef05SAndroid Build Coastguard Worker       Color p2 = get_pixel_fn(src, p2_x, p2_y);
140*89a0ef05SAndroid Build Coastguard Worker       Color p3 = get_pixel_fn(src, p3_x, p3_y);
141*89a0ef05SAndroid Build Coastguard Worker 
142*89a0ef05SAndroid Build Coastguard Worker       Color interp;
143*89a0ef05SAndroid Build Coastguard Worker       interp.r = (float)bicubic_interpolate(p0.r, p1.r, p2.r, p3.r, ori_x - p0_x);
144*89a0ef05SAndroid Build Coastguard Worker       if (src->fmt != UHDR_IMG_FMT_8bppYCbCr400) {
145*89a0ef05SAndroid Build Coastguard Worker         interp.g = (float)bicubic_interpolate(p0.g, p1.g, p2.g, p3.g, ori_x - p0_x);
146*89a0ef05SAndroid Build Coastguard Worker         interp.b = (float)bicubic_interpolate(p0.b, p1.b, p2.b, p3.b, ori_x - p0_x);
147*89a0ef05SAndroid Build Coastguard Worker       }
148*89a0ef05SAndroid Build Coastguard Worker       put_pixel_fn(dst.get(), x, y, interp);
149*89a0ef05SAndroid Build Coastguard Worker     }
150*89a0ef05SAndroid Build Coastguard Worker   }
151*89a0ef05SAndroid Build Coastguard Worker   return dst;
152*89a0ef05SAndroid Build Coastguard Worker }
153*89a0ef05SAndroid Build Coastguard Worker 
154*89a0ef05SAndroid Build Coastguard Worker template void mirror_buffer<uint8_t>(uint8_t*, uint8_t*, int, int, int, int,
155*89a0ef05SAndroid Build Coastguard Worker                                      uhdr_mirror_direction_t);
156*89a0ef05SAndroid Build Coastguard Worker template void mirror_buffer<uint16_t>(uint16_t*, uint16_t*, int, int, int, int,
157*89a0ef05SAndroid Build Coastguard Worker                                       uhdr_mirror_direction_t);
158*89a0ef05SAndroid Build Coastguard Worker template void mirror_buffer<uint32_t>(uint32_t*, uint32_t*, int, int, int, int,
159*89a0ef05SAndroid Build Coastguard Worker                                       uhdr_mirror_direction_t);
160*89a0ef05SAndroid Build Coastguard Worker template void mirror_buffer<uint64_t>(uint64_t*, uint64_t*, int, int, int, int,
161*89a0ef05SAndroid Build Coastguard Worker                                       uhdr_mirror_direction_t);
162*89a0ef05SAndroid Build Coastguard Worker 
163*89a0ef05SAndroid Build Coastguard Worker template void rotate_buffer_clockwise<uint8_t>(uint8_t*, uint8_t*, int, int, int, int, int);
164*89a0ef05SAndroid Build Coastguard Worker template void rotate_buffer_clockwise<uint16_t>(uint16_t*, uint16_t*, int, int, int, int, int);
165*89a0ef05SAndroid Build Coastguard Worker template void rotate_buffer_clockwise<uint32_t>(uint32_t*, uint32_t*, int, int, int, int, int);
166*89a0ef05SAndroid Build Coastguard Worker template void rotate_buffer_clockwise<uint64_t>(uint64_t*, uint64_t*, int, int, int, int, int);
167*89a0ef05SAndroid Build Coastguard Worker 
168*89a0ef05SAndroid Build Coastguard Worker template void resize_buffer<uint8_t>(uint8_t*, uint8_t*, int, int, int, int, int, int);
169*89a0ef05SAndroid Build Coastguard Worker template void resize_buffer<uint16_t>(uint16_t*, uint16_t*, int, int, int, int, int, int);
170*89a0ef05SAndroid Build Coastguard Worker template void resize_buffer<uint32_t>(uint32_t*, uint32_t*, int, int, int, int, int, int);
171*89a0ef05SAndroid Build Coastguard Worker template void resize_buffer<uint64_t>(uint64_t*, uint64_t*, int, int, int, int, int, int);
172*89a0ef05SAndroid Build Coastguard Worker 
uhdr_mirror_effect(uhdr_mirror_direction_t direction)173*89a0ef05SAndroid Build Coastguard Worker uhdr_mirror_effect::uhdr_mirror_effect(uhdr_mirror_direction_t direction) : m_direction{direction} {
174*89a0ef05SAndroid Build Coastguard Worker #if (defined(UHDR_ENABLE_INTRINSICS) && (defined(__ARM_NEON__) || defined(__ARM_NEON)))
175*89a0ef05SAndroid Build Coastguard Worker   m_mirror_uint8_t = mirror_buffer_neon<uint8_t>;
176*89a0ef05SAndroid Build Coastguard Worker   m_mirror_uint16_t = mirror_buffer_neon<uint16_t>;
177*89a0ef05SAndroid Build Coastguard Worker   m_mirror_uint32_t = mirror_buffer_neon<uint32_t>;
178*89a0ef05SAndroid Build Coastguard Worker   m_mirror_uint64_t = mirror_buffer_neon<uint64_t>;
179*89a0ef05SAndroid Build Coastguard Worker #else
180*89a0ef05SAndroid Build Coastguard Worker   m_mirror_uint8_t = mirror_buffer<uint8_t>;
181*89a0ef05SAndroid Build Coastguard Worker   m_mirror_uint16_t = mirror_buffer<uint16_t>;
182*89a0ef05SAndroid Build Coastguard Worker   m_mirror_uint32_t = mirror_buffer<uint32_t>;
183*89a0ef05SAndroid Build Coastguard Worker   m_mirror_uint64_t = mirror_buffer<uint64_t>;
184*89a0ef05SAndroid Build Coastguard Worker #endif
185*89a0ef05SAndroid Build Coastguard Worker }
186*89a0ef05SAndroid Build Coastguard Worker 
uhdr_rotate_effect(int degree)187*89a0ef05SAndroid Build Coastguard Worker uhdr_rotate_effect::uhdr_rotate_effect(int degree) : m_degree{degree} {
188*89a0ef05SAndroid Build Coastguard Worker #if (defined(UHDR_ENABLE_INTRINSICS) && (defined(__ARM_NEON__) || defined(__ARM_NEON)))
189*89a0ef05SAndroid Build Coastguard Worker   m_rotate_uint8_t = rotate_buffer_clockwise_neon<uint8_t>;
190*89a0ef05SAndroid Build Coastguard Worker   m_rotate_uint16_t = rotate_buffer_clockwise_neon<uint16_t>;
191*89a0ef05SAndroid Build Coastguard Worker   m_rotate_uint32_t = rotate_buffer_clockwise_neon<uint32_t>;
192*89a0ef05SAndroid Build Coastguard Worker   m_rotate_uint64_t = rotate_buffer_clockwise_neon<uint64_t>;
193*89a0ef05SAndroid Build Coastguard Worker #else
194*89a0ef05SAndroid Build Coastguard Worker   m_rotate_uint8_t = rotate_buffer_clockwise<uint8_t>;
195*89a0ef05SAndroid Build Coastguard Worker   m_rotate_uint16_t = rotate_buffer_clockwise<uint16_t>;
196*89a0ef05SAndroid Build Coastguard Worker   m_rotate_uint32_t = rotate_buffer_clockwise<uint32_t>;
197*89a0ef05SAndroid Build Coastguard Worker   m_rotate_uint64_t = rotate_buffer_clockwise<uint64_t>;
198*89a0ef05SAndroid Build Coastguard Worker #endif
199*89a0ef05SAndroid Build Coastguard Worker }
200*89a0ef05SAndroid Build Coastguard Worker 
uhdr_crop_effect(int left,int right,int top,int bottom)201*89a0ef05SAndroid Build Coastguard Worker uhdr_crop_effect::uhdr_crop_effect(int left, int right, int top, int bottom)
202*89a0ef05SAndroid Build Coastguard Worker     : m_left(left), m_right(right), m_top(top), m_bottom(bottom) {
203*89a0ef05SAndroid Build Coastguard Worker   m_crop_uint8_t = crop_buffer<uint8_t>;
204*89a0ef05SAndroid Build Coastguard Worker   m_crop_uint16_t = crop_buffer<uint16_t>;
205*89a0ef05SAndroid Build Coastguard Worker   m_crop_uint32_t = crop_buffer<uint32_t>;
206*89a0ef05SAndroid Build Coastguard Worker   m_crop_uint64_t = crop_buffer<uint64_t>;
207*89a0ef05SAndroid Build Coastguard Worker }
208*89a0ef05SAndroid Build Coastguard Worker 
uhdr_resize_effect(int width,int height)209*89a0ef05SAndroid Build Coastguard Worker uhdr_resize_effect::uhdr_resize_effect(int width, int height) : m_width{width}, m_height{height} {
210*89a0ef05SAndroid Build Coastguard Worker   m_resize_uint8_t = resize_buffer<uint8_t>;
211*89a0ef05SAndroid Build Coastguard Worker   m_resize_uint16_t = resize_buffer<uint16_t>;
212*89a0ef05SAndroid Build Coastguard Worker   m_resize_uint32_t = resize_buffer<uint32_t>;
213*89a0ef05SAndroid Build Coastguard Worker   m_resize_uint64_t = resize_buffer<uint64_t>;
214*89a0ef05SAndroid Build Coastguard Worker }
215*89a0ef05SAndroid Build Coastguard Worker 
apply_rotate(ultrahdr::uhdr_rotate_effect_t * desc,uhdr_raw_image_t * src,void * gl_ctxt,void * texture)216*89a0ef05SAndroid Build Coastguard Worker std::unique_ptr<uhdr_raw_image_ext_t> apply_rotate(ultrahdr::uhdr_rotate_effect_t* desc,
217*89a0ef05SAndroid Build Coastguard Worker                                                    uhdr_raw_image_t* src,
218*89a0ef05SAndroid Build Coastguard Worker                                                    [[maybe_unused]] void* gl_ctxt,
219*89a0ef05SAndroid Build Coastguard Worker                                                    [[maybe_unused]] void* texture) {
220*89a0ef05SAndroid Build Coastguard Worker #ifdef UHDR_ENABLE_GLES
221*89a0ef05SAndroid Build Coastguard Worker   if ((src->fmt == UHDR_IMG_FMT_32bppRGBA1010102 || src->fmt == UHDR_IMG_FMT_32bppRGBA8888 ||
222*89a0ef05SAndroid Build Coastguard Worker        src->fmt == UHDR_IMG_FMT_64bppRGBAHalfFloat || src->fmt == UHDR_IMG_FMT_8bppYCbCr400) &&
223*89a0ef05SAndroid Build Coastguard Worker       gl_ctxt != nullptr && *static_cast<GLuint*>(texture) != 0) {
224*89a0ef05SAndroid Build Coastguard Worker     return apply_rotate_gles(desc, src, static_cast<ultrahdr::uhdr_opengl_ctxt*>(gl_ctxt),
225*89a0ef05SAndroid Build Coastguard Worker                              static_cast<GLuint*>(texture));
226*89a0ef05SAndroid Build Coastguard Worker   }
227*89a0ef05SAndroid Build Coastguard Worker #endif
228*89a0ef05SAndroid Build Coastguard Worker   std::unique_ptr<uhdr_raw_image_ext_t> dst;
229*89a0ef05SAndroid Build Coastguard Worker 
230*89a0ef05SAndroid Build Coastguard Worker   if (desc->m_degree == 90 || desc->m_degree == 270) {
231*89a0ef05SAndroid Build Coastguard Worker     dst = std::make_unique<uhdr_raw_image_ext_t>(src->fmt, src->cg, src->ct, src->range, src->h,
232*89a0ef05SAndroid Build Coastguard Worker                                                  src->w, 64);
233*89a0ef05SAndroid Build Coastguard Worker   } else if (desc->m_degree == 180) {
234*89a0ef05SAndroid Build Coastguard Worker     dst = std::make_unique<uhdr_raw_image_ext_t>(src->fmt, src->cg, src->ct, src->range, src->w,
235*89a0ef05SAndroid Build Coastguard Worker                                                  src->h, 64);
236*89a0ef05SAndroid Build Coastguard Worker   } else {
237*89a0ef05SAndroid Build Coastguard Worker     return nullptr;
238*89a0ef05SAndroid Build Coastguard Worker   }
239*89a0ef05SAndroid Build Coastguard Worker 
240*89a0ef05SAndroid Build Coastguard Worker   if (src->fmt == UHDR_IMG_FMT_24bppYCbCrP010) {
241*89a0ef05SAndroid Build Coastguard Worker     uint16_t* src_buffer = static_cast<uint16_t*>(src->planes[UHDR_PLANE_Y]);
242*89a0ef05SAndroid Build Coastguard Worker     uint16_t* dst_buffer = static_cast<uint16_t*>(dst->planes[UHDR_PLANE_Y]);
243*89a0ef05SAndroid Build Coastguard Worker     desc->m_rotate_uint16_t(src_buffer, dst_buffer, src->w, src->h, src->stride[UHDR_PLANE_Y],
244*89a0ef05SAndroid Build Coastguard Worker                             dst->stride[UHDR_PLANE_Y], desc->m_degree);
245*89a0ef05SAndroid Build Coastguard Worker     uint32_t* src_uv_buffer = static_cast<uint32_t*>(src->planes[UHDR_PLANE_UV]);
246*89a0ef05SAndroid Build Coastguard Worker     uint32_t* dst_uv_buffer = static_cast<uint32_t*>(dst->planes[UHDR_PLANE_UV]);
247*89a0ef05SAndroid Build Coastguard Worker     desc->m_rotate_uint32_t(src_uv_buffer, dst_uv_buffer, src->w / 2, src->h / 2,
248*89a0ef05SAndroid Build Coastguard Worker                             src->stride[UHDR_PLANE_UV] / 2, dst->stride[UHDR_PLANE_UV] / 2,
249*89a0ef05SAndroid Build Coastguard Worker                             desc->m_degree);
250*89a0ef05SAndroid Build Coastguard Worker   } else if (src->fmt == UHDR_IMG_FMT_12bppYCbCr420 || src->fmt == UHDR_IMG_FMT_8bppYCbCr400) {
251*89a0ef05SAndroid Build Coastguard Worker     uint8_t* src_buffer = static_cast<uint8_t*>(src->planes[UHDR_PLANE_Y]);
252*89a0ef05SAndroid Build Coastguard Worker     uint8_t* dst_buffer = static_cast<uint8_t*>(dst->planes[UHDR_PLANE_Y]);
253*89a0ef05SAndroid Build Coastguard Worker     desc->m_rotate_uint8_t(src_buffer, dst_buffer, src->w, src->h, src->stride[UHDR_PLANE_Y],
254*89a0ef05SAndroid Build Coastguard Worker                            dst->stride[UHDR_PLANE_Y], desc->m_degree);
255*89a0ef05SAndroid Build Coastguard Worker     if (src->fmt == UHDR_IMG_FMT_12bppYCbCr420) {
256*89a0ef05SAndroid Build Coastguard Worker       for (int i = 1; i < 3; i++) {
257*89a0ef05SAndroid Build Coastguard Worker         src_buffer = static_cast<uint8_t*>(src->planes[i]);
258*89a0ef05SAndroid Build Coastguard Worker         dst_buffer = static_cast<uint8_t*>(dst->planes[i]);
259*89a0ef05SAndroid Build Coastguard Worker         desc->m_rotate_uint8_t(src_buffer, dst_buffer, src->w / 2, src->h / 2, src->stride[i],
260*89a0ef05SAndroid Build Coastguard Worker                                dst->stride[i], desc->m_degree);
261*89a0ef05SAndroid Build Coastguard Worker       }
262*89a0ef05SAndroid Build Coastguard Worker     }
263*89a0ef05SAndroid Build Coastguard Worker   } else if (src->fmt == UHDR_IMG_FMT_32bppRGBA1010102 || src->fmt == UHDR_IMG_FMT_32bppRGBA8888) {
264*89a0ef05SAndroid Build Coastguard Worker     uint32_t* src_buffer = static_cast<uint32_t*>(src->planes[UHDR_PLANE_PACKED]);
265*89a0ef05SAndroid Build Coastguard Worker     uint32_t* dst_buffer = static_cast<uint32_t*>(dst->planes[UHDR_PLANE_PACKED]);
266*89a0ef05SAndroid Build Coastguard Worker     desc->m_rotate_uint32_t(src_buffer, dst_buffer, src->w, src->h, src->stride[UHDR_PLANE_PACKED],
267*89a0ef05SAndroid Build Coastguard Worker                             dst->stride[UHDR_PLANE_PACKED], desc->m_degree);
268*89a0ef05SAndroid Build Coastguard Worker   } else if (src->fmt == UHDR_IMG_FMT_64bppRGBAHalfFloat) {
269*89a0ef05SAndroid Build Coastguard Worker     uint64_t* src_buffer = static_cast<uint64_t*>(src->planes[UHDR_PLANE_PACKED]);
270*89a0ef05SAndroid Build Coastguard Worker     uint64_t* dst_buffer = static_cast<uint64_t*>(dst->planes[UHDR_PLANE_PACKED]);
271*89a0ef05SAndroid Build Coastguard Worker     desc->m_rotate_uint64_t(src_buffer, dst_buffer, src->w, src->h, src->stride[UHDR_PLANE_PACKED],
272*89a0ef05SAndroid Build Coastguard Worker                             dst->stride[UHDR_PLANE_PACKED], desc->m_degree);
273*89a0ef05SAndroid Build Coastguard Worker   } else if (src->fmt == UHDR_IMG_FMT_24bppYCbCr444) {
274*89a0ef05SAndroid Build Coastguard Worker     for (int i = 0; i < 3; i++) {
275*89a0ef05SAndroid Build Coastguard Worker       uint8_t* src_buffer = static_cast<uint8_t*>(src->planes[i]);
276*89a0ef05SAndroid Build Coastguard Worker       uint8_t* dst_buffer = static_cast<uint8_t*>(dst->planes[i]);
277*89a0ef05SAndroid Build Coastguard Worker       desc->m_rotate_uint8_t(src_buffer, dst_buffer, src->w, src->h, src->stride[i], dst->stride[i],
278*89a0ef05SAndroid Build Coastguard Worker                              desc->m_degree);
279*89a0ef05SAndroid Build Coastguard Worker     }
280*89a0ef05SAndroid Build Coastguard Worker   } else if (src->fmt == UHDR_IMG_FMT_30bppYCbCr444) {
281*89a0ef05SAndroid Build Coastguard Worker     for (int i = 0; i < 3; i++) {
282*89a0ef05SAndroid Build Coastguard Worker       uint16_t* src_buffer = static_cast<uint16_t*>(src->planes[i]);
283*89a0ef05SAndroid Build Coastguard Worker       uint16_t* dst_buffer = static_cast<uint16_t*>(dst->planes[i]);
284*89a0ef05SAndroid Build Coastguard Worker       desc->m_rotate_uint16_t(src_buffer, dst_buffer, src->w, src->h, src->stride[i],
285*89a0ef05SAndroid Build Coastguard Worker                               dst->stride[i], desc->m_degree);
286*89a0ef05SAndroid Build Coastguard Worker     }
287*89a0ef05SAndroid Build Coastguard Worker   }
288*89a0ef05SAndroid Build Coastguard Worker   return dst;
289*89a0ef05SAndroid Build Coastguard Worker }
290*89a0ef05SAndroid Build Coastguard Worker 
apply_mirror(ultrahdr::uhdr_mirror_effect_t * desc,uhdr_raw_image_t * src,void * gl_ctxt,void * texture)291*89a0ef05SAndroid Build Coastguard Worker std::unique_ptr<uhdr_raw_image_ext_t> apply_mirror(ultrahdr::uhdr_mirror_effect_t* desc,
292*89a0ef05SAndroid Build Coastguard Worker                                                    uhdr_raw_image_t* src,
293*89a0ef05SAndroid Build Coastguard Worker                                                    [[maybe_unused]] void* gl_ctxt,
294*89a0ef05SAndroid Build Coastguard Worker                                                    [[maybe_unused]] void* texture) {
295*89a0ef05SAndroid Build Coastguard Worker #ifdef UHDR_ENABLE_GLES
296*89a0ef05SAndroid Build Coastguard Worker   if ((src->fmt == UHDR_IMG_FMT_32bppRGBA1010102 || src->fmt == UHDR_IMG_FMT_32bppRGBA8888 ||
297*89a0ef05SAndroid Build Coastguard Worker        src->fmt == UHDR_IMG_FMT_64bppRGBAHalfFloat || src->fmt == UHDR_IMG_FMT_8bppYCbCr400) &&
298*89a0ef05SAndroid Build Coastguard Worker       gl_ctxt != nullptr && *static_cast<GLuint*>(texture) != 0) {
299*89a0ef05SAndroid Build Coastguard Worker     return apply_mirror_gles(desc, src, static_cast<ultrahdr::uhdr_opengl_ctxt*>(gl_ctxt),
300*89a0ef05SAndroid Build Coastguard Worker                              static_cast<GLuint*>(texture));
301*89a0ef05SAndroid Build Coastguard Worker   }
302*89a0ef05SAndroid Build Coastguard Worker #endif
303*89a0ef05SAndroid Build Coastguard Worker   std::unique_ptr<uhdr_raw_image_ext_t> dst = std::make_unique<uhdr_raw_image_ext_t>(
304*89a0ef05SAndroid Build Coastguard Worker       src->fmt, src->cg, src->ct, src->range, src->w, src->h, 64);
305*89a0ef05SAndroid Build Coastguard Worker 
306*89a0ef05SAndroid Build Coastguard Worker   if (src->fmt == UHDR_IMG_FMT_24bppYCbCrP010) {
307*89a0ef05SAndroid Build Coastguard Worker     uint16_t* src_buffer = static_cast<uint16_t*>(src->planes[UHDR_PLANE_Y]);
308*89a0ef05SAndroid Build Coastguard Worker     uint16_t* dst_buffer = static_cast<uint16_t*>(dst->planes[UHDR_PLANE_Y]);
309*89a0ef05SAndroid Build Coastguard Worker     desc->m_mirror_uint16_t(src_buffer, dst_buffer, src->w, src->h, src->stride[UHDR_PLANE_Y],
310*89a0ef05SAndroid Build Coastguard Worker                             dst->stride[UHDR_PLANE_Y], desc->m_direction);
311*89a0ef05SAndroid Build Coastguard Worker     uint32_t* src_uv_buffer = static_cast<uint32_t*>(src->planes[UHDR_PLANE_UV]);
312*89a0ef05SAndroid Build Coastguard Worker     uint32_t* dst_uv_buffer = static_cast<uint32_t*>(dst->planes[UHDR_PLANE_UV]);
313*89a0ef05SAndroid Build Coastguard Worker     desc->m_mirror_uint32_t(src_uv_buffer, dst_uv_buffer, src->w / 2, src->h / 2,
314*89a0ef05SAndroid Build Coastguard Worker                             src->stride[UHDR_PLANE_UV] / 2, dst->stride[UHDR_PLANE_UV] / 2,
315*89a0ef05SAndroid Build Coastguard Worker                             desc->m_direction);
316*89a0ef05SAndroid Build Coastguard Worker   } else if (src->fmt == UHDR_IMG_FMT_12bppYCbCr420 || src->fmt == UHDR_IMG_FMT_8bppYCbCr400) {
317*89a0ef05SAndroid Build Coastguard Worker     uint8_t* src_buffer = static_cast<uint8_t*>(src->planes[UHDR_PLANE_Y]);
318*89a0ef05SAndroid Build Coastguard Worker     uint8_t* dst_buffer = static_cast<uint8_t*>(dst->planes[UHDR_PLANE_Y]);
319*89a0ef05SAndroid Build Coastguard Worker     desc->m_mirror_uint8_t(src_buffer, dst_buffer, src->w, src->h, src->stride[UHDR_PLANE_Y],
320*89a0ef05SAndroid Build Coastguard Worker                            dst->stride[UHDR_PLANE_Y], desc->m_direction);
321*89a0ef05SAndroid Build Coastguard Worker     if (src->fmt == UHDR_IMG_FMT_12bppYCbCr420) {
322*89a0ef05SAndroid Build Coastguard Worker       for (int i = 1; i < 3; i++) {
323*89a0ef05SAndroid Build Coastguard Worker         src_buffer = static_cast<uint8_t*>(src->planes[i]);
324*89a0ef05SAndroid Build Coastguard Worker         dst_buffer = static_cast<uint8_t*>(dst->planes[i]);
325*89a0ef05SAndroid Build Coastguard Worker         desc->m_mirror_uint8_t(src_buffer, dst_buffer, src->w / 2, src->h / 2, src->stride[i],
326*89a0ef05SAndroid Build Coastguard Worker                                dst->stride[i], desc->m_direction);
327*89a0ef05SAndroid Build Coastguard Worker       }
328*89a0ef05SAndroid Build Coastguard Worker     }
329*89a0ef05SAndroid Build Coastguard Worker   } else if (src->fmt == UHDR_IMG_FMT_32bppRGBA1010102 || src->fmt == UHDR_IMG_FMT_32bppRGBA8888) {
330*89a0ef05SAndroid Build Coastguard Worker     uint32_t* src_buffer = static_cast<uint32_t*>(src->planes[UHDR_PLANE_PACKED]);
331*89a0ef05SAndroid Build Coastguard Worker     uint32_t* dst_buffer = static_cast<uint32_t*>(dst->planes[UHDR_PLANE_PACKED]);
332*89a0ef05SAndroid Build Coastguard Worker     desc->m_mirror_uint32_t(src_buffer, dst_buffer, src->w, src->h, src->stride[UHDR_PLANE_PACKED],
333*89a0ef05SAndroid Build Coastguard Worker                             dst->stride[UHDR_PLANE_PACKED], desc->m_direction);
334*89a0ef05SAndroid Build Coastguard Worker   } else if (src->fmt == UHDR_IMG_FMT_64bppRGBAHalfFloat) {
335*89a0ef05SAndroid Build Coastguard Worker     uint64_t* src_buffer = static_cast<uint64_t*>(src->planes[UHDR_PLANE_PACKED]);
336*89a0ef05SAndroid Build Coastguard Worker     uint64_t* dst_buffer = static_cast<uint64_t*>(dst->planes[UHDR_PLANE_PACKED]);
337*89a0ef05SAndroid Build Coastguard Worker     desc->m_mirror_uint64_t(src_buffer, dst_buffer, src->w, src->h, src->stride[UHDR_PLANE_PACKED],
338*89a0ef05SAndroid Build Coastguard Worker                             dst->stride[UHDR_PLANE_PACKED], desc->m_direction);
339*89a0ef05SAndroid Build Coastguard Worker   } else if (src->fmt == UHDR_IMG_FMT_24bppYCbCr444) {
340*89a0ef05SAndroid Build Coastguard Worker     for (int i = 0; i < 3; i++) {
341*89a0ef05SAndroid Build Coastguard Worker       uint8_t* src_buffer = static_cast<uint8_t*>(src->planes[i]);
342*89a0ef05SAndroid Build Coastguard Worker       uint8_t* dst_buffer = static_cast<uint8_t*>(dst->planes[i]);
343*89a0ef05SAndroid Build Coastguard Worker       desc->m_mirror_uint8_t(src_buffer, dst_buffer, src->w, src->h, src->stride[i], dst->stride[i],
344*89a0ef05SAndroid Build Coastguard Worker                              desc->m_direction);
345*89a0ef05SAndroid Build Coastguard Worker     }
346*89a0ef05SAndroid Build Coastguard Worker   } else if (src->fmt == UHDR_IMG_FMT_30bppYCbCr444) {
347*89a0ef05SAndroid Build Coastguard Worker     for (int i = 0; i < 3; i++) {
348*89a0ef05SAndroid Build Coastguard Worker       uint16_t* src_buffer = static_cast<uint16_t*>(src->planes[i]);
349*89a0ef05SAndroid Build Coastguard Worker       uint16_t* dst_buffer = static_cast<uint16_t*>(dst->planes[i]);
350*89a0ef05SAndroid Build Coastguard Worker       desc->m_mirror_uint16_t(src_buffer, dst_buffer, src->w, src->h, src->stride[i],
351*89a0ef05SAndroid Build Coastguard Worker                               dst->stride[i], desc->m_direction);
352*89a0ef05SAndroid Build Coastguard Worker     }
353*89a0ef05SAndroid Build Coastguard Worker   }
354*89a0ef05SAndroid Build Coastguard Worker   return dst;
355*89a0ef05SAndroid Build Coastguard Worker }
356*89a0ef05SAndroid Build Coastguard Worker 
apply_crop(ultrahdr::uhdr_crop_effect_t * desc,uhdr_raw_image_t * src,int left,int top,int wd,int ht,void * gl_ctxt,void * texture)357*89a0ef05SAndroid Build Coastguard Worker std::unique_ptr<uhdr_raw_image_ext_t> apply_crop(ultrahdr::uhdr_crop_effect_t* desc,
358*89a0ef05SAndroid Build Coastguard Worker                                                  uhdr_raw_image_t* src, int left, int top, int wd,
359*89a0ef05SAndroid Build Coastguard Worker                                                  int ht, [[maybe_unused]] void* gl_ctxt,
360*89a0ef05SAndroid Build Coastguard Worker                                                  [[maybe_unused]] void* texture) {
361*89a0ef05SAndroid Build Coastguard Worker #ifdef UHDR_ENABLE_GLES
362*89a0ef05SAndroid Build Coastguard Worker   if ((src->fmt == UHDR_IMG_FMT_32bppRGBA1010102 || src->fmt == UHDR_IMG_FMT_32bppRGBA8888 ||
363*89a0ef05SAndroid Build Coastguard Worker        src->fmt == UHDR_IMG_FMT_64bppRGBAHalfFloat || src->fmt == UHDR_IMG_FMT_8bppYCbCr400) &&
364*89a0ef05SAndroid Build Coastguard Worker       gl_ctxt != nullptr && *static_cast<GLuint*>(texture) != 0) {
365*89a0ef05SAndroid Build Coastguard Worker     return apply_crop_gles(src, left, top, wd, ht,
366*89a0ef05SAndroid Build Coastguard Worker                            static_cast<ultrahdr::uhdr_opengl_ctxt*>(gl_ctxt),
367*89a0ef05SAndroid Build Coastguard Worker                            static_cast<GLuint*>(texture));
368*89a0ef05SAndroid Build Coastguard Worker   }
369*89a0ef05SAndroid Build Coastguard Worker #endif
370*89a0ef05SAndroid Build Coastguard Worker   std::unique_ptr<uhdr_raw_image_ext_t> dst =
371*89a0ef05SAndroid Build Coastguard Worker       std::make_unique<uhdr_raw_image_ext_t>(src->fmt, src->cg, src->ct, src->range, wd, ht, 64);
372*89a0ef05SAndroid Build Coastguard Worker 
373*89a0ef05SAndroid Build Coastguard Worker   if (src->fmt == UHDR_IMG_FMT_24bppYCbCrP010) {
374*89a0ef05SAndroid Build Coastguard Worker     uint16_t* src_buffer = static_cast<uint16_t*>(src->planes[UHDR_PLANE_Y]);
375*89a0ef05SAndroid Build Coastguard Worker     uint16_t* dst_buffer = static_cast<uint16_t*>(dst->planes[UHDR_PLANE_Y]);
376*89a0ef05SAndroid Build Coastguard Worker     desc->m_crop_uint16_t(src_buffer, dst_buffer, src->stride[UHDR_PLANE_Y],
377*89a0ef05SAndroid Build Coastguard Worker                           dst->stride[UHDR_PLANE_Y], left, top, wd, ht);
378*89a0ef05SAndroid Build Coastguard Worker     uint32_t* src_uv_buffer = static_cast<uint32_t*>(src->planes[UHDR_PLANE_UV]);
379*89a0ef05SAndroid Build Coastguard Worker     uint32_t* dst_uv_buffer = static_cast<uint32_t*>(dst->planes[UHDR_PLANE_UV]);
380*89a0ef05SAndroid Build Coastguard Worker     desc->m_crop_uint32_t(src_uv_buffer, dst_uv_buffer, src->stride[UHDR_PLANE_UV] / 2,
381*89a0ef05SAndroid Build Coastguard Worker                           dst->stride[UHDR_PLANE_UV] / 2, left / 2, top / 2, wd / 2, ht / 2);
382*89a0ef05SAndroid Build Coastguard Worker   } else if (src->fmt == UHDR_IMG_FMT_12bppYCbCr420 || src->fmt == UHDR_IMG_FMT_8bppYCbCr400) {
383*89a0ef05SAndroid Build Coastguard Worker     uint8_t* src_buffer = static_cast<uint8_t*>(src->planes[UHDR_PLANE_Y]);
384*89a0ef05SAndroid Build Coastguard Worker     uint8_t* dst_buffer = static_cast<uint8_t*>(dst->planes[UHDR_PLANE_Y]);
385*89a0ef05SAndroid Build Coastguard Worker     desc->m_crop_uint8_t(src_buffer, dst_buffer, src->stride[UHDR_PLANE_Y],
386*89a0ef05SAndroid Build Coastguard Worker                          dst->stride[UHDR_PLANE_Y], left, top, wd, ht);
387*89a0ef05SAndroid Build Coastguard Worker     if (src->fmt == UHDR_IMG_FMT_12bppYCbCr420) {
388*89a0ef05SAndroid Build Coastguard Worker       for (int i = 1; i < 3; i++) {
389*89a0ef05SAndroid Build Coastguard Worker         src_buffer = static_cast<uint8_t*>(src->planes[i]);
390*89a0ef05SAndroid Build Coastguard Worker         dst_buffer = static_cast<uint8_t*>(dst->planes[i]);
391*89a0ef05SAndroid Build Coastguard Worker         desc->m_crop_uint8_t(src_buffer, dst_buffer, src->stride[i], dst->stride[i], left / 2,
392*89a0ef05SAndroid Build Coastguard Worker                              top / 2, wd / 2, ht / 2);
393*89a0ef05SAndroid Build Coastguard Worker       }
394*89a0ef05SAndroid Build Coastguard Worker     }
395*89a0ef05SAndroid Build Coastguard Worker   } else if (src->fmt == UHDR_IMG_FMT_32bppRGBA1010102 || src->fmt == UHDR_IMG_FMT_32bppRGBA8888) {
396*89a0ef05SAndroid Build Coastguard Worker     uint32_t* src_buffer = static_cast<uint32_t*>(src->planes[UHDR_PLANE_PACKED]);
397*89a0ef05SAndroid Build Coastguard Worker     uint32_t* dst_buffer = static_cast<uint32_t*>(dst->planes[UHDR_PLANE_PACKED]);
398*89a0ef05SAndroid Build Coastguard Worker     desc->m_crop_uint32_t(src_buffer, dst_buffer, src->stride[UHDR_PLANE_PACKED],
399*89a0ef05SAndroid Build Coastguard Worker                           dst->stride[UHDR_PLANE_PACKED], left, top, wd, ht);
400*89a0ef05SAndroid Build Coastguard Worker   } else if (src->fmt == UHDR_IMG_FMT_64bppRGBAHalfFloat) {
401*89a0ef05SAndroid Build Coastguard Worker     uint64_t* src_buffer = static_cast<uint64_t*>(src->planes[UHDR_PLANE_PACKED]);
402*89a0ef05SAndroid Build Coastguard Worker     uint64_t* dst_buffer = static_cast<uint64_t*>(dst->planes[UHDR_PLANE_PACKED]);
403*89a0ef05SAndroid Build Coastguard Worker     desc->m_crop_uint64_t(src_buffer, dst_buffer, src->stride[UHDR_PLANE_PACKED],
404*89a0ef05SAndroid Build Coastguard Worker                           dst->stride[UHDR_PLANE_PACKED], left, top, wd, ht);
405*89a0ef05SAndroid Build Coastguard Worker   } else if (src->fmt == UHDR_IMG_FMT_24bppYCbCr444) {
406*89a0ef05SAndroid Build Coastguard Worker     for (int i = 0; i < 3; i++) {
407*89a0ef05SAndroid Build Coastguard Worker       uint8_t* src_buffer = static_cast<uint8_t*>(src->planes[i]);
408*89a0ef05SAndroid Build Coastguard Worker       uint8_t* dst_buffer = static_cast<uint8_t*>(dst->planes[i]);
409*89a0ef05SAndroid Build Coastguard Worker       desc->m_crop_uint8_t(src_buffer, dst_buffer, src->stride[i], dst->stride[i], left, top, wd,
410*89a0ef05SAndroid Build Coastguard Worker                            ht);
411*89a0ef05SAndroid Build Coastguard Worker     }
412*89a0ef05SAndroid Build Coastguard Worker   } else if (src->fmt == UHDR_IMG_FMT_30bppYCbCr444) {
413*89a0ef05SAndroid Build Coastguard Worker     for (int i = 0; i < 3; i++) {
414*89a0ef05SAndroid Build Coastguard Worker       uint16_t* src_buffer = static_cast<uint16_t*>(src->planes[i]);
415*89a0ef05SAndroid Build Coastguard Worker       uint16_t* dst_buffer = static_cast<uint16_t*>(dst->planes[i]);
416*89a0ef05SAndroid Build Coastguard Worker       desc->m_crop_uint16_t(src_buffer, dst_buffer, src->stride[UHDR_PLANE_PACKED],
417*89a0ef05SAndroid Build Coastguard Worker                             dst->stride[UHDR_PLANE_PACKED], left, top, wd, ht);
418*89a0ef05SAndroid Build Coastguard Worker     }
419*89a0ef05SAndroid Build Coastguard Worker   }
420*89a0ef05SAndroid Build Coastguard Worker   return dst;
421*89a0ef05SAndroid Build Coastguard Worker }
422*89a0ef05SAndroid Build Coastguard Worker 
apply_resize(ultrahdr::uhdr_resize_effect_t * desc,uhdr_raw_image_t * src,int dst_w,int dst_h,void * gl_ctxt,void * texture)423*89a0ef05SAndroid Build Coastguard Worker std::unique_ptr<uhdr_raw_image_ext_t> apply_resize(ultrahdr::uhdr_resize_effect_t* desc,
424*89a0ef05SAndroid Build Coastguard Worker                                                    uhdr_raw_image_t* src, int dst_w, int dst_h,
425*89a0ef05SAndroid Build Coastguard Worker                                                    [[maybe_unused]] void* gl_ctxt,
426*89a0ef05SAndroid Build Coastguard Worker                                                    [[maybe_unused]] void* texture) {
427*89a0ef05SAndroid Build Coastguard Worker #ifdef UHDR_ENABLE_GLES
428*89a0ef05SAndroid Build Coastguard Worker   if ((src->fmt == UHDR_IMG_FMT_32bppRGBA1010102 || src->fmt == UHDR_IMG_FMT_32bppRGBA8888 ||
429*89a0ef05SAndroid Build Coastguard Worker        src->fmt == UHDR_IMG_FMT_64bppRGBAHalfFloat || src->fmt == UHDR_IMG_FMT_8bppYCbCr400) &&
430*89a0ef05SAndroid Build Coastguard Worker       gl_ctxt != nullptr && *static_cast<GLuint*>(texture) != 0) {
431*89a0ef05SAndroid Build Coastguard Worker     return apply_resize_gles(src, dst_w, dst_h, static_cast<ultrahdr::uhdr_opengl_ctxt*>(gl_ctxt),
432*89a0ef05SAndroid Build Coastguard Worker                              static_cast<GLuint*>(texture));
433*89a0ef05SAndroid Build Coastguard Worker   }
434*89a0ef05SAndroid Build Coastguard Worker #endif
435*89a0ef05SAndroid Build Coastguard Worker   std::unique_ptr<uhdr_raw_image_ext_t> dst = std::make_unique<uhdr_raw_image_ext_t>(
436*89a0ef05SAndroid Build Coastguard Worker       src->fmt, src->cg, src->ct, src->range, dst_w, dst_h, 64);
437*89a0ef05SAndroid Build Coastguard Worker 
438*89a0ef05SAndroid Build Coastguard Worker   if (src->fmt == UHDR_IMG_FMT_24bppYCbCrP010) {
439*89a0ef05SAndroid Build Coastguard Worker     uint16_t* src_buffer = static_cast<uint16_t*>(src->planes[UHDR_PLANE_Y]);
440*89a0ef05SAndroid Build Coastguard Worker     uint16_t* dst_buffer = static_cast<uint16_t*>(dst->planes[UHDR_PLANE_Y]);
441*89a0ef05SAndroid Build Coastguard Worker     desc->m_resize_uint16_t(src_buffer, dst_buffer, src->w, src->h, dst->w, dst->h,
442*89a0ef05SAndroid Build Coastguard Worker                             src->stride[UHDR_PLANE_Y], dst->stride[UHDR_PLANE_Y]);
443*89a0ef05SAndroid Build Coastguard Worker     uint32_t* src_uv_buffer = static_cast<uint32_t*>(src->planes[UHDR_PLANE_UV]);
444*89a0ef05SAndroid Build Coastguard Worker     uint32_t* dst_uv_buffer = static_cast<uint32_t*>(dst->planes[UHDR_PLANE_UV]);
445*89a0ef05SAndroid Build Coastguard Worker     desc->m_resize_uint32_t(src_uv_buffer, dst_uv_buffer, src->w / 2, src->h / 2, dst->w / 2,
446*89a0ef05SAndroid Build Coastguard Worker                             dst->h / 2, src->stride[UHDR_PLANE_UV] / 2,
447*89a0ef05SAndroid Build Coastguard Worker                             dst->stride[UHDR_PLANE_UV] / 2);
448*89a0ef05SAndroid Build Coastguard Worker   } else if (src->fmt == UHDR_IMG_FMT_12bppYCbCr420 || src->fmt == UHDR_IMG_FMT_8bppYCbCr400) {
449*89a0ef05SAndroid Build Coastguard Worker     uint8_t* src_buffer = static_cast<uint8_t*>(src->planes[UHDR_PLANE_Y]);
450*89a0ef05SAndroid Build Coastguard Worker     uint8_t* dst_buffer = static_cast<uint8_t*>(dst->planes[UHDR_PLANE_Y]);
451*89a0ef05SAndroid Build Coastguard Worker     desc->m_resize_uint8_t(src_buffer, dst_buffer, src->w, src->h, dst->w, dst->h,
452*89a0ef05SAndroid Build Coastguard Worker                            src->stride[UHDR_PLANE_Y], dst->stride[UHDR_PLANE_Y]);
453*89a0ef05SAndroid Build Coastguard Worker     if (src->fmt == UHDR_IMG_FMT_12bppYCbCr420) {
454*89a0ef05SAndroid Build Coastguard Worker       for (int i = 1; i < 3; i++) {
455*89a0ef05SAndroid Build Coastguard Worker         src_buffer = static_cast<uint8_t*>(src->planes[i]);
456*89a0ef05SAndroid Build Coastguard Worker         dst_buffer = static_cast<uint8_t*>(dst->planes[i]);
457*89a0ef05SAndroid Build Coastguard Worker         desc->m_resize_uint8_t(src_buffer, dst_buffer, src->w / 2, src->h / 2, dst->w / 2,
458*89a0ef05SAndroid Build Coastguard Worker                                dst->h / 2, src->stride[i], dst->stride[i]);
459*89a0ef05SAndroid Build Coastguard Worker       }
460*89a0ef05SAndroid Build Coastguard Worker     }
461*89a0ef05SAndroid Build Coastguard Worker   } else if (src->fmt == UHDR_IMG_FMT_32bppRGBA1010102 || src->fmt == UHDR_IMG_FMT_32bppRGBA8888) {
462*89a0ef05SAndroid Build Coastguard Worker     uint32_t* src_buffer = static_cast<uint32_t*>(src->planes[UHDR_PLANE_PACKED]);
463*89a0ef05SAndroid Build Coastguard Worker     uint32_t* dst_buffer = static_cast<uint32_t*>(dst->planes[UHDR_PLANE_PACKED]);
464*89a0ef05SAndroid Build Coastguard Worker     desc->m_resize_uint32_t(src_buffer, dst_buffer, src->w, src->h, dst->w, dst->h,
465*89a0ef05SAndroid Build Coastguard Worker                             src->stride[UHDR_PLANE_PACKED], dst->stride[UHDR_PLANE_PACKED]);
466*89a0ef05SAndroid Build Coastguard Worker   } else if (src->fmt == UHDR_IMG_FMT_64bppRGBAHalfFloat) {
467*89a0ef05SAndroid Build Coastguard Worker     uint64_t* src_buffer = static_cast<uint64_t*>(src->planes[UHDR_PLANE_PACKED]);
468*89a0ef05SAndroid Build Coastguard Worker     uint64_t* dst_buffer = static_cast<uint64_t*>(dst->planes[UHDR_PLANE_PACKED]);
469*89a0ef05SAndroid Build Coastguard Worker     desc->m_resize_uint64_t(src_buffer, dst_buffer, src->w, src->h, dst->w, dst->h,
470*89a0ef05SAndroid Build Coastguard Worker                             src->stride[UHDR_PLANE_PACKED], dst->stride[UHDR_PLANE_PACKED]);
471*89a0ef05SAndroid Build Coastguard Worker   } else if (src->fmt == UHDR_IMG_FMT_24bppYCbCr444) {
472*89a0ef05SAndroid Build Coastguard Worker     for (int i = 0; i < 3; i++) {
473*89a0ef05SAndroid Build Coastguard Worker       uint8_t* src_buffer = static_cast<uint8_t*>(src->planes[i]);
474*89a0ef05SAndroid Build Coastguard Worker       uint8_t* dst_buffer = static_cast<uint8_t*>(dst->planes[i]);
475*89a0ef05SAndroid Build Coastguard Worker       desc->m_resize_uint8_t(src_buffer, dst_buffer, src->w, src->h, dst->w, dst->h, src->stride[i],
476*89a0ef05SAndroid Build Coastguard Worker                              dst->stride[i]);
477*89a0ef05SAndroid Build Coastguard Worker     }
478*89a0ef05SAndroid Build Coastguard Worker   } else if (src->fmt == UHDR_IMG_FMT_30bppYCbCr444) {
479*89a0ef05SAndroid Build Coastguard Worker     for (int i = 0; i < 3; i++) {
480*89a0ef05SAndroid Build Coastguard Worker       uint16_t* src_buffer = static_cast<uint16_t*>(src->planes[i]);
481*89a0ef05SAndroid Build Coastguard Worker       uint16_t* dst_buffer = static_cast<uint16_t*>(dst->planes[i]);
482*89a0ef05SAndroid Build Coastguard Worker       desc->m_resize_uint16_t(src_buffer, dst_buffer, src->w, src->h, dst->w, dst->h,
483*89a0ef05SAndroid Build Coastguard Worker                               src->stride[i], dst->stride[i]);
484*89a0ef05SAndroid Build Coastguard Worker     }
485*89a0ef05SAndroid Build Coastguard Worker   }
486*89a0ef05SAndroid Build Coastguard Worker   return dst;
487*89a0ef05SAndroid Build Coastguard Worker }
488*89a0ef05SAndroid Build Coastguard Worker 
489*89a0ef05SAndroid Build Coastguard Worker }  // namespace ultrahdr
490