mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-30 04:20:23 +00:00
Fixed New Frame: now it copies the entire Cel of the previous frame.
Fixed bugs when undo cels with offset < 0,0 (because the sign wasn't being saved)
This commit is contained in:
parent
f4b4996540
commit
8908d25e07
20
ChangeLog
20
ChangeLog
@ -1,3 +1,21 @@
|
||||
2008-04-13 David A. Capello <dacap@users.sourceforge.net>
|
||||
|
||||
* src/raster/undo.c (read_raw_cel, write_raw_cel): Fixed to
|
||||
read/write the position of the Cel with sign (int16_t instead of
|
||||
uint16_t).
|
||||
|
||||
* src/commands/cmd_advanced_mode.c (cmd_advanced_mode_execute):
|
||||
Fixed another typo (reported by Manuel Quiñones).
|
||||
|
||||
* src/dialogs/tips.c (dialogs_tips): Fixed a typo (reported by
|
||||
Manuel Quiñones).
|
||||
|
||||
* makefile.lnx: Applied Manuel Quiñones's patch to fix the
|
||||
install/uninstall rules.
|
||||
|
||||
* src/commands/cmd_new_frame.c (copy_cel_in_next_frame): Fixed,
|
||||
now it copies the entiry cel instead of the visible area.
|
||||
|
||||
2008-04-11 David A. Capello <dacap@users.sourceforge.net>
|
||||
|
||||
* src/modules/sprites.h (ImageRef): Added.
|
||||
@ -533,7 +551,7 @@
|
||||
2007-11-16 David A. Capello <dacap@users.sourceforge.net>
|
||||
|
||||
* src/raster/cel.c: Renamed "frame" to "cel" to avoid
|
||||
confusion (Manuel Quiñones advice)
|
||||
confusion (Manuel Quiñones advice).
|
||||
|
||||
* src/modules/render.[ch]: Moved to util/.
|
||||
|
||||
|
1
TODO.txt
1
TODO.txt
@ -1,7 +1,6 @@
|
||||
Next beta
|
||||
---------
|
||||
|
||||
- search for "TODO next release"
|
||||
- Check these routines:
|
||||
+ move_cel
|
||||
+ copy_cel
|
||||
|
@ -60,6 +60,7 @@
|
||||
<!-- tools -->
|
||||
<key command="configure_tools" shortcut="C" />
|
||||
<key command="film_editor" shortcut="Tab" />
|
||||
<key command="palette_editor" shortcut="F4" />
|
||||
<key command="convolution_matrix" shortcut="F9" />
|
||||
<key command="color_curve" shortcut="Ctrl+M" />
|
||||
<key command="color_curve" shortcut="F10" />
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Allegro Sprite Editor tips
|
||||
# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2008 David A. Capello
|
||||
# Copyright (C) 2001-2008 David A. Capello
|
||||
|
||||
**********************************************************************
|
||||
\palette ase.pcx
|
||||
|
10
makefile.lnx
10
makefile.lnx
@ -14,13 +14,13 @@ endif
|
||||
######################################################################
|
||||
# Flags for GCC in GNU/Linux system
|
||||
|
||||
#ifdef DEBUGMODE
|
||||
ifdef DEBUGMODE
|
||||
CFLAGS = `allegro-config --cflags debug`
|
||||
LFLAGS = `allegro-config --libs debug`
|
||||
#else
|
||||
else
|
||||
CFLAGS = `allegro-config --cflags`
|
||||
LFLAGS = `allegro-config --libs`
|
||||
#endif
|
||||
endif
|
||||
|
||||
######################################################################
|
||||
# GCC stuff
|
||||
@ -51,12 +51,12 @@ distclean: clean
|
||||
-rm -f $(ASE)
|
||||
|
||||
install:
|
||||
cp ase $(DEFAULT_PREFIX)/bin
|
||||
cp aseprite $(DEFAULT_PREFIX)/bin
|
||||
cp -r data $(DEFAULT_PREFIX)/share/ase
|
||||
cp AUTHORS.txt $(DEFAULT_PREFIX)/share/ase
|
||||
|
||||
uninstall:
|
||||
-rm -vf $(DEFAULT_PREFIX)/bin/ase
|
||||
-rm -vf $(DEFAULT_PREFIX)/bin/aseprite
|
||||
-rm -rvf $(DEFAULT_PREFIX)/share/ase
|
||||
|
||||
-include makefile.dep
|
||||
|
@ -64,7 +64,7 @@ static void cmd_advanced_mode_execute(const char *argument)
|
||||
if (jalert("%s<<%s||%s||%s",
|
||||
_("Warning - Important"),
|
||||
buf,
|
||||
_("&Don't show it again"), _("&Continue")) == 1) {
|
||||
_("&Don't show this again"), _("&Continue")) == 1) {
|
||||
set_config_bool("AdvancedMode", "Warning", FALSE);
|
||||
}
|
||||
}
|
||||
|
@ -73,20 +73,20 @@ static void cmd_merge_down_layer_execute(const char *argument)
|
||||
dst_cel = layer_get_cel(dst_layer, frpos);
|
||||
|
||||
/* get images */
|
||||
if (src_cel)
|
||||
if (src_cel != NULL)
|
||||
src_image = stock_get_image(sprite->stock, src_cel->image);
|
||||
else
|
||||
src_image = NULL;
|
||||
|
||||
if (dst_cel)
|
||||
if (dst_cel != NULL)
|
||||
dst_image = stock_get_image(sprite->stock, dst_cel->image);
|
||||
else
|
||||
dst_image = NULL;
|
||||
|
||||
/* with source image? */
|
||||
if (src_image) {
|
||||
if (src_image != NULL) {
|
||||
/* no destination image */
|
||||
if (!dst_image) {
|
||||
if (dst_image == NULL) {
|
||||
/* copy this cel to the destination layer... */
|
||||
|
||||
/* creating a copy of the image */
|
||||
@ -95,7 +95,7 @@ static void cmd_merge_down_layer_execute(const char *argument)
|
||||
/* adding it in the stock of images */
|
||||
index = stock_add_image(sprite->stock, dst_image);
|
||||
if (undo_is_enabled(sprite->undo))
|
||||
undo_add_image(sprite->undo, sprite->stock, dst_image);
|
||||
undo_add_image(sprite->undo, sprite->stock, index);
|
||||
|
||||
/* creating a copy of the cell */
|
||||
dst_cel = cel_new(frpos, index);
|
||||
@ -124,6 +124,11 @@ static void cmd_merge_down_layer_execute(const char *argument)
|
||||
src_cel->opacity,
|
||||
src_layer->blend_mode);
|
||||
|
||||
if (undo_is_enabled(sprite->undo)) {
|
||||
undo_int(sprite->undo, (GfxObj *)dst_cel, &dst_cel->x);
|
||||
undo_int(sprite->undo, (GfxObj *)dst_cel, &dst_cel->y);
|
||||
}
|
||||
|
||||
cel_set_position(dst_cel, x1, y1);
|
||||
|
||||
if (undo_is_enabled(sprite->undo))
|
||||
|
@ -68,7 +68,7 @@ static void cmd_new_cel_execute(const char *argument)
|
||||
undo_set_label(current_sprite->undo, "New Cel");
|
||||
undo_open(current_sprite->undo);
|
||||
undo_add_image(current_sprite->undo,
|
||||
current_sprite->stock, image);
|
||||
current_sprite->stock, image_index);
|
||||
}
|
||||
|
||||
/* create the new cel */
|
||||
|
@ -117,32 +117,48 @@ static bool new_frame_for_layer(Sprite *sprite, Layer *layer, int frame)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* makes a copy of the cel in 'frame-1' to a new cel in 'frame' */
|
||||
static bool copy_cel_in_next_frame(Sprite *sprite, Layer *layer, int frame)
|
||||
{
|
||||
int image_index;
|
||||
Image *image;
|
||||
Cel *cel;
|
||||
Image *src_image;
|
||||
Image *dst_image;
|
||||
Cel *src_cel;
|
||||
Cel *dst_cel;
|
||||
|
||||
/* create a new empty cel with a new clean image */
|
||||
image = image_new(sprite->imgtype, sprite->w, sprite->h);
|
||||
if (!image) {
|
||||
/* create a copy of the previous cel */
|
||||
src_cel = layer_get_cel(layer, frame-1);
|
||||
src_image = src_cel ? stock_get_image(sprite->stock,
|
||||
src_cel->image):
|
||||
NULL;
|
||||
|
||||
if (src_image == NULL || frame == 0)
|
||||
dst_image = image_new(sprite->imgtype, sprite->w, sprite->h);
|
||||
else
|
||||
dst_image = image_new_copy(src_image);
|
||||
|
||||
if (!dst_image) {
|
||||
console_printf(_("Not enough memory.\n"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* background color */
|
||||
image_clear(image, 0);
|
||||
if (frame > 0)
|
||||
layer_render(layer, image, 0, 0, frame-1);
|
||||
|
||||
/* add the image in the stock */
|
||||
image_index = stock_add_image(sprite->stock, image);
|
||||
undo_add_image(sprite->undo, sprite->stock, image);
|
||||
image_index = stock_add_image(sprite->stock, dst_image);
|
||||
if (undo_is_enabled(sprite->undo))
|
||||
undo_add_image(sprite->undo, sprite->stock, image_index);
|
||||
|
||||
/* create the new cel */
|
||||
dst_cel = cel_new(frame, image_index);
|
||||
|
||||
if (src_cel != NULL) {
|
||||
cel_set_position(dst_cel, src_cel->x, src_cel->y);
|
||||
cel_set_opacity(dst_cel, src_cel->opacity);
|
||||
}
|
||||
|
||||
/* add the cel in the layer */
|
||||
cel = cel_new(frame, image_index);
|
||||
undo_add_cel(sprite->undo, layer, cel);
|
||||
layer_add_cel(layer, cel);
|
||||
if (undo_is_enabled(sprite->undo))
|
||||
undo_add_cel(sprite->undo, layer, dst_cel);
|
||||
layer_add_cel(layer, dst_cel);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ void dialogs_tips(bool forced)
|
||||
button_next = jbutton_new(_("&Next"));
|
||||
view = jview_new();
|
||||
tips = tips_new();
|
||||
check = jcheck_new(_("Show me it in the start up"));
|
||||
check = jcheck_new(_("Show this at startup"));
|
||||
|
||||
jwidget_set_min_size(button_close, 50, 0);
|
||||
jwidget_set_min_size(button_prev, 50, 0);
|
||||
|
@ -311,11 +311,11 @@ void effect_flush(Effect *effect)
|
||||
|
||||
void effect_apply_to_target(Effect *effect)
|
||||
{
|
||||
ImageRef *p, *next, *images;
|
||||
ImageRef *p, *images;
|
||||
bool cancelled = FALSE;
|
||||
int nimages;
|
||||
|
||||
images = sprite_get_images(effect->sprite, effect->target, TRUE);
|
||||
images = images_ref_get_from_sprite(effect->sprite, effect->target, TRUE);
|
||||
if (images == NULL)
|
||||
return;
|
||||
|
||||
@ -351,10 +351,7 @@ void effect_apply_to_target(Effect *effect)
|
||||
}
|
||||
|
||||
/* free all ImageRefs */
|
||||
for (p=images; p; p=next) {
|
||||
next = p->next;
|
||||
jfree(p);
|
||||
}
|
||||
images_ref_free(images);
|
||||
}
|
||||
|
||||
static EffectData *get_effect_data(const char *name)
|
||||
|
@ -49,7 +49,7 @@ Sprite *current_sprite = NULL;
|
||||
static JList sprites_list;
|
||||
static Sprite *clipboard_sprite;
|
||||
|
||||
static ImageRef *layer_get_images(Sprite *sprite, Layer *layer, int target, bool write);
|
||||
static ImageRef *images_ref_get_from_layer(Sprite *sprite, Layer *layer, int target, bool write);
|
||||
static void layer_get_pos(Sprite *sprite, Layer *layer, int target, bool write, int **x, int **y, int *count);
|
||||
|
||||
int init_module_sprites(void)
|
||||
@ -218,15 +218,25 @@ Sprite *lock_current_sprite(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ImageRef *sprite_get_images(struct Sprite *sprite, int target, bool write)
|
||||
ImageRef *images_ref_get_from_sprite(Sprite *sprite, int target, bool write)
|
||||
{
|
||||
Layer *layer = target & TARGET_ALL_LAYERS ? sprite->set:
|
||||
sprite->layer;
|
||||
|
||||
return layer_get_images(sprite, layer, target, write);
|
||||
return images_ref_get_from_layer(sprite, layer, target, write);
|
||||
}
|
||||
|
||||
static ImageRef *layer_get_images(Sprite *sprite, Layer *layer, int target, bool write)
|
||||
void images_ref_free(ImageRef *image_ref)
|
||||
{
|
||||
ImageRef *p, *next;
|
||||
|
||||
for (p=image_ref; p; p=next) {
|
||||
next = p->next;
|
||||
jfree(p);
|
||||
}
|
||||
}
|
||||
|
||||
static ImageRef *images_ref_get_from_layer(Sprite *sprite, Layer *layer, int target, bool write)
|
||||
{
|
||||
#define ADD_IMAGES(images) \
|
||||
{ \
|
||||
@ -288,7 +298,7 @@ static ImageRef *layer_get_images(Sprite *sprite, Layer *layer, int target, bool
|
||||
JLink link;
|
||||
|
||||
JI_LIST_FOR_EACH(layer->layers, link) {
|
||||
sub_images = layer_get_images(sprite, link->data, target, write);
|
||||
sub_images = images_ref_get_from_layer(sprite, link->data, target, write);
|
||||
|
||||
if (sub_images != NULL)
|
||||
ADD_IMAGES(sub_images);
|
||||
|
@ -58,7 +58,8 @@ bool is_current_sprite_writable(void);
|
||||
|
||||
struct Sprite *lock_current_sprite(void);
|
||||
|
||||
ImageRef *sprite_get_images(struct Sprite *sprite, int target, bool write);
|
||||
ImageRef *images_ref_get_from_sprite(struct Sprite *sprite, int target, bool write);
|
||||
void images_ref_free(ImageRef *image_ref);
|
||||
|
||||
#endif /* MODULES_SPRITES_H */
|
||||
|
||||
|
@ -117,10 +117,9 @@ Layer *layer_new_copy(Sprite *dst_sprite, const Layer *src_layer)
|
||||
|
||||
image_copy = image_new_copy(image);
|
||||
|
||||
if (undo_is_enabled(dst_sprite->undo))
|
||||
undo_add_image(dst_sprite->undo, dst_sprite->stock, image_copy);
|
||||
|
||||
cel_copy->image = stock_add_image(dst_sprite->stock, image_copy);
|
||||
if (undo_is_enabled(dst_sprite->undo))
|
||||
undo_add_image(dst_sprite->undo, dst_sprite->stock, cel_copy->image);
|
||||
|
||||
layer_add_cel(layer_copy, cel_copy);
|
||||
}
|
||||
|
@ -135,13 +135,13 @@ static void chunk_flip_invert(UndoStream *stream, UndoChunkFlip *chunk, int stat
|
||||
static void chunk_dirty_new(UndoStream *stream, Dirty *dirty);
|
||||
static void chunk_dirty_invert(UndoStream *stream, UndoChunkDirty *chunk, int state);
|
||||
|
||||
static void chunk_add_image_new(UndoStream *stream, Stock *stock, Image *image);
|
||||
static void chunk_add_image_new(UndoStream *stream, Stock *stock, int image_index);
|
||||
static void chunk_add_image_invert(UndoStream *stream, UndoChunkAddImage *chunk, int state);
|
||||
|
||||
static void chunk_remove_image_new(UndoStream *stream, Stock *stock, Image *image);
|
||||
static void chunk_remove_image_new(UndoStream *stream, Stock *stock, int image_index);
|
||||
static void chunk_remove_image_invert(UndoStream *stream, UndoChunkRemoveImage *chunk, int state);
|
||||
|
||||
static void chunk_replace_image_new(UndoStream *stream, Stock *stock, int index);
|
||||
static void chunk_replace_image_new(UndoStream *stream, Stock *stock, int image_index);
|
||||
static void chunk_replace_image_invert(UndoStream *stream, UndoChunkReplaceImage *chunk, int state);
|
||||
|
||||
static void chunk_add_cel_new(UndoStream *stream, Layer *layer, Cel *cel);
|
||||
@ -762,7 +762,7 @@ static void chunk_dirty_invert(UndoStream *stream, UndoChunkDirty *chunk, int st
|
||||
"add_image"
|
||||
|
||||
DWORD stock ID
|
||||
DWORD index
|
||||
DWORD index of the image in the stock
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
@ -770,45 +770,36 @@ struct UndoChunkAddImage
|
||||
{
|
||||
UndoChunk head;
|
||||
ase_uint32 stock_id;
|
||||
ase_uint32 index;
|
||||
ase_uint32 image_index;
|
||||
};
|
||||
|
||||
/* TODO fix this so it doesn't need to be called as:
|
||||
image_index = stock_add_image(sprite->stock, image);
|
||||
undo_add_image(sprite->undo, sprite->stock, image);
|
||||
*/
|
||||
void undo_add_image(Undo *undo, Stock *stock, Image *image)
|
||||
void undo_add_image(Undo *undo, Stock *stock, int image_index)
|
||||
{
|
||||
chunk_add_image_new(undo->undo_stream, stock, image);
|
||||
chunk_add_image_new(undo->undo_stream, stock, image_index);
|
||||
update_undo(undo);
|
||||
}
|
||||
|
||||
static void chunk_add_image_new(UndoStream *stream, Stock *stock, Image *image)
|
||||
static void chunk_add_image_new(UndoStream *stream, Stock *stock, int image_index)
|
||||
{
|
||||
UndoChunkAddImage *chunk = (UndoChunkAddImage *)
|
||||
undo_chunk_new(stream,
|
||||
UNDO_TYPE_ADD_IMAGE,
|
||||
sizeof(UndoChunkAddImage));
|
||||
int index;
|
||||
|
||||
for (index=0; index<stock->nimage; index++)
|
||||
if (stock->image[index] == image)
|
||||
break;
|
||||
|
||||
chunk->stock_id = stock->gfxobj.id;
|
||||
chunk->index = index;
|
||||
chunk->image_index = image_index;
|
||||
}
|
||||
|
||||
static void chunk_add_image_invert(UndoStream *stream, UndoChunkAddImage *chunk, int state)
|
||||
{
|
||||
unsigned int stock_id = chunk->stock_id;
|
||||
unsigned int index = chunk->index;
|
||||
unsigned int image_index = chunk->image_index;
|
||||
Stock *stock = (Stock *)gfxobj_find(stock_id);
|
||||
|
||||
if (stock) {
|
||||
Image *image = stock_get_image(stock, index);
|
||||
if (image) {
|
||||
chunk_remove_image_new(stream, stock, image);
|
||||
Image *image = stock_get_image(stock, image_index);
|
||||
if (image != NULL) {
|
||||
chunk_remove_image_new(stream, stock, image_index);
|
||||
stock_remove_image(stock, image);
|
||||
image_free(image);
|
||||
}
|
||||
@ -820,7 +811,7 @@ static void chunk_add_image_invert(UndoStream *stream, UndoChunkAddImage *chunk,
|
||||
"remove_image"
|
||||
|
||||
DWORD stock ID
|
||||
DWORD index
|
||||
DWORD index of the image in the stock
|
||||
IMAGE_DATA see read/write_raw_image
|
||||
|
||||
***********************************************************************/
|
||||
@ -829,30 +820,26 @@ struct UndoChunkRemoveImage
|
||||
{
|
||||
UndoChunk head;
|
||||
ase_uint32 stock_id;
|
||||
ase_uint32 index;
|
||||
ase_uint32 image_index;
|
||||
ase_uint8 data[0];
|
||||
};
|
||||
|
||||
void undo_remove_image(Undo *undo, Stock *stock, Image *image)
|
||||
void undo_remove_image(Undo *undo, Stock *stock, int image_index)
|
||||
{
|
||||
chunk_remove_image_new(undo->undo_stream, stock, image);
|
||||
chunk_remove_image_new(undo->undo_stream, stock, image_index);
|
||||
update_undo(undo);
|
||||
}
|
||||
|
||||
static void chunk_remove_image_new(UndoStream *stream, Stock *stock, Image *image)
|
||||
static void chunk_remove_image_new(UndoStream *stream, Stock *stock, int image_index)
|
||||
{
|
||||
Image *image = stock->image[image_index];
|
||||
UndoChunkRemoveImage *chunk = (UndoChunkRemoveImage *)
|
||||
undo_chunk_new(stream,
|
||||
UNDO_TYPE_REMOVE_IMAGE,
|
||||
sizeof(UndoChunkRemoveImage)+get_raw_image_size(image));
|
||||
int index;
|
||||
|
||||
for (index=0; index<stock->nimage; index++)
|
||||
if (stock->image[index] == image)
|
||||
break;
|
||||
|
||||
chunk->stock_id = stock->gfxobj.id;
|
||||
chunk->index = index;
|
||||
chunk->image_index = image_index;
|
||||
|
||||
write_raw_image(chunk->data, image);
|
||||
}
|
||||
@ -860,7 +847,7 @@ static void chunk_remove_image_new(UndoStream *stream, Stock *stock, Image *imag
|
||||
static void chunk_remove_image_invert(UndoStream *stream, UndoChunkRemoveImage *chunk, int state)
|
||||
{
|
||||
unsigned int stock_id = chunk->stock_id;
|
||||
unsigned int index = chunk->index;
|
||||
unsigned int image_index = chunk->image_index;
|
||||
Stock *stock = (Stock *)gfxobj_find(stock_id);
|
||||
|
||||
if (stock) {
|
||||
@ -868,8 +855,8 @@ static void chunk_remove_image_invert(UndoStream *stream, UndoChunkRemoveImage *
|
||||
|
||||
/* assert(image != NULL); */
|
||||
|
||||
stock_replace_image(stock, index, image);
|
||||
chunk_add_image_new(stream, stock, image);
|
||||
stock_replace_image(stock, image_index, image);
|
||||
chunk_add_image_new(stream, stock, image_index);
|
||||
}
|
||||
}
|
||||
|
||||
@ -878,7 +865,7 @@ static void chunk_remove_image_invert(UndoStream *stream, UndoChunkRemoveImage *
|
||||
"replace_image"
|
||||
|
||||
DWORD stock ID
|
||||
DWORD index
|
||||
DWORD index of the image in the stock
|
||||
IMAGE_DATA see read/write_raw_image
|
||||
|
||||
***********************************************************************/
|
||||
@ -887,26 +874,26 @@ struct UndoChunkReplaceImage
|
||||
{
|
||||
UndoChunk head;
|
||||
ase_uint32 stock_id;
|
||||
ase_uint32 index;
|
||||
ase_uint32 image_index;
|
||||
ase_uint8 data[0];
|
||||
};
|
||||
|
||||
void undo_replace_image(Undo *undo, Stock *stock, int index)
|
||||
void undo_replace_image(Undo *undo, Stock *stock, int image_index)
|
||||
{
|
||||
chunk_replace_image_new(undo->undo_stream, stock, index);
|
||||
chunk_replace_image_new(undo->undo_stream, stock, image_index);
|
||||
update_undo(undo);
|
||||
}
|
||||
|
||||
static void chunk_replace_image_new(UndoStream *stream, Stock *stock, int index)
|
||||
static void chunk_replace_image_new(UndoStream *stream, Stock *stock, int image_index)
|
||||
{
|
||||
Image *image = stock->image[index];
|
||||
Image *image = stock->image[image_index];
|
||||
UndoChunkReplaceImage *chunk = (UndoChunkReplaceImage *)
|
||||
undo_chunk_new(stream,
|
||||
UNDO_TYPE_REPLACE_IMAGE,
|
||||
sizeof(UndoChunkReplaceImage)+get_raw_image_size(image));
|
||||
|
||||
chunk->stock_id = stock->gfxobj.id;
|
||||
chunk->index = index;
|
||||
chunk->image_index = image_index;
|
||||
|
||||
write_raw_image(chunk->data, image);
|
||||
}
|
||||
@ -914,18 +901,18 @@ static void chunk_replace_image_new(UndoStream *stream, Stock *stock, int index)
|
||||
static void chunk_replace_image_invert(UndoStream *stream, UndoChunkReplaceImage *chunk, int state)
|
||||
{
|
||||
unsigned long stock_id = chunk->stock_id;
|
||||
unsigned long index = chunk->index;
|
||||
unsigned long image_index = chunk->image_index;
|
||||
Stock *stock = (Stock *)gfxobj_find(stock_id);
|
||||
|
||||
if (stock) {
|
||||
Image *image = read_raw_image(chunk->data);
|
||||
|
||||
chunk_replace_image_new(stream, stock, index);
|
||||
chunk_replace_image_new(stream, stock, image_index);
|
||||
|
||||
if (stock->image[index])
|
||||
image_free(stock->image[index]);
|
||||
if (stock->image[image_index])
|
||||
image_free(stock->image[image_index]);
|
||||
|
||||
stock_replace_image(stock, index, image);
|
||||
stock_replace_image(stock, image_index, image);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1104,7 +1091,8 @@ static void chunk_remove_layer_new(UndoStream *stream, Layer *layer)
|
||||
Layer *after = layer_get_prev(layer);
|
||||
|
||||
chunk->set_id = set->gfxobj.id;
|
||||
chunk->after_id = after ? after->gfxobj.id: 0;
|
||||
chunk->after_id = after != NULL ? after->gfxobj.id: 0;
|
||||
|
||||
write_raw_layer(chunk->data, layer);
|
||||
}
|
||||
|
||||
@ -1113,7 +1101,7 @@ static void chunk_remove_layer_invert(UndoStream *stream, UndoChunkRemoveLayer *
|
||||
Layer *set = (Layer *)gfxobj_find(chunk->set_id);
|
||||
Layer *after = (Layer *)gfxobj_find(chunk->after_id);
|
||||
|
||||
if (set) {
|
||||
if (set != NULL) {
|
||||
Layer *layer = read_raw_layer(chunk->data);
|
||||
|
||||
/* assert(layer != NULL); */
|
||||
@ -1360,6 +1348,13 @@ static void undo_chunk_free(UndoChunk *chunk)
|
||||
raw_data += 2; \
|
||||
}
|
||||
|
||||
#define read_raw_int16(dst) \
|
||||
{ \
|
||||
memcpy(&word, raw_data, 2); \
|
||||
dst = (int16_t)word; \
|
||||
raw_data += 2; \
|
||||
}
|
||||
|
||||
#define read_raw_uint8(dst) \
|
||||
{ \
|
||||
dst = *raw_data; \
|
||||
@ -1386,6 +1381,13 @@ static void undo_chunk_free(UndoChunk *chunk)
|
||||
raw_data += 2; \
|
||||
}
|
||||
|
||||
#define write_raw_int16(src) \
|
||||
{ \
|
||||
word = (int16_t)src; \
|
||||
memcpy(raw_data, &word, 2); \
|
||||
raw_data += 2; \
|
||||
}
|
||||
|
||||
#define write_raw_uint8(src) \
|
||||
{ \
|
||||
*raw_data = src; \
|
||||
@ -1585,6 +1587,7 @@ static ase_uint8 *write_raw_image(ase_uint8 *raw_data, Image *image)
|
||||
|
||||
static int get_raw_image_size(Image *image)
|
||||
{
|
||||
assert(image != NULL);
|
||||
return 4+1+2+2+IMAGE_LINE_SIZE(image, image->w) * image->h;
|
||||
}
|
||||
|
||||
@ -1611,8 +1614,8 @@ static Cel *read_raw_cel(ase_uint8 *raw_data)
|
||||
read_raw_uint32(cel_id);
|
||||
read_raw_uint16(frame);
|
||||
read_raw_uint16(image);
|
||||
read_raw_uint16(x);
|
||||
read_raw_uint16(y);
|
||||
read_raw_int16(x);
|
||||
read_raw_int16(y);
|
||||
read_raw_uint16(opacity);
|
||||
|
||||
cel = cel_new(frame, image);
|
||||
@ -1631,8 +1634,8 @@ static ase_uint8 *write_raw_cel(ase_uint8 *raw_data, Cel *cel)
|
||||
write_raw_uint32(cel->gfxobj.id);
|
||||
write_raw_uint16(cel->frame);
|
||||
write_raw_uint16(cel->image);
|
||||
write_raw_uint16(cel->x);
|
||||
write_raw_uint16(cel->y);
|
||||
write_raw_int16(cel->x);
|
||||
write_raw_int16(cel->y);
|
||||
write_raw_uint16(cel->opacity);
|
||||
|
||||
return raw_data;
|
||||
@ -1684,7 +1687,7 @@ static Layer *read_raw_layer(ase_uint8 *raw_data)
|
||||
/* read cels */
|
||||
for (c=0; c<cels; c++) {
|
||||
Cel *cel;
|
||||
bool as_image;
|
||||
bool has_image;
|
||||
|
||||
/* read the cel */
|
||||
cel = read_raw_cel(raw_data);
|
||||
@ -1694,8 +1697,8 @@ static Layer *read_raw_layer(ase_uint8 *raw_data)
|
||||
layer_add_cel(layer, cel);
|
||||
|
||||
/* read the image */
|
||||
read_raw_uint8(as_image);
|
||||
if (as_image) {
|
||||
read_raw_uint8(has_image);
|
||||
if (has_image) {
|
||||
Image *image = read_raw_image(raw_data);
|
||||
raw_data += get_raw_image_size(image);
|
||||
|
||||
|
@ -74,9 +74,9 @@ void undo_data(Undo *undo, GfxObj *gfxobj, void *data, int size);
|
||||
void undo_image(Undo *undo, struct Image *image, int x, int y, int w, int h);
|
||||
void undo_flip(Undo *undo, struct Image *image, int x1, int y1, int x2, int y2, int horz);
|
||||
void undo_dirty(Undo *undo, struct Dirty *dirty);
|
||||
void undo_add_image(Undo *undo, struct Stock *stock, struct Image *image);
|
||||
void undo_remove_image(Undo *undo, struct Stock *stock, struct Image *image);
|
||||
void undo_replace_image(Undo *undo, struct Stock *stock, int index);
|
||||
void undo_add_image(Undo *undo, struct Stock *stock, int image_index);
|
||||
void undo_remove_image(Undo *undo, struct Stock *stock, int image_index);
|
||||
void undo_replace_image(Undo *undo, struct Stock *stock, int image_index);
|
||||
void undo_add_cel(Undo *undo, struct Layer *layer, struct Cel *cel);
|
||||
void undo_remove_cel(Undo *undo, struct Layer *layer, struct Cel *cel);
|
||||
void undo_add_layer(Undo *undo, struct Layer *set, struct Layer *layer);
|
||||
|
@ -859,7 +859,7 @@ void RemoveCel(Layer *layer, Cel *cel)
|
||||
image = stock_get_image(sprite->stock, cel->image);
|
||||
|
||||
if (undo_is_enabled(sprite->undo))
|
||||
undo_remove_image(sprite->undo, sprite->stock, image);
|
||||
undo_remove_image(sprite->undo, sprite->stock, cel->image);
|
||||
|
||||
stock_remove_image(sprite->stock, image);
|
||||
image_free(image);
|
||||
|
@ -128,7 +128,7 @@ void copy_cel(void)
|
||||
image_index = stock_add_image(sprite->stock, image);
|
||||
|
||||
if (undo_is_enabled(sprite->undo))
|
||||
undo_add_image(sprite->undo, sprite->stock, image);
|
||||
undo_add_image(sprite->undo, sprite->stock, image_index);
|
||||
}
|
||||
|
||||
/* setup the cel */
|
||||
|
@ -309,30 +309,25 @@ int interactive_move_layer(int mode, bool use_undo, int (*callback)(void))
|
||||
gui_feedback();
|
||||
} while (editor_click(editor, &new_x, &new_y, &update, NULL));
|
||||
|
||||
new_x = cel->x;
|
||||
new_y = cel->y;
|
||||
cel_set_position(cel, begin_x, begin_y);
|
||||
|
||||
/* the position was changed */
|
||||
if (!editor_click_cancel(editor)) {
|
||||
if (use_undo && undo_is_enabled(sprite->undo)) {
|
||||
new_x = cel->x;
|
||||
new_y = cel->y;
|
||||
|
||||
undo_set_label(sprite->undo, "Cel Movement");
|
||||
undo_open(sprite->undo);
|
||||
cel->x = begin_x;
|
||||
cel->y = begin_y;
|
||||
undo_int(sprite->undo, (GfxObj *)cel, &cel->x);
|
||||
undo_int(sprite->undo, (GfxObj *)cel, &cel->y);
|
||||
cel->x = new_x;
|
||||
cel->y = new_y;
|
||||
undo_close(sprite->undo);
|
||||
}
|
||||
|
||||
cel_set_position(cel, new_x, new_y);
|
||||
ret = TRUE;
|
||||
}
|
||||
/* the position wasn't changed */
|
||||
else {
|
||||
cel->x = begin_x;
|
||||
cel->y = begin_y;
|
||||
|
||||
ret = FALSE;
|
||||
}
|
||||
|
||||
|
@ -26,15 +26,12 @@
|
||||
#include "raster/image.h"
|
||||
#include "raster/palette.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "raster/stock.h"
|
||||
#include "util/quantize.h"
|
||||
|
||||
/* static int quantize_bitmaps1(struct Stock *stock, struct RGB *pal, int *bmp_i, int fill_other); */
|
||||
/* static int quantize_bitmaps2(struct Stock *stock, struct Palette *pal); */
|
||||
static int quantize_bitmaps(Image **image, int nimage, RGB *pal, int *bmp_i, int fill_other);
|
||||
|
||||
void sprite_quantize(struct Sprite *sprite)
|
||||
void sprite_quantize(Sprite *sprite)
|
||||
{
|
||||
#if 0 /* TODO next release */
|
||||
Palette *palette = palette_new(0, MAX_PALETTE_COLORS);
|
||||
|
||||
sprite_quantize_ex(sprite, palette);
|
||||
@ -42,25 +39,39 @@ void sprite_quantize(struct Sprite *sprite)
|
||||
/* just one palette */
|
||||
sprite_reset_palettes(sprite);
|
||||
sprite_set_palette(sprite, palette, FALSE);
|
||||
#endif
|
||||
|
||||
palette_free(palette);
|
||||
}
|
||||
|
||||
void sprite_quantize_ex(Sprite *sprite, Palette *palette)
|
||||
{
|
||||
#if 0 /* TODO */
|
||||
Stock *stock;
|
||||
Image *flat_image;
|
||||
int c;
|
||||
Image *flat_image, **image_array;
|
||||
ImageRef *p, *images;
|
||||
int c, nimage;
|
||||
|
||||
stock = sprite_get_images(sprite, TARGET_ALL_LAYERS |
|
||||
TARGET_ALL_FRAMES, FALSE, NULL, NULL);
|
||||
if (stock) {
|
||||
images = images_ref_get_from_sprite(sprite, TARGET_ALL_LAYERS |
|
||||
TARGET_ALL_FRAMES, FALSE);
|
||||
if (images != NULL) {
|
||||
/* add a flat image with the current sprite's frame rendered */
|
||||
flat_image = image_new(sprite->imgtype, sprite->w, sprite->h);
|
||||
image_clear(flat_image, 0);
|
||||
sprite_render(sprite, flat_image, 0, 0);
|
||||
stock_add_image(stock, flat_image);
|
||||
|
||||
/* count images in the 'images' list */
|
||||
c = 0;
|
||||
for (p=images; p; p=p->next)
|
||||
c++;
|
||||
c++; /* the 'flat_image' */
|
||||
|
||||
/* create an array of images */
|
||||
nimage = c;
|
||||
image_array = jmalloc(sizeof(Image**) * nimage);
|
||||
|
||||
c = 0;
|
||||
for (p=images; p; p=p->next)
|
||||
image_array[c++] = p->image;
|
||||
image_array[c++] = flat_image; /* the 'flat_image' */
|
||||
|
||||
/* generate the optimized palette */
|
||||
{
|
||||
PALETTE rgbpal;
|
||||
@ -69,25 +80,23 @@ void sprite_quantize_ex(Sprite *sprite, Palette *palette)
|
||||
for (c=0; c<256; c++)
|
||||
rgbpal[c].r = rgbpal[c].g = rgbpal[c].b = 255;
|
||||
|
||||
ibmp = jmalloc(sizeof (int) * stock->nimage);
|
||||
for (c=0; c<stock->nimage; c++)
|
||||
ibmp = jmalloc(sizeof(int) * nimage);
|
||||
for (c=0; c<nimage; c++)
|
||||
ibmp[c] = 128;
|
||||
|
||||
quantize_bitmaps1(stock, rgbpal, ibmp, TRUE);
|
||||
quantize_bitmaps(image_array, nimage, rgbpal, ibmp, TRUE);
|
||||
|
||||
palette_from_allegro(palette, rgbpal);
|
||||
|
||||
jfree(ibmp);
|
||||
}
|
||||
|
||||
stock_free(stock);
|
||||
jfree(image_array);
|
||||
image_free(flat_image);
|
||||
images_ref_free(images);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0 /* TODO next release */
|
||||
|
||||
/* quantize.c
|
||||
* Copyright (C) 2000-2002 by Ben "entheh" Davis
|
||||
*
|
||||
@ -142,10 +151,10 @@ void sprite_quantize_ex(Sprite *sprite, Palette *palette)
|
||||
|
||||
typedef struct PALETTE_NODE
|
||||
{
|
||||
unsigned int rl,gl,bl,rh,gh,bh;
|
||||
unsigned int n1,n2,Sr,Sg,Sb,E;
|
||||
struct PALETTE_NODE *parent;
|
||||
struct PALETTE_NODE *subnode[2][2][2];
|
||||
unsigned int rl,gl,bl,rh,gh,bh;
|
||||
unsigned int n1,n2,Sr,Sg,Sb,E;
|
||||
struct PALETTE_NODE *parent;
|
||||
struct PALETTE_NODE *subnode[2][2][2];
|
||||
} PALETTE_NODE;
|
||||
|
||||
static PALETTE_NODE *rgb_node[64][64][64];
|
||||
@ -155,228 +164,231 @@ static PALETTE_NODE *create_node(unsigned int rl,
|
||||
unsigned int bl,
|
||||
unsigned int rh,
|
||||
unsigned int gh,
|
||||
unsigned int bh,PALETTE_NODE *parent) {
|
||||
PALETTE_NODE *node;
|
||||
unsigned int rm,gm,bm;
|
||||
node=jmalloc(sizeof(PALETTE_NODE));
|
||||
if (!node)
|
||||
return NULL;
|
||||
node->rl=rl;
|
||||
node->gl=gl;
|
||||
node->bl=bl;
|
||||
node->rh=rh;
|
||||
node->gh=gh;
|
||||
node->bh=bh;
|
||||
node->E=node->Sb=node->Sg=node->Sr=node->n2=node->n1=0;
|
||||
node->parent=parent;
|
||||
if (rh-rl>TREE_DEPTH) {
|
||||
rm=(rl+rh)>>1;
|
||||
gm=(gl+gh)>>1;
|
||||
bm=(bl+bh)>>1;
|
||||
node->subnode[0][0][0]=create_node(rl,gl,bl,rm,gm,bm,node);
|
||||
node->subnode[0][0][1]=create_node(rm,gl,bl,rh,gm,bm,node);
|
||||
node->subnode[0][1][0]=create_node(rl,gm,bl,rm,gh,bm,node);
|
||||
node->subnode[0][1][1]=create_node(rm,gm,bl,rh,gh,bm,node);
|
||||
node->subnode[1][0][0]=create_node(rl,gl,bm,rm,gm,bh,node);
|
||||
node->subnode[1][0][1]=create_node(rm,gl,bm,rh,gm,bh,node);
|
||||
node->subnode[1][1][0]=create_node(rl,gm,bm,rm,gh,bh,node);
|
||||
node->subnode[1][1][1]=create_node(rm,gm,bm,rh,gh,bh,node);
|
||||
} else {
|
||||
for (bm=bl;bm<bh;bm++) {
|
||||
for (gm=gl;gm<gh;gm++) {
|
||||
for (rm=rl;rm<rh;rm++) {
|
||||
rgb_node[bm][gm][rm]=node;
|
||||
unsigned int bh,PALETTE_NODE *parent)
|
||||
{
|
||||
PALETTE_NODE *node;
|
||||
unsigned int rm,gm,bm;
|
||||
node=jmalloc(sizeof(PALETTE_NODE));
|
||||
if (!node)
|
||||
return NULL;
|
||||
node->rl=rl;
|
||||
node->gl=gl;
|
||||
node->bl=bl;
|
||||
node->rh=rh;
|
||||
node->gh=gh;
|
||||
node->bh=bh;
|
||||
node->E=node->Sb=node->Sg=node->Sr=node->n2=node->n1=0;
|
||||
node->parent=parent;
|
||||
if (rh-rl>TREE_DEPTH) {
|
||||
rm=(rl+rh)>>1;
|
||||
gm=(gl+gh)>>1;
|
||||
bm=(bl+bh)>>1;
|
||||
node->subnode[0][0][0]=create_node(rl,gl,bl,rm,gm,bm,node);
|
||||
node->subnode[0][0][1]=create_node(rm,gl,bl,rh,gm,bm,node);
|
||||
node->subnode[0][1][0]=create_node(rl,gm,bl,rm,gh,bm,node);
|
||||
node->subnode[0][1][1]=create_node(rm,gm,bl,rh,gh,bm,node);
|
||||
node->subnode[1][0][0]=create_node(rl,gl,bm,rm,gm,bh,node);
|
||||
node->subnode[1][0][1]=create_node(rm,gl,bm,rh,gm,bh,node);
|
||||
node->subnode[1][1][0]=create_node(rl,gm,bm,rm,gh,bh,node);
|
||||
node->subnode[1][1][1]=create_node(rm,gm,bm,rh,gh,bh,node);
|
||||
} else {
|
||||
for (bm=bl;bm<bh;bm++) {
|
||||
for (gm=gl;gm<gh;gm++) {
|
||||
for (rm=rl;rm<rh;rm++) {
|
||||
rgb_node[bm][gm][rm]=node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
node->subnode[1][1][1]=
|
||||
node->subnode[1][1][0]=
|
||||
node->subnode[1][0][1]=
|
||||
node->subnode[1][0][0]=
|
||||
node->subnode[0][1][1]=
|
||||
node->subnode[0][1][0]=
|
||||
node->subnode[0][0][1]=
|
||||
node->subnode[0][0][0]=0;
|
||||
}
|
||||
node->subnode[1][1][1]=
|
||||
node->subnode[1][1][0]=
|
||||
node->subnode[1][0][1]=
|
||||
node->subnode[1][0][0]=
|
||||
node->subnode[0][1][1]=
|
||||
node->subnode[0][1][0]=
|
||||
node->subnode[0][0][1]=
|
||||
node->subnode[0][0][0]=0;
|
||||
}
|
||||
return node;
|
||||
return node;
|
||||
}
|
||||
|
||||
static PALETTE_NODE *collapse_empty(PALETTE_NODE *node,unsigned int *n_colours) {
|
||||
unsigned int b,g,r;
|
||||
for (b=0;b<2;b++) {
|
||||
for (g=0;g<2;g++) {
|
||||
for (r=0;r<2;r++) {
|
||||
if (node->subnode[b][g][r])
|
||||
node->subnode[b][g][r]=collapse_empty(node->subnode[b][g][r],n_colours);
|
||||
}
|
||||
static PALETTE_NODE *collapse_empty(PALETTE_NODE *node,unsigned int *n_colours)
|
||||
{
|
||||
unsigned int b,g,r;
|
||||
for (b=0;b<2;b++) {
|
||||
for (g=0;g<2;g++) {
|
||||
for (r=0;r<2;r++) {
|
||||
if (node->subnode[b][g][r])
|
||||
node->subnode[b][g][r]=collapse_empty(node->subnode[b][g][r],n_colours);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node->n1==0) {
|
||||
jfree(node);
|
||||
node=0;
|
||||
} else if (node->n2) (*n_colours)++;
|
||||
return node;
|
||||
if (node->n1==0) {
|
||||
jfree(node);
|
||||
node=0;
|
||||
} else if (node->n2) (*n_colours)++;
|
||||
return node;
|
||||
}
|
||||
|
||||
static PALETTE_NODE *collapse_nodes(PALETTE_NODE *node,unsigned int *n_colours,
|
||||
unsigned int n_entries,unsigned int Ep) {
|
||||
unsigned int b,g,r;
|
||||
if (node->E<=Ep) {
|
||||
for (b=0;b<2;b++) {
|
||||
for (g=0;g<2;g++) {
|
||||
for (r=0;r<2;r++) {
|
||||
if (node->subnode[b][g][r]) {
|
||||
node->subnode[b][g][r]=collapse_nodes(node->subnode[b][g][r],
|
||||
n_colours,n_entries,0);
|
||||
if (*n_colours<=n_entries) return node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node->parent->n2) (*n_colours)--;
|
||||
node->parent->n2+=node->n2;
|
||||
node->parent->Sr+=node->Sr;
|
||||
node->parent->Sg+=node->Sg;
|
||||
node->parent->Sb+=node->Sb;
|
||||
jfree(node);
|
||||
node=0;
|
||||
} else {
|
||||
for (b=0;b<2;b++) {
|
||||
for (g=0;g<2;g++) {
|
||||
for (r=0;r<2;r++) {
|
||||
if (node->subnode[b][g][r]) {
|
||||
node->subnode[b][g][r]=collapse_nodes(node->subnode[b][g][r],
|
||||
n_colours,n_entries,Ep);
|
||||
if (*n_colours<=n_entries) return node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
static unsigned int distance_squared(int r,int g,int b) {
|
||||
return r*r+g*g+b*b;
|
||||
}
|
||||
|
||||
static void minimum_Ep(PALETTE_NODE *node,unsigned int *Ep) {
|
||||
unsigned int r,g,b;
|
||||
if (node->E<*Ep) *Ep=node->E;
|
||||
for (b=0;b<2;b++) {
|
||||
for (g=0;g<2;g++) {
|
||||
for (r=0;r<2;r++) {
|
||||
if (node->subnode[b][g][r]) minimum_Ep(node->subnode[b][g][r],Ep);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void fill_palette(PALETTE_NODE *node,unsigned int *c,RGB *pal,int depth) {
|
||||
unsigned int r,g,b;
|
||||
if (node->n2) {
|
||||
for (;pal[*c].r!=255;(*c)++);
|
||||
pal[*c].r=node->Sr/node->n2;
|
||||
pal[*c].g=node->Sg/node->n2;
|
||||
pal[*c].b=node->Sb/node->n2;
|
||||
(*c)++;
|
||||
}
|
||||
for (b=0;b<2;b++) {
|
||||
for (g=0;g<2;g++) {
|
||||
for (r=0;r<2;r++) {
|
||||
if (node->subnode[b][g][r])
|
||||
fill_palette(node->subnode[b][g][r],c,pal,depth+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void destroy_tree(PALETTE_NODE *tree) {
|
||||
unsigned int r,g,b;
|
||||
for (b=0;b<2;b++) {
|
||||
for (g=0;g<2;g++) {
|
||||
for (r=0;r<2;r++) {
|
||||
if (tree->subnode[b][g][r]) destroy_tree(tree->subnode[b][g][r]);
|
||||
}
|
||||
}
|
||||
}
|
||||
jfree(tree);
|
||||
}
|
||||
|
||||
static int quantize_bitmaps1(Stock *stock, RGB *pal, int *bmp_i, int fill_other)
|
||||
unsigned int n_entries,unsigned int Ep)
|
||||
{
|
||||
int c_bmp,x,y,c,r,g,b,n_colours=0,n_entries=0,Ep;
|
||||
PALETTE_NODE *tree,*node;
|
||||
|
||||
/* only support RGB bitmaps */
|
||||
if ((stock->nimage < 1) || (stock->imgtype != IMAGE_RGB))
|
||||
return 0;
|
||||
|
||||
/*Create the tree structure*/
|
||||
tree=create_node(0,0,0,64,64,64,0);
|
||||
/*Scan the bitmaps*/
|
||||
/* add_progress(stock->nimage+1); */
|
||||
for (c_bmp=0;c_bmp<stock->nimage;c_bmp++) {
|
||||
if (stock->image[c_bmp]) {
|
||||
/* add_progress(stock->image[c_bmp]->h); */
|
||||
for (y=0;y<stock->image[c_bmp]->h;y++) {
|
||||
for (x=0;x<stock->image[c_bmp]->w;x++) {
|
||||
c=stock->image[c_bmp]->method->getpixel(stock->image[c_bmp],x,y);
|
||||
r=_rgba_getr(c)>>2;
|
||||
g=_rgba_getg(c)>>2;
|
||||
b=_rgba_getb(c)>>2;
|
||||
node=rgb_node[b][g][r];
|
||||
node->n2+=bmp_i[c_bmp];
|
||||
node->Sr+=r*bmp_i[c_bmp];
|
||||
node->Sg+=g*bmp_i[c_bmp];
|
||||
node->Sb+=b*bmp_i[c_bmp];
|
||||
do {
|
||||
node->n1+=bmp_i[c_bmp];
|
||||
node->E+=distance_squared((r<<1)-node->rl-node->rh,
|
||||
(g<<1)-node->gl-node->gh,
|
||||
(b<<1)-node->bl-node->bh)*bmp_i[c_bmp];
|
||||
node=node->parent;
|
||||
} while (node);
|
||||
unsigned int b,g,r;
|
||||
if (node->E<=Ep) {
|
||||
for (b=0;b<2;b++) {
|
||||
for (g=0;g<2;g++) {
|
||||
for (r=0;r<2;r++) {
|
||||
if (node->subnode[b][g][r]) {
|
||||
node->subnode[b][g][r]=collapse_nodes(node->subnode[b][g][r],
|
||||
n_colours,n_entries,0);
|
||||
if (*n_colours<=n_entries) return node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node->parent->n2) (*n_colours)--;
|
||||
node->parent->n2+=node->n2;
|
||||
node->parent->Sr+=node->Sr;
|
||||
node->parent->Sg+=node->Sg;
|
||||
node->parent->Sb+=node->Sb;
|
||||
jfree(node);
|
||||
node=0;
|
||||
} else {
|
||||
for (b=0;b<2;b++) {
|
||||
for (g=0;g<2;g++) {
|
||||
for (r=0;r<2;r++) {
|
||||
if (node->subnode[b][g][r]) {
|
||||
node->subnode[b][g][r]=collapse_nodes(node->subnode[b][g][r],
|
||||
n_colours,n_entries,Ep);
|
||||
if (*n_colours<=n_entries) return node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* do_progress(y); */
|
||||
}
|
||||
/* del_progress(); */
|
||||
}
|
||||
/* do_progress(c_bmp); */
|
||||
}
|
||||
/*Collapse empty nodes in the tree, and count leaves*/
|
||||
tree=collapse_empty(tree,&n_colours);
|
||||
/*Count free palette entries*/
|
||||
for (c=0;c<256;c++) {
|
||||
if (pal[c].r==255) n_entries++;
|
||||
}
|
||||
/*Collapse nodes until there are few enough to fit in the palette*/
|
||||
if (n_colours > n_entries) {
|
||||
/* int n_colours1 = n_colours; */
|
||||
/* add_progress(n_colours1 - n_entries); */
|
||||
while (n_colours>n_entries) {
|
||||
Ep=0xFFFFFFFFul;
|
||||
minimum_Ep(tree,&Ep);
|
||||
tree=collapse_nodes(tree,&n_colours,n_entries,Ep);
|
||||
|
||||
/* if (n_colours > n_entries) */
|
||||
/* do_progress(n_colours1 - n_colours); */
|
||||
}
|
||||
/* del_progress(); */
|
||||
}
|
||||
/* del_progress(); */
|
||||
/*Fill palette*/
|
||||
c=0;
|
||||
fill_palette(tree,&c,pal,1);
|
||||
if (fill_other) {
|
||||
for (;c<256;c++) {
|
||||
if (pal[c].r==255)
|
||||
pal[c].b=pal[c].g=pal[c].r=0;
|
||||
}
|
||||
}
|
||||
/*Free memory used by tree*/
|
||||
destroy_tree(tree);
|
||||
return n_colours;
|
||||
return node;
|
||||
}
|
||||
|
||||
#endif
|
||||
static unsigned int distance_squared(int r,int g,int b)
|
||||
{
|
||||
return r*r+g*g+b*b;
|
||||
}
|
||||
|
||||
static void minimum_Ep(PALETTE_NODE *node,unsigned int *Ep)
|
||||
{
|
||||
unsigned int r,g,b;
|
||||
if (node->E<*Ep) *Ep=node->E;
|
||||
for (b=0;b<2;b++) {
|
||||
for (g=0;g<2;g++) {
|
||||
for (r=0;r<2;r++) {
|
||||
if (node->subnode[b][g][r]) minimum_Ep(node->subnode[b][g][r],Ep);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void fill_palette(PALETTE_NODE *node,unsigned int *c,RGB *pal,int depth)
|
||||
{
|
||||
unsigned int r,g,b;
|
||||
if (node->n2) {
|
||||
for (;pal[*c].r!=255;(*c)++);
|
||||
pal[*c].r=node->Sr/node->n2;
|
||||
pal[*c].g=node->Sg/node->n2;
|
||||
pal[*c].b=node->Sb/node->n2;
|
||||
(*c)++;
|
||||
}
|
||||
for (b=0;b<2;b++) {
|
||||
for (g=0;g<2;g++) {
|
||||
for (r=0;r<2;r++) {
|
||||
if (node->subnode[b][g][r])
|
||||
fill_palette(node->subnode[b][g][r],c,pal,depth+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void destroy_tree(PALETTE_NODE *tree)
|
||||
{
|
||||
unsigned int r,g,b;
|
||||
for (b=0;b<2;b++) {
|
||||
for (g=0;g<2;g++) {
|
||||
for (r=0;r<2;r++) {
|
||||
if (tree->subnode[b][g][r]) destroy_tree(tree->subnode[b][g][r]);
|
||||
}
|
||||
}
|
||||
}
|
||||
jfree(tree);
|
||||
}
|
||||
|
||||
static int quantize_bitmaps(Image **image, int nimage, RGB *pal, int *bmp_i, int fill_other)
|
||||
{
|
||||
int c_bmp,x,y,c,r,g,b,n_colours=0,n_entries=0,Ep;
|
||||
PALETTE_NODE *tree,*node;
|
||||
|
||||
/* only support RGB bitmaps */
|
||||
if ((nimage < 1) || (image[0]->imgtype != IMAGE_RGB))
|
||||
return 0;
|
||||
|
||||
/*Create the tree structure*/
|
||||
tree=create_node(0,0,0,64,64,64,0);
|
||||
/*Scan the bitmaps*/
|
||||
/* add_progress(nimage+1); */
|
||||
for (c_bmp=0;c_bmp<nimage;c_bmp++) {
|
||||
/* add_progress(image[c_bmp]->h); */
|
||||
for (y=0;y<image[c_bmp]->h;y++) {
|
||||
for (x=0;x<image[c_bmp]->w;x++) {
|
||||
c=image[c_bmp]->method->getpixel(image[c_bmp],x,y);
|
||||
r=_rgba_getr(c)>>2;
|
||||
g=_rgba_getg(c)>>2;
|
||||
b=_rgba_getb(c)>>2;
|
||||
node=rgb_node[b][g][r];
|
||||
node->n2+=bmp_i[c_bmp];
|
||||
node->Sr+=r*bmp_i[c_bmp];
|
||||
node->Sg+=g*bmp_i[c_bmp];
|
||||
node->Sb+=b*bmp_i[c_bmp];
|
||||
do {
|
||||
node->n1+=bmp_i[c_bmp];
|
||||
node->E+=distance_squared((r<<1)-node->rl-node->rh,
|
||||
(g<<1)-node->gl-node->gh,
|
||||
(b<<1)-node->bl-node->bh)*bmp_i[c_bmp];
|
||||
node=node->parent;
|
||||
} while (node);
|
||||
}
|
||||
/* do_progress(y); */
|
||||
}
|
||||
/* del_progress(); */
|
||||
/* do_progress(c_bmp); */
|
||||
}
|
||||
/*Collapse empty nodes in the tree, and count leaves*/
|
||||
tree=collapse_empty(tree,&n_colours);
|
||||
/*Count free palette entries*/
|
||||
for (c=0;c<256;c++) {
|
||||
if (pal[c].r==255) n_entries++;
|
||||
}
|
||||
/*Collapse nodes until there are few enough to fit in the palette*/
|
||||
if (n_colours > n_entries) {
|
||||
/* int n_colours1 = n_colours; */
|
||||
/* add_progress(n_colours1 - n_entries); */
|
||||
while (n_colours>n_entries) {
|
||||
Ep=0xFFFFFFFFul;
|
||||
minimum_Ep(tree,&Ep);
|
||||
tree=collapse_nodes(tree,&n_colours,n_entries,Ep);
|
||||
|
||||
/* if (n_colours > n_entries) */
|
||||
/* do_progress(n_colours1 - n_colours); */
|
||||
}
|
||||
/* del_progress(); */
|
||||
}
|
||||
/* del_progress(); */
|
||||
/* fill palette */
|
||||
c=0;
|
||||
fill_palette(tree,&c,pal,1);
|
||||
if (fill_other) {
|
||||
for (;c<256;c++) {
|
||||
if (pal[c].r==255)
|
||||
pal[c].b=pal[c].g=pal[c].r=0;
|
||||
}
|
||||
}
|
||||
/* free memory used by tree */
|
||||
destroy_tree(tree);
|
||||
return n_colours;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user