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