Created
June 16, 2024 13:58
-
-
Save mjy9088/d83644effad787701d5569d4a05d4cbe to your computer and use it in GitHub Desktop.
serialize bmp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "bmp.h" | |
#include <stdlib.h> | |
static uint32_t u32_to_le(uint32_t u32) { | |
const uint32_t test = 42; | |
const char *const source = (const char *)&u32; | |
uint32_t result; | |
char *const dest = (char *)&result; | |
if (*((char *)&test)) | |
return (u32); | |
dest[0] = source[3]; | |
dest[1] = source[2]; | |
dest[2] = source[1]; | |
dest[3] = source[0]; | |
return (result); | |
} | |
static uint16_t u16_to_le(uint16_t u16) { | |
const uint16_t test = 42; | |
const char *const source = (const char *)&u16; | |
uint16_t result; | |
char *const dest = (char *)&result; | |
if (*((char *)&test)) | |
return (u16); | |
dest[0] = source[1]; | |
dest[1] = source[0]; | |
return (result); | |
} | |
bool serialize_bmp(bmp_t *self, char **out, size_t *out_length) { | |
const size_t row_padding = (4 - (self->width * 3) % 4) % 4; | |
const size_t row_size = self->width * 3 + row_padding; | |
const size_t whole_size = row_size * self->height; | |
const size_t length = 54 + whole_size; | |
char *const result = malloc(length); | |
if (!result) | |
return (true); | |
// header | |
result[0] = 'B'; | |
result[1] = 'M'; | |
*((uint32_t *)(result + 2)) = u32_to_le(54 + (uint32_t)whole_size); | |
*((uint32_t *)(result + 6)) = u32_to_le(0); | |
*((uint32_t *)(result + 10)) = u32_to_le(54); | |
*((uint32_t *)(result + 14)) = u32_to_le(40); | |
*((uint32_t *)(result + 18)) = u32_to_le((uint32_t)self->width); | |
*((uint32_t *)(result + 22)) = u32_to_le((uint32_t)self->height); | |
*((uint16_t *)(result + 26)) = u16_to_le(1); | |
*((uint16_t *)(result + 28)) = u16_to_le(24); | |
*((uint32_t *)(result + 30)) = u32_to_le(0); | |
*((uint32_t *)(result + 34)) = u32_to_le((uint32_t)whole_size); | |
*((uint32_t *)(result + 38)) = u32_to_le(0); | |
*((uint32_t *)(result + 42)) = u32_to_le(0); | |
*((uint32_t *)(result + 46)) = u32_to_le(0); | |
*((uint32_t *)(result + 50)) = u32_to_le(0); | |
// image data | |
size_t offset = 54; | |
for (size_t y = self->height - 1; y != (size_t)-1; y--) { // per line | |
for (size_t x = 0; x < self->width; x++) { | |
*((uint8_t *)&result[offset++]) = self->extra[self->width * y + x].b; | |
*((uint8_t *)&result[offset++]) = self->extra[self->width * y + x].g; | |
*((uint8_t *)&result[offset++]) = self->extra[self->width * y + x].r; | |
} | |
// padding | |
for (size_t i = 0; i < row_padding; i++) | |
result[offset++] = 0; | |
} | |
*out_length = length; | |
*out = result; | |
return (false); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <stddef.h> | |
#include <stdint.h> | |
#include <stdbool.h> | |
typedef struct bmp_pixel { | |
uint8_t r; | |
uint8_t g; | |
uint8_t b; | |
} bmp_pixel_t; | |
typedef struct bmp { | |
size_t width; | |
size_t height; | |
bmp_pixel_t extra[]; | |
} bmp_t; | |
/** | |
* @brief Serialize bmp | |
* | |
* @param self target image | |
* @param out serialized result | |
* @param out_length result length | |
* @return true on failure | |
* @return false on success | |
*/ | |
bool serialize_bmp(bmp_t *self, char **out, size_t *out_length); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
cmake_minimum_required(VERSION 3.10) | |
project(bmp) | |
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) | |
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR}) | |
add_executable(dummy_bmp main.c bmp.c) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include "bmp.h" | |
static char buf[256 * 256 * sizeof(bmp_pixel_t) + sizeof(bmp_t)]; | |
int main(int argc, char *argv[]) { | |
// arguments validation | |
if (argc != 2) | |
exit(EXIT_FAILURE); | |
// dummy image | |
bmp_t *bmp = (void *)&buf[0]; | |
bmp->width = 256; | |
bmp->height = 256; | |
for (size_t i = 0; i < 256; i++) { | |
for (size_t j = 0; j < 256; j++) { | |
size_t index = i * 256 + j; | |
bmp->extra[index].r = i; | |
bmp->extra[index].g = j; | |
bmp->extra[index].b = 255; | |
} | |
} | |
// serialize | |
char *result; | |
size_t length; | |
if (serialize_bmp(bmp, &result, &length)) { | |
exit(EXIT_FAILURE); | |
} | |
FILE *fp = fopen(argv[1], "wb"); | |
if (!fp) | |
exit(EXIT_FAILURE); | |
if (fwrite(result, 1, length, fp) != length) | |
exit(EXIT_FAILURE); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment