imgconvert.c 7.9 KB
Newer Older
Fabrice Bellard's avatar
Fabrice Bellard committed
1
/*
Diego Biurrun's avatar
Diego Biurrun committed
2
 * Misc image conversion routines
3
 * Copyright (c) 2001, 2002, 2003 Fabrice Bellard
Fabrice Bellard's avatar
Fabrice Bellard committed
4
 *
5 6 7
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
8 9
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
Fabrice Bellard's avatar
Fabrice Bellard committed
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
Fabrice Bellard's avatar
Fabrice Bellard committed
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
Fabrice Bellard's avatar
Fabrice Bellard committed
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
Fabrice Bellard's avatar
Fabrice Bellard committed
20
 */
Michael Niedermayer's avatar
Michael Niedermayer committed
21 22

/**
23
 * @file
Diego Biurrun's avatar
Diego Biurrun committed
24
 * misc image conversion routines
Michael Niedermayer's avatar
Michael Niedermayer committed
25 26
 */

Fabrice Bellard's avatar
Fabrice Bellard committed
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"
Fabrice Bellard's avatar
Fabrice Bellard committed
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 43
    *h_shift = desc->log2_chroma_w;
    *v_shift = desc->log2_chroma_h;
44
}
45
#endif
46

47 48 49 50
int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt,
                             enum AVPixelFormat src_pix_fmt,
                             int has_alpha)
{
51
    return av_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha);
52 53
}

54 55
enum AVPixelFormat avcodec_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2,
                                            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 61
enum AVPixelFormat avcodec_find_best_pix_fmt2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2,
                                            enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr)
62 63 64 65
{
    return avcodec_find_best_pix_fmt_of_2(dst_pix_fmt1, dst_pix_fmt2, src_pix_fmt, has_alpha, loss_ptr);
}

66
enum AVPixelFormat avcodec_find_best_pix_fmt_of_list(const enum AVPixelFormat *pix_fmt_list,
67
                                            enum AVPixelFormat src_pix_fmt,
68 69 70
                                            int has_alpha, int *loss_ptr){
    int i;

71
    enum AVPixelFormat best = AV_PIX_FMT_NONE;
72
    int loss;
73

74
    for (i=0; pix_fmt_list[i] != AV_PIX_FMT_NONE; i++) {
75
        loss = loss_ptr ? *loss_ptr : 0;
76 77
        best = avcodec_find_best_pix_fmt_of_2(best, pix_fmt_list[i], src_pix_fmt, has_alpha, &loss);
    }
78

79 80
    if (loss_ptr)
        *loss_ptr = loss;
81 82 83
    return best;
}

84 85
#if FF_API_AVPICTURE
FF_DISABLE_DEPRECATION_WARNINGS
86
/* return true if yuv planar */
87
static inline int is_yuv_planar(const AVPixFmtDescriptor *desc)
88
{
89 90 91
    int i;
    int planes[4] = { 0 };

92 93
    if (     desc->flags & AV_PIX_FMT_FLAG_RGB
        || !(desc->flags & AV_PIX_FMT_FLAG_PLANAR))
94 95 96 97 98 99 100 101 102 103 104
        return 0;

    /* set the used planes */
    for (i = 0; i < desc->nb_components; i++)
        planes[desc->comp[i].plane] = 1;

    /* if there is an unused plane, the format is not planar */
    for (i = 0; i < desc->nb_components; i++)
        if (!planes[i])
            return 0;
    return 1;
105 106
}

107
int av_picture_crop(AVPicture *dst, const AVPicture *src,
108
                    enum AVPixelFormat pix_fmt, int top_band, int left_band)
109
{
110
    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
111 112
    int y_shift;
    int x_shift;
113
    int max_step[4];
114

115
    if (pix_fmt < 0 || pix_fmt >= AV_PIX_FMT_NB)
116 117
        return -1;

118 119
    y_shift = desc->log2_chroma_h;
    x_shift = desc->log2_chroma_w;
120
    av_image_fill_max_pixsteps(max_step, NULL, desc);
121

122
    if (is_yuv_planar(desc)) {
123 124 125
    dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band;
    dst->data[1] = src->data[1] + ((top_band >> y_shift) * src->linesize[1]) + (left_band >> x_shift);
    dst->data[2] = src->data[2] + ((top_band >> y_shift) * src->linesize[2]) + (left_band >> x_shift);
126 127 128
    } else{
        if(top_band % (1<<y_shift) || left_band % (1<<x_shift))
            return -1;
129
        dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + (left_band * max_step[0]);
130
    }
131 132 133 134 135 136 137

    dst->linesize[0] = src->linesize[0];
    dst->linesize[1] = src->linesize[1];
    dst->linesize[2] = src->linesize[2];
    return 0;
}

138
int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width,
139
                   enum AVPixelFormat pix_fmt, int padtop, int padbottom, int padleft, int padright,
Luca Barbato's avatar
Luca Barbato committed
140
            int *color)
141
{
142
    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
143
    uint8_t *optr;
144 145 146 147
    int y_shift;
    int x_shift;
    int yheight;
    int i, y;
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
    int max_step[4];

    if (pix_fmt < 0 || pix_fmt >= AV_PIX_FMT_NB)
        return -1;

    if (!is_yuv_planar(desc)) {
        if (src)
            return -1; //TODO: Not yet implemented

        av_image_fill_max_pixsteps(max_step, NULL, desc);

        if (padtop || padleft) {
            memset(dst->data[0], color[0],
                    dst->linesize[0] * padtop + (padleft * max_step[0]));
        }

        if (padleft || padright) {
            optr = dst->data[0] + dst->linesize[0] * padtop +
                    (dst->linesize[0] - (padright * max_step[0]));
            yheight = height - 1 - (padtop + padbottom);
            for (y = 0; y < yheight; y++) {
                memset(optr, color[0], (padleft + padright) * max_step[0]);
                optr += dst->linesize[0];
            }
        }

        if (padbottom || padright) {
            optr = dst->data[0] + dst->linesize[0] * (height - padbottom) -
                    (padright * max_step[0]);
            memset(optr, color[0], dst->linesize[0] * padbottom +
                    (padright * max_step[0]));
        }
180

181 182
        return 0;
    }
183 184

    for (i = 0; i < 3; i++) {
185 186
        x_shift = i ? desc->log2_chroma_w : 0;
        y_shift = i ? desc->log2_chroma_h : 0;
187 188

        if (padtop || padleft) {
Luca Barbato's avatar
Luca Barbato committed
189 190
            memset(dst->data[i], color[i],
                dst->linesize[i] * (padtop >> y_shift) + (padleft >> x_shift));
191 192
        }

193 194 195 196 197 198 199
        if (padleft || padright) {
            optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
                (dst->linesize[i] - (padright >> x_shift));
            yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
            for (y = 0; y < yheight; y++) {
                memset(optr, color[i], (padleft + padright) >> x_shift);
                optr += dst->linesize[i];
200
            }
201 202 203 204 205 206
        }

        if (src) { /* first line */
            uint8_t *iptr = src->data[i];
            optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
                    (padleft >> x_shift);
207
            memcpy(optr, iptr, (width - padleft - padright) >> x_shift);
208
            iptr += src->linesize[i];
Luca Barbato's avatar
Luca Barbato committed
209 210
            optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
                (dst->linesize[i] - (padright >> x_shift));
211 212 213
            yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
            for (y = 0; y < yheight; y++) {
                memset(optr, color[i], (padleft + padright) >> x_shift);
214
                memcpy(optr + ((padleft + padright) >> x_shift), iptr,
215
                       (width - padleft - padright) >> x_shift);
216
                iptr += src->linesize[i];
217 218 219 220 221
                optr += dst->linesize[i];
            }
        }

        if (padbottom || padright) {
Luca Barbato's avatar
Luca Barbato committed
222 223 224 225
            optr = dst->data[i] + dst->linesize[i] *
                ((height - padbottom) >> y_shift) - (padright >> x_shift);
            memset(optr, color[i],dst->linesize[i] *
                (padbottom >> y_shift) + (padright >> x_shift));
226 227
        }
    }
228

229 230
    return 0;
}
231
FF_ENABLE_DEPRECATION_WARNINGS
232
#endif /* FF_API_AVPICTURE */