[GB.IMAGE]

* NEW: New API for marking an image as modified, and for synchronizing it 
  before reading it, when the temporary image owner needs it.


git-svn-id: svn://localhost/gambas/trunk@3016 867c0c6c-44f3-4631-809d-bfa615b0a4ec
This commit is contained in:
Benoît Minisini 2010-06-19 12:38:28 +00:00
parent b2bba45700
commit 6059d4dcb7
14 changed files with 103 additions and 55 deletions

View file

@ -70,7 +70,7 @@
}
}
{ VBox1 VBox
MoveScaled(28,0,29,17)
MoveScaled(28,0,28,17)
Expand = True
{ chkIgnoreStrings CheckBox
MoveScaled(0,0,25,4)
@ -132,7 +132,7 @@
Index = 1
Text = ("Browse")
{ VBox4 VBox
MoveScaled(1,1,81.00000000000001,31)
MoveScaled(1,1,81,31)
Expand = True
Spacing = True
{ panBrowse Panel

View file

@ -51,22 +51,13 @@ static void *temp_image(GB_IMG *img)
return image;
}
static void lock_image(void *image)
{
}
static void unlock_image(void *image, int changed)
{
}
static GB_IMG_OWNER _image_owner = {
"gb.gtk",
GB_IMAGE_RGBA,
free_image,
free_image,
temp_image,
lock_image,
unlock_image,
NULL
};
gPicture *CIMAGE_get(CIMAGE *_object)

View file

@ -48,22 +48,13 @@ static void *temp_image(GB_IMG *img)
return image;
}
static void lock_image(void *image)
{
}
static void unlock_image(void *image, int changed)
{
}
static GB_IMG_OWNER _image_owner = {
"gb.image.imlib",
GB_IMAGE_BGRA,
free_image,
free_image,
temp_image,
lock_image,
unlock_image,
NULL,
};
Imlib_Image check_image(void *_object)

View file

@ -128,6 +128,7 @@ BEGIN_METHOD(CIMAGE_save, GB_STRING path; GB_INTEGER quality)
goto __END;
}
SYNCHRONIZE_IMAGE(THIS);
IMAGE.Convert(THIS, GB_IMAGE_RGBA);
image = gdk_pixbuf_new_from_data((const guchar *)THIS->data, GDK_COLORSPACE_RGB, TRUE, 8, THIS->width, THIS->height, THIS->width * sizeof(uint), NULL, NULL);

View file

@ -95,22 +95,13 @@ static void *temp_image(GB_IMG *img)
return image;
}
static void lock_image(void *image)
{
}
static void unlock_image(void *image, int changed)
{
}
static GB_IMG_OWNER _image_owner = {
"gb.qt4",
GB_IMAGE_BGRA,
free_image,
free_image,
temp_image,
lock_image,
unlock_image,
NULL,
};
QImage *CIMAGE_get(CIMAGE *_object)

View file

@ -33,6 +33,18 @@ static void free_image(GB_IMG *img, void *image)
delete (SDLsurface *)image;
}
static void check_modified(GB_IMG *img)
{
// Vérifie le flag modified
if (img->modified)
{
// Synchronize l'image image->texture
// Réinitialise le flag modified
img->modified = false;
}
}
static void *temp_image(GB_IMG *img)
{
SDLsurface *image;
@ -40,19 +52,23 @@ static void *temp_image(GB_IMG *img)
if (!img->data)
image = new SDLsurface();
else
{
// Pas besoin de faire de synchro image->texture, vu qu'on crée une nouvelle surface ?
image = new SDLsurface((char *)img->data, img->width, img->height);
}
image->SetAlphaBuffer(true);
return image;
}
static void lock_image(void *image)
static void sync_image(GB_IMG *image)
{
// Synchronize l'image texture->image
// Puis mets le flag de synchro à false
image->sync = false;
}
static void unlock_image(void *image, int changed)
{
}
static GB_IMG_OWNER _image_owner = {
"gb.sdl",
@ -60,13 +76,17 @@ static GB_IMG_OWNER _image_owner = {
free_image,
free_image,
temp_image,
lock_image,
unlock_image,
sync_image,
};
SDLsurface *CIMAGE_get(CIMAGE *_object)
{
return (SDLsurface *)IMAGE.Check(THIS_IMAGE, &_image_owner);
GB_IMG *img = THIS_IMAGE;
// Si ce n'est pas nécessaire de le faire systématiquement chaque fois qu'on a besoin de l'image,
// alors ne pas le faire ici, mais explicitement où c'est vraiment nécessaire.
check_modified(img);
return (SDLsurface *)IMAGE.Check(img, &_image_owner);
}
#define check_image CIMAGE_get

View file

@ -47,9 +47,6 @@ typedef
typedef
struct {
STREAM_CLASS *type;
char *buffer;
short buffer_pos;
short buffer_len;
short mode;
unsigned swap : 1;
unsigned eol : 2;
@ -65,6 +62,9 @@ typedef
#else
unsigned _reserved : 7;
#endif
short buffer_pos;
short buffer_len;
char *buffer;
}
PACKED
STREAM_COMMON;

View file

@ -31,6 +31,8 @@ static void get_info(GB_IMAGE img, uint **data, uint *width, uint *height, uint
{
GB_IMG *info = (GB_IMG *)img;
SYNCHRONIZE_IMAGE(info);
*data = (uint *)info->data;
if (width) *width = info->width;
if (height) *height = info->height;

View file

@ -68,6 +68,7 @@ QImage::QImage(GB_IMAGE image)
{
init();
img = (GB_IMG *)image;
SYNCHRONIZE_IMAGE(img);
getInfo();
}

View file

@ -74,7 +74,7 @@ public:
void reset() { };
void release();
void create(int w, int h, bool t);
GB_IMAGE object() { created = false; return (GB_IMAGE)img; }
GB_IMAGE object() { created = false; MODIFY_IMAGE(img); return (GB_IMAGE)img; }
int depth() const { return 32; }
int width() const { return img->width; }
int height() const { return img->height; }

View file

@ -70,8 +70,7 @@ typedef
void (*free)(struct GB_IMG *img, void *handle); // free owner handle
void (*release)(struct GB_IMG *img, void *handle); // free temporary handle
void *(*temp)(struct GB_IMG *img); // create a temporary handle for an image and returns it
void (*lock)(void *handle); // lock, before accessing pixels
void (*unlock)(void *handle, int changed); // unlock, after accessing pixels, indicate if image was changed
void (*sync)(struct GB_IMG *img); // synchronize the data. Called only if the GB_IMG.sync flag is set
}
GB_IMG_OWNER;
@ -88,6 +87,8 @@ typedef
void *owner_handle; // handle for the owner
GB_IMG_OWNER *temp_owner; // owner of the temporary handle that does not own the data
void *temp_handle; // temporary handle
unsigned modified : 1; // data has been modified by gb.image
unsigned sync : 1; // data must be synchronized by calling GB_IMG_OWNER.sync()
}
GB_IMG;
@ -129,6 +130,8 @@ typedef
void (*Take)(GB_IMG *img, GB_IMG_OWNER *owner, void *owner_handle, int width, int height, unsigned char *data);
// Create a temporary handle on the image without becoming the owner.
void *(*Check)(GB_IMG *img, GB_IMG_OWNER *temp_owner);
// Synchronize the image data if needed
void (*Synchronize)(GB_IMG *img);
// Return the size of the image data in bytes
int (*Size)(GB_IMG *img);
// Set the default format used when creating images
@ -150,6 +153,9 @@ typedef
#define GB_IMG_HANDLE(_image) ((_image)->temp_handle)
#define SYNCHRONIZE_IMAGE(_image) (IMAGE.Synchronize(_image))
#define MODIFY_IMAGE(_image) ((_image)->modified = 1)
#define COLOR_DEFAULT (-1)
#endif

View file

@ -141,22 +141,13 @@ static void free_image(GB_IMG *img, void *image)
GB.Free(POINTER(&img->data));
}
static void lock_image(void *image)
{
}
static void unlock_image(void *image, int changed)
{
}
static GB_IMG_OWNER _image_owner = {
"gb.image",
0,
free_image,
free_image,
NULL,
lock_image,
unlock_image,
NULL
};
@ -365,6 +356,9 @@ __PREMULTIPLIED:
}
}
#define SYNCHRONIZE(_img) ({ if ((_img)->sync) (*(_img)->temp_owner->sync)(_img); })
#define MODIFY(_img) ((_img)->modified = TRUE)
int IMAGE_size(GB_IMG *img)
{
return img->width * img->height * (GB_IMAGE_FMT_IS_24_BITS(img->format) ? 3 : 4);
@ -439,6 +433,8 @@ void *IMAGE_check(GB_IMG *img, GB_IMG_OWNER *temp_owner)
// If we are not the owner, then we will have to create the temporary handle ourself
else
{
// Synchronize the image if needed
SYNCHRONIZE(img);
// Conversion can make gb.image the new owner and temporary owner
IMAGE_convert(img, temp_owner->format);
img->temp_handle = (*temp_owner->temp)(img);
@ -495,6 +491,11 @@ void IMAGE_delete(GB_IMG *img)
img->format = 0;
}
void IMAGE_synchronize(GB_IMG *img)
{
SYNCHRONIZE(img);
}
#define GET_POINTER(_img, _p, _pm) \
uint *_p = (uint *)(_img)->data; \
uint *_pm = (uint *)GET_END_POINTER(_img);
@ -506,6 +507,8 @@ void IMAGE_fill(GB_IMG *img, GB_COLOR col)
col = from_GB_COLOR(col, img->format);
while (p != pm)
*p++ = col;
MODIFY(img);
}
// GB_IMAGE_RGB[APX] only
@ -515,6 +518,8 @@ void IMAGE_make_gray(GB_IMG *img)
uint col;
uchar g;
SYNCHRONIZE(img);
while (p != pm)
{
col = BGRA_from_format(*p, img->format);
@ -522,6 +527,8 @@ void IMAGE_make_gray(GB_IMG *img)
*p++ = BGRA_to_format(RGBA(g, g, g, ALPHA(col)), img->format);
}
MODIFY(img);
}
GB_COLOR IMAGE_get_pixel(GB_IMG *img, int x, int y)
@ -531,6 +538,7 @@ GB_COLOR IMAGE_get_pixel(GB_IMG *img, int x, int y)
if (!is_valid(img, x, y))
return (-1);
SYNCHRONIZE(img);
col = ((uint *)img->data)[y * img->width + x];
return to_GB_COLOR(col, img->format);
}
@ -540,7 +548,9 @@ void IMAGE_set_pixel(GB_IMG *img, int x, int y, GB_COLOR col)
if (!is_valid(img, x, y))
return;
SYNCHRONIZE(img);
((uint *)img->data)[y * img->width + x] = from_GB_COLOR(col, img->format);
MODIFY(img);
}
void IMAGE_fill_rect(GB_IMG *img, int x, int y, int w, int h, GB_COLOR col)
@ -558,6 +568,8 @@ void IMAGE_fill_rect(GB_IMG *img, int x, int y, int w, int h, GB_COLOR col)
if (w <= 0 || h <= 0) return;
SYNCHRONIZE(img);
c = from_GB_COLOR(col, img->format);
p = &((uint *)img->data)[y * img->width + x];
@ -568,6 +580,8 @@ void IMAGE_fill_rect(GB_IMG *img, int x, int y, int w, int h, GB_COLOR col)
h--;
p += img->width - w;
}
MODIFY(img);
}
void IMAGE_replace(GB_IMG *img, GB_COLOR src, GB_COLOR dst, bool noteq)
@ -577,6 +591,8 @@ void IMAGE_replace(GB_IMG *img, GB_COLOR src, GB_COLOR dst, bool noteq)
src = from_GB_COLOR(src, img->format);
dst = from_GB_COLOR(dst, img->format);
SYNCHRONIZE(img);
if (noteq)
{
while (p != pm)
@ -595,6 +611,8 @@ void IMAGE_replace(GB_IMG *img, GB_COLOR src, GB_COLOR dst, bool noteq)
p++;
}
}
MODIFY(img);
}
// Comes from the GIMP
@ -678,6 +696,8 @@ void IMAGE_make_transparent(GB_IMG *img, GB_COLOR col)
//fprintf(stderr, "IMAGE_make_transparent: %d x %d / %d\n", img->width, img->height, img->format);
SYNCHRONIZE(img);
color = from_GB_COLOR(col, img->format);
rgb_color.b = BLUE(color) / 255.0;
rgb_color.g = GREEN(color) / 255.0;
@ -706,6 +726,7 @@ void IMAGE_make_transparent(GB_IMG *img, GB_COLOR col)
p++;
}
MODIFY(img);
//fprintf(stderr, "IMAGE_make_transparent: ** DONE **\n");
}
@ -739,6 +760,9 @@ void IMAGE_bitblt(GB_IMG *dst, int dx, int dy, GB_IMG *src, int sx, int sy, int
if ( dy + sh > dst->height ) sh = dst->height - dy;
if ( sw <= 0 || sh <= 0 ) return; // Nothing left to copy
SYNCHRONIZE(src);
SYNCHRONIZE(dst);
if (GB_IMAGE_FMT_IS_32_BITS(src->format))
{
uint *d = (uint *)dst->data + dy * dst->width + dx;
@ -787,6 +811,8 @@ void IMAGE_bitblt(GB_IMG *dst, int dx, int dy, GB_IMG *src, int sx, int sy, int
s += ds;
}
}
MODIFY(dst);
}
void IMAGE_compose(GB_IMG *dst, int dx, int dy, GB_IMG *src, int sx, int sy, int sw, int sh)
@ -808,6 +834,9 @@ void IMAGE_compose(GB_IMG *dst, int dx, int dy, GB_IMG *src, int sx, int sy, int
if ( dy + sh > dst->height ) sh = dst->height - dy;
if ( sw <= 0 || sh <= 0 ) return;
SYNCHRONIZE(src);
SYNCHRONIZE(dst);
/*if ( src->hasAlphaBuffer() ) {
QRgb* d = (QRgb*)dst->scanLine(dy) + dx;
QRgb* s = (QRgb*)src->scanLine(sy) + sx;
@ -871,6 +900,8 @@ void IMAGE_compose(GB_IMG *dst, int dx, int dy, GB_IMG *src, int sx, int sy, int
break;
}
}
MODIFY(dst);
}
void IMAGE_colorize(GB_IMG *img, GB_COLOR color)
@ -881,6 +912,8 @@ void IMAGE_colorize(GB_IMG *img, GB_COLOR color)
int r, g, b;
int hcol, scol, vcol;
SYNCHRONIZE(img);
col = from_GB_COLOR(color, img->format);
COLOR_rgb_to_hsv(RED(col), GREEN(col), BLUE(col), &hcol, &scol, &vcol);
@ -891,6 +924,8 @@ void IMAGE_colorize(GB_IMG *img, GB_COLOR color)
COLOR_hsv_to_rgb(hcol, scol, v, &r, &g, &b);
*p++ = BGRA_to_format(RGBA(r, g, b, ALPHA(col)), img->format);
}
MODIFY(img);
}
void IMAGE_mask(GB_IMG *img, GB_COLOR color)
@ -900,6 +935,8 @@ void IMAGE_mask(GB_IMG *img, GB_COLOR color)
unsigned char red[256], blue[256], green[256], alpha[256];
int i, r, g, b, a;
SYNCHRONIZE(img);
col = from_GB_COLOR(color, img->format);
r = RED(col);
g = GREEN(col);
@ -919,6 +956,8 @@ void IMAGE_mask(GB_IMG *img, GB_COLOR color)
col = BGRA_from_format(*p, img->format);
*p++ = BGRA_to_format(RGBA(red[RED(col)], green[GREEN(col)], blue[BLUE(col)], alpha[ALPHA(col)]), img->format);
}
MODIFY(img);
}
void IMAGE_mirror(GB_IMG *src, GB_IMG *dst, bool horizontal, bool vertical)
@ -935,6 +974,8 @@ void IMAGE_mirror(GB_IMG *src, GB_IMG *dst, bool horizontal, bool vertical)
int dy = vertical ? (h - 1) : 0;
int sx, sy;
SYNCHRONIZE(src);
if (GB_IMAGE_FMT_IS_24_BITS(src->format))
{
for (sy = 0; sy < h; sy++, dy += dyi)
@ -957,6 +998,8 @@ void IMAGE_mirror(GB_IMG *src, GB_IMG *dst, bool horizontal, bool vertical)
dsl[dx] = ssl[sx];
}
}
MODIFY(dst);
}
#if 0

View file

@ -38,6 +38,7 @@ void IMAGE_create(GB_IMG *img, int width, int height, int format);
void IMAGE_create_with_data(GB_IMG *img, int width, int height, int format, unsigned char *data);
void IMAGE_take(GB_IMG *img, GB_IMG_OWNER *owner, void *owner_handle, int width, int height, unsigned char *data);
void *IMAGE_check(GB_IMG *img, GB_IMG_OWNER *temp_owner);
void IMAGE_synchronize(GB_IMG *img);
void IMAGE_delete(GB_IMG *img);
void IMAGE_convert(GB_IMG *img, int format);
void IMAGE_fill(GB_IMG *img, GB_COLOR col);

View file

@ -58,6 +58,7 @@ void *GB_IMAGE_1[] EXPORT =
(void *)create_image,
(void *)IMAGE_take,
(void *)IMAGE_check,
(void *)IMAGE_synchronize,
(void *)IMAGE_size,
(void *)IMAGE_set_default_format,
(void *)IMAGE_get_default_format,