diff options
author | Niklas Haas <git@nand.wakku.to> | 2015-02-27 23:31:38 +0300 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2015-02-28 05:34:57 +0300 |
commit | 888a33c070f1e96b683e13e7b0b6af891428c6c3 (patch) | |
tree | 8fb29389be650d7f06abf29d3cd1fac96aa66b78 /libavcodec/pngenc.c | |
parent | 0a23129bfc6f14c30c25aafcbf45c4b1b0f728ee (diff) |
lavc/pngenc: Support writing colorspace tags.
These are defined in http://www.w3.org/TR/PNG/#11addnlcolinfo.
Diffstat (limited to 'libavcodec/pngenc.c')
-rw-r--r-- | libavcodec/pngenc.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c index ef33332179..9fd8eefd25 100644 --- a/libavcodec/pngenc.c +++ b/libavcodec/pngenc.c @@ -231,6 +231,81 @@ static int png_write_row(PNGEncContext *s, const uint8_t *data, int size) return 0; } +#define AV_WB32_PNG(buf, n) (AV_WB32(buf, round((n) * 100000))) +static int png_get_chrm(enum AVColorPrimaries prim, uint8_t *buf) +{ + double rx, ry, gx, gy, bx, by, wx = 0.3127, wy = 0.3290; + switch (prim) { + case AVCOL_PRI_BT709: + rx = 0.640; ry = 0.330; + gx = 0.300; gy = 0.600; + bx = 0.150; by = 0.060; + break; + case AVCOL_PRI_BT470M: + rx = 0.670; ry = 0.330; + gx = 0.210; gy = 0.710; + bx = 0.140; by = 0.080; + wx = 0.310; wy = 0.316; + break; + case AVCOL_PRI_BT470BG: + rx = 0.640; ry = 0.330; + gx = 0.290; gy = 0.600; + bx = 0.150; by = 0.060; + break; + case AVCOL_PRI_SMPTE170M: + case AVCOL_PRI_SMPTE240M: + rx = 0.630; ry = 0.340; + gx = 0.310; gy = 0.595; + bx = 0.155; by = 0.070; + break; + case AVCOL_PRI_BT2020: + rx = 0.708; ry = 0.292; + gx = 0.170; gy = 0.797; + bx = 0.131; by = 0.046; + break; + default: + return 0; + } + + AV_WB32_PNG(buf , wx); AV_WB32_PNG(buf + 4 , wy); + AV_WB32_PNG(buf + 8 , rx); AV_WB32_PNG(buf + 12, ry); + AV_WB32_PNG(buf + 16, gx); AV_WB32_PNG(buf + 20, gy); + AV_WB32_PNG(buf + 24, bx); AV_WB32_PNG(buf + 28, by); + return 1; +} + +static int png_get_gama(enum AVColorTransferCharacteristic trc, uint8_t *buf) +{ + double gamma; + switch (trc) { + case AVCOL_TRC_BT709: + case AVCOL_TRC_SMPTE170M: + case AVCOL_TRC_SMPTE240M: + case AVCOL_TRC_BT1361_ECG: + case AVCOL_TRC_BT2020_10: + case AVCOL_TRC_BT2020_12: + /* these share a segmented TRC, but gamma 1.961 is a close + approximation, and also more correct for decoding content */ + gamma = 1.961; + break; + case AVCOL_TRC_GAMMA22: + case AVCOL_TRC_IEC61966_2_1: + gamma = 2.2; + break; + case AVCOL_TRC_GAMMA28: + gamma = 2.8; + break; + case AVCOL_TRC_LINEAR: + gamma = 1.0; + break; + default: + return 0; + } + + AV_WB32_PNG(buf, 1.0 / gamma); + return 1; +} + static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet) { @@ -358,6 +433,18 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, } png_write_chunk(&s->bytestream, MKTAG('p', 'H', 'Y', 's'), s->buf, 9); + /* write colorspace information */ + if (pict->color_primaries == AVCOL_PRI_BT709 && + pict->color_trc == AVCOL_TRC_IEC61966_2_1) { + s->buf[0] = 1; /* rendering intent, relative colorimetric by default */ + png_write_chunk(&s->bytestream, MKTAG('s', 'R', 'G', 'B'), s->buf, 1); + } + + if (png_get_chrm(pict->color_primaries, s->buf)) + png_write_chunk(&s->bytestream, MKTAG('c', 'H', 'R', 'M'), s->buf, 32); + if (png_get_gama(pict->color_trc, s->buf)) + png_write_chunk(&s->bytestream, MKTAG('g', 'A', 'M', 'A'), s->buf, 4); + /* put the palette if needed */ if (color_type == PNG_COLOR_TYPE_PALETTE) { int has_alpha, alpha, i; |