/*
core.c
The tool with multiple enhancements and manipulations of pictures
-11.11.2022
+03.12.2022
Copyright (C) 2014, 2015, 2022 Balthasar SzczepaĆski
uint_fast16_t n_pictures = 0;
struct Picture * picture;
-char INIT_FAILED[] = "Failae to set up library.\n";
-char LOAD_FAILED[] = "Failed to load picture.\n";
-char SAVE_FAILED[] = "Failed to save picture.\n";
-char CREATE_FAILED[] = "Failed to create picture(s).\n";
-char CONVERT_FAILED[] = "Failed to convert picture.\n";
+char INIT_FAILED[] = "Failed to set up library.\n";
+char LOAD_FAILED[] = "Failed to load picture.\n";
+char SAVE_FAILED[] = "Failed to save picture.\n";
+char CREATE_FAILED[] = "Failed to create picture(s).\n";
+char CONVERT_FAILED[] = "Failed to convert picture.\n";
+char SIZE_MISMATCH[] = "Pictures have different sizes.\n";
+char MULTIPLE_FORBIDDEN[] = "Picture is not allowed to have multiple frames.\n";
+char INDEXED_REQUIRED[] = "Picture must be indexed.\n";
+char PALETTE_ONLY_REQUIRED[]= "Palette-only operation must be allowed.\n";
+char BAD_PALETTE_SIZE[] = "Palette has wrong number of colours.\n";
char NO_STR[] = "";
int init (void)
return -1;
}
+int get_data (uint_fast16_t id, void **data, ILuint frame)
+{
+ if (id >= n_pictures)
+ return EINVAL;
+ if (!(picture[id].open))
+ return EIO;
+ ilBindImage(picture[id].handle);
+ if (frame > ilGetInteger(IL_NUM_IMAGES))
+ return EINVAL;
+ ilActiveImage(frame);
+ *data = ilGetData();
+ return 0;
+}
+
+int get_palette (uint_fast16_t id, void *palette, ILuint frame)
+{
+ if (id >= n_pictures)
+ return EINVAL;
+ if (!(picture[id].open))
+ return EIO;
+ ilBindImage(picture[id].handle);
+ if (frame > ilGetInteger(IL_NUM_IMAGES))
+ return EINVAL;
+ ilActiveImage(frame);
+ if (ilGetInteger(IL_IMAGE_FORMAT) != IL_COLOUR_INDEX)
+ return EINVAL;
+ *((void **)palette) = ilGetPalette();
+ return 0;
+}
+
+int set_palette (uint_fast16_t id, void *palette, ILuint size, ILenum type, ILuint frame)
+{
+ if (id >= n_pictures)
+ return EINVAL;
+ if (!(picture[id].open))
+ return EIO;
+ ilBindImage(picture[id].handle);
+ if (frame > ilGetInteger(IL_NUM_IMAGES))
+ return EINVAL;
+ ilActiveImage(frame);
+ if (ilGetInteger(IL_IMAGE_FORMAT) != IL_COLOUR_INDEX)
+ return EINVAL;
+ ilRegisterPal(palette, size, type);
+ return 0;
+}
+
void create_picture (uint_fast16_t id)
{
if (id<n_pictures)
return 0;
}
-int convert_picture (uint_fast16_t id, FLAG_TYPE flags)
+void get_flags (struct IL_full_info *info, FLAG_TYPE *flags)
+{
+ *flags &= ~(HAS_ALPHA | IS_GRAY | IS_INDEXED | IS_MULTIPLE | IS_OVER_8BIT | EFF_ALPHA | EFF_GRAY | EFF_INDEXED);
+
+ if (info->num_images > 0)
+ *flags |= IS_MULTIPLE;
+
+ if (info->image_bpc > 1)
+ *flags |= IS_OVER_8BIT;
+
+ switch (info->image_format)
+ {
+ case IL_COLOUR_INDEX:
+ *flags |= IS_INDEXED | EFF_INDEXED;
+ switch (info->palette_type)
+ {
+ case IL_PAL_BGR32:
+ case IL_PAL_RGB32:
+ *flags |= IS_OVER_8BIT;
+ break;
+ case IL_PAL_BGRA32:
+ case IL_PAL_RGBA32:
+ *flags |= HAS_ALPHA | EFF_ALPHA;
+ break;
+ case IL_PAL_RGB24:
+ case IL_PAL_BGR24:
+ default:
+ break;
+ }
+ break;
+ case IL_LUMINANCE_ALPHA:
+ *flags |= HAS_ALPHA | EFF_ALPHA;
+ case IL_LUMINANCE:
+ *flags |= IS_GRAY | EFF_GRAY;
+ break;
+ case IL_RGBA:
+ case IL_BGRA:
+ *flags |= HAS_ALPHA | EFF_ALPHA;
+ case IL_RGB:
+ case IL_BGR:
+ default:
+ break;
+ }
+}
+
+int convert_picture (uint_fast16_t id, struct IL_full_info *info, FLAG_TYPE *flags)
{
ILint current_format;
ILint final_format;
ILint final_type;
ILint current_palette_type;
ILint final_palette_type;
- ILboolean r;
+ struct IL_full_info info_c;
+ int r;
if (id >= n_pictures)
return EINVAL;
+ if (!(picture[id].open))
+ return EINVAL;
+
+ r = get_info (id, &info_c, 0);
+ if (r!=0)
+ return r;
+
ilBindImage(picture[id].handle);
- current_format = ilGetInteger(IL_IMAGE_FORMAT);
+ current_format = info_c.image_format;
final_format = current_format;
- current_type = ilGetInteger(IL_IMAGE_TYPE);
+ current_type = info_c.image_type;
final_type = current_type;
- if (!(flags & CAN_BE_MULTIPLE))
+ if (!(*flags & CAN_BE_MULTIPLE))
{
if (ilGetInteger(IL_NUM_IMAGES) > 0)
{
- fputs("Picture is not allowed to have multiple frames.\n", stderr);
+ fputs(MULTIPLE_FORBIDDEN, stderr);
return EINVAL;
}
}
if (final_format == IL_COLOUR_INDEX)
{
- current_palette_type = ilGetInteger(IL_PALETTE_TYPE);
+ current_palette_type = info_c.palette_type;
final_palette_type = current_palette_type;
- if (flags & CANNOT_BE_INDEXED)
+ if (*flags & (CANNOT_BE_INDEXED | MUST_BE_GRAY))
{
switch (final_palette_type)
{
}
else
{
- if (!(flags & CAN_BE_OVER_8BIT))
+ if (!(*flags & CAN_BE_OVER_8BIT))
{
switch (final_palette_type)
{
}
}
- if (flags & MUST_HAVE_ALPHA)
+ if (*flags & MUST_HAVE_ALPHA)
{
switch (final_palette_type)
{
break;
}
}
- else if (flags & CANNOT_HAVE_ALPHA)
+ else if (*flags & CANNOT_HAVE_ALPHA)
{
switch (final_palette_type)
{
}
}
- /* TODO: GRAY */
-
if (final_palette_type != current_palette_type)
{
- fputs("CONVERT PAL!\n", stderr);
- r = ilConvertPal(final_palette_type);
- if (!r)
+ fputs("Palette was converted!\n", stderr);
+ if (!(ilConvertPal(final_palette_type)))
{
fputs("Palette conversion failed.\n", stderr);
return EIO;
if (final_format != IL_COLOUR_INDEX) /* might have changed */
{
- if (flags & MUST_BE_INDEXED)
+ if (*flags & MUST_BE_INDEXED)
{
- fputs("Picture is not allowed to be indexed.\n", stderr);
+ fputs(INDEXED_REQUIRED, stderr);
return EINVAL;
}
- if (flags & MUST_HAVE_ALPHA)
+ if (*flags & MUST_HAVE_ALPHA)
{
switch (final_format)
{
break;
}
}
- else if (flags & CANNOT_HAVE_ALPHA)
+ else if (*flags & CANNOT_HAVE_ALPHA)
{
switch (final_format)
{
}
}
- if (flags & MUST_BE_GRAY)
+ if (*flags & MUST_BE_GRAY)
{
switch (final_format)
{
break;
}
}
- else if (flags & CANNOT_BE_GRAY)
+ else if (*flags & CANNOT_BE_GRAY)
{
switch (final_format)
{
final_format = IL_RGB;
break;
case IL_LUMINANCE_ALPHA:
- final_format = IL_RGB;
+ final_format = IL_RGBA;
break;
default:
break;
}
}
- if (flags & CAN_BE_OVER_8BIT)
+ if (*flags & CAN_BE_OVER_8BIT)
{
switch(final_type)
{
if ((final_type != current_type) || (final_format != current_format))
{
- fputs("CONVERT IMG!\n", stderr);
- r = ilConvertImage(final_format, final_type);
- if (!r)
+ fputs("Picture is converted!\n", stderr);
+ if (!(ilConvertImage(final_format, final_type)))
{
fputs("Image format conversion failed.\n", stderr);
return EIO;
}
}
}
+ if (info == NULL)
+ {
+ r = get_info (id, &info_c, 0);
+ if (r!=0)
+ return r;
+ get_flags(&info_c, flags);
+ }
+ else
+ {
+ r = get_info (id, info, 0);
+ if (r!=0)
+ return r;
+ get_flags(info, flags);
+ }
return 0;
}
-int load_picture (uint_fast16_t id, char *path, FLAG_TYPE flags)
+int load_picture (uint_fast16_t id, char *path, struct IL_full_info *info, FLAG_TYPE *flags)
{
- ILboolean r;
+ if (id >= n_pictures)
+ return EINVAL;
+
+ // if(!(picture[id].open))
+ create_picture(id);
+
+ ilBindImage(picture[id].handle);
+ if (!ilLoadImage(path))
+ return EIO;
+ return convert_picture(id, info, flags);
+}
+
+int load_picture_mem (uint_fast16_t id, const void *address, ILuint size, struct IL_full_info *info, FLAG_TYPE *flags)
+{
if (id >= n_pictures)
return EINVAL;
+ // if(!(picture[id].open))
+ create_picture(id);
+
ilBindImage(picture[id].handle);
- r = ilLoadImage(path);
- if (!r)
+ if (!ilLoadL(IL_TYPE_UNKNOWN, address, size))
return EIO;
- return convert_picture(id, flags);
+ return convert_picture(id, info, flags);
+}
+
+int build_picture (uint_fast16_t id, ILint width, ILint height, ILint frames, struct IL_full_info *info, FLAG_TYPE *flags)
+{
+ struct IL_full_info reference_info;
+
+ reference_info.image_width = width;
+ reference_info.image_height = height;
+ if (*flags & CAN_BE_MULTIPLE)
+ reference_info.num_images = frames-1;
+ else
+ reference_info.num_images = 0;
+
+ if (*flags & MUST_BE_INDEXED)
+ {
+ reference_info.image_format = IL_COLOUR_INDEX;
+ reference_info.image_type = IL_UNSIGNED_BYTE;
+ reference_info.image_channels = 1;
+ }
+ else
+ {
+ if (*flags & MUST_BE_GRAY)
+ {
+ if (*flags & MUST_HAVE_ALPHA)
+ {
+ reference_info.image_format = IL_LUMINANCE_ALPHA;
+ reference_info.image_channels = 2;
+ }
+ else
+ {
+ reference_info.image_format = IL_LUMINANCE;
+ reference_info.image_channels = 1;
+ }
+ }
+ else
+ {
+ if (*flags & MUST_HAVE_ALPHA)
+ {
+ reference_info.image_format = IL_RGBA;
+ reference_info.image_channels = 4;
+ }
+ else
+ {
+ reference_info.image_format = IL_RGB;
+ reference_info.image_channels = 3;
+ }
+ }
+ if (*flags & CAN_BE_OVER_8BIT)
+ reference_info.image_type = IL_UNSIGNED_SHORT;
+ else
+ reference_info.image_type = IL_UNSIGNED_BYTE;
+ }
+ return build_picture_from_info(id, &reference_info, info, flags);
+}
+
+int build_picture_from_info (uint_fast16_t id, struct IL_full_info *reference_info, struct IL_full_info *info, FLAG_TYPE *flags)
+{
+ ILint i;
+
+ if (id >= n_pictures)
+ return EINVAL;
+
+ // if(!(picture[id].open))
+ create_picture(id);
+
+ ilBindImage(picture[id].handle);
+ if (reference_info->num_images > 0)
+ {
+ if (!ilCreateSubImage(IL_SUB_NEXT, reference_info->num_images))
+ return EIO;
+ }
+
+ for (i=0; i<=reference_info->num_images; ++i)
+ {
+ ilBindImage(picture[id].handle);
+ ilActiveImage(i);
+ if (!ilTexImage(
+ reference_info->image_width,
+ reference_info->image_height,
+ 0,
+ reference_info->image_channels,
+ reference_info->image_format,
+ reference_info->image_type,
+ NULL
+ ))
+ return EIO;
+ }
+
+ return convert_picture (id, info, flags);
+}
+
+int save_picture (uint_fast16_t id, char *path, FLAG_TYPE flags)
+{
+ int r;
+
+ if (id >= n_pictures)
+ return EINVAL;
+
+ ilBindImage(picture[id].handle);
+ r = convert_picture(id, NULL, &flags);
+ if (r)
+ return r;
+
+ if (!ilSaveImage(path))
+ return EIO;
+ return 0;
}
int get_info (uint_fast16_t id, struct IL_full_info *info, ILint frame)
return r;
}
-int action_1picture (
+int perform_action_1picture (
uint_fast16_t id,
- ILint x0, ILint y0, ILint width, ILint height,
+ ILint x0, ILint y0, ILint f0,
+ ILint width, ILint height, ILint frames,
ACTION_F *function,
FLAG_TYPE flags,
void *data
)
{
- ILint f;
- ILint frames;
- struct PixelInfo p;
+ return perform_action(
+ 1,
+ &id,
+ &x0, &y0, &f0,
+ width, height, frames,
+ function,
+ &flags,
+ data
+ );
+}
+
+int perform_action_1picture_1pixel (
+ uint_fast16_t id,
+ ILint x, ILint y, ILint f,
+ ACTION_F *function,
+ FLAG_TYPE flags,
+ void *data
+)
+{
+ return perform_action_1picture (
+ id,
+ x, y, f,
+ 1, 1, 1,
+ function,
+ flags | IN_WINDOW,
+ data
+ );
+}
+
+int perform_action (
+ uint_fast16_t n,
+ uint_fast16_t *id,
+ ILint *x0, ILint *y0, ILint *f0,
+ ILint width, ILint height, ILint frames,
+ ACTION_F *function,
+ FLAG_TYPE *flags,
+ void *data
+)
+{
+ uint_fast16_t i, j;
+ uint_fast8_t palette_only = 1;
+ uint_fast8_t skip_frame;
+ uint_fast8_t skip_line;
+ uint_fast8_t skip_pixel;
+ ILint actual_frames = 0x7FFFFFFF;
+ ILint actual_width = 0x7FFFFFFF;
+ ILint actual_height = 0x7FFFFFFF;
+ ILint actual_colours= 0x7FFFFFFF;
+ ILint x, y, f;
+ struct PixelInfo *p;
int r = 0;
- p.flags = flags & ~(IS_MULTIPLE);
+ if (n==0)
+ return 0;
- if (id >= n_pictures)
- return EINVAL;
+ p = malloc((sizeof (struct PixelInfo)) * n);
+ if (p == NULL)
+ {
+ perror("perform_action(): malloc():");
+ return (r=errno);
+ }
- ilBindImage(picture[id].handle);
- get_info(id, &(p.info), 0);
-
- if (p.info.num_images > 0)
- p.flags |= IS_MULTIPLE;
- frames = (p.flags & CAN_BE_MULTIPLE) ? (p.info.num_images+1) : 1;
-
- for (
- f = 0;
- (f < frames) && (r == 0);
- ++f
- ){
- p.f_window = f;
- p.f_pict = f;
+ for (i=0; i<n; ++i)
+ {
+ p[i].id = id[i];
+ p[i].handle = get_handle(p[i].id);
+ p[i].flags = flags[i] & ~(IS_MULTIPLE);
- ilBindImage(picture[id].handle);
- ilActiveImage(f);
- p.data = ilGetData();
- p.flags &= ~(IS_GRAY|IS_INDEXED|IS_OVER_8BIT|IS_PALETTE_ONLY);
+ if (p[i].id >= n_pictures)
+ {
+ free(p);
+ return EINVAL;
+ }
+ if (!(picture[p[i].id].open))
+ {
+ free(p);
+ return EINVAL;
+ }
- p.alpha_offset = 0;
- p.value_offset = 0;
- p.index_offset = 0;
- p.red_offset = 0;
- p.green_offset = 0;
- p.blue_offset = 0;
+ r = get_info(p[i].id, &(p[i].info), 0);
+ if (r!=0)
+ return r;
+ p[i].frames = p[i].info.num_images + 1;
+
+ if (p[i].frames > 0)
+ p[i].flags |= IS_MULTIPLE;
+ if (p[i].flags & CAN_BE_MULTIPLE)
+ {
+ if (p[i].frames < actual_frames)
+ actual_frames = p[i].frames;
+ }
+ else
+ actual_frames = 1;
+
+ if (p[i].info.image_width < actual_width)
+ actual_width = p[i].info.image_width;
+ if (p[i].info.image_height < actual_height)
+ actual_height = p[i].info.image_height;
- switch (p.info.image_format)
+ if (*flags & IN_WINDOW) /* check first flags only! */
+ {
+ p[i].f0 = f0[i];
+ p[i].x0 = x0[i];
+ p[i].y0 = y0[i];
+ }
+ else
+ {
+ p[i].f0 = 0;
+ p[i].x0 = 0;
+ p[i].y0 = 0;
+ }
+
+ if ((p[i].info.image_format != IL_COLOUR_INDEX) || (!(p[i].flags & OK_PALETTE_ONLY)))
+ palette_only = 0;
+ }
+
+ if (!(*flags & IN_WINDOW)) /* check first flags only! */
+ {
+ width = actual_width;
+ height = actual_height;
+ frames = actual_frames;
+ }
+
+ for (f = 0; (f < frames) && (r == 0); ++f)
+ {
+ skip_frame = 0;
+ for (i=0; i<n; ++i)
{
- case IL_COLOUR_INDEX:
- p.flags |= IS_INDEXED;
- p.palette = ilGetPalette();
- switch (p.info.palette_type)
+ p[i].f_window = f;
+ p[i].f_pict = p[i].f0 + f;
+ if ((p[i].f_pict < 0) || (p[i].f_pict >= p[i].frames))
{
- case IL_PAL_BGR32:
- case IL_PAL_RGB32:
- p.flags |= IS_OVER_8BIT;
+ skip_frame = 1;
break;
- case IL_PAL_BGRA32:
- p.flags |= HAS_ALPHA;
- p.alpha_offset = 3;
- case IL_PAL_BGR24:
- p.red_offset = 2;
- p.green_offset = 1;
- p.blue_offset = 0;
+ }
+
+ r = get_info(p[i].id, &(p[i].info), p[i].f_pict);
+ if (r!=0)
break;
- case IL_PAL_RGBA32:
- p.flags |= HAS_ALPHA;
- p.alpha_offset = 3;
- case IL_PAL_RGB24:
+
+ r = get_data(p[i].id, &(p[i].data), p[i].f_pict);
+ if (r!=0)
+ break;
+
+ p[i].flags &= ~(HAS_ALPHA|IS_GRAY|IS_INDEXED|IS_OVER_8BIT|IS_PALETTE_ONLY|EFF_ALPHA|EFF_GRAY|EFF_INDEXED);
+ if (palette_only)
+ p[i].flags |= IS_PALETTE_ONLY;
+
+ p[i].alpha_offset = 0;
+ p[i].value_offset = 0;
+ p[i].index_offset = 0;
+ p[i].red_offset = 0;
+ p[i].green_offset = 0;
+ p[i].blue_offset = 0;
+
+ if (palette_only)
+ {
+ if (p[i].info.palette_num_cols < actual_colours)
+ actual_colours = p[i].info.palette_num_cols;
+ }
+
+ switch (p[i].info.image_format)
+ {
+ case IL_COLOUR_INDEX:
+ p[i].flags |= IS_INDEXED | EFF_INDEXED;
+ r = get_palette(p[i].id, &(p[i].palette), p[i].f_pict);
+ if (r!=0)
+ break;
+ switch (p[i].info.palette_type)
+ {
+ case IL_PAL_BGR32:
+ case IL_PAL_RGB32:
+ p[i].flags |= IS_OVER_8BIT;
+ break;
+ case IL_PAL_BGRA32:
+ p[i].flags |= HAS_ALPHA | EFF_ALPHA;
+ p[i].alpha_offset = 3;
+ case IL_PAL_BGR24:
+ p[i].red_offset = 2;
+ p[i].green_offset = 1;
+ p[i].blue_offset = 0;
+ break;
+ case IL_PAL_RGBA32:
+ p[i].flags |= HAS_ALPHA | EFF_ALPHA;
+ p[i].alpha_offset = 3;
+ case IL_PAL_RGB24:
+ default:
+ p[i].red_offset = 0;
+ p[i].green_offset = 1;
+ p[i].blue_offset = 2;
+ break;
+ }
+ break;
+ case IL_LUMINANCE_ALPHA:
+ p[i].flags |= HAS_ALPHA | EFF_ALPHA;
+ p[i].alpha_offset = 1 * p[i].info.image_bpc;
+ case IL_LUMINANCE:
+ p[i].flags |= IS_GRAY | EFF_GRAY;
+ p[i].value_offset = 0 * p[i].info.image_bpc;
+ break;
+ case IL_BGRA:
+ p[i].flags |= HAS_ALPHA | EFF_ALPHA;
+ p[i].alpha_offset = 3 * p[i].info.image_bpc;
+ case IL_BGR:
+ p[i].red_offset = 2 * p[i].info.image_bpc;
+ p[i].green_offset = 1 * p[i].info.image_bpc;
+ p[i].blue_offset = 0 * p[i].info.image_bpc;
+ break;
+ case IL_RGBA:
+ p[i].flags |= HAS_ALPHA | EFF_ALPHA;
+ p[i].alpha_offset = 3 * p[i].info.image_bpc;
+ case IL_RGB:
default:
- p.red_offset = 0;
- p.green_offset = 1;
- p.blue_offset = 2;
+ p[i].red_offset = 0 * p[i].info.image_bpc;
+ p[i].green_offset = 1 * p[i].info.image_bpc;
+ p[i].blue_offset = 2 * p[i].info.image_bpc;
break;
}
- break;
- case IL_LUMINANCE_ALPHA:
- p.flags |= HAS_ALPHA;
- p.alpha_offset = 1 * p.info.image_bpc;
- case IL_LUMINANCE:
- p.flags |= IS_GRAY;
- p.value_offset = 0 * p.info.image_bpc;
- break;
- case IL_BGRA:
- p.flags |= HAS_ALPHA;
- p.alpha_offset = 3 * p.info.image_bpc;
- case IL_BGR:
- p.red_offset = 2 * p.info.image_bpc;
- p.green_offset = 1 * p.info.image_bpc;
- p.blue_offset = 0 * p.info.image_bpc;
- break;
- case IL_RGBA:
- p.flags |= HAS_ALPHA;
- p.alpha_offset = 3 * p.info.image_bpc;
- case IL_RGB:
- default:
- p.red_offset = 0 * p.info.image_bpc;
- p.green_offset = 1 * p.info.image_bpc;
- p.blue_offset = 2 * p.info.image_bpc;
- break;
+ if (p[i].info.image_bpc > 1)
+ p[i].flags |= IS_OVER_8BIT;
+
+ if ((p[i].flags & IS_INDEXED) && (p[i].flags & CANNOT_BE_INDEXED))
+ p[i].flags &= ~EFF_INDEXED;
+ if ((p[i].flags & IS_GRAY) && (p[i].flags & CANNOT_BE_GRAY))
+ p[i].flags &= ~EFF_GRAY;
+ else if (!(p[i].flags & IS_GRAY) && (p[i].flags & MUST_BE_GRAY))
+ p[i].flags |= EFF_GRAY;
+ if ((!(p[i].flags & HAS_ALPHA)) && (p[i].flags & MUST_HAVE_ALPHA))
+ p[i].flags |= EFF_ALPHA;
+ else if ((p[i].flags & HAS_ALPHA) && (p[i].flags & CANNOT_HAVE_ALPHA))
+ p[i].flags &= ~EFF_ALPHA;
}
- if (p.info.image_bpc > 1)
- p.flags |= IS_OVER_8BIT;
-
- if ((p.flags & IS_INDEXED) && (p.flags & OK_PALETTE_ONLY))
- {
- p.flags |= IS_PALETTE_ONLY;
- for (
- p.index = 0, p.pal_offset=0;
- (p.index < p.info.palette_num_cols) && (r == 0);
- ++p.index, p.pal_offset += p.info.palette_bpp
- ){
- if (!(p.flags & NOT_READABLE))
+ if (!skip_frame)
+ {
+ if (palette_only)
+ {
+ for (i=0; i<n; ++i)
{
- p.red = (ILuint)(*((ILubyte*)(p.palette + p.pal_offset + p.red_offset)));
- p.green = (ILuint)(*((ILubyte*)(p.palette + p.pal_offset + p.green_offset)));
- p.blue = (ILuint)(*((ILubyte*)(p.palette + p.pal_offset + p.blue_offset)));
- if (p.flags & HAS_ALPHA)
- {
- if (p.flags & CANNOT_HAVE_ALPHA)
- p.alpha = 0xFF;
- else
- p.alpha = (ILuint)(*((ILubyte*)(p.palette + p.pal_offset + p.alpha_offset)));
- }
- else if (p.flags & MUST_HAVE_ALPHA)
- p.alpha = 0xFF;
- if (p.flags & MUST_BE_GRAY)
- p.value = (p.red + p.green + p.blue) / 3;
+ p[i].index = 0;
+ p[i].pal_offset = 0;
+ flags[i] |= IS_PALETTE_ONLY;
}
-
- r = function(1, &p, data);
- if (r)
- break;
-
- if (!(p.flags & NOT_READABLE))
+ for (j=0; (j<actual_colours) && (r==0); ++j)
{
- if (p.flags & MUST_BE_GRAY)
+ for (i=0; i<n; ++i)
{
- p.red = p.value;
- p.green = p.value;
- p.blue = p.value;
+ if (!(p[i].flags & NOT_READABLE))
+ {
+ p[i].red = (ILuint)(*((ILubyte*)(p[i].palette + p[i].pal_offset + p[i].red_offset)));
+ p[i].green = (ILuint)(*((ILubyte*)(p[i].palette + p[i].pal_offset + p[i].green_offset)));
+ p[i].blue = (ILuint)(*((ILubyte*)(p[i].palette + p[i].pal_offset + p[i].blue_offset)));
+ if (p[i].flags & HAS_ALPHA)
+ {
+ if (p[i].flags & CANNOT_HAVE_ALPHA)
+ p[i].alpha = 0xFF;
+ else
+ p[i].alpha = (ILuint)(*((ILubyte*)(p[i].palette + p[i].pal_offset + p[i].alpha_offset)));
+ }
+ else if (p[i].flags & MUST_HAVE_ALPHA)
+ p[i].alpha = 0xFF;
+ if (p[i].flags & MUST_BE_GRAY)
+ p[i].value = (p[i].red + p[i].green + p[i].blue) / 3;
+ }
}
- if (p.flags & HAS_ALPHA)
+
+ r = function(n, p, data);
+ if (r)
+ break;
+
+ for (i=0; i<n; ++i)
{
- if (p.flags & CANNOT_HAVE_ALPHA)
- p.alpha = 0xFF;
- *((ILubyte*)(p.palette + p.pal_offset + p.alpha_offset)) = (ILubyte)p.alpha;
+ if (!(p[i].flags & NOT_WRITABLE))
+ {
+ if (p[i].flags & MUST_BE_GRAY)
+ {
+ p[i].red = p[i].value;
+ p[i].green = p[i].value;
+ p[i].blue = p[i].value;
+ }
+ if (p[i].flags & HAS_ALPHA)
+ {
+ if (p[i].flags & CANNOT_HAVE_ALPHA)
+ p[i].alpha = 0xFF;
+ *((ILubyte*)(p[i].palette + p[i].pal_offset + p[i].alpha_offset)) = (ILubyte)(p[i].alpha);
+ }
+ *((ILubyte*)(p[i].palette + p[i].pal_offset + p[i].red_offset)) = (ILubyte)(p[i].red);
+ *((ILubyte*)(p[i].palette + p[i].pal_offset + p[i].green_offset)) = (ILubyte)(p[i].green);
+ *((ILubyte*)(p[i].palette + p[i].pal_offset + p[i].blue_offset)) = (ILubyte)(p[i].blue);
+ }
+
+ ++(p[i].index);
+ p[i].pal_offset += p[i].info.palette_bpp;
}
- *((ILubyte*)(p.palette + p.pal_offset + p.red_offset)) = (ILubyte)p.red;
- *((ILubyte*)(p.palette + p.pal_offset + p.green_offset)) = (ILubyte)p.green;
- *((ILubyte*)(p.palette + p.pal_offset + p.blue_offset)) = (ILubyte)p.blue;
}
}
- }
- else
- {
- p.line_bytes = p.info.image_bytes_per_pixel * p.info.image_width;
- p.frame_bytes = p.line_bytes * p.info.image_height;
-
- if (p.info.origin_mode == IL_ORIGIN_LOWER_LEFT)
- {
- p.line_start = p.frame_bytes - p.line_bytes;
- p.line_bytes = 0 - p.line_bytes;
- }
else
- p.line_start = 0;
-
- if (!(flags & IN_WINDOW))
{
- x0 = 0;
- y0 = 0;
- width = p.info.image_width;
- height = p.info.image_height;
- }
-
- for (
- p.y_window = 0, p.y_pict = y0, p.line_offset = p.line_start + (p.y_pict * p.line_bytes);
- (p.y_window < height) && (r == 0);
- ++p.y_window, ++p.y_pict, p.line_offset += p.line_bytes
- ){
- if ((p.y_pict >= 0) && (p.y_pict < p.info.image_height))
+ for (i=0; i<n; ++i)
{
- for (
- p.x_window = 0, p.x_pict = x0, p.pixel_offset = p.line_offset + (p.x_pict * p.info.image_bytes_per_pixel);
- (p.x_window < width) && (r == 0);
- ++p.x_window, ++p.x_pict, p.pixel_offset += p.info.image_bytes_per_pixel
- ){
- if ((p.x_pict >=0) && (p.x_pict < p.info.image_width))
+ p[i].line_bytes = p[i].info.image_bytes_per_pixel * p[i].info.image_width;
+ p[i].frame_bytes = p[i].line_bytes * p[i].info.image_height;
+
+ if (p[i].info.image_origin == IL_ORIGIN_LOWER_LEFT)
+ {
+ p[i].line_start = p[i].frame_bytes - p[i].line_bytes;
+ p[i].line_bytes = 0 - p[i].line_bytes;
+ }
+ else
+ p[i].line_start = 0;
+
+ p[i].y_window = 0;
+ p[i].y_pict = p[i].y0;
+ p[i].line_offset = p[i].line_start + (p[i].y_pict * p[i].line_bytes);
+ }
+ for (y=0; (y<height) && (r == 0); ++y)
+ {
+ skip_line = 0;
+ for (i=0; i<n; ++i)
+ {
+ if ((p[i].y_pict < 0) || (p[i].y_pict >= p[i].info.image_height))
+ {
+ skip_line = 1;
+ break;
+ }
+
+ p[i].x_window = 0;
+ p[i].x_pict = p[i].x0;
+ p[i].pixel_offset = p[i].line_offset + (p[i].x_pict * p[i].info.image_bytes_per_pixel);
+ }
+ if (!skip_line)
+ {
+ for (x=0; x<width; ++x)
{
- if (!(p.flags & NOT_READABLE))
+ skip_pixel = 0;
+ for (i=0; i<n; ++i)
+ {
+ if ((p[i].x_pict < 0) || (p[i].x_pict >= p[i].info.image_width))
+ {
+ skip_pixel = 1;
+ break;
+ }
+ }
+ if (!skip_pixel)
{
- /* can this be done better? think about it */
- switch (p.info.image_type)
+ for (i=0; i<n; ++i)
{
- case IL_INT:
- case IL_UNSIGNED_INT:
- if(p.flags & IS_INDEXED)
- p.index = *((ILuint*)(p.data + p.pixel_offset + p.index_offset));
- else
+ if (!(p[i].flags & NOT_READABLE))
{
- if(p.flags & IS_GRAY)
- p.value = *((ILuint*)(p.data + p.pixel_offset + p.value_offset));
- else
+ /* can this be done better? think about it */
+ switch (p[i].info.image_type)
{
- p.red = *((ILuint*)(p.data + p.pixel_offset + p.red_offset));
- p.green = *((ILuint*)(p.data + p.pixel_offset + p.green_offset));
- p.blue = *((ILuint*)(p.data + p.pixel_offset + p.blue_offset));
+ case IL_INT:
+ case IL_UNSIGNED_INT:
+ if (p[i].flags & IS_INDEXED)
+ p[i].index = *((ILuint*)(p[i].data + p[i].pixel_offset + p[i].index_offset));
+ else
+ {
+ if (p[i].flags & IS_GRAY)
+ p[i].value = *((ILuint*)(p[i].data + p[i].pixel_offset + p[i].value_offset));
+ else
+ {
+ p[i].red = *((ILuint*)(p[i].data + p[i].pixel_offset + p[i].red_offset));
+ p[i].green = *((ILuint*)(p[i].data + p[i].pixel_offset + p[i].green_offset));
+ p[i].blue = *((ILuint*)(p[i].data + p[i].pixel_offset + p[i].blue_offset));
+ }
+ if (p[i].flags & HAS_ALPHA)
+ p[i].alpha = *((ILuint*)(p[i].data + p[i].pixel_offset + p[i].alpha_offset));
+ }
+ break;
+ case IL_SHORT:
+ case IL_UNSIGNED_SHORT:
+ if (p[i].flags & IS_INDEXED)
+ p[i].index = (ILuint)(*((ILushort*)(p[i].data + p[i].pixel_offset + p[i].index_offset)));
+ else
+ {
+ if(p[i].flags & IS_GRAY)
+ p[i].value = (ILuint)(*((ILushort*)(p[i].data + p[i].pixel_offset + p[i].value_offset)));
+ else
+ {
+ p[i].red = (ILuint)(*((ILushort*)(p[i].data + p[i].pixel_offset + p[i].red_offset)));
+ p[i].green = (ILuint)(*((ILushort*)(p[i].data + p[i].pixel_offset + p[i].green_offset)));
+ p[i].blue = (ILuint)(*((ILushort*)(p[i].data + p[i].pixel_offset + p[i].blue_offset)));
+ }
+ if(p[i].flags & HAS_ALPHA)
+ p[i].alpha = (ILuint)(*((ILushort*)(p[i].data + p[i].pixel_offset + p[i].alpha_offset)));
+ }
+ break;
+ case IL_BYTE:
+ case IL_UNSIGNED_BYTE:
+ if(p[i].flags & IS_INDEXED)
+ p[i].index = (ILuint)(*((ILubyte*)(p[i].data + p[i].pixel_offset + p[i].index_offset)));
+ else
+ {
+ if(p[i].flags & IS_GRAY)
+ p[i].value = (ILuint)(*((ILubyte*)(p[i].data + p[i].pixel_offset + p[i].value_offset)));
+ else
+ {
+ p[i].red = (ILuint)(*((ILubyte*)(p[i].data + p[i].pixel_offset + p[i].red_offset)));
+ p[i].green = (ILuint)(*((ILubyte*)(p[i].data + p[i].pixel_offset + p[i].green_offset)));
+ p[i].blue = (ILuint)(*((ILubyte*)(p[i].data + p[i].pixel_offset + p[i].blue_offset)));
+ }
+ if(p[i].flags & HAS_ALPHA)
+ p[i].alpha = (ILuint)(*((ILubyte*)(p[i].data + p[i].pixel_offset + p[i].alpha_offset)));
+ }
+ break;
+ default:
+ break;
}
- if(p.flags & HAS_ALPHA)
- p.alpha = *((ILuint*)(p.data + p.pixel_offset + p.alpha_offset));
- }
- break;
- case IL_SHORT:
- case IL_UNSIGNED_SHORT:
- if(p.flags & IS_INDEXED)
- p.index = (ILuint)(*((ILushort*)(p.data + p.pixel_offset + p.index_offset)));
- else
- {
- if(p.flags & IS_GRAY)
- p.value = (ILuint)(*((ILushort*)(p.data + p.pixel_offset + p.value_offset)));
- else
+
+ if ((p[i].flags & IS_INDEXED) && (p[i].flags & CANNOT_BE_INDEXED))
{
- p.red = (ILuint)(*((ILushort*)(p.data + p.pixel_offset + p.red_offset)));
- p.green = (ILuint)(*((ILushort*)(p.data + p.pixel_offset + p.green_offset)));
- p.blue = (ILuint)(*((ILushort*)(p.data + p.pixel_offset + p.blue_offset)));
+ if (p[i].index < p[i].info.palette_num_cols)
+ {
+ p[i].pal_offset = p[i].index * p[i].info.palette_bpp;
+ p[i].red = (ILuint)(*((ILubyte*)(p[i].palette + p[i].pal_offset + p[i].red_offset)));
+ p[i].green = (ILuint)(*((ILubyte*)(p[i].palette + p[i].pal_offset + p[i].green_offset)));
+ p[i].blue = (ILuint)(*((ILubyte*)(p[i].palette + p[i].pal_offset + p[i].blue_offset)));
+ if (p[i].flags & HAS_ALPHA)
+ p[i].alpha = (ILuint)(*((ILubyte*)(p[i].palette + p[i].pal_offset + p[i].alpha_offset)));
+ }
}
- if(p.flags & HAS_ALPHA)
- p.alpha = (ILuint)(*((ILushort*)(p.data + p.pixel_offset + p.alpha_offset)));
- }
- break;
- case IL_BYTE:
- case IL_UNSIGNED_BYTE:
- if(p.flags & IS_INDEXED)
- p.index = (ILuint)(*((ILubyte*)(p.data + p.pixel_offset + p.index_offset)));
- else
- {
- if(p.flags & IS_GRAY)
- p.value = (ILuint)(*((ILubyte*)(p.data + p.pixel_offset + p.value_offset)));
- else
+
+ if ((p[i].flags & IS_GRAY) && (p[i].flags & CANNOT_BE_GRAY))
{
- p.red = (ILuint)(*((ILubyte*)(p.data + p.pixel_offset + p.red_offset)));
- p.green = (ILuint)(*((ILubyte*)(p.data + p.pixel_offset + p.green_offset)));
- p.blue = (ILuint)(*((ILubyte*)(p.data + p.pixel_offset + p.blue_offset)));
+ p[i].red = p[i].value;
+ p[i].green = p[i].value;
+ p[i].blue = p[i].value;
}
- if(p.flags & HAS_ALPHA)
- p.alpha = (ILuint)(*((ILubyte*)(p.data + p.pixel_offset + p.alpha_offset)));
- }
- break;
- default:
- break;
- }
-
- if ((p.flags & IS_INDEXED) && (p.flags & CANNOT_BE_INDEXED))
- {
- if (p.index < p.info.palette_num_cols)
- {
- p.pal_offset = p.index * p.info.palette_bpp;
- p.red = (ILuint)(*((ILubyte*)(p.palette + p.pal_offset + p.red_offset)));
- p.green = (ILuint)(*((ILubyte*)(p.palette + p.pal_offset + p.green_offset)));
- p.blue = (ILuint)(*((ILubyte*)(p.palette + p.pal_offset + p.blue_offset)));
- if (p.flags & HAS_ALPHA)
- p.alpha = (ILuint)(*((ILubyte*)(p.palette + p.pal_offset + p.alpha_offset)));
- }
- }
-
- if ((p.flags & IS_GRAY) && (p.flags & CANNOT_BE_GRAY))
- {
- p.red = p.value;
- p.green = p.value;
- p.blue = p.value;
- }
- else if (!(p.flags & IS_GRAY) && (p.flags & MUST_BE_GRAY))
- p.value = (p.red + p.green + p.blue) / 3;
-
- if (((!(p.flags & HAS_ALPHA)) && (p.flags & MUST_HAVE_ALPHA)) || ((p.flags & HAS_ALPHA) && (p.flags & CANNOT_HAVE_ALPHA)))
- {
- switch (p.info.image_type)
- {
- case IL_INT:
- case IL_UNSIGNED_INT:
- p.alpha = 0xFFFFFFFF;
- break;
- case IL_SHORT:
- case IL_UNSIGNED_SHORT:
- p.alpha = 0xFFFF;
- break;
- case IL_BYTE:
- case IL_UNSIGNED_BYTE:
- p.alpha = 0xFF;
- break;
- default:
- break;
+ else if (!(p[i].flags & IS_GRAY) && (p[i].flags & MUST_BE_GRAY))
+ p[i].value = (p[i].red + p[i].green + p[i].blue) / 3;
+
+ if (((!(p[i].flags & HAS_ALPHA)) && (p[i].flags & MUST_HAVE_ALPHA)) || ((p[i].flags & HAS_ALPHA) && (p[i].flags & CANNOT_HAVE_ALPHA)))
+ p[i].alpha = upscale_value(0xFF, p[i].info.image_bpc);
}
}
- }
-
- r = function(1, &p, data);
- if (r)
- break;
-
- if (!(p.flags & NOT_WRITABLE))
- {
- if ((p.flags & HAS_ALPHA) && (p.flags & CANNOT_HAVE_ALPHA))
- p.alpha = 0xFFFFFFFF;
- else if (!(p.flags & IS_GRAY) && (p.flags & MUST_BE_GRAY))
- {
- p.red = p.value;
- p.green = p.value;
- p.blue = p.value;
- }
- else if ((p.flags & IS_GRAY) && (p.flags & CANNOT_BE_GRAY))
- p.value = (p.red + p.green + p.blue) / 3;
+ r = function(n, p, data);
+ if (r)
+ break;
- switch (p.info.image_type)
+ for (i=0; i<n; ++i)
{
- case IL_INT:
- case IL_UNSIGNED_INT:
- if(p.flags & IS_INDEXED)
- *((ILuint*)(p.data + p.pixel_offset + p.index_offset)) = p.index;
- else
+ if (!(p[i].flags & NOT_WRITABLE))
{
- if(p.flags & IS_GRAY)
- *((ILuint*)(p.data + p.pixel_offset + p.value_offset)) = p.value;
- else
+ if ((p[i].flags & HAS_ALPHA) && (p[i].flags & CANNOT_HAVE_ALPHA))
+ p[i].alpha = upscale_value(0xFF, p[i].info.image_bpc);
+
+ else if (!(p[i].flags & IS_GRAY) && (p[i].flags & MUST_BE_GRAY))
{
- *((ILuint*)(p.data + p.pixel_offset + p.red_offset)) = p.red;
- *((ILuint*)(p.data + p.pixel_offset + p.green_offset)) = p.green;
- *((ILuint*)(p.data + p.pixel_offset + p.blue_offset)) = p.blue;
+ p[i].red = p[i].value;
+ p[i].green = p[i].value;
+ p[i].blue = p[i].value;
}
- if(p.flags & HAS_ALPHA)
- *((ILuint*)(p.data + p.pixel_offset + p.alpha_offset)) = (ILubyte)p.alpha;
- }
- break;
- case IL_SHORT:
- case IL_UNSIGNED_SHORT:
- if(p.flags & IS_INDEXED)
- *((ILushort*)(p.data + p.pixel_offset + p.index_offset)) = (ILushort)p.index;
- else
- {
- if(p.flags & IS_GRAY)
- *((ILushort*)(p.data + p.pixel_offset + p.value_offset)) = (ILushort)p.value;
- else
+ else if ((p[i].flags & IS_GRAY) && (p[i].flags & CANNOT_BE_GRAY))
+ p[i].value = (p[i].red + p[i].green + p[i].blue) / 3;
+
+ switch (p[i].info.image_type)
{
- *((ILushort*)(p.data + p.pixel_offset + p.red_offset)) = (ILushort)p.red;
- *((ILushort*)(p.data + p.pixel_offset + p.green_offset)) = (ILushort)p.green;
- *((ILushort*)(p.data + p.pixel_offset + p.blue_offset)) = (ILushort)p.blue;
+ case IL_INT:
+ case IL_UNSIGNED_INT:
+ if(p[i].flags & IS_INDEXED)
+ *((ILuint*)(p[i].data + p[i].pixel_offset + p[i].index_offset)) = p[i].index;
+ else
+ {
+ if(p[i].flags & IS_GRAY)
+ *((ILuint*)(p[i].data + p[i].pixel_offset + p[i].value_offset)) = p[i].value;
+ else
+ {
+ *((ILuint*)(p[i].data + p[i].pixel_offset + p[i].red_offset)) = p[i].red;
+ *((ILuint*)(p[i].data + p[i].pixel_offset + p[i].green_offset)) = p[i].green;
+ *((ILuint*)(p[i].data + p[i].pixel_offset + p[i].blue_offset)) = p[i].blue;
+ }
+ if(p[i].flags & HAS_ALPHA)
+ *((ILuint*)(p[i].data + p[i].pixel_offset + p[i].alpha_offset)) = (ILubyte)p[i].alpha;
+ }
+ break;
+ case IL_SHORT:
+ case IL_UNSIGNED_SHORT:
+ if(p[i].flags & IS_INDEXED)
+ *((ILushort*)(p[i].data + p[i].pixel_offset + p[i].index_offset)) = (ILushort)p[i].index;
+ else
+ {
+ if(p[i].flags & IS_GRAY)
+ *((ILushort*)(p[i].data + p[i].pixel_offset + p[i].value_offset)) = (ILushort)p[i].value;
+ else
+ {
+ *((ILushort*)(p[i].data + p[i].pixel_offset + p[i].red_offset)) = (ILushort)p[i].red;
+ *((ILushort*)(p[i].data + p[i].pixel_offset + p[i].green_offset)) = (ILushort)p[i].green;
+ *((ILushort*)(p[i].data + p[i].pixel_offset + p[i].blue_offset)) = (ILushort)p[i].blue;
+ }
+ if(p[i].flags & HAS_ALPHA)
+ *((ILushort*)(p[i].data + p[i].pixel_offset + p[i].alpha_offset)) = (ILushort)p[i].alpha;
+ }
+ break;
+ case IL_BYTE:
+ case IL_UNSIGNED_BYTE:
+ if(p[i].flags & IS_INDEXED)
+ *((ILubyte*)(p[i].data + p[i].pixel_offset + p[i].index_offset)) = (ILubyte)p[i].index;
+ else
+ {
+ if(p[i].flags & IS_GRAY)
+ *((ILubyte*)(p[i].data + p[i].pixel_offset + p[i].value_offset)) = (ILubyte)p[i].value;
+ else
+ {
+ *((ILubyte*)(p[i].data + p[i].pixel_offset + p[i].red_offset)) = (ILubyte)p[i].red;
+ *((ILubyte*)(p[i].data + p[i].pixel_offset + p[i].green_offset)) = (ILubyte)p[i].green;
+ *((ILubyte*)(p[i].data + p[i].pixel_offset + p[i].blue_offset)) = (ILubyte)p[i].blue;
+ }
+ if(p[i].flags & HAS_ALPHA)
+ *((ILubyte*)(p[i].data + p[i].pixel_offset + p[i].alpha_offset)) = (ILubyte)p[i].alpha;
+ }
+ break;
+ default:
+ break;
}
- if(p.flags & HAS_ALPHA)
- *((ILushort*)(p.data + p.pixel_offset + p.alpha_offset)) = (ILushort)p.alpha;
}
- break;
- case IL_BYTE:
- case IL_UNSIGNED_BYTE:
- if(p.flags & IS_INDEXED)
- *((ILubyte*)(p.data + p.pixel_offset + p.index_offset)) = (ILubyte)p.index;
- else
- {
- if(p.flags & IS_GRAY)
- *((ILubyte*)(p.data + p.pixel_offset + p.value_offset)) = (ILubyte)p.value;
- else
- {
- *((ILubyte*)(p.data + p.pixel_offset + p.red_offset)) = (ILubyte)p.red;
- *((ILubyte*)(p.data + p.pixel_offset + p.green_offset)) = (ILubyte)p.green;
- *((ILubyte*)(p.data + p.pixel_offset + p.blue_offset)) = (ILubyte)p.blue;
- }
- if(p.flags & HAS_ALPHA)
- *((ILubyte*)(p.data + p.pixel_offset + p.alpha_offset)) = (ILubyte)p.alpha;
- }
- break;
- default:
- break;
}
}
+ for (i=0; i<n; ++i)
+ {
+ ++(p[i].x_window);
+ ++(p[i].x_pict);
+ p[i].pixel_offset += p[i].info.image_bytes_per_pixel;
+ }
}
}
+ for (i=0; i<n; ++i)
+ {
+ ++(p[i].y_window);
+ ++(p[i].y_pict);
+ p[i].line_offset += p[i].line_bytes;
+ }
}
}
}
}
+ free(p);
return r;
}
-int action(
- ILuint n, struct PixelInfo *info, void *data
+
+int perform_action_palette_mix (
+ uint_fast16_t *id,
+ ACTION_F *function,
+ FLAG_TYPE *flags,
+ void *data
)
{
- printf(
- "%04lu %04lu %04lu: %03lu %03lu %03lu %03lu %03lu %03lu\n",
- (unsigned long)(info->x_pict), (unsigned long)(info->y_pict), (unsigned long)(info->f_pict),
- (unsigned long)(info->red), (unsigned long)(info->green), (unsigned long)(info->blue),
- (unsigned long)(info->alpha), (unsigned long)(info->value), (unsigned long)(info->index)
- );
+ uint_fast16_t i;
+ int r = 0;
+ struct PixelInfo p[3];
+ ILuint n_colors;
+ ILint actual_frames = 0x7FFFFFFF;
+ ILint f;
+ uint_fast8_t skip_frame;
+ ILuint j, k;
+
+
+ for (i=0; i<3; ++i)
+ {
+ p[i].id = id[i];
+ p[i].handle = get_handle(p[i].id);
+ p[i].flags = flags[i];
+ r = get_info(p[i].id, &(p[i].info), 0);
+ if (r!=0)
+ return r;
+ get_flags(&(p[i].info), &(p[i].flags));
+
+ if (!(p[i].flags & IS_INDEXED))
+ {
+ fputs(INDEXED_REQUIRED, stderr);
+ return EINVAL;
+ }
+ if (!(p[i].flags & OK_PALETTE_ONLY))
+ {
+ fputs(PALETTE_ONLY_REQUIRED, stderr);
+ return EINVAL;
+ }
+ if (p[i].flags & CAN_BE_MULTIPLE)
+ {
+ if (p[i].info.num_images+1 < actual_frames)
+ actual_frames = p[i].info.num_images+1;
+ }
+ else
+ actual_frames = 1;
+
+ p[i].f0 = 0;
+ }
+
+ n_colors = p[0].info.palette_num_cols * p[1].info.palette_num_cols;
+ if (p[2].info.palette_num_cols < n_colors)
+ {
+ fputs(BAD_PALETTE_SIZE, stderr);
+ return EINVAL;
+ }
+
+ for (f = 0; (f < actual_frames) && (r == 0); ++f)
+ {
+ skip_frame = 0;
+ for (i=0; i<3; ++i)
+ {
+ p[i].f_window = f;
+ p[i].f_pict = p[i].f0 + f;
+ if ((p[i].f_pict < 0) || (p[i].f_pict > p[i].info.num_images))
+ {
+ skip_frame = 1;
+ break;
+ }
+
+ r = get_info(p[i].id, &(p[i].info), p[i].f_pict);
+ if (r!=0)
+ return r;
+
+ get_flags(&(p[i].info), &(p[i].flags));
+ p[i].flags |= IS_PALETTE_ONLY;
+
+ r = get_data(p[i].id, &(p[i].data), p[i].f_pict);
+ if (r!=0)
+ return r;
+
+ r = get_palette(p[i].id, &(p[i].palette), p[i].f_pict);
+ if (r!=0)
+ return r;
+
+ if (!(p[i].flags & IS_INDEXED))
+ {
+ fputs(INDEXED_REQUIRED, stderr);
+ return EINVAL;
+ }
+
+ p[i].alpha_offset = 0;
+ p[i].value_offset = 0;
+ p[i].index_offset = 0;
+ p[i].red_offset = 0;
+ p[i].green_offset = 0;
+ p[i].blue_offset = 0;
+
+ switch (p[i].info.palette_type)
+ {
+ case IL_PAL_BGR32:
+ case IL_PAL_RGB32:
+ break;
+ case IL_PAL_BGRA32:
+ p[i].alpha_offset = 3;
+ case IL_PAL_BGR24:
+ p[i].red_offset = 2;
+ p[i].green_offset = 1;
+ p[i].blue_offset = 0;
+ break;
+ case IL_PAL_RGBA32:
+ p[i].alpha_offset = 3;
+ case IL_PAL_RGB24:
+ default:
+ p[i].red_offset = 0;
+ p[i].green_offset = 1;
+ p[i].blue_offset = 2;
+ break;
+ }
+
+ if ((p[i].flags & IS_GRAY) && (p[i].flags & CANNOT_BE_GRAY))
+ p[i].flags &= ~EFF_GRAY;
+ else if (!(p[i].flags & IS_GRAY) && (p[i].flags & MUST_BE_GRAY))
+ p[i].flags |= EFF_GRAY;
+ if ((!(p[i].flags & HAS_ALPHA)) && (p[i].flags & MUST_HAVE_ALPHA))
+ p[i].flags |= EFF_ALPHA;
+ else if ((p[i].flags & HAS_ALPHA) && (p[i].flags & CANNOT_HAVE_ALPHA))
+ p[i].flags &= ~EFF_ALPHA;
+ }
+ if (!skip_frame)
+ {
+ p[0].index = 0;
+ p[0].pal_offset = 0;
+ p[2].index = 0;
+ p[2].pal_offset = 0;
+ for (j=0; j<p[0].info.palette_num_cols; ++j)
+ {
+ p[1].index = 0;
+ p[1].pal_offset = 0;
+ for (k=0; k<p[1].info.palette_num_cols; ++k)
+ {
+ for (i=0; i<3; ++i)
+ {
+ if (!(p[i].flags & NOT_READABLE))
+ {
+ p[i].red = (ILuint)(*((ILubyte*)(p[i].palette + p[i].pal_offset + p[i].red_offset)));
+ p[i].green = (ILuint)(*((ILubyte*)(p[i].palette + p[i].pal_offset + p[i].green_offset)));
+ p[i].blue = (ILuint)(*((ILubyte*)(p[i].palette + p[i].pal_offset + p[i].blue_offset)));
+ if (p[i].flags & HAS_ALPHA)
+ {
+ if (p[i].flags & CANNOT_HAVE_ALPHA)
+ p[i].alpha = 0xFF;
+ else
+ p[i].alpha = (ILuint)(*((ILubyte*)(p[i].palette + p[i].pal_offset + p[i].alpha_offset)));
+ }
+ else if (p[i].flags & MUST_HAVE_ALPHA)
+ p[i].alpha = 0xFF;
+ if (p[i].flags & MUST_BE_GRAY)
+ p[i].value = (p[i].red + p[i].green + p[i].blue) / 3;
+ }
+ }
+
+ r = function(3, p, data);
+ if (r)
+ break;
+
+ for (i=0; i<3; ++i)
+ {
+ if (!(p[i].flags & NOT_WRITABLE))
+ {
+ if (p[i].flags & MUST_BE_GRAY)
+ {
+ p[i].red = p[i].value;
+ p[i].green = p[i].value;
+ p[i].blue = p[i].value;
+ }
+ if (p[i].flags & HAS_ALPHA)
+ {
+ if (p[i].flags & CANNOT_HAVE_ALPHA)
+ p[i].alpha = 0xFF;
+ *((ILubyte*)(p[i].palette + p[i].pal_offset + p[i].alpha_offset)) = (ILubyte)(p[i].alpha);
+ }
+ *((ILubyte*)(p[i].palette + p[i].pal_offset + p[i].red_offset)) = (ILubyte)(p[i].red);
+ *((ILubyte*)(p[i].palette + p[i].pal_offset + p[i].green_offset)) = (ILubyte)(p[i].green);
+ *((ILubyte*)(p[i].palette + p[i].pal_offset + p[i].blue_offset)) = (ILubyte)(p[i].blue);
+ }
+ }
+
+ ++p[1].index;
+ p[1].pal_offset += p[1].info.palette_bpp;
+ ++p[2].index;
+ p[2].pal_offset += p[1].info.palette_bpp;
+ }
+ ++p[0].index;
+ p[0].pal_offset += p[0].info.palette_bpp;
+ }
+ }
+ }
+
+ return r;
+}
+
+ILuint upscale_value (ILubyte x, ILint bytes)
+{
+ ILint i;
+ ILuint y = 0;
+
+ for (i=0; i<bytes; ++i)
+ {
+ y <<= 8;
+ y |= x;
+ }
+ return y;
+}
+
+ILubyte downscale_value (ILuint x, ILint bytes)
+{
+ return (ILubyte)(x >> (8 * (bytes-1)));
+}
+
+int copy_pixels (ILuint n, struct PixelInfo *p, void *data)
+{
+ ILuint max = *((ILuint *)data);
+
+ if (n < 2)
+ return EINVAL;
+
+ if (p[0].flags & EFF_INDEXED)
+ {
+ if (!(p[1].flags & EFF_INDEXED))
+ return EINVAL;
+ p[1].index = p[0].index;
+ }
+ else if (p[0].flags & EFF_ALPHA)
+ {
+ if (p[0].flags & EFF_GRAY)
+ {
+ if (!(p[1].flags & EFF_GRAY))
+ return EINVAL;
+ p[1].value = copy_1p_alpha(p[0].value, p[1].value, p[0].alpha, max);
+ }
+ else
+ {
+ if (p[1].flags & EFF_GRAY)
+ return EINVAL;
+ p[1].red = copy_1p_alpha(p[0].red, p[1].red, p[0].alpha, max);
+ p[1].green = copy_1p_alpha(p[0].green, p[1].green, p[0].alpha, max);
+ p[1].blue = copy_1p_alpha(p[0].blue, p[1].blue, p[0].alpha, max);
+ }
+ if (p[1].flags & EFF_ALPHA)
+ p[1].alpha = copy_1p_alpha(max, p[1].alpha, p[0].alpha, max);
+ }
+ else
+ {
+ if (p[0].flags & EFF_GRAY)
+ {
+ if (!(p[1].flags & EFF_GRAY))
+ return EINVAL;
+ p[1].value = p[0].value;
+ }
+ else
+ {
+ if (p[1].flags & EFF_GRAY)
+ return EINVAL;
+ p[1].red = p[0].red;
+ p[1].green = p[0].green;
+ p[1].blue = p[0].blue;
+ }
+ if (p[1].flags & EFF_ALPHA)
+ p[1].alpha = max;
+ }
+
+ return 0;
+}
+
+int fill_color (ILuint n, struct PixelInfo *p, void *data)
+{
+ struct ColorInfo *d = data;
+
+ if (p->flags & EFF_INDEXED)
+ {
+ p->index = d->index;
+ }
+ else
+ {
+ if (p->flags & EFF_ALPHA)
+ p->alpha = d->alpha;
+ if (p->flags & EFF_GRAY)
+ p->value = d->value;
+ else
+ {
+ p->red = d->red;
+ p->green = d->green;
+ p->blue = d->blue;
+ }
+ }
+
return 0;
}
+ILuint copy_1p_alpha (ILint64 src, ILint64 dst, ILint64 alpha, ILint64 max)
+{
+ ILint64 v = (src * alpha + dst * (max - alpha)) / max;
+ return (ILuint)v;
+}
+
+int palette_mix_index (ILuint n, struct PixelInfo *p, void *data)
+{
+ if (n < 3)
+ return EIO;
+
+ p[2].index = p[0].index * p[1].info.palette_num_cols + p[1].index;
+
+ return 0;
+}
+
+ILuint tsqrt(ILuint s)
+{
+ switch(s)
+ {
+ case 256:
+ return 16;
+ case 225:
+ return 15;
+ case 196:
+ return 14;
+ case 169:
+ return 13;
+ case 144:
+ return 12;
+ case 121:
+ return 11;
+ case 100:
+ return 10;
+ case 81:
+ return 9;
+ case 64:
+ return 8;
+ case 49:
+ return 7;
+ case 36:
+ return 6;
+ case 25:
+ return 5;
+ case 16:
+ return 4;
+ case 9:
+ return 3;
+ case 4:
+ return 2;
+ case 1:
+ return 1;
+ default: // not a square - please fail
+ return 0;
+ }
+}
+
+//unsigned short isqrt(unsigned s)
+//{
+// unsigned short r;
+// unsigned short b=0x0040;
+//
+// while(b>s)
+// b>>=2;
+// while(b)
+// {
+// if(s>=r+b)
+// {
+// s-=r+b;
+// r=(r>>1)+b;
+// }
+// else
+// r>>1;
+// b>>2;
+// }
+// return r;
+//}
+
+
+// int action(
+ // ILuint n, struct PixelInfo *info, void *data
+// )
+// {
+ // printf(
+ // "%04lu %04lu %04lu: %03lu %03lu %03lu %03lu %03lu %03lu\n",
+ // (unsigned long)(info->x_pict), (unsigned long)(info->y_pict), (unsigned long)(info->f_pict),
+ // (unsigned long)(info->red), (unsigned long)(info->green), (unsigned long)(info->blue),
+ // (unsigned long)(info->alpha), (unsigned long)(info->value), (unsigned long)(info->index)
+ // );
+ // return 0;
+// }