Skip to content

Commit 73ed44b

Browse files
committed
Added support for 8-bit grayscale output to fmt2bmp() for frame2bmp()
conversions (reduces memory use for grayscale). Cleanup / Addressing PR suggestions
1 parent a6f13d9 commit 73ed44b

File tree

1 file changed

+35
-23
lines changed

1 file changed

+35
-23
lines changed

conversions/to_bmp.c

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)