2 * This file is part of FFmpeg.
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 * misc image utilities
28 #include "intreadwrite.h"
30 #include "mathematics.h"
34 void av_image_fill_max_pixsteps(int max_pixsteps
[4], int max_pixstep_comps
[4],
35 const AVPixFmtDescriptor
*pixdesc
)
38 memset(max_pixsteps
, 0, 4*sizeof(max_pixsteps
[0]));
39 if (max_pixstep_comps
)
40 memset(max_pixstep_comps
, 0, 4*sizeof(max_pixstep_comps
[0]));
42 for (i
= 0; i
< 4; i
++) {
43 const AVComponentDescriptor
*comp
= &(pixdesc
->comp
[i
]);
44 if ((comp
->step_minus1
+1) > max_pixsteps
[comp
->plane
]) {
45 max_pixsteps
[comp
->plane
] = comp
->step_minus1
+1;
46 if (max_pixstep_comps
)
47 max_pixstep_comps
[comp
->plane
] = i
;
53 int image_get_linesize(int width
, int plane
,
54 int max_step
, int max_step_comp
,
55 const AVPixFmtDescriptor
*desc
)
57 int s
, shifted_w
, linesize
;
60 return AVERROR(EINVAL
);
63 return AVERROR(EINVAL
);
64 s
= (max_step_comp
== 1 || max_step_comp
== 2) ? desc
->log2_chroma_w
: 0;
65 shifted_w
= ((width
+ (1 << s
) - 1)) >> s
;
66 if (shifted_w
&& max_step
> INT_MAX
/ shifted_w
)
67 return AVERROR(EINVAL
);
68 linesize
= max_step
* shifted_w
;
70 if (desc
->flags
& AV_PIX_FMT_FLAG_BITSTREAM
)
71 linesize
= (linesize
+ 7) >> 3;
75 int av_image_get_linesize(enum AVPixelFormat pix_fmt
, int width
, int plane
)
77 const AVPixFmtDescriptor
*desc
= av_pix_fmt_desc_get(pix_fmt
);
78 int max_step
[4]; /* max pixel step for each plane */
79 int max_step_comp
[4]; /* the component for each plane which has the max pixel step */
81 if ((unsigned)pix_fmt
>= AV_PIX_FMT_NB
|| desc
->flags
& AV_PIX_FMT_FLAG_HWACCEL
)
82 return AVERROR(EINVAL
);
84 av_image_fill_max_pixsteps(max_step
, max_step_comp
, desc
);
85 return image_get_linesize(width
, plane
, max_step
[plane
], max_step_comp
[plane
], desc
);
88 int av_image_fill_linesizes(int linesizes
[4], enum AVPixelFormat pix_fmt
, int width
)
91 const AVPixFmtDescriptor
*desc
= av_pix_fmt_desc_get(pix_fmt
);
92 int max_step
[4]; /* max pixel step for each plane */
93 int max_step_comp
[4]; /* the component for each plane which has the max pixel step */
95 memset(linesizes
, 0, 4*sizeof(linesizes
[0]));
97 if (!desc
|| desc
->flags
& AV_PIX_FMT_FLAG_HWACCEL
)
98 return AVERROR(EINVAL
);
100 av_image_fill_max_pixsteps(max_step
, max_step_comp
, desc
);
101 for (i
= 0; i
< 4; i
++) {
102 if ((ret
= image_get_linesize(width
, i
, max_step
[i
], max_step_comp
[i
], desc
)) < 0)
110 int av_image_fill_pointers(uint8_t *data
[4], enum AVPixelFormat pix_fmt
, int height
,
111 uint8_t *ptr
, const int linesizes
[4])
113 int i
, total_size
, size
[4] = { 0 }, has_plane
[4] = { 0 };
115 const AVPixFmtDescriptor
*desc
= av_pix_fmt_desc_get(pix_fmt
);
116 memset(data
, 0, sizeof(data
[0])*4);
118 if (!desc
|| desc
->flags
& AV_PIX_FMT_FLAG_HWACCEL
)
119 return AVERROR(EINVAL
);
122 if (linesizes
[0] > (INT_MAX
- 1024) / height
)
123 return AVERROR(EINVAL
);
124 size
[0] = linesizes
[0] * height
;
126 if (desc
->flags
& AV_PIX_FMT_FLAG_PAL
||
127 desc
->flags
& AV_PIX_FMT_FLAG_PSEUDOPAL
) {
128 size
[0] = (size
[0] + 3) & ~3;
129 data
[1] = ptr
+ size
[0]; /* palette is stored here as 256 32 bits words */
130 return size
[0] + 256 * 4;
133 for (i
= 0; i
< 4; i
++)
134 has_plane
[desc
->comp
[i
].plane
] = 1;
136 total_size
= size
[0];
137 for (i
= 1; i
< 4 && has_plane
[i
]; i
++) {
138 int h
, s
= (i
== 1 || i
== 2) ? desc
->log2_chroma_h
: 0;
139 data
[i
] = data
[i
-1] + size
[i
-1];
140 h
= (height
+ (1 << s
) - 1) >> s
;
141 if (linesizes
[i
] > INT_MAX
/ h
)
142 return AVERROR(EINVAL
);
143 size
[i
] = h
* linesizes
[i
];
144 if (total_size
> INT_MAX
- size
[i
])
145 return AVERROR(EINVAL
);
146 total_size
+= size
[i
];
152 int avpriv_set_systematic_pal2(uint32_t pal
[256], enum AVPixelFormat pix_fmt
)
156 for (i
= 0; i
< 256; i
++) {
160 case AV_PIX_FMT_RGB8
:
165 case AV_PIX_FMT_BGR8
:
170 case AV_PIX_FMT_RGB4_BYTE
:
175 case AV_PIX_FMT_BGR4_BYTE
:
180 case AV_PIX_FMT_GRAY8
:
184 return AVERROR(EINVAL
);
186 pal
[i
] = b
+ (g
<< 8) + (r
<< 16) + (0xFFU
<< 24);
192 int av_image_alloc(uint8_t *pointers
[4], int linesizes
[4],
193 int w
, int h
, enum AVPixelFormat pix_fmt
, int align
)
195 const AVPixFmtDescriptor
*desc
= av_pix_fmt_desc_get(pix_fmt
);
200 return AVERROR(EINVAL
);
202 if ((ret
= av_image_check_size(w
, h
, 0, NULL
)) < 0)
204 if ((ret
= av_image_fill_linesizes(linesizes
, pix_fmt
, align
>7 ? FFALIGN(w
, 8) : w
)) < 0)
207 for (i
= 0; i
< 4; i
++)
208 linesizes
[i
] = FFALIGN(linesizes
[i
], align
);
210 if ((ret
= av_image_fill_pointers(pointers
, pix_fmt
, h
, NULL
, linesizes
)) < 0)
212 buf
= av_malloc(ret
+ align
);
214 return AVERROR(ENOMEM
);
215 if ((ret
= av_image_fill_pointers(pointers
, pix_fmt
, h
, buf
, linesizes
)) < 0) {
219 if (desc
->flags
& AV_PIX_FMT_FLAG_PAL
|| desc
->flags
& AV_PIX_FMT_FLAG_PSEUDOPAL
)
220 avpriv_set_systematic_pal2((uint32_t*)pointers
[1], pix_fmt
);
225 typedef struct ImgUtils
{
226 const AVClass
*class;
231 static const AVClass imgutils_class
= { "IMGUTILS", av_default_item_name
, NULL
, LIBAVUTIL_VERSION_INT
, offsetof(ImgUtils
, log_offset
), offsetof(ImgUtils
, log_ctx
) };
233 int av_image_check_size(unsigned int w
, unsigned int h
, int log_offset
, void *log_ctx
)
235 ImgUtils imgutils
= { &imgutils_class
, log_offset
, log_ctx
};
237 if ((int)w
>0 && (int)h
>0 && (w
+128)*(uint64_t)(h
+128) < INT_MAX
/8)
240 av_log(&imgutils
, AV_LOG_ERROR
, "Picture size %ux%u is invalid\n", w
, h
);
241 return AVERROR(EINVAL
);
244 int av_image_check_sar(unsigned int w
, unsigned int h
, AVRational sar
)
249 return AVERROR(EINVAL
);
251 if (!sar
.num
|| sar
.num
== sar
.den
)
254 if (sar
.num
< sar
.den
)
255 scaled_dim
= av_rescale_rnd(w
, sar
.num
, sar
.den
, AV_ROUND_ZERO
);
257 scaled_dim
= av_rescale_rnd(h
, sar
.den
, sar
.num
, AV_ROUND_ZERO
);
262 return AVERROR(EINVAL
);
265 void av_image_copy_plane(uint8_t *dst
, int dst_linesize
,
266 const uint8_t *src
, int src_linesize
,
267 int bytewidth
, int height
)
271 av_assert0(abs(src_linesize
) >= bytewidth
);
272 av_assert0(abs(dst_linesize
) >= bytewidth
);
273 for (;height
> 0; height
--) {
274 memcpy(dst
, src
, bytewidth
);
280 void av_image_copy(uint8_t *dst_data
[4], int dst_linesizes
[4],
281 const uint8_t *src_data
[4], const int src_linesizes
[4],
282 enum AVPixelFormat pix_fmt
, int width
, int height
)
284 const AVPixFmtDescriptor
*desc
= av_pix_fmt_desc_get(pix_fmt
);
286 if (!desc
|| desc
->flags
& AV_PIX_FMT_FLAG_HWACCEL
)
289 if (desc
->flags
& AV_PIX_FMT_FLAG_PAL
||
290 desc
->flags
& AV_PIX_FMT_FLAG_PSEUDOPAL
) {
291 av_image_copy_plane(dst_data
[0], dst_linesizes
[0],
292 src_data
[0], src_linesizes
[0],
294 /* copy the palette */
295 memcpy(dst_data
[1], src_data
[1], 4*256);
297 int i
, planes_nb
= 0;
299 for (i
= 0; i
< desc
->nb_components
; i
++)
300 planes_nb
= FFMAX(planes_nb
, desc
->comp
[i
].plane
+ 1);
302 for (i
= 0; i
< planes_nb
; i
++) {
304 int bwidth
= av_image_get_linesize(pix_fmt
, width
, i
);
306 av_log(NULL
, AV_LOG_ERROR
, "av_image_get_linesize failed\n");
309 if (i
== 1 || i
== 2) {
310 h
= FF_CEIL_RSHIFT(height
, desc
->log2_chroma_h
);
312 av_image_copy_plane(dst_data
[i
], dst_linesizes
[i
],
313 src_data
[i
], src_linesizes
[i
],
319 int av_image_fill_arrays(uint8_t *dst_data
[4], int dst_linesize
[4],
321 enum AVPixelFormat pix_fmt
, int width
, int height
, int align
)
325 if ((ret
= av_image_check_size(width
, height
, 0, NULL
)) < 0)
328 if ((ret
= av_image_fill_linesizes(dst_linesize
, pix_fmt
, width
)) < 0)
331 for (i
= 0; i
< 4; i
++)
332 dst_linesize
[i
] = FFALIGN(dst_linesize
[i
], align
);
334 return av_image_fill_pointers(dst_data
, pix_fmt
, height
, (uint8_t *)src
, dst_linesize
);
337 int av_image_get_buffer_size(enum AVPixelFormat pix_fmt
, int width
, int height
, int align
)
339 const AVPixFmtDescriptor
*desc
= av_pix_fmt_desc_get(pix_fmt
);
344 return AVERROR(EINVAL
);
345 if (av_image_check_size(width
, height
, 0, NULL
) < 0)
346 return AVERROR(EINVAL
);
347 if (desc
->flags
& AV_PIX_FMT_FLAG_PSEUDOPAL
)
348 // do not include palette for these pseudo-paletted formats
349 return width
* height
;
350 return av_image_fill_arrays(data
, linesize
, NULL
, pix_fmt
, width
, height
, align
);
353 int av_image_copy_to_buffer(uint8_t *dst
, int dst_size
,
354 const uint8_t * const src_data
[4], const int src_linesize
[4],
355 enum AVPixelFormat pix_fmt
, int width
, int height
, int align
)
357 int i
, j
, nb_planes
= 0, linesize
[4];
358 const AVPixFmtDescriptor
*desc
= av_pix_fmt_desc_get(pix_fmt
);
359 int size
= av_image_get_buffer_size(pix_fmt
, width
, height
, align
);
361 if (size
> dst_size
|| size
< 0)
362 return AVERROR(EINVAL
);
364 for (i
= 0; i
< desc
->nb_components
; i
++)
365 nb_planes
= FFMAX(desc
->comp
[i
].plane
, nb_planes
);
368 av_image_fill_linesizes(linesize
, pix_fmt
, width
);
369 for (i
= 0; i
< nb_planes
; i
++) {
370 int h
, shift
= (i
== 1 || i
== 2) ? desc
->log2_chroma_h
: 0;
371 const uint8_t *src
= src_data
[i
];
372 h
= (height
+ (1 << shift
) - 1) >> shift
;
374 for (j
= 0; j
< h
; j
++) {
375 memcpy(dst
, src
, linesize
[i
]);
376 dst
+= FFALIGN(linesize
[i
], align
);
377 src
+= src_linesize
[i
];
381 if (desc
->flags
& AV_PIX_FMT_FLAG_PAL
) {
382 uint32_t *d32
= (uint32_t *)(((size_t)dst
+ 3) & ~3);
383 for (i
= 0; i
<256; i
++)
384 AV_WL32(d32
+ i
, AV_RN32(src_data
[1] + 4*i
));