8a16e58f63cfe97ea49928ad5f88115cf62fe963
[profile/ivi/libvpx.git] / vpx_codec / src / vpx_image.c
1 /*
2  *  Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license and patent
5  *  grant that can be found in the LICENSE file in the root of the source
6  *  tree. All contributing project authors may be found in the AUTHORS
7  *  file in the root of the source tree.
8  */
9
10
11 #include <stdlib.h>
12 #include <string.h>
13 #include "vpx_codec/vpx_image.h"
14
15 static vpx_image_t *img_alloc_helper(vpx_image_t  *img,
16                                      img_fmt_t     fmt,
17                                      unsigned int  d_w,
18                                      unsigned int  d_h,
19                                      unsigned int  stride_align,
20                                      unsigned char      *img_data)
21 {
22
23     unsigned int  h, w, s, xcs, ycs, bps;
24     int           align;
25
26     /* Treat align==0 like align==1 */
27     if (!stride_align)
28         stride_align = 1;
29
30     /* Validate alignment (must be power of 2) */
31     if (stride_align & (stride_align - 1))
32         goto fail;
33
34     /* Get sample size for this format */
35     switch (fmt)
36     {
37     case IMG_FMT_RGB32:
38     case IMG_FMT_RGB32_LE:
39     case IMG_FMT_ARGB:
40     case IMG_FMT_ARGB_LE:
41         bps = 32;
42         break;
43     case IMG_FMT_RGB24:
44     case IMG_FMT_BGR24:
45         bps = 24;
46         break;
47     case IMG_FMT_RGB565:
48     case IMG_FMT_RGB565_LE:
49     case IMG_FMT_RGB555:
50     case IMG_FMT_RGB555_LE:
51     case IMG_FMT_UYVY:
52     case IMG_FMT_YUY2:
53     case IMG_FMT_YVYU:
54         bps = 16;
55         break;
56     case IMG_FMT_I420:
57     case IMG_FMT_YV12:
58     case IMG_FMT_VPXI420:
59     case IMG_FMT_VPXYV12:
60         bps = 12;
61         break;
62     default:
63         bps = 16;
64         break;
65     }
66
67     /* Get chroma shift values for this format */
68     switch (fmt)
69     {
70     case IMG_FMT_I420:
71     case IMG_FMT_YV12:
72     case IMG_FMT_VPXI420:
73     case IMG_FMT_VPXYV12:
74         xcs = 1;
75         break;
76     default:
77         xcs = 0;
78         break;
79     }
80
81     switch (fmt)
82     {
83     case IMG_FMT_I420:
84     case IMG_FMT_YV12:
85     case IMG_FMT_VPXI420:
86     case IMG_FMT_VPXYV12:
87         ycs = 1;
88         break;
89     default:
90         ycs = 0;
91         break;
92     }
93
94     /* Calculate storage sizes given the chroma subsampling */
95     align = (1 << xcs) - 1;
96     w = (d_w + align) & ~align;
97     align = (1 << ycs) - 1;
98     h = (d_h + align) & ~align;
99     s = (fmt & IMG_FMT_PLANAR) ? w : bps * w / 8;
100     s = (s + stride_align - 1) & ~(stride_align - 1);
101
102     /* Allocate the new image */
103     if (!img)
104     {
105         img = (vpx_image_t *)calloc(1, sizeof(vpx_image_t));
106
107         if (!img)
108             goto fail;
109
110         img->self_allocd = 1;
111     }
112     else
113     {
114         memset(img, 0, sizeof(vpx_image_t));
115     }
116
117     img->img_data = img_data;
118
119     if (!img_data)
120     {
121         img->img_data = malloc((fmt & IMG_FMT_PLANAR) ? h * w * bps / 8 : h * s);
122         img->img_data_owner = 1;
123     }
124
125     if (!img->img_data)
126         goto fail;
127
128     img->fmt = fmt;
129     img->w = w;
130     img->h = h;
131     img->x_chroma_shift = xcs;
132     img->y_chroma_shift = ycs;
133     img->bps = bps;
134
135     /* Calculate strides */
136     img->stride[PLANE_Y] = img->stride[PLANE_ALPHA] = s;
137     img->stride[PLANE_U] = img->stride[PLANE_V] = s >> xcs;
138
139     /* Default viewport to entire image */
140     if (!vpx_img_set_rect(img, 0, 0, d_w, d_h))
141         return img;
142
143 fail:
144     vpx_img_free(img);
145     return NULL;
146 }
147
148 vpx_image_t *vpx_img_alloc(vpx_image_t  *img,
149                            img_fmt_t     fmt,
150                            unsigned int  d_w,
151                            unsigned int  d_h,
152                            unsigned int  stride_align)
153 {
154     return img_alloc_helper(img, fmt, d_w, d_h, stride_align, NULL);
155 }
156
157 vpx_image_t *vpx_img_wrap(vpx_image_t  *img,
158                           img_fmt_t     fmt,
159                           unsigned int  d_w,
160                           unsigned int  d_h,
161                           unsigned int  stride_align,
162                           unsigned char       *img_data)
163 {
164     return img_alloc_helper(img, fmt, d_w, d_h, stride_align, img_data);
165 }
166
167 int vpx_img_set_rect(vpx_image_t  *img,
168                      unsigned int  x,
169                      unsigned int  y,
170                      unsigned int  w,
171                      unsigned int  h)
172 {
173     unsigned char      *data;
174
175     if (x + w <= img->w && y + h <= img->h)
176     {
177         img->d_w = w;
178         img->d_h = h;
179
180         /* Calculate plane pointers */
181         if (!(img->fmt & IMG_FMT_PLANAR))
182         {
183             img->planes[PLANE_PACKED] =
184                 img->img_data + x * img->bps / 8 + y * img->stride[PLANE_PACKED];
185         }
186         else
187         {
188             data = img->img_data;
189
190             if (img->fmt & IMG_FMT_HAS_ALPHA)
191             {
192                 img->planes[PLANE_ALPHA] =
193                     data + x + y * img->stride[PLANE_ALPHA];
194                 data += img->h * img->stride[PLANE_ALPHA];
195             }
196
197             img->planes[PLANE_Y] = data + x + y * img->stride[PLANE_Y];
198             data += img->h * img->stride[PLANE_Y];
199
200             if (!(img->fmt & IMG_FMT_UV_FLIP))
201             {
202                 img->planes[PLANE_U] = data
203                                        + (x >> img->x_chroma_shift)
204                                        + (y >> img->y_chroma_shift) * img->stride[PLANE_U];
205                 data += (img->h >> img->y_chroma_shift) * img->stride[PLANE_U];
206                 img->planes[PLANE_V] = data
207                                        + (x >> img->x_chroma_shift)
208                                        + (y >> img->y_chroma_shift) * img->stride[PLANE_V];
209             }
210             else
211             {
212                 img->planes[PLANE_V] = data
213                                        + (x >> img->x_chroma_shift)
214                                        + (y >> img->y_chroma_shift) * img->stride[PLANE_V];
215                 data += (img->h >> img->y_chroma_shift) * img->stride[PLANE_V];
216                 img->planes[PLANE_U] = data
217                                        + (x >> img->x_chroma_shift)
218                                        + (y >> img->y_chroma_shift) * img->stride[PLANE_U];
219             }
220         }
221
222         return 0;
223     }
224
225     return -1;
226 }
227
228 void vpx_img_flip(vpx_image_t *img)
229 {
230     /* Note: In the calculation pointer adjustment calculation, we want the
231      * rhs to be promoted to a signed type. Section 6.3.1.8 of the ISO C99
232      * standard indicates that if the adjustment parameter is unsigned, the
233      * stride parameter will be promoted to unsigned, causing errors when
234      * the lhs is a larger type than the rhs.
235      */
236     img->planes[PLANE_Y] += (signed)(img->d_h - 1) * img->stride[PLANE_Y];
237     img->stride[PLANE_Y] = -img->stride[PLANE_Y];
238
239     img->planes[PLANE_U] += (signed)((img->d_h >> img->y_chroma_shift) - 1)
240                             * img->stride[PLANE_U];
241     img->stride[PLANE_U] = -img->stride[PLANE_U];
242
243     img->planes[PLANE_V] += (signed)((img->d_h >> img->y_chroma_shift) - 1)
244                             * img->stride[PLANE_V];
245     img->stride[PLANE_V] = -img->stride[PLANE_V];
246
247     img->planes[PLANE_ALPHA] += (signed)(img->d_h - 1) * img->stride[PLANE_ALPHA];
248     img->stride[PLANE_ALPHA] = -img->stride[PLANE_ALPHA];
249 }
250
251 void vpx_img_free(vpx_image_t *img)
252 {
253     if (img)
254     {
255         if (img->img_data && img->img_data_owner)
256             free(img->img_data);
257
258         if (img->self_allocd)
259             free(img);
260     }
261 }