1 /*
2 * Copyright (c) 2011 The LibYuv project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "libyuv/general.h"
12
13 #include <string.h> // memcpy(), memset()
14
15 #include "libyuv/planar_functions.h"
16
17 namespace libyuv {
18
19 int
I420Mirror(const uint8 * src_yplane,int src_ystride,const uint8 * src_uplane,int src_ustride,const uint8 * src_vplane,int src_vstride,uint8 * dst_yplane,int dst_ystride,uint8 * dst_uplane,int dst_ustride,uint8 * dst_vplane,int dst_vstride,int width,int height)20 I420Mirror(const uint8* src_yplane, int src_ystride,
21 const uint8* src_uplane, int src_ustride,
22 const uint8* src_vplane, int src_vstride,
23 uint8* dst_yplane, int dst_ystride,
24 uint8* dst_uplane, int dst_ustride,
25 uint8* dst_vplane, int dst_vstride,
26 int width, int height) {
27 if (src_yplane == NULL || src_uplane == NULL || src_vplane == NULL ||
28 dst_yplane == NULL || dst_uplane == NULL || dst_vplane == NULL) {
29 return -1;
30 }
31
32 int indO = 0;
33 int indS = 0;
34 int wind, hind;
35 uint8 tmpVal, tmpValU, tmpValV;
36 // Will swap two values per iteration
37 const int halfWidth = (width + 1) >> 1;
38
39 // Y
40 for (wind = 0; wind < halfWidth; wind++) {
41 for (hind = 0; hind < height; hind++) {
42 indO = hind * src_ystride + wind;
43 indS = hind * dst_ystride + (width - wind - 1);
44 tmpVal = src_yplane[indO];
45 dst_yplane[indO] = src_yplane[indS];
46 dst_yplane[indS] = tmpVal;
47 }
48 }
49
50 const int halfHeight = (height + 1) >> 1;
51 const int halfSrcuvStride = (height + 1) >> 1;
52 const int halfuvWidth = (width + 1) >> 2;
53
54 for (wind = 0; wind < halfuvWidth; wind++) {
55 for (hind = 0; hind < halfHeight; hind++) {
56 indO = hind * halfSrcuvStride + wind;
57 indS = hind * halfSrcuvStride + (halfuvWidth - wind - 1);
58 // U
59 tmpValU = src_uplane[indO];
60 dst_uplane[indO] = src_uplane[indS];
61 dst_uplane[indS] = tmpValU;
62 // V
63 tmpValV = src_vplane[indO];
64 dst_vplane[indO] = src_vplane[indS];
65 dst_vplane[indS] = tmpValV;
66 }
67 }
68 return 0;
69 }
70
71 // Make a center cut
72 int
I420Crop(uint8 * frame,int src_width,int src_height,int dst_width,int dst_height)73 I420Crop(uint8* frame,
74 int src_width, int src_height,
75 int dst_width, int dst_height)
76 {
77 if (frame == NULL)
78 return -1;
79
80 if (src_width == dst_width && src_height == dst_height) {
81 // Nothing to do
82 return 3 * dst_height * dst_width / 2;
83 }
84 if (dst_width > src_width || dst_height > src_height) {
85 // error
86 return -1;
87 }
88 int i = 0;
89 int m = 0;
90 int loop = 0;
91 int half_dst_width = dst_width / 2;
92 int halfdst_height = dst_height / 2;
93 int halfsrc_width = src_width / 2;
94 int half_dst_height= src_height / 2;
95 int crop_height = ( src_height - dst_height ) / 2;
96 int crop_width = ( src_width - dst_width ) / 2;
97
98 for (i = src_width * crop_height + crop_width; loop < dst_height ;
99 loop++, i += src_width) {
100 memcpy(&frame[m],&frame[i],dst_width);
101 m += dst_width;
102 }
103 i = src_width * src_height; // ilum
104 loop = 0;
105 for ( i += (halfsrc_width * crop_height / 2 + crop_width / 2);
106 loop < halfdst_height; loop++,i += halfsrc_width) {
107 memcpy(&frame[m],&frame[i],half_dst_width);
108 m += half_dst_width;
109 }
110 loop = 0;
111 i = src_width * src_height + half_dst_height * halfsrc_width; // ilum + Cr
112 for ( i += (halfsrc_width * crop_height / 2 + crop_width / 2);
113 loop < halfdst_height; loop++, i += halfsrc_width) {
114 memcpy(&frame[m],&frame[i],half_dst_width);
115 m += half_dst_width;
116 }
117 return 0;
118 }
119
120
121 int
I420CropPad(const uint8 * src_frame,int src_width,int src_height,uint8 * dst_frame,int dst_width,int dst_height)122 I420CropPad(const uint8* src_frame, int src_width,
123 int src_height, uint8* dst_frame,
124 int dst_width, int dst_height)
125 {
126 if (src_width < 1 || dst_width < 1 || src_height < 1 || dst_height < 1) {
127 return -1;
128 }
129 if (src_width == dst_width && src_height == dst_height) {
130 memcpy(dst_frame, src_frame, 3 * dst_width * (dst_height >> 1));
131 } else {
132 if (src_height < dst_height) {
133 // pad height
134 int pad_height = dst_height - src_height;
135 int i = 0;
136 int pad_width = 0;
137 int crop_width = 0;
138 int width = src_width;
139 if (src_width < dst_width) {
140 // pad width
141 pad_width = dst_width - src_width;
142 } else {
143 // cut width
144 crop_width = src_width - dst_width;
145 width = dst_width;
146 }
147 if (pad_height) {
148 memset(dst_frame, 0, dst_width * (pad_height >> 1));
149 dst_frame += dst_width * (pad_height >> 1);
150 }
151 for (i = 0; i < src_height;i++) {
152 if (pad_width) {
153 memset(dst_frame, 0, pad_width / 2);
154 dst_frame += pad_width / 2;
155 }
156 src_frame += crop_width >> 1; // in case we have a cut
157 memcpy(dst_frame,src_frame ,width);
158 src_frame += crop_width >> 1;
159 dst_frame += width;
160 src_frame += width;
161 if (pad_width) {
162 memset(dst_frame, 0, pad_width / 2);
163 dst_frame += pad_width / 2;
164 }
165 }
166 if (pad_height) {
167 memset(dst_frame, 0, dst_width * (pad_height >> 1));
168 dst_frame += dst_width * (pad_height >> 1);
169 }
170 if (pad_height) {
171 memset(dst_frame, 127, (dst_width >> 2) * (pad_height >> 1));
172 dst_frame += (dst_width >> 2) * (pad_height >> 1);
173 }
174 for (i = 0; i < (src_height >> 1); i++) {
175 if (pad_width) {
176 memset(dst_frame, 127, pad_width >> 2);
177 dst_frame += pad_width >> 2;
178 }
179 src_frame += crop_width >> 2; // in case we have a cut
180 memcpy(dst_frame, src_frame,width >> 1);
181 src_frame += crop_width >> 2;
182 dst_frame += width >> 1;
183 src_frame += width >> 1;
184 if (pad_width) {
185 memset(dst_frame, 127, pad_width >> 2);
186 dst_frame += pad_width >> 2;
187 }
188 }
189 if (pad_height) {
190 memset(dst_frame, 127, (dst_width >> 1) * (pad_height >> 1));
191 dst_frame += (dst_width >> 1) * (pad_height >> 1);
192 }
193 for (i = 0; i < (src_height >> 1); i++) {
194 if (pad_width) {
195 memset(dst_frame, 127, pad_width >> 2);
196 dst_frame += pad_width >> 2;
197 }
198 src_frame += crop_width >> 2; // in case we have a cut
199 memcpy(dst_frame, src_frame,width >> 1);
200 src_frame += crop_width >> 2;
201 dst_frame += width >> 1;
202 src_frame += width >> 1;
203 if (pad_width) {
204 memset(dst_frame, 127, pad_width >> 2);
205 dst_frame += pad_width >> 2;
206 }
207 }
208 if (pad_height) {
209 memset(dst_frame, 127, (dst_width >> 2) * (pad_height >> 1));
210 dst_frame += (dst_width >> 2) * (pad_height >> 1);
211 }
212 } else {
213 // cut height
214 int i = 0;
215 int pad_width = 0;
216 int crop_width = 0;
217 int width = src_width;
218
219 if (src_width < dst_width) {
220 // pad width
221 pad_width = dst_width - src_width;
222 } else {
223 // cut width
224 crop_width = src_width - dst_width;
225 width = dst_width;
226 }
227 int diff_height = src_height - dst_height;
228 src_frame += src_width * (diff_height >> 1); // skip top I
229
230 for (i = 0; i < dst_height; i++) {
231 if (pad_width) {
232 memset(dst_frame, 0, pad_width / 2);
233 dst_frame += pad_width / 2;
234 }
235 src_frame += crop_width >> 1; // in case we have a cut
236 memcpy(dst_frame,src_frame ,width);
237 src_frame += crop_width >> 1;
238 dst_frame += width;
239 src_frame += width;
240 if (pad_width) {
241 memset(dst_frame, 0, pad_width / 2);
242 dst_frame += pad_width / 2;
243 }
244 }
245 src_frame += src_width * (diff_height >> 1); // skip end I
246 src_frame += (src_width >> 2) * (diff_height >> 1); // skip top of Cr
247 for (i = 0; i < (dst_height >> 1); i++) {
248 if (pad_width) {
249 memset(dst_frame, 127, pad_width >> 2);
250 dst_frame += pad_width >> 2;
251 }
252 src_frame += crop_width >> 2; // in case we have a cut
253 memcpy(dst_frame, src_frame,width >> 1);
254 src_frame += crop_width >> 2;
255 dst_frame += width >> 1;
256 src_frame += width >> 1;
257 if (pad_width) {
258 memset(dst_frame, 127, pad_width >> 2);
259 dst_frame += pad_width >> 2;
260 }
261 }
262 src_frame += (src_width >> 2) * (diff_height >> 1); // skip end of Cr
263 src_frame += (src_width >> 2) * (diff_height >> 1); // skip top of Cb
264 for (i = 0; i < (dst_height >> 1); i++) {
265 if (pad_width) {
266 memset(dst_frame, 127, pad_width >> 2);
267 dst_frame += pad_width >> 2;
268 }
269 src_frame += crop_width >> 2; // in case we have a cut
270 memcpy(dst_frame, src_frame, width >> 1);
271 src_frame += crop_width >> 2;
272 dst_frame += width >> 1;
273 src_frame += width >> 1;
274 if (pad_width) {
275 memset(dst_frame, 127, pad_width >> 2);
276 dst_frame += pad_width >> 2;
277 }
278 }
279 }
280 }
281 return 0;
282 }
283
284 } // namespace libyuv
285