dwebp: add support for BMP output
Supports alpha output too. Change-Id: I42ea0bf7b6bbb420f0e537d372a3b13fe00528a9
This commit is contained in:
parent
ff885bfe1f
commit
b66caee410
5
README
5
README
@ -247,9 +247,10 @@ Decodes the WebP image file to PNG format [Default]
|
|||||||
Use following options to convert into alternate image formats:
|
Use following options to convert into alternate image formats:
|
||||||
-pam ......... save the raw RGBA samples as a color PAM
|
-pam ......... save the raw RGBA samples as a color PAM
|
||||||
-ppm ......... save the raw RGB samples as a color PPM
|
-ppm ......... save the raw RGB samples as a color PPM
|
||||||
|
-bmp ......... save as uncompressed BMP format
|
||||||
-pgm ......... save the raw YUV samples as a grayscale PGM
|
-pgm ......... save the raw YUV samples as a grayscale PGM
|
||||||
file with IMC4 layout.
|
file with IMC4 layout
|
||||||
-yuv ......... save the raw YUV samples in flat layout.
|
-yuv ......... save the raw YUV samples in flat layout
|
||||||
|
|
||||||
Other options are:
|
Other options are:
|
||||||
-version .... print version number and exit.
|
-version .... print version number and exit.
|
||||||
|
@ -62,6 +62,7 @@ typedef enum {
|
|||||||
PAM,
|
PAM,
|
||||||
PPM,
|
PPM,
|
||||||
PGM,
|
PGM,
|
||||||
|
BMP,
|
||||||
YUV,
|
YUV,
|
||||||
ALPHA_PLANE_ONLY // this is for experimenting only
|
ALPHA_PLANE_ONLY // this is for experimenting only
|
||||||
} OutputFileFormat;
|
} OutputFileFormat;
|
||||||
@ -225,6 +226,72 @@ static int WritePPM(FILE* fout, const WebPDecBuffer* const buffer, int alpha) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void PutLE16(uint8_t* const dst, uint32_t value) {
|
||||||
|
dst[0] = (value >> 0) & 0xff;
|
||||||
|
dst[1] = (value >> 8) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PutLE32(uint8_t* const dst, uint32_t value) {
|
||||||
|
PutLE16(dst + 0, (value >> 0) & 0xffff);
|
||||||
|
PutLE16(dst + 2, (value >> 16) & 0xffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BMP_HEADER_SIZE 54
|
||||||
|
static int WriteBMP(FILE* fout, const WebPDecBuffer* const buffer) {
|
||||||
|
const int has_alpha = (buffer->colorspace != MODE_BGR);
|
||||||
|
const uint32_t width = buffer->width;
|
||||||
|
const uint32_t height = buffer->height;
|
||||||
|
const uint8_t* const rgba = buffer->u.RGBA.rgba;
|
||||||
|
const int stride = buffer->u.RGBA.stride;
|
||||||
|
const size_t bytes_per_px = has_alpha ? 4 : 3;
|
||||||
|
uint32_t y;
|
||||||
|
const int line_size = bytes_per_px * width;
|
||||||
|
const int bmp_stride = (line_size + 3) & ~3; // pad to 4
|
||||||
|
const uint32_t total_size = bmp_stride * height + BMP_HEADER_SIZE;
|
||||||
|
uint8_t bmp_header[BMP_HEADER_SIZE] = { 0 };
|
||||||
|
|
||||||
|
// bitmap file header
|
||||||
|
PutLE16(bmp_header + 0, 0x4d42); // signature 'BM'
|
||||||
|
PutLE32(bmp_header + 2, total_size); // size including header
|
||||||
|
PutLE32(bmp_header + 6, 0); // reserved
|
||||||
|
PutLE32(bmp_header + 10, BMP_HEADER_SIZE); // offset to pixel array
|
||||||
|
// bitmap info header
|
||||||
|
PutLE32(bmp_header + 14, 40); // DIB header size
|
||||||
|
PutLE32(bmp_header + 18, width); // dimensions
|
||||||
|
PutLE32(bmp_header + 22, -(int)height); // vertical flip!
|
||||||
|
PutLE16(bmp_header + 26, 1); // number of planes
|
||||||
|
PutLE16(bmp_header + 28, bytes_per_px * 8); // bits per pixel
|
||||||
|
PutLE32(bmp_header + 30, 0); // no compression (BI_RGB)
|
||||||
|
PutLE32(bmp_header + 34, 0); // image size (dummy)
|
||||||
|
PutLE32(bmp_header + 38, 2400); // x pixels/meter
|
||||||
|
PutLE32(bmp_header + 42, 2400); // y pixels/meter
|
||||||
|
PutLE32(bmp_header + 46, 0); // number of palette colors
|
||||||
|
PutLE32(bmp_header + 50, 0); // important color count
|
||||||
|
|
||||||
|
// TODO(skal): color profile
|
||||||
|
|
||||||
|
// write header
|
||||||
|
if (fwrite(bmp_header, sizeof(bmp_header), 1, fout) != 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write pixel array
|
||||||
|
for (y = 0; y < height; ++y) {
|
||||||
|
if (fwrite(rgba + y * stride, line_size, 1, fout) != 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// write padding zeroes
|
||||||
|
if (bmp_stride != line_size) {
|
||||||
|
const uint8_t zeroes[3] = { 0 };
|
||||||
|
if (fwrite(zeroes, bmp_stride - line_size, 1, fout) != 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#undef BMP_HEADER_SIZE
|
||||||
|
|
||||||
static int WriteAlphaPlane(FILE* fout, const WebPDecBuffer* const buffer) {
|
static int WriteAlphaPlane(FILE* fout, const WebPDecBuffer* const buffer) {
|
||||||
const uint32_t width = buffer->width;
|
const uint32_t width = buffer->width;
|
||||||
const uint32_t height = buffer->height;
|
const uint32_t height = buffer->height;
|
||||||
@ -320,6 +387,8 @@ static void SaveOutput(const WebPDecBuffer* const buffer,
|
|||||||
ok &= WritePPM(fout, buffer, 1);
|
ok &= WritePPM(fout, buffer, 1);
|
||||||
} else if (format == PPM) {
|
} else if (format == PPM) {
|
||||||
ok &= WritePPM(fout, buffer, 0);
|
ok &= WritePPM(fout, buffer, 0);
|
||||||
|
} else if (format == BMP) {
|
||||||
|
ok &= WriteBMP(fout, buffer);
|
||||||
} else if (format == PGM || format == YUV) {
|
} else if (format == PGM || format == YUV) {
|
||||||
ok &= WritePGMOrYUV(fout, buffer, format);
|
ok &= WritePGMOrYUV(fout, buffer, format);
|
||||||
} else if (format == ALPHA_PLANE_ONLY) {
|
} else if (format == ALPHA_PLANE_ONLY) {
|
||||||
@ -345,9 +414,10 @@ static void Help(void) {
|
|||||||
"Use following options to convert into alternate image formats:\n"
|
"Use following options to convert into alternate image formats:\n"
|
||||||
" -pam ......... save the raw RGBA samples as a color PAM\n"
|
" -pam ......... save the raw RGBA samples as a color PAM\n"
|
||||||
" -ppm ......... save the raw RGB samples as a color PPM\n"
|
" -ppm ......... save the raw RGB samples as a color PPM\n"
|
||||||
|
" -bmp ......... save as uncompressed BMP format\n"
|
||||||
" -pgm ......... save the raw YUV samples as a grayscale PGM\n"
|
" -pgm ......... save the raw YUV samples as a grayscale PGM\n"
|
||||||
" file with IMC4 layout.\n"
|
" file with IMC4 layout\n"
|
||||||
" -yuv ......... save the raw YUV samples in flat layout.\n"
|
" -yuv ......... save the raw YUV samples in flat layout\n"
|
||||||
"\n"
|
"\n"
|
||||||
" Other options are:\n"
|
" Other options are:\n"
|
||||||
" -version .... print version number and exit.\n"
|
" -version .... print version number and exit.\n"
|
||||||
@ -401,6 +471,8 @@ int main(int argc, const char *argv[]) {
|
|||||||
format = PAM;
|
format = PAM;
|
||||||
} else if (!strcmp(argv[c], "-ppm")) {
|
} else if (!strcmp(argv[c], "-ppm")) {
|
||||||
format = PPM;
|
format = PPM;
|
||||||
|
} else if (!strcmp(argv[c], "-bmp")) {
|
||||||
|
format = BMP;
|
||||||
} else if (!strcmp(argv[c], "-version")) {
|
} else if (!strcmp(argv[c], "-version")) {
|
||||||
const int version = WebPGetDecoderVersion();
|
const int version = WebPGetDecoderVersion();
|
||||||
printf("%d.%d.%d\n",
|
printf("%d.%d.%d\n",
|
||||||
@ -481,6 +553,9 @@ int main(int argc, const char *argv[]) {
|
|||||||
case PPM:
|
case PPM:
|
||||||
output_buffer->colorspace = MODE_RGB; // drops alpha for PPM
|
output_buffer->colorspace = MODE_RGB; // drops alpha for PPM
|
||||||
break;
|
break;
|
||||||
|
case BMP:
|
||||||
|
output_buffer->colorspace = bitstream->has_alpha ? MODE_BGRA : MODE_BGR;
|
||||||
|
break;
|
||||||
case PGM:
|
case PGM:
|
||||||
case YUV:
|
case YUV:
|
||||||
output_buffer->colorspace = bitstream->has_alpha ? MODE_YUVA : MODE_YUV;
|
output_buffer->colorspace = bitstream->has_alpha ? MODE_YUVA : MODE_YUV;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" Hey, EMACS: -*- nroff -*-
|
.\" Hey, EMACS: -*- nroff -*-
|
||||||
.TH DWEBP 1 "February 01, 2013"
|
.TH DWEBP 1 "April 09, 2013"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
dwebp \- decompress a WebP file to an image file
|
dwebp \- decompress a WebP file to an image file
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -24,6 +24,9 @@ Print the version number (as major.minor.revision) and exit.
|
|||||||
.BI \-o " string
|
.BI \-o " string
|
||||||
Specify the name of the output file (as PNG format by default).
|
Specify the name of the output file (as PNG format by default).
|
||||||
.TP
|
.TP
|
||||||
|
.B \-bmp
|
||||||
|
Change the output format to uncompressed BMP.
|
||||||
|
.TP
|
||||||
.B \-pam
|
.B \-pam
|
||||||
Change the output format to PAM (retains alpha).
|
Change the output format to PAM (retains alpha).
|
||||||
.TP
|
.TP
|
||||||
|
Loading…
x
Reference in New Issue
Block a user