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/imgutils.h" 26#include "libavutil/avassert.h" 27#include "avcodec.h" 28#include "bytestream.h" 29#include "bmp.h" 30#include "codec_internal.h" 31#include "encode.h" 32 33static const uint32_t monoblack_pal[] = { 0x000000, 0xFFFFFF }; 34static const uint32_t rgb565_masks[] = { 0xF800, 0x07E0, 0x001F }; 35static const uint32_t rgb444_masks[] = { 0x0F00, 0x00F0, 0x000F }; 36 37static av_cold int bmp_encode_init(AVCodecContext *avctx){ 38 switch (avctx->pix_fmt) { 39 case AV_PIX_FMT_BGRA: 40 avctx->bits_per_coded_sample = 32; 41 break; 42 case AV_PIX_FMT_BGR24: 43 avctx->bits_per_coded_sample = 24; 44 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 return 0; 64} 65 66static int bmp_encode_frame(AVCodecContext *avctx, AVPacket *pkt, 67 const AVFrame *pict, int *got_packet) 68{ 69 const AVFrame * const p = pict; 70 int n_bytes_image, n_bytes_per_row, n_bytes, i, n, hsize, ret; 71 const uint32_t *pal = NULL; 72 uint32_t palette256[256]; 73 int pad_bytes_per_row, pal_entries = 0, compression = BMP_RGB; 74 int bit_count = avctx->bits_per_coded_sample; 75 uint8_t *ptr, *buf; 76 77 switch (avctx->pix_fmt) { 78 case AV_PIX_FMT_RGB444: 79 compression = BMP_BITFIELDS; 80 pal = rgb444_masks; // abuse pal to hold color masks 81 pal_entries = 3; 82 break; 83 case AV_PIX_FMT_RGB565: 84 compression = BMP_BITFIELDS; 85 pal = rgb565_masks; // abuse pal to hold color masks 86 pal_entries = 3; 87 break; 88 case AV_PIX_FMT_RGB8: 89 case AV_PIX_FMT_BGR8: 90 case AV_PIX_FMT_RGB4_BYTE: 91 case AV_PIX_FMT_BGR4_BYTE: 92 case AV_PIX_FMT_GRAY8: 93 av_assert1(bit_count == 8); 94 avpriv_set_systematic_pal2(palette256, avctx->pix_fmt); 95 pal = palette256; 96 break; 97 case AV_PIX_FMT_PAL8: 98 pal = (uint32_t *)p->data[1]; 99 break; 100 case AV_PIX_FMT_MONOBLACK: 101 pal = monoblack_pal; 102 break; 103 } 104 if (pal && !pal_entries) pal_entries = 1 << bit_count; 105 n_bytes_per_row = ((int64_t)avctx->width * (int64_t)bit_count + 7LL) >> 3LL; 106 pad_bytes_per_row = (4 - n_bytes_per_row) & 3; 107 n_bytes_image = avctx->height * (n_bytes_per_row + pad_bytes_per_row); 108 109 // STRUCTURE.field refer to the MSVC documentation for BITMAPFILEHEADER 110 // and related pages. 111#define SIZE_BITMAPFILEHEADER 14 112#define SIZE_BITMAPINFOHEADER 40 113 hsize = SIZE_BITMAPFILEHEADER + SIZE_BITMAPINFOHEADER + (pal_entries << 2); 114 n_bytes = n_bytes_image + hsize; 115 if ((ret = ff_get_encode_buffer(avctx, pkt, n_bytes, 0)) < 0) 116 return ret; 117 buf = pkt->data; 118 bytestream_put_byte(&buf, 'B'); // BITMAPFILEHEADER.bfType 119 bytestream_put_byte(&buf, 'M'); // do. 120 bytestream_put_le32(&buf, n_bytes); // BITMAPFILEHEADER.bfSize 121 bytestream_put_le16(&buf, 0); // BITMAPFILEHEADER.bfReserved1 122 bytestream_put_le16(&buf, 0); // BITMAPFILEHEADER.bfReserved2 123 bytestream_put_le32(&buf, hsize); // BITMAPFILEHEADER.bfOffBits 124 bytestream_put_le32(&buf, SIZE_BITMAPINFOHEADER); // BITMAPINFOHEADER.biSize 125 bytestream_put_le32(&buf, avctx->width); // BITMAPINFOHEADER.biWidth 126 bytestream_put_le32(&buf, avctx->height); // BITMAPINFOHEADER.biHeight 127 bytestream_put_le16(&buf, 1); // BITMAPINFOHEADER.biPlanes 128 bytestream_put_le16(&buf, bit_count); // BITMAPINFOHEADER.biBitCount 129 bytestream_put_le32(&buf, compression); // BITMAPINFOHEADER.biCompression 130 bytestream_put_le32(&buf, n_bytes_image); // BITMAPINFOHEADER.biSizeImage 131 bytestream_put_le32(&buf, 0); // BITMAPINFOHEADER.biXPelsPerMeter 132 bytestream_put_le32(&buf, 0); // BITMAPINFOHEADER.biYPelsPerMeter 133 bytestream_put_le32(&buf, 0); // BITMAPINFOHEADER.biClrUsed 134 bytestream_put_le32(&buf, 0); // BITMAPINFOHEADER.biClrImportant 135 for (i = 0; i < pal_entries; i++) 136 bytestream_put_le32(&buf, pal[i] & 0xFFFFFF); 137 // BMP files are bottom-to-top so we start from the end... 138 ptr = p->data[0] + (avctx->height - 1) * p->linesize[0]; 139 buf = pkt->data + hsize; 140 for(i = 0; i < avctx->height; i++) { 141 if (HAVE_BIGENDIAN && bit_count == 16) { 142 const uint16_t *src = (const uint16_t *) ptr; 143 for(n = 0; n < avctx->width; n++) 144 AV_WL16(buf + 2 * n, src[n]); 145 } else { 146 memcpy(buf, ptr, n_bytes_per_row); 147 } 148 buf += n_bytes_per_row; 149 memset(buf, 0, pad_bytes_per_row); 150 buf += pad_bytes_per_row; 151 ptr -= p->linesize[0]; // ... and go back 152 } 153 154 *got_packet = 1; 155 return 0; 156} 157 158const FFCodec ff_bmp_encoder = { 159 .p.name = "bmp", 160 .p.long_name = NULL_IF_CONFIG_SMALL("BMP (Windows and OS/2 bitmap)"), 161 .p.type = AVMEDIA_TYPE_VIDEO, 162 .p.id = AV_CODEC_ID_BMP, 163 .p.capabilities = AV_CODEC_CAP_DR1, 164 .init = bmp_encode_init, 165 FF_CODEC_ENCODE_CB(bmp_encode_frame), 166 .p.pix_fmts = (const enum AVPixelFormat[]){ 167 AV_PIX_FMT_BGRA, AV_PIX_FMT_BGR24, 168 AV_PIX_FMT_RGB565, AV_PIX_FMT_RGB555, AV_PIX_FMT_RGB444, 169 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, 170 AV_PIX_FMT_MONOBLACK, 171 AV_PIX_FMT_NONE 172 }, 173 .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, 174}; 175