cleaned code, transparency now actually working

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

2
.gitignore vendored

@ -1,2 +1,4 @@
*.out *.out
*.o *.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 <stdio.h>
#include "images.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) { int image_new(int width, int height, Image* img) {
//Image* img = malloc(sizeof(Image)); //Image img = malloc(sizeof(Image));
if (img == NULL) return 0; if (img == NULL) return 0;
@ -42,101 +21,46 @@ int image_new(int width, int height, Image* img) {
return 1; return 1;
} }
int image_byte_size(Image *image) { int image_set_px(Image image, int x, int y, int r, int g, int b) {
// calculate size: if (!image_check_coords(image, x, y)) return 0;
// 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); image.bitmap[y][(3 * x) + 0] = (char) r;
image.bitmap[y][(3 * x) + 1] = (char) g;
image.bitmap[y][(3 * x) + 2] = (char) b;
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; return 1;
} }
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) {
if (!image_check_coords(image, x, y)) return 0; if (!image_check_coords(image, x, y)) return 0;
image->bitmap[y][(3 * x) + 0] = (char) r; if (color.alpha == 0) return 1;
image->bitmap[y][(3 * x) + 1] = (char) g;
image->bitmap[y][(3 * x) + 2] = (char) b;
return 1; if (color.alpha == 1) {
} image.bitmap[y][(3 * x) + 0] = color.r;
int image_set_px_c(Image* image, int x, int y, Color* color) { image.bitmap[y][(3 * x) + 1] = color.g;
if (!image_check_coords(image, x, y)) return 0; image.bitmap[y][(3 * x) + 2] = color.b;
} else {
image->bitmap[y][(3 * x) + 0] = (char) color->r; //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) + 1] = (char) color->g;
image->bitmap[y][(3 * x) + 2] = (char) color->b; 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; return 1;
} }
int image_check_coords(Image* image, int x, int y) { int image_check_coords(Image image, int x, int y) {
return x >= 0 && x < image->width && return x >= 0 && x < image.width &&
y >= 0 && y < image->height; y >= 0 && y < image.height;
} }
int image_destroy(Image* image) { int image_destroy(Image image) {
for (int i = 0; i < image->height; i++) { for (int i = 0; i < image.height; i++) {
free(image->bitmap[i]); free(image.bitmap[i]);
} }
free(image->bitmap); free(image.bitmap);
return 1; return 1;
} }
@ -144,15 +68,43 @@ int image_destroy(Image* image) {
///////// Colors ///////// Colors
Color* color_new(int r, int g, int b) { Color color_new(int r, int g, int b) {
Color* c = malloc(sizeof(Color)); Color c;
c->r = r; c.r = r;
c->g = g; c.g = g;
c->b = b; 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; 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 retval = 1;
int y; int y;
for (; x1 < x2; x1++) { 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; 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 #define IMAGES_H
typedef struct _color { typedef struct _color {
char r; unsigned char r;
char g; unsigned char g;
char b; unsigned char b;
float alpha;
} Color; } Color;
typedef struct _image { typedef struct _image {
char** bitmap; unsigned char** bitmap;
int width; int width;
int height; int height;
} Image; } 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(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_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 "images.c"
#include "bmp-format.c"
#endif #endif

@ -2,37 +2,70 @@
#include <stdio.h> #include <stdio.h>
#include "images/images.h" #include "images/images.h"
void test_transparency();
void test_4k_gradient();
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
test_transparency();
test_4k_gradient();
}
void test_transparency() {
Image img; Image img;
image_new(512,512, &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);
Color* green = color_new(0,255,0); image_new(512, 512, &img);
Color* purple = color_new(125,17,249);
image_draw_rect(&img, 255, 0, 512, 255, green); // make it white
image_draw_rect(&img, 0, 255, 255, 512, purple); image_draw_rect(img, 0, 0, 512, 512, white);
for (int i = 0; i < 255; i++) { // draw some circs
for (int j = 0; j < 255; j++) { blue.alpha = 0.5;
image_set_px(&img, i, j, i, 0, 0); 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);
// 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");
} }
for (int i = 0; i <= 256; i++) {
for (int j = 0; j <= 256; j++) { image_destroy(img);
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")) { if (!image_save_bmp(img, "test-4k.bmp")) {
printf("Error writing file!\n"); printf("error writing file!\n");
} else { } else {
printf("Wrote file successfully\n"); printf("writing finished\n");
} }
image_destroy(&img); image_destroy(img);
printf("image destroyed\n");
free(green);
free(purple);
} }
Loading…
Cancel
Save