image: flips, including in-place

This commit is contained in:
Lephe 2022-05-14 20:27:16 +01:00
parent 9468a8d725
commit 818f950fff
No known key found for this signature in database
GPG key ID: 1BBA026E13FC0495
9 changed files with 165 additions and 24 deletions

View file

@ -159,6 +159,7 @@ set(SOURCES_CG
src/r61524/r61524.c
# Image library
src/image/image_alloc.c
src/image/image_alloc_palette.c
src/image/image_alpha.c
src/image/image_clear.c
src/image/image_copy.c
@ -171,11 +172,15 @@ set(SOURCES_CG
src/image/image_fill.c
src/image/image_free.c
src/image/image_get_pixel.c
src/image/image_palette_size.c
src/image/image_hflip.c
src/image/image_hflip_alloc.c
src/image/image_set_palette.c
src/image/image_set_pixel.c
src/image/image_sub.c
src/image/image_target.c
src/image/image_valid.c
src/image/image_vflip.c
src/image/image_vflip_alloc.c
# Rendering
src/render-cg/dclear.c
src/render-cg/dpixel.c

View file

@ -314,11 +314,6 @@ int image_decode_pixel(image_t const *img, int pixel);
image's data array, and might be much larger than the sub-image. */
int image_data_size(image_t const *img);
/* image_palette_size(): Compute the size of the [palette] array
This function returns the size of the palette array, in bytes. This can be
used to duplicate the palette. For images without a palette, returns -1. */
int image_palette_size(image_t const *img);
//---
// Basic image modifications
//---
@ -457,6 +452,10 @@ image_t *image_sub(image_t const *src, int x, int y, int w, int h,
void image_hflip(image_t const *src, image_t *dst);
image_t *image_hflip_alloc(image_t const *src);
/* image_vflip(): Flip vertically (supports in-place) */
void image_vflip(image_t const *src, image_t *dst);
image_t *image_vflip_alloc(image_t const *src);
/* TODO: Geometric transforms */
//---

View file

@ -1,30 +1,31 @@
#include <gint/image.h>
#include <gint/defs/util.h>
#include <stdlib.h>
#include <string.h>
bool image_alloc_palette(image_t *img, int size)
{
if(!img || !IMAGE_IS_INDEXED(img))
return;
if(img->flags & IMAGE_FLAGS_PALETTE_OWN)
if(!img || !IMAGE_IS_INDEXED(img->format))
return false;
if(img->flags & IMAGE_FLAGS_PALETTE_ALLOC)
free(img->palette);
if(IMAGE_IS_P8(img)) {
if(IMAGE_IS_P8(img->format)) {
size = (size <= 0) ? 256 : min(size, 256);
}
if(IMAGE_IS_P4(img)) {
if(IMAGE_IS_P4(img->format)) {
size = 16;
}
img->palette = calloc(size, 2);
img->color_count = 0;
img->flags &= ~IMAGE_FLAGS_PALETTE_OWN;
img->flags &= ~IMAGE_FLAGS_PALETTE_ALLOC;
if(!img->palette)
return false;
memset(img->palette, 0, 2*size);
img->color_count = size;
img->flags |= IMAGE_FLAGS_PALETTE_OWN;
img->flags |= IMAGE_FLAGS_PALETTE_ALLOC;
return true;
}

47
src/image/image_hflip.c Normal file
View file

@ -0,0 +1,47 @@
#include <gint/image.h>
void image_hflip(image_t const *src, image_t *dst)
{
if(!image_target(src, dst, DATA_RW, SAME_DEPTH, SAME_SIZE))
return;
void *src_px = src->data;
void *dst_px = dst->data;
int src_alpha = image_alpha(src->format);
int dst_alpha = image_alpha(dst->format);
int h = src->height;
if(IMAGE_IS_RGB16(src->format)) {
while(h-- > 0) {
for(int x1 = 0; x1 < (src->width + 1) >> 1; x1++) {
int x2 = src->width - 1 - x1;
int px1 = ((uint16_t *)src_px)[x1];
int px2 = ((uint16_t *)src_px)[x2];
if(px1 != src_alpha)
((uint16_t *)dst_px)[x2] = px1 - (px1 == dst_alpha);
if(px2 != src_alpha)
((uint16_t *)dst_px)[x1] = px2 - (px2 == dst_alpha);
}
src_px += src->stride;
dst_px += dst->stride;
}
}
else if(IMAGE_IS_P8(src->format)) {
while(h-- > 0) {
for(int x1 = 0; x1 < (src->width + 1) >> 1; x1++) {
int x2 = src->width - 1 - x1;
int px1 = ((int8_t *)src_px)[x1];
int px2 = ((int8_t *)src_px)[x2];
if(px1 != src_alpha)
((int8_t *)dst_px)[x2] = px1;
if(px2 != src_alpha)
((int8_t *)dst_px)[x1] = px2;
}
src_px += src->stride;
dst_px += dst->stride;
}
}
}

View file

@ -0,0 +1,17 @@
#include <gint/image.h>
image_t *image_hflip_alloc(image_t const *src)
{
if(!image_valid(src))
return NULL;
image_t *dst = image_alloc(src->width, src->height, src->format);
if(!dst || !image_copy_palette(src, dst, -1)) {
image_free(dst);
return NULL;
}
image_clear(dst);
image_hflip(src, dst);
return dst;
}

View file

@ -1,7 +0,0 @@
#include <gint/image.h>
int image_palette_size(image_t const *img)
{
return (img->color_count >= 0) ? img->color_count* 2 : -1;
}

View file

@ -3,16 +3,16 @@
void image_set_palette(image_t *img, uint16_t *palette, int size, bool owns)
{
if(!img || !IMAGE_IS_INDEXED(img))
if(!img || !IMAGE_IS_INDEXED(img->format))
return;
if(img->flags & IMAGE_FLAGS_PALETTE_OWN)
if(img->flags & IMAGE_FLAGS_PALETTE_ALLOC)
free(img->palette);
img->palette = palette;
img->color_count = size;
if(owns)
img->flags |= IMAGE_FLAGS_PALETTE_OWN;
img->flags |= IMAGE_FLAGS_PALETTE_ALLOC;
else
img->flags &= ~IMAGE_FLAGS_PALETTE_OWN;
img->flags &= ~IMAGE_FLAGS_PALETTE_ALLOC;
}

62
src/image/image_vflip.c Normal file
View file

@ -0,0 +1,62 @@
#include <gint/image.h>
#include <stdlib.h>
#include <string.h>
static void copy_row_rgb16(uint16_t *src, uint16_t *dst, int src_alpha,
int dst_alpha, int width)
{
for(int x = 0; x < width; x++) {
int px = src[x];
if(px != src_alpha)
dst[x] = px - (px == dst_alpha);
}
}
static void copy_row_p8(int8_t *src, int8_t *dst, int src_alpha, int width)
{
for(int x = 0; x < width; x++) {
int px = src[x];
if(px != src_alpha)
dst[x] = px;
}
}
void image_vflip(image_t const *src, image_t *dst)
{
if(!image_target(src, dst, DATA_RW, SAME_DEPTH, SAME_SIZE))
return;
int h = src->height;
void *src_top = src->data;
void *src_bot = src->data + (h - 1) * src->stride;
void *dst_top = dst->data;
void *dst_bot = dst->data + (h - 1) * dst->stride;
int src_alpha = image_alpha(src->format);
int dst_alpha = image_alpha(dst->format);
int row_length = src->stride;
void *row = malloc(row_length);
if(!row)
return;
for(int y = 0; y < (h + 1) >> 1; y++) {
memcpy(row, src_top, row_length);
if(IMAGE_IS_RGB16(src->format)) {
copy_row_rgb16(src_bot, dst_top, src_alpha, dst_alpha, src->width);
copy_row_rgb16(row, dst_bot, src_alpha, dst_alpha, src->width);
}
else {
copy_row_p8(src_bot, dst_top, src_alpha, src->width);
copy_row_p8(row, dst_bot, src_alpha, src->width);
}
src_top += src->stride;
src_bot -= src->stride;
dst_top += dst->stride;
dst_bot -= dst->stride;
}
free(row);
}

View file

@ -0,0 +1,17 @@
#include <gint/image.h>
image_t *image_vflip_alloc(image_t const *src)
{
if(!image_valid(src))
return NULL;
image_t *dst = image_alloc(src->width, src->height, src->format);
if(!dst || !image_copy_palette(src, dst, -1)) {
image_free(dst);
return NULL;
}
image_clear(dst);
image_vflip(src, dst);
return dst;
}