cleaned code, transparency now actually working

master
Anton Lydike 5 years ago
parent 83ab573efb
commit 5e8bab38f0

2
.gitignore vendored

@ -1,2 +1,4 @@
*.out
*.o
*.bmp

@ -0,0 +1,91 @@
#include <stdio.h>
#include <stdlib.h>
#include "images.h"
// write an int to a byte array
void bmp__write_int(char* bytes, int num) {
for (int i = 0; i < 4; i++) {
bytes[i] = num >> (i * 8);
}
}
void bmp__write_byte(char* bytes, int num) {
bytes[0] = (char) num;
}
void bmp__write_16bit(char* bytes, int num) {
for (int i = 0; i < 2; i++) {
bytes[i] = num >> (i * 8);
}
}
int bmp__align_to_four_bytes(int size) {
int os = size % 4;
return os == 0 ? size : size + (4 - os);
}
int bmp__image_byte_size(Image image) {
// calculate size:
// bitmap file header = 14
// BITMAPCOREHEADER = 12 bytes
int size = 14 + 12;
// width must be padded to align to 4 bytes
int width_bytes = bmp__align_to_four_bytes(image.width * 3); // 3 bytes per pixel
// add width_bytes * height to total size
size += width_bytes * image.height;
return size;
}
// header format:
// BMP header (14 bytes)
// 0x42 0x4D "BM"
// 0xAA 0xBB 0xCC 0xDD bmp file size (int)
// 0x00 0x00 0x00 0x00 nulls
// 0x1A 0x00 0x00 0x00 pixel array offset (int) (= 14 + 12);
// DIB Header (BITMAPCOREHEADER) (12 bytes)
// 0x0C 0x00 0x00 0x00 header size (int) (= 12)
// 0xAA 0xBB width (unsigned 16 bit int)
// 0xCC 0xDD height (unsigned 16 bit int)
// 0x01 0x00 number of color planes (must be 1)
// 0x18 0x00 number of bits per pixel (3 * 8 = 24)
int image_save_bmp(Image image, char* path) {
int size = bmp__image_byte_size(image);
char* bytes = calloc(sizeof(char), size);
// magic bytes, signature "BM"
bytes[0] = 0x42;
bytes[1] = 0x4d;
// write size to header
bmp__write_int(bytes + 2, size);
// the next 4 byte are zeros
// piyel array offset
bmp__write_int(bytes + 10, 14 + 12);
bmp__write_int(bytes + 14, 12);
bmp__write_16bit(bytes + 18, image.width); // width
bmp__write_16bit(bytes + 20, image.height); // height
bmp__write_16bit(bytes + 22, 1); // color planes
bmp__write_16bit(bytes + 24, 3 * 8); // bits per pixel
int byte_offset = 26;
int byte_pos = 0;
int line;
for (line = 0; line < image.height; line++) {
byte_pos = 0;
for (int px = 0; px < image.width * 3; px += 3) {
bytes[byte_offset + byte_pos++] = image.bitmap[line][px + 2];
bytes[byte_offset + byte_pos++] = image.bitmap[line][px + 1];
bytes[byte_offset + byte_pos++] = image.bitmap[line][px + 0];
}
byte_offset += bmp__align_to_four_bytes(byte_pos);
}
printf("generated %i bytes out of %i calculated ones\n", byte_offset, size);
FILE *fp = fopen(path, "w");
int written = fwrite(bytes, sizeof(char), size, fp);
printf("wrote %i bytes...\n", written);
fclose(fp);
free(bytes);
return 1;
}

@ -2,30 +2,9 @@
#include <stdio.h>
#include "images.h"
// write an int to a byte array
void write_int(char* bytes, int num) {
for (int i = 0; i < 4; i++) {
bytes[i] = num >> (i * 8);
}
}
void write_byte(char* bytes, int num) {
bytes[0] = (char) num;
}
void write_16bit(char* bytes, int num) {
for (int i = 0; i < 2; i++) {
bytes[i] = num >> (i * 8);
}
}
int align_to_four_bytes(int size) {
int os = size % 4;
return os == 0 ? size : size + (4 - os);
}
int image_new(int width, int height, Image* img) {
//Image* img = malloc(sizeof(Image));
//Image img = malloc(sizeof(Image));
if (img == NULL) return 0;
@ -42,101 +21,46 @@ int image_new(int width, int height, Image* img) {
return 1;
}
int image_byte_size(Image *image) {
// calculate size:
// bitmap file header = 14
// BITMAPCOREHEADER = 12 bytes
int size = 14 + 12;
// width must be padded to align to 4 bytes
int width_bytes = align_to_four_bytes(image->width * 3); // 3 bytes per pixel
// add width_bytes * height to total size
size += width_bytes * image->height;
return size;
}
// header format:
// BMP header (14 bytes)
// 0x42 0x4D "BM"
// 0xAA 0xBB 0xCC 0xDD bmp file size (int)
// 0x00 0x00 0x00 0x00 nulls
// 0x1A 0x00 0x00 0x00 pixel array offset (int) (= 14 + 12);
// DIB Header (BITMAPCOREHEADER) (12 bytes)
// 0x0C 0x00 0x00 0x00 header size (int) (= 12)
// 0xAA 0xBB width (unsigned 16 bit int)
// 0xCC 0xDD height (unsigned 16 bit int)
// 0x01 0x00 number of color planes (must be 1)
// 0x18 0x00 number of bits per pixel (3 * 8 = 24)
int image_save(Image* image, char* path) {
int size = image_byte_size(image);
char* bytes = calloc(sizeof(char), size);
// magic bytes, signature "BM"
bytes[0] = 0x42;
bytes[1] = 0x4d;
// write size to header
write_int(bytes + 2, size);
// the next 4 byte are zeros
// piyel array offset
write_int(bytes + 10, 14 + 12);
write_int(bytes + 14, 12);
write_16bit(bytes + 18, image->width); // width
write_16bit(bytes + 20, image->height); // height
write_16bit(bytes + 22, 1); // color planes
write_16bit(bytes + 24, 3 * 8); // bits per pixel
int byte_offset = 26;
int byte_pos = 0;
int line;
for (line = 0; line < image->height; line++) {
byte_pos = 0;
for (int px = 0; px < image->width * 3; px += 3) {
bytes[byte_offset + byte_pos++] = image->bitmap[line][px + 2];
bytes[byte_offset + byte_pos++] = image->bitmap[line][px + 1];
bytes[byte_offset + byte_pos++] = image->bitmap[line][px + 0];
}
byte_offset += align_to_four_bytes(byte_pos);
}
printf("generated %i bytes out of %i calculated ones\n", byte_offset, size);
FILE *fp = fopen(path, "w");
int written = fwrite(bytes, sizeof(char), size, fp);
printf("wrote %i bytes...\n", written);
fclose(fp);
free(bytes);
return 1;
}
int image_set_px(Image* image, int x, int y, int r, int g, int b) {
int image_set_px(Image image, int x, int y, int r, int g, int b) {
if (!image_check_coords(image, x, y)) return 0;
image->bitmap[y][(3 * x) + 0] = (char) r;
image->bitmap[y][(3 * x) + 1] = (char) g;
image->bitmap[y][(3 * x) + 2] = (char) b;
image.bitmap[y][(3 * x) + 0] = (char) r;
image.bitmap[y][(3 * x) + 1] = (char) g;
image.bitmap[y][(3 * x) + 2] = (char) b;
return 1;
}
int image_set_px_c(Image* image, int x, int y, Color* color) {
int image_set_px_c(Image image, int x, int y, Color color) {
if (!image_check_coords(image, x, y)) return 0;
image->bitmap[y][(3 * x) + 0] = (char) color->r;
image->bitmap[y][(3 * x) + 1] = (char) color->g;
image->bitmap[y][(3 * x) + 2] = (char) color->b;
if (color.alpha == 0) return 1;
if (color.alpha == 1) {
image.bitmap[y][(3 * x) + 0] = color.r;
image.bitmap[y][(3 * x) + 1] = color.g;
image.bitmap[y][(3 * x) + 2] = color.b;
} else {
//printf("adding %d to %f\n", (color.alpha * color.r), ((1.0f - color.alpha) * (image.bitmap[y][(3 * x) + 0]/* & 0x000000ff */)));
image.bitmap[y][(3 * x) + 0] = (color.alpha * (color.r/* & 0x000000ff */)) + ((1.0f - color.alpha) * (image.bitmap[y][(3 * x) + 0]/* & 0x000000ff */));
image.bitmap[y][(3 * x) + 1] = (color.alpha * (color.g/* & 0x000000ff */)) + ((1.0f - color.alpha) * (image.bitmap[y][(3 * x) + 1]/* & 0x000000ff */));
image.bitmap[y][(3 * x) + 2] = (color.alpha * (color.b/* & 0x000000ff */)) + ((1.0f - color.alpha) * (image.bitmap[y][(3 * x) + 2]/* & 0x000000ff */));
}
return 1;
}
int image_check_coords(Image* image, int x, int y) {
return x >= 0 && x < image->width &&
y >= 0 && y < image->height;
int image_check_coords(Image image, int x, int y) {
return x >= 0 && x < image.width &&
y >= 0 && y < image.height;
}
int image_destroy(Image* image) {
for (int i = 0; i < image->height; i++) {
free(image->bitmap[i]);
int image_destroy(Image image) {
for (int i = 0; i < image.height; i++) {
free(image.bitmap[i]);
}
free(image->bitmap);
free(image.bitmap);
return 1;
}
@ -144,15 +68,43 @@ int image_destroy(Image* image) {
///////// Colors
Color* color_new(int r, int g, int b) {
Color* c = malloc(sizeof(Color));
c->r = r;
c->g = g;
c->b = b;
Color color_new(int r, int g, int b) {
Color c;
c.r = r;
c.g = g;
c.b = b;
c.alpha = 1;
return c;
}
Color color_new_alpha(int r, int g, int b, float alpha) {
Color c;
c.r = r;
c.g = g;
c.b = b;
c.alpha = alpha;
return c;
}
int image_draw_rect(Image* image, int x1, int y1, int x2, int y2, Color* color) {
void print_color(Color c) {
printf("color is: #%02hhX%02hhX%02hhX\n", c.r, c.g, c.b);
}
Color color_mix(Color c1, Color c2, float ratio) {
return color_new_alpha(
ratio * c1.r + ((1 - ratio) * c2.r),
ratio * c1.g + ((1 - ratio) * c2.g),
ratio * c1.b + ((1 - ratio) * c2.b),
ratio * c1.alpha + ((1 - ratio) * c2.alpha)
);
}
//// IMAGE DRAWING HELPERS
int image_draw_rect(Image image, int x1, int y1, int x2, int y2, Color color) {
int retval = 1;
int y;
for (; x1 < x2; x1++) {
@ -164,3 +116,25 @@ int image_draw_rect(Image* image, int x1, int y1, int x2, int y2, Color* color)
return retval;
}
int image_draw_circ(Image image, int x, int y, int r, Color color) {
int retval = 1;
int i, j, r2 = r * r;
for (i = -r+1; i < r; i++) {
for (j = -r+1; j < r; j++) {
if (i*i + j*j >= r2) continue;
if (!image_set_px_c(image, x + i, y + j, color)) retval = 0;
}
}
return retval;
}
int image_draw_square(Image image, int x, int y, int size, Color color) {
int retval = 1;
int i, j;
for (i = -size / 2; i <= size / 2; i++) {
for (j = -size / 2; j <= size / 2; j++) {
if (!image_set_px_c(image, x + i, y + j, color)) retval = 0;
}
}
return retval;
}

@ -2,37 +2,46 @@
#define IMAGES_H
typedef struct _color {
char r;
char g;
char b;
unsigned char r;
unsigned char g;
unsigned char b;
float alpha;
} Color;
typedef struct _image {
char** bitmap;
unsigned char** bitmap;
int width;
int height;
} Image;
int image_new(int width, int height, Image* image);
// basic image manipulation
int image_save(Image* image, char* path);
int image_new(int width, int height, Image* image);
int image_set_px(Image* image, int x, int y, int r, int g, int b);
int image_set_px_c(Image* image, int x, int y, Color* color);
int image_set_px(Image image, int x, int y, int r, int g, int b);
int image_set_px_c(Image image, int x, int y, Color color);
int image_check_coords(Image* image, int x, int y);
int image_check_coords(Image image, int x, int y);
int image_destroy(Image* image);
int image_destroy(Image image);
int image_byte_size(Image *image);
// drawing
int image_draw_rect(Image image, int x1, int y1, int x2, int y2, Color color);
int image_draw_circ(Image image, int x, int y, int r, Color color);
int image_draw_square(Image image, int x, int y, int s, Color color);
int image_draw_rect(Image* image, int x1, int y1, int x2, int y2, Color* color);
Color color_new(int r, int g, int b);
Color color_new_alpha(int r, int g, int b, float alpha);
void print_color(Color c);
Color color_mix(Color c1, Color c2, float ratio);
Color* color_new(int r, int g, int b);
// bmp format specifics:
int image_save_bmp(Image image, char* path);
#include "images.c"
#include "bmp-format.c"
#endif

@ -2,37 +2,70 @@
#include <stdio.h>
#include "images/images.h"
void test_transparency();
void test_4k_gradient();
int main(int argc, char* argv[]) {
test_transparency();
test_4k_gradient();
}
void test_transparency() {
Image img;
Color white = color_new(255,255,255);
Color green = color_new(0,255,0);
Color blue = color_new(30,50,210);
Color black = color_new(0,0,0);
image_new(512, 512, &img);
Color* green = color_new(0,255,0);
Color* purple = color_new(125,17,249);
// make it white
image_draw_rect(img, 0, 0, 512, 512, white);
image_draw_rect(&img, 255, 0, 512, 255, green);
image_draw_rect(&img, 0, 255, 255, 512, purple);
// draw some circs
blue.alpha = 0.5;
image_draw_circ(img, 255,255, 100, blue);
image_draw_circ(img, 255,155, 100, blue);
image_draw_circ(img, 255,355, 100, blue);
green.alpha = .6;
image_draw_circ(img, 255, 255, 12, green);
for (int i = 0; i < 255; i++) {
for (int j = 0; j < 255; j++) {
image_set_px(&img, i, j, i, 0, 0);
// draw a couple of rects
black.alpha = 0.5;
white.alpha = 0.5;
image_draw_square(img, 200, 255, 111, black);
image_draw_square(img, 200, 255, 101, white);
if (!image_save_bmp(img, "test-transparency.bmp")) {
printf("error writing file!\n");
} else {
printf("writing finished\n");
}
image_destroy(img);
}
for (int i = 0; i <= 256; i++) {
for (int j = 0; j <= 256; j++) {
image_set_px(&img, i + 255, j + 255, j, j, 255);
void test_4k_gradient() {
printf("allocating image\n");
Image img;
image_new(1920 * 4,1080 * 4, &img);
printf("writing pixies\n");
for (int i = 0; i < 1920 * 4; i++) {
for (int j = 0; j < 1080 * 4; j++) {
float color = (j / (1080.0f * 4)) * 255;
image_set_px(img, i, j, (int) color, 255, 255);
}
}
printf("Writing file to /home/anton/projects/mona/chaos/test.bmp\n");
printf("writing file to disk\n");
if (!image_save(&img, "/home/anton/projects/mona/chaos/test.bmp")) {
printf("Error writing file!\n");
if (!image_save_bmp(img, "test-4k.bmp")) {
printf("error writing file!\n");
} else {
printf("Wrote file successfully\n");
printf("writing finished\n");
}
image_destroy(&img);
free(green);
free(purple);
image_destroy(img);
printf("image destroyed\n");
}
Loading…
Cancel
Save