@@ -302,7 +302,13 @@ bool fmt2bmp(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixf
302302 * out_len = 0 ;
303303
304304 int pix_count = width * height ;
305- size_t out_size = (pix_count * 3 ) + BMP_HEADER_LEN ;
305+
306+ // With BMP, 8-bit greyscale requires a palette.
307+ // For a 640x480 image though, that's a savings
308+ // over going RGB-24.
309+ int bpp = (format == PIXFORMAT_GRAYSCALE ) ? 1 : 3 ;
310+ int palette_size = (format == PIXFORMAT_GRAYSCALE ) ? 4 * 256 : 0 ;
311+ size_t out_size = (pix_count * bpp ) + BMP_HEADER_LEN + palette_size ;
306312 uint8_t * out_buf = (uint8_t * )_malloc (out_size );
307313 if (!out_buf ) {
308314 ESP_LOGE (TAG , "_malloc failed! %u" , out_size );
@@ -314,45 +320,51 @@ bool fmt2bmp(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixf
314320 bmp_header_t * bitmap = (bmp_header_t * )& out_buf [2 ];
315321 bitmap -> reserved = 0 ;
316322 bitmap -> filesize = out_size ;
317- bitmap -> fileoffset_to_pixelarray = BMP_HEADER_LEN ;
323+ bitmap -> fileoffset_to_pixelarray = BMP_HEADER_LEN + palette_size ;
318324 bitmap -> dibheadersize = 40 ;
319325 bitmap -> width = width ;
320326 bitmap -> height = - height ;//set negative for top to bottom
321327 bitmap -> planes = 1 ;
322- bitmap -> bitsperpixel = 24 ;
328+ bitmap -> bitsperpixel = bpp * 8 ;
323329 bitmap -> compression = 0 ;
324- bitmap -> imagesize = pix_count * 3 ;
330+ bitmap -> imagesize = pix_count * bpp ;
325331 bitmap -> ypixelpermeter = 0x0B13 ; //2835 , 72 DPI
326332 bitmap -> xpixelpermeter = 0x0B13 ; //2835 , 72 DPI
327333 bitmap -> numcolorspallette = 0 ;
328334 bitmap -> mostimpcolor = 0 ;
329335
330- uint8_t * rgb_buf = out_buf + BMP_HEADER_LEN ;
336+ uint8_t * palette_buf = out_buf + BMP_HEADER_LEN ;
337+ uint8_t * pix_buf = palette_buf + palette_size ;
331338 uint8_t * src_buf = src ;
332339
340+ if (palette_size > 0 ) {
341+ // Grayscale palette
342+ for (int i = 0 ; i < 256 ; ++ i ) {
343+ for (int j = 0 ; j < 3 ; ++ j ) {
344+ * palette_buf = i ;
345+ palette_buf ++ ;
346+ }
347+ // Reserved / alpha channel.
348+ * palette_buf = 0 ;
349+ palette_buf ++ ;
350+ }
351+ }
333352
334353 //convert data to RGB888
335354 if (format == PIXFORMAT_RGB888 ) {
336- memcpy (rgb_buf , src_buf , pix_count * 3 );
355+ memcpy (pix_buf , src_buf , pix_count * 3 );
337356 } else if (format == PIXFORMAT_RGB565 ) {
338357 int i ;
339358 uint8_t hb , lb ;
340359 for (i = 0 ; i < pix_count ; i ++ ) {
341360 hb = * src_buf ++ ;
342361 lb = * src_buf ++ ;
343- * rgb_buf ++ = (lb & 0x1F ) << 3 ;
344- * rgb_buf ++ = (hb & 0x07 ) << 5 | (lb & 0xE0 ) >> 3 ;
345- * rgb_buf ++ = hb & 0xF8 ;
362+ * pix_buf ++ = (lb & 0x1F ) << 3 ;
363+ * pix_buf ++ = (hb & 0x07 ) << 5 | (lb & 0xE0 ) >> 3 ;
364+ * pix_buf ++ = hb & 0xF8 ;
346365 }
347366 } else if (format == PIXFORMAT_GRAYSCALE ) {
348- int i ;
349- uint8_t b ;
350- for (i = 0 ; i < pix_count ; i ++ ) {
351- b = * src_buf ++ ;
352- * rgb_buf ++ = b ;
353- * rgb_buf ++ = b ;
354- * rgb_buf ++ = b ;
355- }
367+ memcpy (pix_buf , src_buf , pix_count );
356368 } else if (format == PIXFORMAT_YUV422 ) {
357369 int i , maxi = pix_count / 2 ;
358370 uint8_t y0 , y1 , u , v ;
@@ -364,14 +376,14 @@ bool fmt2bmp(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixf
364376 v = * src_buf ++ ;
365377
366378 yuv2rgb (y0 , u , v , & r , & g , & b );
367- * rgb_buf ++ = b ;
368- * rgb_buf ++ = g ;
369- * rgb_buf ++ = r ;
379+ * pix_buf ++ = b ;
380+ * pix_buf ++ = g ;
381+ * pix_buf ++ = r ;
370382
371383 yuv2rgb (y1 , u , v , & r , & g , & b );
372- * rgb_buf ++ = b ;
373- * rgb_buf ++ = g ;
374- * rgb_buf ++ = r ;
384+ * pix_buf ++ = b ;
385+ * pix_buf ++ = g ;
386+ * pix_buf ++ = r ;
375387 }
376388 }
377389 * out = out_buf ;
0 commit comments