static void bmp_write_palette(bmpfile_t *bmp, FILE *fp) { if (bmp->dib.depth == 1 || bmp->dib.depth == 4 || bmp->dib.depth == 8) { int i; for (i = 0; i < bmp->dib.ncolors; ++i) fwrite(&(bmp->colors[i]), sizeof(rgb_pixel_t), 1, fp); } else if (bmp->dib.depth == 16) { /* the bit masks, not palette */ uint16_t red_mask = 63488; /* bits 1-5 */ uint16_t green_mask = 2016; /* bits 6-11 */ uint16_t blue_mask = 31; /* bits 12-16 */ uint16_t zero_word = 0; if (_is_big_endian()) { red_mask = UINT16_SWAP_LE_BE_CONSTANT(red_mask); green_mask = UINT16_SWAP_LE_BE_CONSTANT(green_mask); blue_mask = UINT16_SWAP_LE_BE_CONSTANT(blue_mask); } fwrite(&red_mask, sizeof(uint16_t), 1, fp); fwrite(&zero_word, sizeof(uint16_t), 1, fp); fwrite(&green_mask, sizeof(uint16_t), 1, fp); fwrite(&zero_word, sizeof(uint16_t), 1, fp); fwrite(&blue_mask, sizeof(uint16_t), 1, fp); fwrite(&zero_word, sizeof(uint16_t), 1, fp); } }
void bmp_write_palette(bmp_structp bmp) { if (bmp->dib.depth == 1 || bmp->dib.depth == 4 || bmp->dib.depth == 8) { bmp->write_fn(bmp, (uint8_t*)bmp->colors, sizeof(rgb_pixel_t) * bmp->dib.ncolors); } else if (bmp->dib.depth == 16) { /* the bit masks, not palette */ uint16_t red_mask = 63488; /* bits 1-5 */ uint16_t green_mask = 2016; /* bits 6-11 */ uint16_t blue_mask = 31; /* bits 12-16 */ uint16_t zero_word = 0; if (_is_big_endian()) { red_mask = UINT16_SWAP_LE_BE_CONSTANT(red_mask); green_mask = UINT16_SWAP_LE_BE_CONSTANT(green_mask); blue_mask = UINT16_SWAP_LE_BE_CONSTANT(blue_mask); } bmp->write_fn(bmp, (uint8_t*)&red_mask, sizeof(uint16_t)); bmp->write_fn(bmp, (uint8_t*)&zero_word, sizeof(uint16_t)); bmp->write_fn(bmp, (uint8_t*)&green_mask, sizeof(uint16_t)); bmp->write_fn(bmp, (uint8_t*)&zero_word, sizeof(uint16_t)); bmp->write_fn(bmp, (uint8_t*)&blue_mask, sizeof(uint16_t)); bmp->write_fn(bmp, (uint8_t*)&zero_word, sizeof(uint16_t)); } }
void bmp_write_header(bmp_structp bmp) { if (_is_big_endian()) bmp_header_swap_endianess(&bmp->header); bmp->write_fn(bmp, (uint8_t*)&bmp->header.magic, sizeof(uint8_t) * 2); bmp->write_fn(bmp, (uint8_t*)&bmp->header.filesz, sizeof(uint32_t)); bmp->write_fn(bmp, (uint8_t*)&bmp->header.creator1, sizeof(uint16_t)); bmp->write_fn(bmp, (uint8_t*)&bmp->header.creator2, sizeof(uint16_t)); bmp->write_fn(bmp, (uint8_t*)&bmp->header.offset, sizeof(uint32_t)); }
static void bmp_write_header(bmpfile_t *bmp, FILE *fp) { bmp_header_t header = bmp->header; if (_is_big_endian()) bmp_header_swap_endianess(&header); fwrite(header.magic, sizeof(header.magic), 1, fp); fwrite(&(header.filesz), sizeof(uint32_t), 1, fp); fwrite(&(header.creator1), sizeof(uint16_t), 1, fp); fwrite(&(header.creator2), sizeof(uint16_t), 1, fp); fwrite(&(header.offset), sizeof(uint32_t), 1, fp); }
void bmp_write_dib(bmp_structp bmp) { if (_is_big_endian()) bmp_dib_v3_header_swap_endianess(&bmp->dib); bmp->write_fn(bmp, (uint8_t*)&bmp->dib.header_sz, sizeof(uint32_t)); bmp->write_fn(bmp, (uint8_t*)&bmp->dib.width, sizeof(uint32_t)); bmp->write_fn(bmp, (uint8_t*)&bmp->dib.height, sizeof(uint32_t)); bmp->write_fn(bmp, (uint8_t*)&bmp->dib.nplanes, sizeof(uint16_t)); bmp->write_fn(bmp, (uint8_t*)&bmp->dib.depth, sizeof(uint16_t)); bmp->write_fn(bmp, (uint8_t*)&bmp->dib.compress_type, sizeof(uint32_t)); bmp->write_fn(bmp, (uint8_t*)&bmp->dib.bmp_bytesz, sizeof(uint32_t)); bmp->write_fn(bmp, (uint8_t*)&bmp->dib.hres, sizeof(uint32_t)); bmp->write_fn(bmp, (uint8_t*)&bmp->dib.vres, sizeof(uint32_t)); bmp->write_fn(bmp, (uint8_t*)&bmp->dib.ncolors, sizeof(uint32_t)); bmp->write_fn(bmp, (uint8_t*)&bmp->dib.nimpcolors, sizeof(uint32_t)); }
static void bmp_write_dib(bmpfile_t *bmp, FILE *fp) { bmp_dib_v3_header_t dib = bmp->dib; if (_is_big_endian()) bmp_dib_v3_header_swap_endianess(&dib); fwrite(&(dib.header_sz), sizeof(uint32_t), 1, fp); fwrite(&(dib.width), sizeof(uint32_t), 1, fp); fwrite(&(dib.height), sizeof(uint32_t), 1, fp); fwrite(&(dib.nplanes), sizeof(uint16_t), 1, fp); fwrite(&(dib.depth), sizeof(uint16_t), 1, fp); fwrite(&(dib.compress_type), sizeof(uint32_t), 1, fp); fwrite(&(dib.bmp_bytesz), sizeof(uint32_t), 1, fp); fwrite(&(dib.hres), sizeof(uint32_t), 1, fp); fwrite(&(dib.vres), sizeof(uint32_t), 1, fp); fwrite(&(dib.ncolors), sizeof(uint32_t), 1, fp); fwrite(&(dib.nimpcolors), sizeof(uint32_t), 1, fp); }
void bmp_write_pixels(bmp_structp bmp, uint32_t offset, uint32_t length) { int index; unsigned char *buf; if (bmp->dib.depth == 16) { uint32_t data_bytes = bmp->dib.width * 2; uint32_t padding_bytes = 4 - data_bytes % 4; unsigned char zero_byte = 0; for (; index = bmp->dib.height * data_bytes; ++index) { uint16_t red = (uint16_t)(bmp->pixels[index].red / 8); uint16_t green = (uint16_t)(bmp->pixels[index].green / 4); uint16_t blue = (uint16_t)(bmp->pixels[index].blue / 8); uint16_t value = (red << 11) + (green << 5) + blue; if (_is_big_endian()) value = UINT16_SWAP_LE_BE_CONSTANT(value); bmp->write_fn(bmp, (uint8_t*)&value, sizeof(uint16_t)); } } else { double bytes_per_pixel; int bytes_per_line; bytes_per_pixel = (bmp->dib.depth * 1.0) / 8.0; bytes_per_line = (int)ceil(bytes_per_pixel * bmp->dib.width); if (bytes_per_line % 4 != 0) bytes_per_line += 4 - bytes_per_line % 4; int row; buf = (unsigned char*)malloc(bytes_per_line); for (row = bmp->dib.height - 1; row >= 0; --row) { memset(buf, 0, bytes_per_line); switch (bmp->dib.depth) { case 1: bmp_get_row_data_for_1(bmp, buf, bytes_per_line, row); break; case 4: bmp_get_row_data_for_4(bmp, buf, bytes_per_line, row); break; case 8: bmp_get_row_data_for_8(bmp, buf, bytes_per_line, row); break; case 24: bmp_get_row_data_for_24(bmp, buf, bytes_per_line, row); break; case 32: bmp_get_row_data_for_32(bmp, buf, bytes_per_line, row); break; } bmp->write_fn(bmp, buf, bytes_per_line); } free(buf); } }
bool bmp_save(bmpfile_t *bmp, const char *filename) { FILE *fp; int row; unsigned char *buf; /* Create the file */ if ((fp = fopen(filename, "wb")) == NULL) return FALSE; /* Write the file */ bmp_write_header(bmp, fp); bmp_write_dib(bmp, fp); bmp_write_palette(bmp, fp); if (bmp->dib.depth == 16) { uint32_t data_bytes = bmp->dib.width * 2; uint32_t padding_bytes = 4 - data_bytes % 4; for (row = bmp->dib.height - 1; row >= 0; --row) { int i; unsigned char zero_byte = 0; uint32_t write_number = 0; for (i = 0; write_number < data_bytes; ++i, write_number += 2) { uint16_t red = (uint16_t)(bmp->pixels[i][row].uniColour / 8); uint16_t green = (uint16_t)(bmp->pixels[i][row].uniColour / 4); uint16_t blue = (uint16_t)(bmp->pixels[i][row].uniColour / 8); uint16_t value = (red << 11) + (green << 5) + blue; if (_is_big_endian()) value = UINT16_SWAP_LE_BE_CONSTANT(value); fwrite(&value, sizeof(uint16_t), 1, fp); } for (write_number = 0; write_number < padding_bytes; ++write_number) fwrite(&zero_byte, 1, 1, fp); } } else { double bytes_per_pixel; int bytes_per_line; bytes_per_pixel = (bmp->dib.depth * 1.0) / 8.0; bytes_per_line = (int)ceil(bytes_per_pixel * bmp->dib.width); if (bytes_per_line % 4 != 0) bytes_per_line += 4 - bytes_per_line % 4; buf = malloc(bytes_per_line); for (row = bmp->dib.height - 1; row >= 0; --row) { memset(buf, 0, bytes_per_line); switch (bmp->dib.depth) { case 1: bmp_get_row_data_for_1(bmp, buf, bytes_per_line, row); break; case 4: bmp_get_row_data_for_4(bmp, buf, bytes_per_line, row); break; case 8: bmp_get_row_data_for_8(bmp, buf, bytes_per_line, row); break; case 24: bmp_get_row_data_for_24(bmp, buf, bytes_per_line, row); break; case 32: bmp_get_row_data_for_32(bmp, buf, bytes_per_line, row); break; } fwrite(buf, bytes_per_line, 1, fp); } free(buf); } fclose(fp); return TRUE; }