blob: 1547f18966e09c5aa6cf3668b9aed3f6081deaea
1 | /* |
2 | * Misc image conversion routines |
3 | * Copyright (c) 2001, 2002, 2003 Fabrice Bellard |
4 | * |
5 | * This file is part of FFmpeg. |
6 | * |
7 | * FFmpeg is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU Lesser General Public |
9 | * License as published by the Free Software Foundation; either |
10 | * version 2.1 of the License, or (at your option) any later version. |
11 | * |
12 | * FFmpeg 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 GNU |
15 | * Lesser General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU Lesser General Public |
18 | * License along with FFmpeg; if not, write to the Free Software |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | */ |
21 | |
22 | /** |
23 | * @file |
24 | * misc image conversion routines |
25 | */ |
26 | |
27 | #include "avcodec.h" |
28 | #include "internal.h" |
29 | #include "mathops.h" |
30 | #include "libavutil/avassert.h" |
31 | #include "libavutil/colorspace.h" |
32 | #include "libavutil/common.h" |
33 | #include "libavutil/pixdesc.h" |
34 | #include "libavutil/internal.h" |
35 | #include "libavutil/imgutils.h" |
36 | |
37 | #if FF_API_GETCHROMA |
38 | void avcodec_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int *v_shift) |
39 | { |
40 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); |
41 | av_assert0(desc); |
42 | *h_shift = desc->log2_chroma_w; |
43 | *v_shift = desc->log2_chroma_h; |
44 | } |
45 | #endif |
46 | |
47 | int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, |
48 | enum AVPixelFormat src_pix_fmt, |
49 | int has_alpha) |
50 | { |
51 | return av_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha); |
52 | } |
53 | |
54 | enum AVPixelFormat avcodec_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, |
55 | enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr) |
56 | { |
57 | return av_find_best_pix_fmt_of_2(dst_pix_fmt1, dst_pix_fmt2, src_pix_fmt, has_alpha, loss_ptr); |
58 | } |
59 | |
60 | enum AVPixelFormat avcodec_find_best_pix_fmt2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, |
61 | enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr) |
62 | { |
63 | return avcodec_find_best_pix_fmt_of_2(dst_pix_fmt1, dst_pix_fmt2, src_pix_fmt, has_alpha, loss_ptr); |
64 | } |
65 | |
66 | enum AVPixelFormat avcodec_find_best_pix_fmt_of_list(const enum AVPixelFormat *pix_fmt_list, |
67 | enum AVPixelFormat src_pix_fmt, |
68 | int has_alpha, int *loss_ptr){ |
69 | int i; |
70 | |
71 | enum AVPixelFormat best = AV_PIX_FMT_NONE; |
72 | |
73 | for(i=0; pix_fmt_list[i] != AV_PIX_FMT_NONE; i++) |
74 | best = avcodec_find_best_pix_fmt_of_2(best, pix_fmt_list[i], src_pix_fmt, has_alpha, loss_ptr); |
75 | |
76 | return best; |
77 | } |
78 | |
79 | #if FF_API_AVPICTURE |
80 | FF_DISABLE_DEPRECATION_WARNINGS |
81 | /* return true if yuv planar */ |
82 | static inline int is_yuv_planar(const AVPixFmtDescriptor *desc) |
83 | { |
84 | int i; |
85 | int planes[4] = { 0 }; |
86 | |
87 | if ( desc->flags & AV_PIX_FMT_FLAG_RGB |
88 | || !(desc->flags & AV_PIX_FMT_FLAG_PLANAR)) |
89 | return 0; |
90 | |
91 | /* set the used planes */ |
92 | for (i = 0; i < desc->nb_components; i++) |
93 | planes[desc->comp[i].plane] = 1; |
94 | |
95 | /* if there is an unused plane, the format is not planar */ |
96 | for (i = 0; i < desc->nb_components; i++) |
97 | if (!planes[i]) |
98 | return 0; |
99 | return 1; |
100 | } |
101 | |
102 | int av_picture_crop(AVPicture *dst, const AVPicture *src, |
103 | enum AVPixelFormat pix_fmt, int top_band, int left_band) |
104 | { |
105 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); |
106 | int y_shift; |
107 | int x_shift; |
108 | int max_step[4]; |
109 | |
110 | if (pix_fmt < 0 || pix_fmt >= AV_PIX_FMT_NB) |
111 | return -1; |
112 | |
113 | y_shift = desc->log2_chroma_h; |
114 | x_shift = desc->log2_chroma_w; |
115 | av_image_fill_max_pixsteps(max_step, NULL, desc); |
116 | |
117 | if (is_yuv_planar(desc)) { |
118 | dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band; |
119 | dst->data[1] = src->data[1] + ((top_band >> y_shift) * src->linesize[1]) + (left_band >> x_shift); |
120 | dst->data[2] = src->data[2] + ((top_band >> y_shift) * src->linesize[2]) + (left_band >> x_shift); |
121 | } else{ |
122 | if(top_band % (1<<y_shift) || left_band % (1<<x_shift)) |
123 | return -1; |
124 | dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + (left_band * max_step[0]); |
125 | } |
126 | |
127 | dst->linesize[0] = src->linesize[0]; |
128 | dst->linesize[1] = src->linesize[1]; |
129 | dst->linesize[2] = src->linesize[2]; |
130 | return 0; |
131 | } |
132 | |
133 | int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width, |
134 | enum AVPixelFormat pix_fmt, int padtop, int padbottom, int padleft, int padright, |
135 | int *color) |
136 | { |
137 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); |
138 | uint8_t *optr; |
139 | int y_shift; |
140 | int x_shift; |
141 | int yheight; |
142 | int i, y; |
143 | int max_step[4]; |
144 | |
145 | if (pix_fmt < 0 || pix_fmt >= AV_PIX_FMT_NB) |
146 | return -1; |
147 | |
148 | if (!is_yuv_planar(desc)) { |
149 | if (src) |
150 | return -1; //TODO: Not yet implemented |
151 | |
152 | av_image_fill_max_pixsteps(max_step, NULL, desc); |
153 | |
154 | if (padtop || padleft) { |
155 | memset(dst->data[0], color[0], |
156 | dst->linesize[0] * padtop + (padleft * max_step[0])); |
157 | } |
158 | |
159 | if (padleft || padright) { |
160 | optr = dst->data[0] + dst->linesize[0] * padtop + |
161 | (dst->linesize[0] - (padright * max_step[0])); |
162 | yheight = height - 1 - (padtop + padbottom); |
163 | for (y = 0; y < yheight; y++) { |
164 | memset(optr, color[0], (padleft + padright) * max_step[0]); |
165 | optr += dst->linesize[0]; |
166 | } |
167 | } |
168 | |
169 | if (padbottom || padright) { |
170 | optr = dst->data[0] + dst->linesize[0] * (height - padbottom) - |
171 | (padright * max_step[0]); |
172 | memset(optr, color[0], dst->linesize[0] * padbottom + |
173 | (padright * max_step[0])); |
174 | } |
175 | |
176 | return 0; |
177 | } |
178 | |
179 | for (i = 0; i < 3; i++) { |
180 | x_shift = i ? desc->log2_chroma_w : 0; |
181 | y_shift = i ? desc->log2_chroma_h : 0; |
182 | |
183 | if (padtop || padleft) { |
184 | memset(dst->data[i], color[i], |
185 | dst->linesize[i] * (padtop >> y_shift) + (padleft >> x_shift)); |
186 | } |
187 | |
188 | if (padleft || padright) { |
189 | optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) + |
190 | (dst->linesize[i] - (padright >> x_shift)); |
191 | yheight = (height - 1 - (padtop + padbottom)) >> y_shift; |
192 | for (y = 0; y < yheight; y++) { |
193 | memset(optr, color[i], (padleft + padright) >> x_shift); |
194 | optr += dst->linesize[i]; |
195 | } |
196 | } |
197 | |
198 | if (src) { /* first line */ |
199 | uint8_t *iptr = src->data[i]; |
200 | optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) + |
201 | (padleft >> x_shift); |
202 | memcpy(optr, iptr, (width - padleft - padright) >> x_shift); |
203 | iptr += src->linesize[i]; |
204 | optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) + |
205 | (dst->linesize[i] - (padright >> x_shift)); |
206 | yheight = (height - 1 - (padtop + padbottom)) >> y_shift; |
207 | for (y = 0; y < yheight; y++) { |
208 | memset(optr, color[i], (padleft + padright) >> x_shift); |
209 | memcpy(optr + ((padleft + padright) >> x_shift), iptr, |
210 | (width - padleft - padright) >> x_shift); |
211 | iptr += src->linesize[i]; |
212 | optr += dst->linesize[i]; |
213 | } |
214 | } |
215 | |
216 | if (padbottom || padright) { |
217 | optr = dst->data[i] + dst->linesize[i] * |
218 | ((height - padbottom) >> y_shift) - (padright >> x_shift); |
219 | memset(optr, color[i],dst->linesize[i] * |
220 | (padbottom >> y_shift) + (padright >> x_shift)); |
221 | } |
222 | } |
223 | |
224 | return 0; |
225 | } |
226 | FF_ENABLE_DEPRECATION_WARNINGS |
227 | #endif /* FF_API_AVPICTURE */ |
228 |