diff --git a/render/image.c b/render/image.c index a618f782..a374ceb4 100644 --- a/render/image.c +++ b/render/image.c @@ -28,6 +28,18 @@ #define FLOOR(i) ((i) & (~0UL << FRACTION)) #define AVERAGE(a, b) (((((a) ^ (b)) & 0xfefefefeL) >> 1) + ((a) & (b))) +void RrImagePicInit(RrImagePic *pic, gint w, gint h, RrPixel32 *data) +{ + gint i; + + pic->width = w; + pic->height = h; + pic->data = data; + pic->sum = 0; + for (i = w*h; i > 0; --i) + pic->sum += *(data++); +} + /*! Add a picture to an Image, that is, add another copy of the image at another size. This may add it to the "originals" list or to the "resized" list. */ @@ -98,7 +110,7 @@ static RrImagePic* ResizeImage(RrPixel32 *src, gulong srcW, gulong srcH, gulong dstW, gulong dstH) { - RrPixel32 *dst; + RrPixel32 *dst, *dststart; RrImagePic *pic; gulong dstX, dstY, srcX, srcY; gulong srcX1, srcX2, srcY1, srcY2; @@ -118,11 +130,7 @@ static RrImagePic* ResizeImage(RrPixel32 *src, if (srcW == dstW && srcH == dstH) return NULL; /* no scaling needed ! */ - pic = g_new(RrImagePic, 1); - dst = g_new(RrPixel32, dstW * dstH); - pic->width = dstW; - pic->height = dstH; - pic->data = dst; + dststart = dst = g_new(RrPixel32, dstW * dstH); ratioX = (srcW << FRACTION) / dstW; ratioY = (srcH << FRACTION) / dstH; @@ -194,6 +202,9 @@ static RrImagePic* ResizeImage(RrPixel32 *src, } } + pic = g_new(RrImagePic, 1); + RrImagePicInit(pic, dstW, dstH, dststart); + return pic; } @@ -343,9 +354,7 @@ void RrImageAddPicture(RrImage *self, RrPixel32 *data, gint w, gint h) /* add the new picture */ pic = g_new(RrImagePic, 1); - pic->width = w; - pic->height = h; - pic->data = g_memdup(data, w*h*sizeof(RrPixel32)); + RrImagePicInit(pic, w, h, g_memdup(data, w*h*sizeof(RrPixel32))); AddPicture(self, &self->original, &self->n_original, pic); } diff --git a/render/image.h b/render/image.h index 28f29c2c..b478daf9 100644 --- a/render/image.h +++ b/render/image.h @@ -22,6 +22,9 @@ #include "render.h" #include "geom.h" +/*! Initialize an RrImagePicture to the specified dimensions and pixel data */ +void RrImagePicInit(RrImagePic *pic, gint w, gint h, RrPixel32 *data); + void RrImageDrawImage(RrPixel32 *target, RrTextureImage *img, gint target_w, gint target_h, RrRect *area); diff --git a/render/imagecache.c b/render/imagecache.c index 9ebaec13..9c605f9d 100644 --- a/render/imagecache.c +++ b/render/imagecache.c @@ -18,6 +18,7 @@ #include "render.h" #include "imagecache.h" +#include "image.h" static gboolean RrImagePicEqual(const RrImagePic *p1, const RrImagePic *p2); @@ -56,9 +57,8 @@ RrImage* RrImageCacheFind(RrImageCache *self, RrPixel32 *data, gint w, gint h) { RrImagePic pic; - pic.width = w; - pic.height = h; - pic.data = data; + + RrImagePicInit(&pic, w, h, data); return g_hash_table_lookup(self->table, &pic); } @@ -139,21 +139,6 @@ guint RrImagePicHash(const RrImagePic *p) static gboolean RrImagePicEqual(const RrImagePic *p1, const RrImagePic *p2) { - guint s1, s2; - RrPixel32 *data1, *data2; - gint i; - - if (p1->width != p2->width || p1->height != p2->height) return FALSE; - - /* strcmp() would probably suck on 4k of data.. sum all their values and - see if they get the same thing. they already matched on their hashes - at this point. */ - s1 = s2 = 0; - data1 = p1->data; - data2 = p2->data; - for (i = 0; i < p1->width * p1->height; ++i, ++data1) - s1 += *data1; - for (i = 0; i < p2->width * p2->height; ++i, ++data2) - s2 += *data2; - return s1 == s2; + return p1->width == p2->width && p1->height == p2->height && + p1->sum == p2->sum; } diff --git a/render/render.h b/render/render.h index 7053664d..f7bc5041 100644 --- a/render/render.h +++ b/render/render.h @@ -227,6 +227,9 @@ struct _RrAppearance { struct _RrImagePic { gint width, height; RrPixel32 *data; + /* The sum of all the pixels. This is used to compare pictures if their + hashes match. */ + gint sum; }; /*! An RrImage is a sort of meta-image. It can contain multiple versions of