Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | * BMP image format encoder | ||
3 | * Copyright (c) 2006, 2007 Michel Bardiaux | ||
4 | * Copyright (c) 2009 Daniel Verkamp <daniel at drv.nu> | ||
5 | * | ||
6 | * This file is part of FFmpeg. | ||
7 | * | ||
8 | * FFmpeg is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU Lesser General Public | ||
10 | * License as published by the Free Software Foundation; either | ||
11 | * version 2.1 of the License, or (at your option) any later version. | ||
12 | * | ||
13 | * FFmpeg is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public | ||
19 | * License along with FFmpeg; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
21 | */ | ||
22 | |||
23 | #include "config.h" | ||
24 | |||
25 | #include "libavutil/avassert.h" | ||
26 | #include "libavutil/imgutils_internal.h" | ||
27 | #include "avcodec.h" | ||
28 | #include "bytestream.h" | ||
29 | #include "bmp.h" | ||
30 | #include "codec_internal.h" | ||
31 | #include "encode.h" | ||
32 | |||
33 | static const uint32_t monoblack_pal[] = { 0x000000, 0xFFFFFF }; | ||
34 | static const uint32_t rgb565_masks[] = { 0xF800, 0x07E0, 0x001F }; | ||
35 | static const uint32_t rgb444_masks[] = { 0x0F00, 0x00F0, 0x000F }; | ||
36 | |||
37 | 4 | static av_cold int bmp_encode_init(AVCodecContext *avctx){ | |
38 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
4 | switch (avctx->pix_fmt) { |
39 | ✗ | case AV_PIX_FMT_BGRA: | |
40 | ✗ | avctx->bits_per_coded_sample = 32; | |
41 | ✗ | break; | |
42 | 4 | case AV_PIX_FMT_BGR24: | |
43 | 4 | avctx->bits_per_coded_sample = 24; | |
44 | 4 | break; | |
45 | ✗ | case AV_PIX_FMT_RGB555: | |
46 | case AV_PIX_FMT_RGB565: | ||
47 | case AV_PIX_FMT_RGB444: | ||
48 | ✗ | avctx->bits_per_coded_sample = 16; | |
49 | ✗ | break; | |
50 | ✗ | case AV_PIX_FMT_RGB8: | |
51 | case AV_PIX_FMT_BGR8: | ||
52 | case AV_PIX_FMT_RGB4_BYTE: | ||
53 | case AV_PIX_FMT_BGR4_BYTE: | ||
54 | case AV_PIX_FMT_GRAY8: | ||
55 | case AV_PIX_FMT_PAL8: | ||
56 | ✗ | avctx->bits_per_coded_sample = 8; | |
57 | ✗ | break; | |
58 | ✗ | case AV_PIX_FMT_MONOBLACK: | |
59 | ✗ | avctx->bits_per_coded_sample = 1; | |
60 | ✗ | break; | |
61 | } | ||
62 | |||
63 | 4 | return 0; | |
64 | } | ||
65 | |||
66 | 16 | static int bmp_encode_frame(AVCodecContext *avctx, AVPacket *pkt, | |
67 | const AVFrame *pict, int *got_packet) | ||
68 | { | ||
69 | 16 | const AVFrame * const p = pict; | |
70 | int n_bytes_image, n_bytes_per_row, n_bytes, i, n, hsize, ret; | ||
71 | 16 | const uint32_t *pal = NULL; | |
72 | uint32_t palette256[256]; | ||
73 | 16 | int pad_bytes_per_row, pal_entries = 0, compression = BMP_RGB; | |
74 | 16 | int bit_count = avctx->bits_per_coded_sample; | |
75 | const uint8_t *ptr; | ||
76 | uint8_t *buf; | ||
77 | |||
78 |
1/6✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 16 times.
|
16 | switch (avctx->pix_fmt) { |
79 | ✗ | case AV_PIX_FMT_RGB444: | |
80 | ✗ | compression = BMP_BITFIELDS; | |
81 | ✗ | pal = rgb444_masks; // abuse pal to hold color masks | |
82 | ✗ | pal_entries = 3; | |
83 | ✗ | break; | |
84 | ✗ | case AV_PIX_FMT_RGB565: | |
85 | ✗ | compression = BMP_BITFIELDS; | |
86 | ✗ | pal = rgb565_masks; // abuse pal to hold color masks | |
87 | ✗ | pal_entries = 3; | |
88 | ✗ | break; | |
89 | ✗ | case AV_PIX_FMT_RGB8: | |
90 | case AV_PIX_FMT_BGR8: | ||
91 | case AV_PIX_FMT_RGB4_BYTE: | ||
92 | case AV_PIX_FMT_BGR4_BYTE: | ||
93 | case AV_PIX_FMT_GRAY8: | ||
94 | av_assert1(bit_count == 8); | ||
95 | ✗ | avpriv_set_systematic_pal2(palette256, avctx->pix_fmt); | |
96 | ✗ | pal = palette256; | |
97 | ✗ | break; | |
98 | ✗ | case AV_PIX_FMT_PAL8: | |
99 | ✗ | pal = (uint32_t *)p->data[1]; | |
100 | ✗ | break; | |
101 | ✗ | case AV_PIX_FMT_MONOBLACK: | |
102 | ✗ | pal = monoblack_pal; | |
103 | ✗ | break; | |
104 | } | ||
105 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
16 | if (pal && !pal_entries) pal_entries = 1 << bit_count; |
106 | 16 | n_bytes_per_row = ((int64_t)avctx->width * (int64_t)bit_count + 7LL) >> 3LL; | |
107 | 16 | pad_bytes_per_row = (4 - n_bytes_per_row) & 3; | |
108 | 16 | n_bytes_image = avctx->height * (n_bytes_per_row + pad_bytes_per_row); | |
109 | |||
110 | // STRUCTURE.field refer to the MSVC documentation for BITMAPFILEHEADER | ||
111 | // and related pages. | ||
112 | #define SIZE_BITMAPFILEHEADER 14 | ||
113 | #define SIZE_BITMAPINFOHEADER 40 | ||
114 | 16 | hsize = SIZE_BITMAPFILEHEADER + SIZE_BITMAPINFOHEADER + (pal_entries << 2); | |
115 | 16 | n_bytes = n_bytes_image + hsize; | |
116 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
|
16 | if ((ret = ff_get_encode_buffer(avctx, pkt, n_bytes, 0)) < 0) |
117 | ✗ | return ret; | |
118 | 16 | buf = pkt->data; | |
119 | 16 | bytestream_put_byte(&buf, 'B'); // BITMAPFILEHEADER.bfType | |
120 | 16 | bytestream_put_byte(&buf, 'M'); // do. | |
121 | 16 | bytestream_put_le32(&buf, n_bytes); // BITMAPFILEHEADER.bfSize | |
122 | 16 | bytestream_put_le16(&buf, 0); // BITMAPFILEHEADER.bfReserved1 | |
123 | 16 | bytestream_put_le16(&buf, 0); // BITMAPFILEHEADER.bfReserved2 | |
124 | 16 | bytestream_put_le32(&buf, hsize); // BITMAPFILEHEADER.bfOffBits | |
125 | 16 | bytestream_put_le32(&buf, SIZE_BITMAPINFOHEADER); // BITMAPINFOHEADER.biSize | |
126 | 16 | bytestream_put_le32(&buf, avctx->width); // BITMAPINFOHEADER.biWidth | |
127 | 16 | bytestream_put_le32(&buf, avctx->height); // BITMAPINFOHEADER.biHeight | |
128 | 16 | bytestream_put_le16(&buf, 1); // BITMAPINFOHEADER.biPlanes | |
129 | 16 | bytestream_put_le16(&buf, bit_count); // BITMAPINFOHEADER.biBitCount | |
130 | 16 | bytestream_put_le32(&buf, compression); // BITMAPINFOHEADER.biCompression | |
131 | 16 | bytestream_put_le32(&buf, n_bytes_image); // BITMAPINFOHEADER.biSizeImage | |
132 | 16 | bytestream_put_le32(&buf, 0); // BITMAPINFOHEADER.biXPelsPerMeter | |
133 | 16 | bytestream_put_le32(&buf, 0); // BITMAPINFOHEADER.biYPelsPerMeter | |
134 | 16 | bytestream_put_le32(&buf, 0); // BITMAPINFOHEADER.biClrUsed | |
135 | 16 | bytestream_put_le32(&buf, 0); // BITMAPINFOHEADER.biClrImportant | |
136 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | for (i = 0; i < pal_entries; i++) |
137 | ✗ | bytestream_put_le32(&buf, pal[i] & 0xFFFFFF); | |
138 | // BMP files are bottom-to-top so we start from the end... | ||
139 | 16 | ptr = p->data[0] + (avctx->height - 1) * p->linesize[0]; | |
140 | 16 | buf = pkt->data + hsize; | |
141 |
2/2✓ Branch 0 taken 4716 times.
✓ Branch 1 taken 16 times.
|
4732 | for(i = 0; i < avctx->height; i++) { |
142 | if (HAVE_BIGENDIAN && bit_count == 16) { | ||
143 | const uint16_t *src = (const uint16_t *) ptr; | ||
144 | for(n = 0; n < avctx->width; n++) | ||
145 | AV_WL16(buf + 2 * n, src[n]); | ||
146 | } else { | ||
147 | 4716 | memcpy(buf, ptr, n_bytes_per_row); | |
148 | } | ||
149 | 4716 | buf += n_bytes_per_row; | |
150 | 4716 | memset(buf, 0, pad_bytes_per_row); | |
151 | 4716 | buf += pad_bytes_per_row; | |
152 | 4716 | ptr -= p->linesize[0]; // ... and go back | |
153 | } | ||
154 | |||
155 | 16 | *got_packet = 1; | |
156 | 16 | return 0; | |
157 | } | ||
158 | |||
159 | const FFCodec ff_bmp_encoder = { | ||
160 | .p.name = "bmp", | ||
161 | CODEC_LONG_NAME("BMP (Windows and OS/2 bitmap)"), | ||
162 | .p.type = AVMEDIA_TYPE_VIDEO, | ||
163 | .p.id = AV_CODEC_ID_BMP, | ||
164 | .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, | ||
165 | .init = bmp_encode_init, | ||
166 | FF_CODEC_ENCODE_CB(bmp_encode_frame), | ||
167 | .p.pix_fmts = (const enum AVPixelFormat[]){ | ||
168 | AV_PIX_FMT_BGRA, AV_PIX_FMT_BGR24, | ||
169 | AV_PIX_FMT_RGB565, AV_PIX_FMT_RGB555, AV_PIX_FMT_RGB444, | ||
170 | AV_PIX_FMT_RGB8, AV_PIX_FMT_BGR8, AV_PIX_FMT_RGB4_BYTE, AV_PIX_FMT_BGR4_BYTE, AV_PIX_FMT_GRAY8, AV_PIX_FMT_PAL8, | ||
171 | AV_PIX_FMT_MONOBLACK, | ||
172 | AV_PIX_FMT_NONE | ||
173 | }, | ||
174 | }; | ||
175 |