Replace images_ref functions (src/effect) with ImagesCollector class (src/raster).

This commit is contained in:
David Capello 2010-12-26 17:03:35 -03:00
parent 4c8c7463ed
commit d301fc7530
7 changed files with 221 additions and 243 deletions

View File

@ -170,7 +170,6 @@ add_library(aseprite-library
effect/colcurve.cpp
effect/convmatr.cpp
effect/effect.cpp
effect/images_ref.cpp
effect/invrtcol.cpp
effect/median.cpp
effect/replcol.cpp
@ -202,6 +201,7 @@ add_library(aseprite-library
raster/dirty.cpp
raster/gfxobj.cpp
raster/image.cpp
raster/images_collector.cpp
raster/layer.cpp
raster/mask.cpp
raster/palette.cpp

View File

@ -35,10 +35,10 @@
#include "effect/invrtcol.h"
#include "effect/median.h"
#include "effect/replcol.h"
#include "effect/images_ref.h"
#include "modules/editors.h"
#include "raster/cel.h"
#include "raster/image.h"
#include "raster/images_collector.h"
#include "raster/layer.h"
#include "raster/mask.h"
#include "raster/sprite.h"
@ -70,7 +70,7 @@ static EffectData effects_data[] = {
static EffectData *get_effect_data(const char *name);
static void effect_init(Effect* effect, const Layer* layer, Image* image, int offset_x, int offset_y);
static void effect_apply_to_image(Effect *effect, ImageRef *p, int x, int y);
static void effect_apply_to_image(Effect* effect, Layer* layer, Image* image, int x, int y);
static bool effect_update_mask(Effect* effect, Mask* mask, const Image* image);
int init_module_effect()
@ -294,47 +294,43 @@ void effect_flush(Effect *effect)
void effect_apply_to_target(Effect *effect)
{
ImageRef *p, *images;
bool cancelled = false;
int nimages;
images = images_ref_get_from_sprite(effect->sprite, effect->target, true);
if (images == NULL)
ImagesCollector images(effect->sprite,
(effect->target & TARGET_ALL_LAYERS) == TARGET_ALL_LAYERS,
(effect->target & TARGET_ALL_FRAMES) == TARGET_ALL_FRAMES,
true); // we will write in each image
if (images.empty())
return;
nimages = 0;
for (p=images; p; p=p->next)
nimages++;
/* open undo group of operations */
if (nimages > 1) {
// Open group of undo operations
if (images.size() > 1) {
if (effect->sprite->getUndo()->isEnabled())
effect->sprite->getUndo()->undo_open();
}
effect->progress_base = 0.0f;
effect->progress_width = 1.0f / nimages;
effect->progress_width = 1.0f / images.size();
/* for each target image */
for (p=images; p && !cancelled; p=p->next) {
effect_apply_to_image(effect, p, p->cel->x, p->cel->y);
// For each target image
for (ImagesCollector::ItemsIterator it = images.begin();
it != images.end() && !cancelled;
++it) {
effect_apply_to_image(effect, it->layer(), it->image(), it->cel()->x, it->cel()->y);
/* there is a 'is_cancelled' hook? */
// There is a 'is_cancelled' hook?
if (effect->is_cancelled != NULL)
cancelled = (effect->is_cancelled)(effect->progress_data);
/* progress */
// Make progress
effect->progress_base += effect->progress_width;
}
/* close undo group of operations */
if (nimages > 1) {
// Close group of undo operations
if (images.size() > 1) {
if (effect->sprite->getUndo()->isEnabled())
effect->sprite->getUndo()->undo_close();
}
/* free all ImageRefs */
images_ref_free(images);
}
static EffectData *get_effect_data(const char *name)
@ -382,9 +378,9 @@ static void effect_init(Effect* effect, const Layer* layer, Image* image,
effect->target &= ~TARGET_ALPHA_CHANNEL;
}
static void effect_apply_to_image(Effect* effect, ImageRef* p, int x, int y)
static void effect_apply_to_image(Effect* effect, Layer* layer, Image* image, int x, int y)
{
effect_init(effect, p->layer, p->image, x, y);
effect_init(effect, layer, image, x, y);
effect_apply(effect);
}

View File

@ -1,126 +0,0 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2010 David Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "gui/jlist.h"
#include "effect/effect.h"
#include "effect/images_ref.h"
#include "raster/cel.h"
#include "raster/image.h"
#include "raster/layer.h"
#include "raster/mask.h"
#include "raster/sprite.h"
#include "raster/stock.h"
static ImageRef* images_ref_get_from_layer(Layer* layer, int target, bool write);
ImageRef* images_ref_get_from_sprite(const Sprite* sprite, int target, bool write)
{
Layer* layer = target & TARGET_ALL_LAYERS ? sprite->getFolder():
sprite->getCurrentLayer();
return images_ref_get_from_layer(layer, target, 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(Layer* layer, int target, bool write)
{
#define ADD_IMAGES(images) \
{ \
if (first_image == NULL) { \
first_image = images; \
last_image = images; \
} \
else { \
ASSERT(last_image != NULL); \
last_image->next = images; \
} \
\
while (last_image->next != NULL) \
last_image = last_image->next; \
}
#define NEW_IMAGE(layer, cel) \
{ \
ImageRef* image_ref = jnew(ImageRef, 1); \
\
image_ref->image = sprite->getStock()->getImage(cel->image); \
image_ref->layer = layer; \
image_ref->cel = cel; \
image_ref->next = NULL; \
\
ADD_IMAGES(image_ref); \
}
const Sprite* sprite = layer->getSprite();
ImageRef* first_image = NULL;
ImageRef* last_image = NULL;
int frame = sprite->getCurrentFrame();
if (!layer->is_readable())
return NULL;
if (write && !layer->is_writable())
return NULL;
switch (layer->getType()) {
case GFXOBJ_LAYER_IMAGE: {
if (target & TARGET_ALL_FRAMES) {
for (frame=0; frame<sprite->getTotalFrames(); frame++) {
Cel* cel = static_cast<LayerImage*>(layer)->getCel(frame);
if (cel != NULL)
NEW_IMAGE(layer, cel);
}
}
else {
Cel* cel = static_cast<LayerImage*>(layer)->getCel(frame);
if (cel != NULL)
NEW_IMAGE(layer, cel);
}
break;
}
case GFXOBJ_LAYER_FOLDER: {
ImageRef* sub_images;
LayerIterator it = static_cast<LayerFolder*>(layer)->get_layer_begin();
LayerIterator end = static_cast<LayerFolder*>(layer)->get_layer_end();
for (; it != end; ++it) {
sub_images = images_ref_get_from_layer(*it, target, write);
if (sub_images != NULL)
ADD_IMAGES(sub_images);
}
break;
}
}
return first_image;
}

View File

@ -1,39 +0,0 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2010 David Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef EFFECT_IMAGES_REF_H_INCLUDED
#define EFFECT_IMAGES_REF_H_INCLUDED
class Sprite;
class Image;
class Layer;
class Cel;
struct ImageRef
{
Image* image;
Layer* layer;
Cel* cel;
ImageRef* next;
};
ImageRef* images_ref_get_from_sprite(const Sprite* sprite, int target, bool write);
void images_ref_free(ImageRef* image_ref);
#endif

View File

@ -0,0 +1,86 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2010 David Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "raster/cel.h"
#include "raster/image.h"
#include "raster/images_collector.h"
#include "raster/layer.h"
#include "raster/mask.h"
#include "raster/sprite.h"
#include "raster/stock.h"
ImagesCollector::ImagesCollector(const Sprite* sprite, bool allLayers, bool allFrames, bool forWrite)
: m_allFrames(allFrames)
, m_forWrite(forWrite)
{
Layer* layer = allLayers ? sprite->getFolder():
sprite->getCurrentLayer();
collectFromLayer(layer);
}
void ImagesCollector::collectFromLayer(Layer* layer)
{
const Sprite* sprite = layer->getSprite();
int frame = sprite->getCurrentFrame();
if (!layer->is_readable())
return;
if (m_forWrite && !layer->is_writable())
return;
switch (layer->getType()) {
case GFXOBJ_LAYER_IMAGE: {
if (m_allFrames) {
for (frame=0; frame<sprite->getTotalFrames(); frame++) {
Cel* cel = static_cast<LayerImage*>(layer)->getCel(frame);
if (cel != NULL)
collectImage(layer, cel);
}
}
else {
Cel* cel = static_cast<LayerImage*>(layer)->getCel(frame);
if (cel != NULL)
collectImage(layer, cel);
}
break;
}
case GFXOBJ_LAYER_FOLDER: {
LayerIterator it = static_cast<LayerFolder*>(layer)->get_layer_begin();
LayerIterator end = static_cast<LayerFolder*>(layer)->get_layer_end();
for (; it != end; ++it)
collectFromLayer(*it);
break;
}
}
}
void ImagesCollector::collectImage(Layer* layer, Cel* cel)
{
Image* image = layer->getSprite()->getStock()->getImage(cel->image);
m_items.push_back(Item(layer, cel, image));
}

View File

@ -0,0 +1,79 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2010 David Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef RASTER_IMAGES_REF_H_INCLUDED
#define RASTER_IMAGES_REF_H_INCLUDED
#include <list>
class Sprite;
class Image;
class Layer;
class Cel;
// Collects images from a sprite
class ImagesCollector
{
public:
class Item {
public:
Item(Layer* layer, Cel* cel, Image* image)
: m_layer(layer)
, m_cel(cel)
, m_image(image)
{ }
Layer* layer() const { return m_layer; }
Cel* cel() const { return m_cel; }
Image* image() const { return m_image; }
private:
Layer* m_layer;
Cel* m_cel;
Image* m_image;
};
typedef std::list<Item> Items;
typedef std::list<Item>::iterator ItemsIterator;
// Creates a collection of images from the specified sprite.
// Parameters:
// * allLayers: True if you want to collect images from all layers or
// false if you want to images from the current layer only.
// * allFrames: True if you want to collect images from all frames
// or false if you need images from the current frame.
// * forWrite: True if you will modify the images (it is used to avoid
// returning images from layers which are read-only/write-locked).
ImagesCollector(const Sprite* sprite, bool allLayers, bool allFrames, bool forWrite);
ItemsIterator begin() { return m_items.begin(); }
ItemsIterator end() { return m_items.end(); }
size_t size() const { return m_items.size(); }
bool empty() const { return m_items.empty(); }
private:
void collectFromLayer(Layer* layer);
void collectImage(Layer* layer, Cel* cel);
Items m_items;
bool m_allFrames;
bool m_forWrite;
};
#endif

View File

@ -18,16 +18,15 @@
#include "config.h"
#include "effect/effect.h"
#include "effect/images_ref.h"
#include "gfx/hsv.h"
#include "gfx/rgb.h"
#include "raster/blend.h"
#include "raster/image.h"
#include "raster/images_collector.h"
#include "raster/palette.h"
#include "raster/quantization.h"
#include "raster/rgbmap.h"
#include "raster/sprite.h"
using namespace gfx;
@ -37,64 +36,49 @@ static Image* ordered_dithering(const Image* src_image,
const RgbMap* rgbmap,
const Palette* palette);
static int create_palette_from_bitmaps(Image **image, int nimage, RGB *pal, int *bmp_i, int fill_other);
static int create_palette_from_bitmaps(Image** image, int nimage, RGB* pal, int* bmp_i, int fill_other);
Palette* quantization::create_palette_from_rgb(const Sprite* sprite)
{
Palette* palette = new Palette(0, 256);
Image* flat_image;
Image** image_array;
ImageRef* p;
ImageRef* images;
int c, nimage;
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->getImgType(), sprite->getWidth(), sprite->getHeight());
image_clear(flat_image, 0);
sprite->render(flat_image, 0, 0);
ImagesCollector images(sprite,
true, // all layers
true, // all frames,
false); // forWrite=false, read only
/* count images in the 'images' list */
c = 0;
for (p=images; p; p=p->next)
c++;
c++; /* the 'flat_image' */
// Add a flat image with the current sprite's frame rendered
flat_image = image_new(sprite->getImgType(), sprite->getWidth(), sprite->getHeight());
image_clear(flat_image, 0);
sprite->render(flat_image, 0, 0);
/* create an array of images */
nimage = c;
image_array = (Image**)jmalloc(sizeof(Image*) * nimage);
// Create an array of images
size_t nimage = images.size() + 1; // +1 for flat_image
std::vector<Image*> image_array(nimage);
c = 0;
for (p=images; p; p=p->next)
image_array[c++] = p->image;
image_array[c++] = flat_image; /* the 'flat_image' */
size_t c = 0;
for (ImagesCollector::ItemsIterator it=images.begin(); it!=images.end(); ++it)
image_array[c++] = it->image();
image_array[c++] = flat_image; // The 'flat_image'
/* generate the optimized palette */
{
PALETTE rgbpal;
int *ibmp;
// Generate an optimized palette for all images
{
PALETTE rgbpal;
for (c=0; c<256; c++)
rgbpal[c].r = rgbpal[c].g = rgbpal[c].b = 255;
for (c=0; c<256; c++)
rgbpal[c].r = rgbpal[c].g = rgbpal[c].b = 255;
ibmp = (int*)jmalloc(sizeof(int) * nimage);
for (c=0; c<nimage; c++)
ibmp[c] = 128;
std::vector<int> ibmp(nimage);
for (c=0; c<nimage; c++)
ibmp[c] = 128;
create_palette_from_bitmaps(image_array, nimage, rgbpal, ibmp, true);
create_palette_from_bitmaps(&image_array[0], nimage, rgbpal, &ibmp[0], true);
palette->fromAllegro(rgbpal);
jfree(ibmp);
}
jfree(image_array);
image_free(flat_image);
images_ref_free(images);
palette->fromAllegro(rgbpal);
}
delete flat_image;
return palette;
}
@ -415,9 +399,7 @@ static PALETTE_NODE *create_node(unsigned int rl,
{
PALETTE_NODE *node;
unsigned int rm,gm,bm;
node=(PALETTE_NODE*)jmalloc(sizeof(PALETTE_NODE));
if (!node)
return NULL;
node = new PALETTE_NODE;
node->rl=rl;
node->gl=gl;
node->bl=bl;
@ -470,7 +452,7 @@ static PALETTE_NODE *collapse_empty(PALETTE_NODE *node,unsigned int *n_colours)
}
}
if (node->n1==0) {
jfree(node);
delete node;
node=0;
} else if (node->n2) (*n_colours)++;
return node;
@ -497,7 +479,7 @@ static PALETTE_NODE *collapse_nodes(PALETTE_NODE *node,unsigned int *n_colours,
node->parent->Sr+=node->Sr;
node->parent->Sg+=node->Sg;
node->parent->Sb+=node->Sb;
jfree(node);
delete node;
node=0;
} else {
for (b=0;b<2;b++) {
@ -563,10 +545,10 @@ static void destroy_tree(PALETTE_NODE *tree)
}
}
}
jfree(tree);
delete tree;
}
static int create_palette_from_bitmaps(Image **image, int nimage, RGB *pal, int *bmp_i, int fill_other)
static int create_palette_from_bitmaps(Image** image, int nimage, RGB* pal, int* bmp_i, int fill_other)
{
int c_bmp,x,y,r,g,b;
unsigned int n_colours=0;