1 : /*
2 : * Copyright (c) 2010 The WebM 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 :
12 : #include <stdlib.h>
13 : #include <string.h>
14 : #include "vpx/vpx_image.h"
15 :
16 0 : static vpx_image_t *img_alloc_helper(vpx_image_t *img,
17 : vpx_img_fmt_t fmt,
18 : unsigned int d_w,
19 : unsigned int d_h,
20 : unsigned int stride_align,
21 : unsigned char *img_data)
22 : {
23 :
24 : unsigned int h, w, s, xcs, ycs, bps;
25 : int align;
26 :
27 : /* Treat align==0 like align==1 */
28 0 : if (!stride_align)
29 0 : stride_align = 1;
30 :
31 : /* Validate alignment (must be power of 2) */
32 0 : if (stride_align & (stride_align - 1))
33 0 : goto fail;
34 :
35 : /* Get sample size for this format */
36 0 : switch (fmt)
37 : {
38 : case VPX_IMG_FMT_RGB32:
39 : case VPX_IMG_FMT_RGB32_LE:
40 : case VPX_IMG_FMT_ARGB:
41 : case VPX_IMG_FMT_ARGB_LE:
42 0 : bps = 32;
43 0 : break;
44 : case VPX_IMG_FMT_RGB24:
45 : case VPX_IMG_FMT_BGR24:
46 0 : bps = 24;
47 0 : break;
48 : case VPX_IMG_FMT_RGB565:
49 : case VPX_IMG_FMT_RGB565_LE:
50 : case VPX_IMG_FMT_RGB555:
51 : case VPX_IMG_FMT_RGB555_LE:
52 : case VPX_IMG_FMT_UYVY:
53 : case VPX_IMG_FMT_YUY2:
54 : case VPX_IMG_FMT_YVYU:
55 0 : bps = 16;
56 0 : break;
57 : case VPX_IMG_FMT_I420:
58 : case VPX_IMG_FMT_YV12:
59 : case VPX_IMG_FMT_VPXI420:
60 : case VPX_IMG_FMT_VPXYV12:
61 0 : bps = 12;
62 0 : break;
63 : default:
64 0 : bps = 16;
65 0 : break;
66 : }
67 :
68 : /* Get chroma shift values for this format */
69 0 : switch (fmt)
70 : {
71 : case VPX_IMG_FMT_I420:
72 : case VPX_IMG_FMT_YV12:
73 : case VPX_IMG_FMT_VPXI420:
74 : case VPX_IMG_FMT_VPXYV12:
75 0 : xcs = 1;
76 0 : break;
77 : default:
78 0 : xcs = 0;
79 0 : break;
80 : }
81 :
82 0 : switch (fmt)
83 : {
84 : case VPX_IMG_FMT_I420:
85 : case VPX_IMG_FMT_YV12:
86 : case VPX_IMG_FMT_VPXI420:
87 : case VPX_IMG_FMT_VPXYV12:
88 0 : ycs = 1;
89 0 : break;
90 : default:
91 0 : ycs = 0;
92 0 : break;
93 : }
94 :
95 : /* Calculate storage sizes given the chroma subsampling */
96 0 : align = (1 << xcs) - 1;
97 0 : w = (d_w + align) & ~align;
98 0 : align = (1 << ycs) - 1;
99 0 : h = (d_h + align) & ~align;
100 0 : s = (fmt & VPX_IMG_FMT_PLANAR) ? w : bps * w / 8;
101 0 : s = (s + stride_align - 1) & ~(stride_align - 1);
102 :
103 : /* Allocate the new image */
104 0 : if (!img)
105 : {
106 0 : img = (vpx_image_t *)calloc(1, sizeof(vpx_image_t));
107 :
108 0 : if (!img)
109 0 : goto fail;
110 :
111 0 : img->self_allocd = 1;
112 : }
113 : else
114 : {
115 0 : memset(img, 0, sizeof(vpx_image_t));
116 : }
117 :
118 0 : img->img_data = img_data;
119 :
120 0 : if (!img_data)
121 : {
122 0 : img->img_data = malloc((fmt & VPX_IMG_FMT_PLANAR) ? h * w * bps / 8 : h * s);
123 0 : img->img_data_owner = 1;
124 : }
125 :
126 0 : if (!img->img_data)
127 0 : goto fail;
128 :
129 0 : img->fmt = fmt;
130 0 : img->w = w;
131 0 : img->h = h;
132 0 : img->x_chroma_shift = xcs;
133 0 : img->y_chroma_shift = ycs;
134 0 : img->bps = bps;
135 :
136 : /* Calculate strides */
137 0 : img->stride[VPX_PLANE_Y] = img->stride[VPX_PLANE_ALPHA] = s;
138 0 : img->stride[VPX_PLANE_U] = img->stride[VPX_PLANE_V] = s >> xcs;
139 :
140 : /* Default viewport to entire image */
141 0 : if (!vpx_img_set_rect(img, 0, 0, d_w, d_h))
142 0 : return img;
143 :
144 : fail:
145 0 : vpx_img_free(img);
146 0 : return NULL;
147 : }
148 :
149 0 : vpx_image_t *vpx_img_alloc(vpx_image_t *img,
150 : vpx_img_fmt_t fmt,
151 : unsigned int d_w,
152 : unsigned int d_h,
153 : unsigned int stride_align)
154 : {
155 0 : return img_alloc_helper(img, fmt, d_w, d_h, stride_align, NULL);
156 : }
157 :
158 0 : vpx_image_t *vpx_img_wrap(vpx_image_t *img,
159 : vpx_img_fmt_t fmt,
160 : unsigned int d_w,
161 : unsigned int d_h,
162 : unsigned int stride_align,
163 : unsigned char *img_data)
164 : {
165 0 : return img_alloc_helper(img, fmt, d_w, d_h, stride_align, img_data);
166 : }
167 :
168 0 : int vpx_img_set_rect(vpx_image_t *img,
169 : unsigned int x,
170 : unsigned int y,
171 : unsigned int w,
172 : unsigned int h)
173 : {
174 : unsigned char *data;
175 :
176 0 : if (x + w <= img->w && y + h <= img->h)
177 : {
178 0 : img->d_w = w;
179 0 : img->d_h = h;
180 :
181 : /* Calculate plane pointers */
182 0 : if (!(img->fmt & VPX_IMG_FMT_PLANAR))
183 : {
184 0 : img->planes[VPX_PLANE_PACKED] =
185 0 : img->img_data + x * img->bps / 8 + y * img->stride[VPX_PLANE_PACKED];
186 : }
187 : else
188 : {
189 0 : data = img->img_data;
190 :
191 0 : if (img->fmt & VPX_IMG_FMT_HAS_ALPHA)
192 : {
193 0 : img->planes[VPX_PLANE_ALPHA] =
194 0 : data + x + y * img->stride[VPX_PLANE_ALPHA];
195 0 : data += img->h * img->stride[VPX_PLANE_ALPHA];
196 : }
197 :
198 0 : img->planes[VPX_PLANE_Y] = data + x + y * img->stride[VPX_PLANE_Y];
199 0 : data += img->h * img->stride[VPX_PLANE_Y];
200 :
201 0 : if (!(img->fmt & VPX_IMG_FMT_UV_FLIP))
202 : {
203 0 : img->planes[VPX_PLANE_U] = data
204 0 : + (x >> img->x_chroma_shift)
205 0 : + (y >> img->y_chroma_shift) * img->stride[VPX_PLANE_U];
206 0 : data += (img->h >> img->y_chroma_shift) * img->stride[VPX_PLANE_U];
207 0 : img->planes[VPX_PLANE_V] = data
208 0 : + (x >> img->x_chroma_shift)
209 0 : + (y >> img->y_chroma_shift) * img->stride[VPX_PLANE_V];
210 : }
211 : else
212 : {
213 0 : img->planes[VPX_PLANE_V] = data
214 0 : + (x >> img->x_chroma_shift)
215 0 : + (y >> img->y_chroma_shift) * img->stride[VPX_PLANE_V];
216 0 : data += (img->h >> img->y_chroma_shift) * img->stride[VPX_PLANE_V];
217 0 : img->planes[VPX_PLANE_U] = data
218 0 : + (x >> img->x_chroma_shift)
219 0 : + (y >> img->y_chroma_shift) * img->stride[VPX_PLANE_U];
220 : }
221 : }
222 :
223 0 : return 0;
224 : }
225 :
226 0 : return -1;
227 : }
228 :
229 0 : void vpx_img_flip(vpx_image_t *img)
230 : {
231 : /* Note: In the calculation pointer adjustment calculation, we want the
232 : * rhs to be promoted to a signed type. Section 6.3.1.8 of the ISO C99
233 : * standard indicates that if the adjustment parameter is unsigned, the
234 : * stride parameter will be promoted to unsigned, causing errors when
235 : * the lhs is a larger type than the rhs.
236 : */
237 0 : img->planes[VPX_PLANE_Y] += (signed)(img->d_h - 1) * img->stride[VPX_PLANE_Y];
238 0 : img->stride[VPX_PLANE_Y] = -img->stride[VPX_PLANE_Y];
239 :
240 0 : img->planes[VPX_PLANE_U] += (signed)((img->d_h >> img->y_chroma_shift) - 1)
241 0 : * img->stride[VPX_PLANE_U];
242 0 : img->stride[VPX_PLANE_U] = -img->stride[VPX_PLANE_U];
243 :
244 0 : img->planes[VPX_PLANE_V] += (signed)((img->d_h >> img->y_chroma_shift) - 1)
245 0 : * img->stride[VPX_PLANE_V];
246 0 : img->stride[VPX_PLANE_V] = -img->stride[VPX_PLANE_V];
247 :
248 0 : img->planes[VPX_PLANE_ALPHA] += (signed)(img->d_h - 1) * img->stride[VPX_PLANE_ALPHA];
249 0 : img->stride[VPX_PLANE_ALPHA] = -img->stride[VPX_PLANE_ALPHA];
250 0 : }
251 :
252 0 : void vpx_img_free(vpx_image_t *img)
253 : {
254 0 : if (img)
255 : {
256 0 : if (img->img_data && img->img_data_owner)
257 0 : free(img->img_data);
258 :
259 0 : if (img->self_allocd)
260 0 : free(img);
261 : }
262 0 : }
|