95 lines
3.8 KiB
C
95 lines
3.8 KiB
C
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
|
|
#include "bmp.h"
|
|
|
|
uint32_t calc_bitmap_pixel_array_size_bytes(const bitmap *bitmap_in) {
|
|
/* We will assume that the bitmap bits per pixel is always a multiple of 8 and sizeof byte is always 8 bits */
|
|
uint32_t bytes_unpadded = (((bitmap_in->image_width * bitmap_in->image_height) * bitmap_in->bits_per_pixel) / 8);
|
|
return bytes_unpadded + ((bytes_unpadded / 6) * 2); /* Add padding to ensure 4 byte allignment */
|
|
};
|
|
|
|
uint32_t calc_bitmap_file_size_bytes(const bitmap *bitmap_in) {
|
|
/* We will assume that the bitmap bits per pixel is always a multiple of 8 and sizeof byte is always 8 bits */
|
|
return sizeof(bitmap) + calc_bitmap_pixel_array_size_bytes(bitmap_in) - 2 ; /* Take away two to account for compiler padding struct */
|
|
};
|
|
|
|
uint32_t calc_bitmap_header_size_bytes() {
|
|
return sizeof(bitmap) - 2 ; /* Take away two to account for compiler padding struct */
|
|
};
|
|
|
|
/* Change name to init_bitmap_header */
|
|
bitmap init_bitmap(const int32_t image_width_in, const int32_t image_height_in) {
|
|
bitmap new_bitmap;
|
|
/* Bitmap Info Header */
|
|
new_bitmap.info_header_size_bytes = 40;
|
|
new_bitmap.image_width = image_width_in;
|
|
new_bitmap.image_height = image_height_in;
|
|
new_bitmap.color_planes_used = 1;
|
|
new_bitmap.bits_per_pixel = 24;
|
|
new_bitmap.compression_method = 0;
|
|
|
|
new_bitmap.image_size = calc_bitmap_pixel_array_size_bytes(&new_bitmap);
|
|
new_bitmap.horizontal_resolution_pixels_per_metre = 2835; /* Approx 72DPI */
|
|
new_bitmap.vertical_resolution_pixels_per_metre = 2835;
|
|
new_bitmap.colors_in_palette = 0;
|
|
new_bitmap.important_colors = 0;
|
|
|
|
/* File Header */
|
|
new_bitmap.header_field[0] = 'B';
|
|
new_bitmap.header_field[1] = 'M';
|
|
new_bitmap.file_size_bytes = calc_bitmap_file_size_bytes(&new_bitmap);
|
|
new_bitmap.reserved1 = 0;
|
|
new_bitmap.reserved2 = 0;
|
|
new_bitmap.image_data_start_offset = 54;
|
|
|
|
return new_bitmap;
|
|
};
|
|
|
|
/* Change the name to init_bitmap_file */
|
|
bitmap_file write_to_bitmap(const bitmap *bitmap_in, const char *filename) {
|
|
bitmap_file new_bitmap_file;
|
|
int8_t write_status;
|
|
uint32_t current_byte;
|
|
uint8_t blank_byte_buffer[1] = { 0 };
|
|
uint8_t *bitmap_in_byte_ptr = (uint8_t *)bitmap_in + 2; /* Offset by two to account for padding */
|
|
int8_t fd = open(filename, O_WRONLY | O_CREAT, 0666);
|
|
if (fd == -1)
|
|
/* TODO Need an error return type */
|
|
return new_bitmap_file;
|
|
/* Write Header */
|
|
write_status = write(fd, bitmap_in_byte_ptr, calc_bitmap_header_size_bytes());
|
|
/* Write blank pixel array */
|
|
for (current_byte = bitmap_in->image_data_start_offset; current_byte <= calc_bitmap_file_size_bytes(bitmap_in); ++current_byte)
|
|
write_status = pwrite(fd, blank_byte_buffer, 1, current_byte);
|
|
if (fd == -1) {
|
|
close(fd);
|
|
/* TODO Need an error return type */
|
|
return new_bitmap_file;
|
|
}
|
|
close(fd);
|
|
|
|
new_bitmap_file.filename = filename;
|
|
new_bitmap_file.bitmap_metadata = bitmap_in;
|
|
return new_bitmap_file;
|
|
};
|
|
|
|
int write_bitmap_pixel(const bitmap_file *bitmap_file_in, const bitmap_pixel_color *bitmap_pixel_in, const int32_t x_in, const int32_t y_in) {
|
|
int8_t write_status;
|
|
int32_t byte_position_end = ((bitmap_file_in->bitmap_metadata->image_width * (y_in - 1)) + x_in) * 3; /* Three bytes */
|
|
int32_t byte_position_end_padded = byte_position_end + ((byte_position_end / 8) * 2); /* Account for padding of all pixels before this one */
|
|
int32_t byte_position_start = byte_position_end_padded - 3;
|
|
uint8_t *bitmap_pixel_in_byte_ptr = (uint8_t *)bitmap_pixel_in;
|
|
|
|
int8_t fd = open(bitmap_file_in->filename, O_WRONLY | O_CREAT, 0666);
|
|
|
|
if (fd == -1)
|
|
return -1;
|
|
if (byte_position_start % 4)
|
|
write_status = pwrite(fd, bitmap_pixel_in_byte_ptr, 5, bitmap_file_in->bitmap_metadata->image_data_start_offset + byte_position_start);
|
|
else
|
|
write_status = pwrite(fd, bitmap_pixel_in_byte_ptr, 3, bitmap_file_in->bitmap_metadata->image_data_start_offset + byte_position_start);
|
|
return 0;
|
|
};
|