2023-04-06 18:54:30 +02:00
|
|
|
#include <defocus/image.h>
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#define STB_IMAGE_IMPLEMENTATION
|
|
|
|
#include <stb_image.h>
|
|
|
|
|
|
|
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
|
|
|
#include <stb_image_write.h>
|
|
|
|
|
|
|
|
struct df_image
|
|
|
|
{
|
|
|
|
int width;
|
|
|
|
int height;
|
|
|
|
uint8_t *pixels;
|
|
|
|
};
|
|
|
|
|
2023-05-09 13:04:14 +02:00
|
|
|
DF_API df_result df_create_image(int w, int h, df_image **out_image)
|
2023-04-06 18:54:30 +02:00
|
|
|
{
|
|
|
|
df_image *img = malloc(sizeof(df_image));
|
|
|
|
if (!img)
|
|
|
|
return df_result_out_of_memory;
|
|
|
|
DF_ZERO_STRUCT(img);
|
|
|
|
|
|
|
|
img->width = w;
|
|
|
|
img->height = h;
|
|
|
|
img->pixels = malloc(4 * sizeof(uint8_t) * w * h);
|
|
|
|
if (!img->pixels) {
|
|
|
|
free(img);
|
|
|
|
return df_result_out_of_memory;
|
|
|
|
}
|
|
|
|
memset(img->pixels, 0, 4 * w * h);
|
|
|
|
|
|
|
|
*out_image = img;
|
|
|
|
return df_result_success;
|
|
|
|
}
|
|
|
|
|
2023-05-09 13:04:14 +02:00
|
|
|
DF_API df_result df_load_image(const char *path, int *out_w, int *out_h, df_image **out_image)
|
2023-04-06 18:54:30 +02:00
|
|
|
{
|
|
|
|
int w, h, c;
|
|
|
|
stbi_uc *pixels = stbi_load(path, &w, &h, &c, 4);
|
|
|
|
if (!pixels) {
|
|
|
|
fprintf(stderr, "ERROR: failed to load %s: %s\n", path, stbi_failure_reason());
|
|
|
|
return df_result_io_error;
|
|
|
|
}
|
|
|
|
|
|
|
|
df_result res = df_result_success;
|
|
|
|
df_image *img = malloc(sizeof(df_image));
|
|
|
|
if (!img) {
|
|
|
|
res = df_result_out_of_memory;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
DF_ZERO_STRUCT(img);
|
|
|
|
|
|
|
|
img->width = w;
|
|
|
|
img->height = h;
|
|
|
|
img->pixels = (uint8_t *)pixels;
|
|
|
|
|
|
|
|
*out_image = img;
|
|
|
|
*out_w = w;
|
|
|
|
*out_h = h;
|
|
|
|
|
|
|
|
goto out;
|
|
|
|
err:
|
|
|
|
free(img);
|
|
|
|
out:
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2023-05-09 13:04:14 +02:00
|
|
|
DF_API void df_release_image(df_image *img)
|
2023-04-06 18:54:30 +02:00
|
|
|
{
|
|
|
|
if (img) {
|
|
|
|
free(img->pixels);
|
|
|
|
free(img);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-09 13:04:14 +02:00
|
|
|
DF_API df_result df_write_image(df_image *image, const char *path)
|
2023-04-06 18:54:30 +02:00
|
|
|
{
|
|
|
|
df_result res = stbi_write_png(path, image->width, image->height, 4, image->pixels, image->width * 4)
|
|
|
|
? df_result_success
|
|
|
|
: df_result_io_error;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2023-05-09 13:04:14 +02:00
|
|
|
DF_API void df_get_image_size(const df_image *image, int *w, int *h)
|
2023-04-06 18:54:30 +02:00
|
|
|
{
|
|
|
|
if (w)
|
|
|
|
*w = image->width;
|
|
|
|
if (h)
|
|
|
|
*h = image->height;
|
|
|
|
}
|
|
|
|
|
2023-05-09 13:04:14 +02:00
|
|
|
DF_API df_color df_get_image_pixel(const df_image *image, int x, int y)
|
2023-04-06 18:54:30 +02:00
|
|
|
{
|
|
|
|
df_color c = {0, 0, 0, 255};
|
|
|
|
if (x >= 0 && x < image->width && y >= 0 && y < image->height) {
|
|
|
|
memcpy(&c.e[0], &image->pixels[4 * (y * image->width + x)], 4);
|
|
|
|
}
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2023-05-09 13:04:14 +02:00
|
|
|
DF_API void df_set_image_pixel(df_image *image, int x, int y, df_color c)
|
2023-04-06 18:54:30 +02:00
|
|
|
{
|
|
|
|
if (x >= 0 && x < image->width && y >= 0 && y < image->height) {
|
|
|
|
memcpy(&image->pixels[4 * (y * image->width + x)], &c.e[0], 4);
|
|
|
|
}
|
|
|
|
}
|