150 lines
3.1 KiB
C
150 lines
3.1 KiB
C
#include <vhex/display/image.h>
|
|
#include <vhex/defs/utils.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
//---
|
|
// Image-object API
|
|
//---
|
|
|
|
/* image_alloc(): Create a new (uninitialized) image */
|
|
image_t *image_alloc(size_t width, size_t height, int format)
|
|
{
|
|
image_t *img = image_create(width, height, format);
|
|
if(img == NULL)
|
|
return (NULL);
|
|
|
|
if(IMAGE_IS_RGB16(format))
|
|
img->stride = ((width + 1) >> 1) * 4;
|
|
else if(IMAGE_IS_P8(format))
|
|
img->stride = width;
|
|
else if(IMAGE_IS_P4(format))
|
|
img->stride = ((width + 1) >> 1);
|
|
|
|
void *data = malloc(height * img->stride);
|
|
if(data == NULL) {
|
|
image_free(img);
|
|
return (NULL);
|
|
}
|
|
|
|
img->data = data;
|
|
img->flags |= IMAGE_FLAGS_DATA_ALLOC;
|
|
return img;
|
|
}
|
|
|
|
/* image_create(): Create a bare image with no data/palette */
|
|
image_t *image_create(size_t width, size_t height, int format)
|
|
{
|
|
if(!IMAGE_IS_RGB16(format)
|
|
&& !IMAGE_IS_P8(format)
|
|
&& !IMAGE_IS_P4(format)) {
|
|
return (NULL);
|
|
}
|
|
if(width > 0xffff || height > 0xffff)
|
|
return (NULL);
|
|
|
|
image_t *img = calloc(1, sizeof(image_t));
|
|
if(img == NULL)
|
|
return (NULL);
|
|
|
|
img->format = format;
|
|
img->flags = 0;
|
|
img->color_count = 0;
|
|
img->width = width;
|
|
img->height = height;
|
|
img->stride = 0;
|
|
img->data = NULL;
|
|
img->palette = NULL;
|
|
|
|
return (img);
|
|
}
|
|
|
|
/* image_free(): Free and image and the data it owns */
|
|
void image_free(image_t *img)
|
|
{
|
|
if(img == NULL)
|
|
return;
|
|
|
|
if(img->flags & IMAGE_FLAGS_DATA_ALLOC)
|
|
free(img->data);
|
|
if(img->flags & IMAGE_FLAGS_PALETTE_ALLOC)
|
|
free(img->palette);
|
|
|
|
if (!(img->flags & IMAGE_FLAGS_RO))
|
|
free(img);
|
|
}
|
|
|
|
//---
|
|
// Palette API
|
|
//---
|
|
|
|
/* image_set_palette(): Specify an external palette for an image */
|
|
void image_set_palette(image_t *img, uint16_t *palette, size_t size, bool owns)
|
|
{
|
|
if(img == NULL || !IMAGE_IS_INDEXED(img->format))
|
|
return;
|
|
|
|
if(img->flags & IMAGE_FLAGS_PALETTE_ALLOC)
|
|
free(img->palette);
|
|
|
|
img->palette = palette;
|
|
img->color_count = size;
|
|
|
|
if(owns) {
|
|
img->flags |= IMAGE_FLAGS_PALETTE_ALLOC;
|
|
} else {
|
|
img->flags &= ~IMAGE_FLAGS_PALETTE_ALLOC;
|
|
}
|
|
}
|
|
|
|
|
|
/* image_alloc_palette(): Allocate a new palette for an image */
|
|
bool image_alloc_palette(image_t *img, int size)
|
|
{
|
|
if(img == NULL || !IMAGE_IS_INDEXED(img->format))
|
|
return (false);
|
|
|
|
if(img->flags & IMAGE_FLAGS_PALETTE_ALLOC)
|
|
free(img->palette);
|
|
|
|
if(IMAGE_IS_P8(img->format)) {
|
|
size = (size <= 0) ? 256 : min(size, 256);
|
|
}
|
|
if(IMAGE_IS_P4(img->format)) {
|
|
size = 16;
|
|
}
|
|
|
|
img->palette = calloc(size, sizeof(uint16_t));
|
|
img->color_count = 0;
|
|
img->flags &= ~IMAGE_FLAGS_PALETTE_ALLOC;
|
|
|
|
if(img->palette == NULL)
|
|
return (false);
|
|
|
|
memset(img->palette, 0, size * sizeof(uint16_t));
|
|
img->color_count = size;
|
|
img->flags |= IMAGE_FLAGS_PALETTE_ALLOC;
|
|
return (true);
|
|
}
|
|
|
|
/* image_copy_palette(): Copy another image's palette */
|
|
bool image_copy_palette(image_t const *src, image_t *dst, int size)
|
|
{
|
|
if(!image_valid(src) || dst == NULL)
|
|
return (false);
|
|
|
|
if(!IMAGE_IS_INDEXED(dst->format))
|
|
return (true);
|
|
|
|
if(size < 0)
|
|
size = src->color_count;
|
|
if(!image_alloc_palette(dst, size))
|
|
return (false);
|
|
|
|
int N = min(src->color_count, dst->color_count);
|
|
memcpy(dst->palette, src->palette, N * sizeof(uint16_t));
|
|
return (true);
|
|
}
|
|
|