|
|
|
@ -25,6 +25,7 @@ |
|
|
|
|
#include "png.h" |
|
|
|
|
|
|
|
|
|
#include "libavutil/avassert.h" |
|
|
|
|
#include "libavutil/opt.h" |
|
|
|
|
|
|
|
|
|
/* TODO:
|
|
|
|
|
* - add 2, 4 and 16 bit depth support |
|
|
|
@ -37,6 +38,7 @@ |
|
|
|
|
#define IOBUF_SIZE 4096 |
|
|
|
|
|
|
|
|
|
typedef struct PNGEncContext { |
|
|
|
|
AVClass *class; |
|
|
|
|
DSPContext dsp; |
|
|
|
|
|
|
|
|
|
uint8_t *bytestream; |
|
|
|
@ -48,6 +50,8 @@ typedef struct PNGEncContext { |
|
|
|
|
|
|
|
|
|
z_stream zstream; |
|
|
|
|
uint8_t buf[IOBUF_SIZE]; |
|
|
|
|
int dpi; ///< Physical pixel density, in dots per inch, if set
|
|
|
|
|
int dpm; ///< Physical pixel density, in dots per meter, if set
|
|
|
|
|
} PNGEncContext; |
|
|
|
|
|
|
|
|
|
static void png_get_interlaced_row(uint8_t *dst, int row_size, |
|
|
|
@ -331,9 +335,15 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, |
|
|
|
|
|
|
|
|
|
png_write_chunk(&s->bytestream, MKTAG('I', 'H', 'D', 'R'), s->buf, 13); |
|
|
|
|
|
|
|
|
|
AV_WB32(s->buf, avctx->sample_aspect_ratio.num); |
|
|
|
|
AV_WB32(s->buf + 4, avctx->sample_aspect_ratio.den); |
|
|
|
|
s->buf[8] = 0; /* unit specifier is unknown */ |
|
|
|
|
if (s->dpm) { |
|
|
|
|
AV_WB32(s->buf, s->dpm); |
|
|
|
|
AV_WB32(s->buf + 4, s->dpm); |
|
|
|
|
s->buf[8] = 1; /* unit specifier is meter */ |
|
|
|
|
} else { |
|
|
|
|
AV_WB32(s->buf, avctx->sample_aspect_ratio.num); |
|
|
|
|
AV_WB32(s->buf + 4, avctx->sample_aspect_ratio.den); |
|
|
|
|
s->buf[8] = 0; /* unit specifier is unknown */ |
|
|
|
|
} |
|
|
|
|
png_write_chunk(&s->bytestream, MKTAG('p', 'H', 'Y', 's'), s->buf, 9); |
|
|
|
|
|
|
|
|
|
/* put the palette if needed */ |
|
|
|
@ -458,9 +468,31 @@ static av_cold int png_enc_init(AVCodecContext *avctx){ |
|
|
|
|
if(avctx->pix_fmt == AV_PIX_FMT_MONOBLACK) |
|
|
|
|
s->filter_type = PNG_FILTER_VALUE_NONE; |
|
|
|
|
|
|
|
|
|
if (s->dpi && s->dpm) { |
|
|
|
|
av_log(avctx, AV_LOG_ERROR, "Only one of 'dpi' or 'dpm' options should be set\n"); |
|
|
|
|
return AVERROR(EINVAL); |
|
|
|
|
} else if (s->dpi) { |
|
|
|
|
s->dpm = s->dpi * 10000 / 254; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#define OFFSET(x) offsetof(PNGEncContext, x) |
|
|
|
|
#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM |
|
|
|
|
static const AVOption options[] = { |
|
|
|
|
{"dpi", "Set image resolution (in dots per inch)", OFFSET(dpi), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 0x10000, VE}, |
|
|
|
|
{"dpm", "Set image resolution (in dots per meter)", OFFSET(dpm), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 0x10000, VE}, |
|
|
|
|
{ NULL } |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static const AVClass pngenc_class = { |
|
|
|
|
.class_name = "PNG encoder", |
|
|
|
|
.item_name = av_default_item_name, |
|
|
|
|
.option = options, |
|
|
|
|
.version = LIBAVUTIL_VERSION_INT, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
AVCodec ff_png_encoder = { |
|
|
|
|
.name = "png", |
|
|
|
|
.type = AVMEDIA_TYPE_VIDEO, |
|
|
|
@ -478,4 +510,5 @@ AVCodec ff_png_encoder = { |
|
|
|
|
AV_PIX_FMT_MONOBLACK, AV_PIX_FMT_NONE |
|
|
|
|
}, |
|
|
|
|
.long_name = NULL_IF_CONFIG_SMALL("PNG (Portable Network Graphics) image"), |
|
|
|
|
.priv_class = &pngenc_class, |
|
|
|
|
}; |
|
|
|
|