1 /*
2
3 # RGB / YUV flip/rotate routines
4
5 # (C) 2008 Hans de Goede <hdegoede@redhat.com>
6
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU Lesser General Public License as published by
9 # the Free Software Foundation; either version 2.1 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU Lesser General Public License for more details.
16 #
17 # You should have received a copy of the GNU Lesser General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
20
21 */
22
23 #include <string.h>
24 #include "libv4lconvert-priv.h"
25
v4lconvert_vflip_rgbbgr24(unsigned char * src,unsigned char * dest,struct v4l2_format * fmt)26 static void v4lconvert_vflip_rgbbgr24(unsigned char *src, unsigned char *dest,
27 struct v4l2_format *fmt)
28 {
29 int y;
30
31 src += fmt->fmt.pix.height * fmt->fmt.pix.bytesperline;
32 for (y = 0; y < fmt->fmt.pix.height; y++) {
33 src -= fmt->fmt.pix.bytesperline;
34 memcpy(dest, src, fmt->fmt.pix.width * 3);
35 dest += fmt->fmt.pix.width * 3;
36 }
37 }
38
v4lconvert_vflip_yuv420(unsigned char * src,unsigned char * dest,struct v4l2_format * fmt)39 static void v4lconvert_vflip_yuv420(unsigned char *src, unsigned char *dest,
40 struct v4l2_format *fmt)
41 {
42 int y;
43
44 /* First flip the Y plane */
45 src += fmt->fmt.pix.height * fmt->fmt.pix.bytesperline;
46 for (y = 0; y < fmt->fmt.pix.height; y++) {
47 src -= fmt->fmt.pix.bytesperline;
48 memcpy(dest, src, fmt->fmt.pix.width);
49 dest += fmt->fmt.pix.width;
50 }
51
52 /* Now flip the U plane */
53 src += fmt->fmt.pix.height * fmt->fmt.pix.bytesperline * 5 / 4;
54 for (y = 0; y < fmt->fmt.pix.height / 2; y++) {
55 src -= fmt->fmt.pix.bytesperline / 2;
56 memcpy(dest, src, fmt->fmt.pix.width / 2);
57 dest += fmt->fmt.pix.width / 2;
58 }
59
60 /* Last flip the V plane */
61 src += fmt->fmt.pix.height * fmt->fmt.pix.bytesperline / 2;
62 for (y = 0; y < fmt->fmt.pix.height / 2; y++) {
63 src -= fmt->fmt.pix.bytesperline / 2;
64 memcpy(dest, src, fmt->fmt.pix.width / 2);
65 dest += fmt->fmt.pix.width / 2;
66 }
67 }
68
v4lconvert_hflip_rgbbgr24(unsigned char * src,unsigned char * dest,struct v4l2_format * fmt)69 static void v4lconvert_hflip_rgbbgr24(unsigned char *src, unsigned char *dest,
70 struct v4l2_format *fmt)
71 {
72 int x, y;
73
74 for (y = 0; y < fmt->fmt.pix.height; y++) {
75 src += fmt->fmt.pix.width * 3;
76 for (x = 0; x < fmt->fmt.pix.width; x++) {
77 src -= 3;
78 dest[0] = src[0];
79 dest[1] = src[1];
80 dest[2] = src[2];
81 dest += 3;
82 }
83 src += fmt->fmt.pix.bytesperline;
84 }
85 }
86
v4lconvert_hflip_yuv420(unsigned char * src,unsigned char * dest,struct v4l2_format * fmt)87 static void v4lconvert_hflip_yuv420(unsigned char *src, unsigned char *dest,
88 struct v4l2_format *fmt)
89 {
90 int x, y;
91
92 /* First flip the Y plane */
93 for (y = 0; y < fmt->fmt.pix.height; y++) {
94 src += fmt->fmt.pix.width;
95 for (x = 0; x < fmt->fmt.pix.width; x++)
96 *dest++ = *--src;
97 src += fmt->fmt.pix.bytesperline;
98 }
99
100 /* Now flip the U plane */
101 for (y = 0; y < fmt->fmt.pix.height / 2; y++) {
102 src += fmt->fmt.pix.width / 2;
103 for (x = 0; x < fmt->fmt.pix.width / 2; x++)
104 *dest++ = *--src;
105 src += fmt->fmt.pix.bytesperline / 2;
106 }
107
108 /* Last flip the V plane */
109 for (y = 0; y < fmt->fmt.pix.height / 2; y++) {
110 src += fmt->fmt.pix.width / 2;
111 for (x = 0; x < fmt->fmt.pix.width / 2; x++)
112 *dest++ = *--src;
113 src += fmt->fmt.pix.bytesperline / 2;
114 }
115 }
116
v4lconvert_rotate180_rgbbgr24(const unsigned char * src,unsigned char * dst,int width,int height)117 static void v4lconvert_rotate180_rgbbgr24(const unsigned char *src,
118 unsigned char *dst, int width, int height)
119 {
120 int i;
121
122 src += 3 * width * height - 3;
123
124 for (i = 0; i < width * height; i++) {
125 dst[0] = src[0];
126 dst[1] = src[1];
127 dst[2] = src[2];
128 dst += 3;
129 src -= 3;
130 }
131 }
132
v4lconvert_rotate180_yuv420(const unsigned char * src,unsigned char * dst,int width,int height)133 static void v4lconvert_rotate180_yuv420(const unsigned char *src,
134 unsigned char *dst, int width, int height)
135 {
136 int i;
137
138 /* First flip x and y of the Y plane */
139 src += width * height - 1;
140 for (i = 0; i < width * height; i++)
141 *dst++ = *src--;
142
143 /* Now flip the U plane */
144 src += width * height * 5 / 4;
145 for (i = 0; i < width * height / 4; i++)
146 *dst++ = *src--;
147
148 /* Last flip the V plane */
149 src += width * height / 2;
150 for (i = 0; i < width * height / 4; i++)
151 *dst++ = *src--;
152 }
153
v4lconvert_rotate90_rgbbgr24(const unsigned char * src,unsigned char * dst,int destwidth,int destheight)154 static void v4lconvert_rotate90_rgbbgr24(const unsigned char *src,
155 unsigned char *dst, int destwidth, int destheight)
156 {
157 int x, y;
158 #define srcwidth destheight
159 #define srcheight destwidth
160
161 for (y = 0; y < destheight; y++)
162 for (x = 0; x < destwidth; x++) {
163 int offset = ((srcheight - x - 1) * srcwidth + y) * 3;
164 *dst++ = src[offset++];
165 *dst++ = src[offset++];
166 *dst++ = src[offset];
167 }
168 }
169
v4lconvert_rotate90_yuv420(const unsigned char * src,unsigned char * dst,int destwidth,int destheight)170 static void v4lconvert_rotate90_yuv420(const unsigned char *src,
171 unsigned char *dst, int destwidth, int destheight)
172 {
173 int x, y;
174
175 /* Y-plane */
176 for (y = 0; y < destheight; y++)
177 for (x = 0; x < destwidth; x++) {
178 int offset = (srcheight - x - 1) * srcwidth + y;
179 *dst++ = src[offset];
180 }
181
182 /* U-plane */
183 src += srcwidth * srcheight;
184 destwidth /= 2;
185 destheight /= 2;
186 for (y = 0; y < destheight; y++)
187 for (x = 0; x < destwidth; x++) {
188 int offset = (srcheight - x - 1) * srcwidth + y;
189 *dst++ = src[offset];
190 }
191
192 /* V-plane */
193 src += srcwidth * srcheight;
194 for (y = 0; y < destheight; y++)
195 for (x = 0; x < destwidth; x++) {
196 int offset = (srcheight - x - 1) * srcwidth + y;
197 *dst++ = src[offset];
198 }
199 }
200
v4lconvert_rotate90(unsigned char * src,unsigned char * dest,struct v4l2_format * fmt)201 void v4lconvert_rotate90(unsigned char *src, unsigned char *dest,
202 struct v4l2_format *fmt)
203 {
204 int tmp;
205
206 tmp = fmt->fmt.pix.width;
207 fmt->fmt.pix.width = fmt->fmt.pix.height;
208 fmt->fmt.pix.height = tmp;
209
210 switch (fmt->fmt.pix.pixelformat) {
211 case V4L2_PIX_FMT_RGB24:
212 case V4L2_PIX_FMT_BGR24:
213 v4lconvert_rotate90_rgbbgr24(src, dest, fmt->fmt.pix.width,
214 fmt->fmt.pix.height);
215 break;
216 case V4L2_PIX_FMT_YUV420:
217 case V4L2_PIX_FMT_YVU420:
218 v4lconvert_rotate90_yuv420(src, dest, fmt->fmt.pix.width,
219 fmt->fmt.pix.height);
220 break;
221 }
222 v4lconvert_fixup_fmt(fmt);
223 }
224
v4lconvert_flip(unsigned char * src,unsigned char * dest,struct v4l2_format * fmt,int hflip,int vflip)225 void v4lconvert_flip(unsigned char *src, unsigned char *dest,
226 struct v4l2_format *fmt, int hflip, int vflip)
227 {
228 if (vflip && hflip) {
229 switch (fmt->fmt.pix.pixelformat) {
230 case V4L2_PIX_FMT_RGB24:
231 case V4L2_PIX_FMT_BGR24:
232 v4lconvert_rotate180_rgbbgr24(src, dest, fmt->fmt.pix.width,
233 fmt->fmt.pix.height);
234 break;
235 case V4L2_PIX_FMT_YUV420:
236 case V4L2_PIX_FMT_YVU420:
237 v4lconvert_rotate180_yuv420(src, dest, fmt->fmt.pix.width,
238 fmt->fmt.pix.height);
239 break;
240 }
241 } else if (hflip) {
242 switch (fmt->fmt.pix.pixelformat) {
243 case V4L2_PIX_FMT_RGB24:
244 case V4L2_PIX_FMT_BGR24:
245 v4lconvert_hflip_rgbbgr24(src, dest, fmt);
246 break;
247 case V4L2_PIX_FMT_YUV420:
248 case V4L2_PIX_FMT_YVU420:
249 v4lconvert_hflip_yuv420(src, dest, fmt);
250 break;
251 }
252 } else if (vflip) {
253 switch (fmt->fmt.pix.pixelformat) {
254 case V4L2_PIX_FMT_RGB24:
255 case V4L2_PIX_FMT_BGR24:
256 v4lconvert_vflip_rgbbgr24(src, dest, fmt);
257 break;
258 case V4L2_PIX_FMT_YUV420:
259 case V4L2_PIX_FMT_YVU420:
260 v4lconvert_vflip_yuv420(src, dest, fmt);
261 break;
262 }
263 }
264
265 /* Our newly written data has no padding */
266 v4lconvert_fixup_fmt(fmt);
267 }
268