mirror of
				https://github.com/webmproject/libwebp.git
				synced 2025-10-31 10:25:46 +01:00 
			
		
		
		
	dwebp: add support for BMP output
Supports alpha output too. Change-Id: I42ea0bf7b6bbb420f0e537d372a3b13fe00528a9
This commit is contained in:
		
							
								
								
									
										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 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user