ooh is imlib2 ever workign fast now baybeee.. blending one image onto

another .. with clipping, scaling, anti-aliasing and more.. need to add
a bit to the api, and move the stuff nowin api.c off into imlib backend
sinc ethat stuff doesnt belong in api.c


SVN revision: 227
This commit is contained in:
Carsten Haitzler 1999-09-10 02:33:11 +00:00
parent bc0b2d2f28
commit bc86f38d1a
6 changed files with 328 additions and 34 deletions

237
api.c
View File

@ -227,7 +227,10 @@ imlib_image_set_has_alpha(Imlib_Image image, char has_alpha)
ImlibImage *im;
CAST_IMAGE(im, image);
UNSET_FLAG(im->flags, F_HAS_ALPHA);
if (has_alpha)
SET_FLAG(im->flags, F_HAS_ALPHA);
else
UNSET_FLAG(im->flags, F_HAS_ALPHA);
}
void
@ -325,6 +328,14 @@ imlib_render_image_on_drawable_at_size(Imlib_Image image, Display *display,
cm);
}
#define LINESIZE 16
/* useful macro */
#define CLIP(x, y, w, h, xx, yy, ww, hh) \
if (x < xx) {w += x; x = xx;} \
if (y < yy) {h += y; y = xx;} \
if ((x + w) > ww) {w = ww - x;} \
if ((y + h) > hh) {h = hh - y;}
void
imlib_blend_image_onto_image(Imlib_Image source_image,
Imlib_Image destination_image,
@ -334,27 +345,219 @@ imlib_blend_image_onto_image(Imlib_Image source_image,
int destination_width, int destination_height)
{
ImlibImage *im_src, *im_dst;
int sx, sy, sw, sh, dx, dy, dw, dh, sj, dj;
char anitalias = 1;
CAST_IMAGE(im_src, source_image);
CAST_IMAGE(im_dst, destination_image);
/* FIXME: doesnt do clipping in any way or form - must fix */
sx = source_x;
sy = source_y;
sw = source_width;
sh = source_height;
dx = destination_x;
dy = destination_y;
dw = destination_width;
dh = destination_height;
if (IMAGE_HAS_ALPHA(im_dst))
__imlib_BlendRGBAToRGBA(im_src->data, 0, im_dst->data, 0,
source_width, source_height);
else
__imlib_BlendRGBAToRGB(im_src->data, 0, im_dst->data, 0,
source_width, source_height);
if ((source_width == destination_width) &&
(source_height == destination_height))
{
if (IMAGE_HAS_ALPHA(im_dst))
__imlib_BlendRGBAToData(im_src->data, im_src->w, im_src->h,
im_dst->data, im_dst->w, im_dst->h,
source_x, source_y,
destination_x, destination_y,
source_width, source_height, 1);
else
__imlib_BlendRGBAToData(im_src->data, im_src->w, im_src->h,
im_dst->data, im_dst->w, im_dst->h,
source_x, source_y,
destination_x, destination_y,
source_width, source_height, 0);
}
else
{
DATA32 **ypoints = NULL;
int *xpoints = NULL;
int *yapoints = NULL;
int *xapoints = NULL;
DATA32 *buf = NULL;
int sx, sy, sw, sh, dx, dy, dw, dh, dxx, dyy, scw, sch, y2, x2;
int psx, psy, psw, psh;
char xup = 0, yup = 0;
int y, h, hh;
sx = source_x;
sy = source_x;
sw = source_width;
sh = source_height;
dx = destination_x;
dy = destination_y;
dw = destination_width;
dh = destination_height;
/* dont do anything if we have a 0 widht or height image to render */
/* if the input rect size < 0 dont render either */
if ((dw <= 0) || (dh <= 0) || (sw <= 0) || (sh <= 0))
return;
/* if the output is too big (8k arbitary limit here) dont bother */
if ((dw > 8192) || (dh > 8192))
return;
/* clip the source rect to be within the actual image */
psx = sx;
psy = sy;
psw = sw;
psh = sh;
CLIP(sx, sy, sw, sh, 0, 0, im_src->w, im_src->h);
/* clip output coords to clipped input coords */
if (psx != sx)
dx += ((sx - psx) * destination_width) / source_width;
if (psy != sy)
dy += ((sy - psy) * destination_height) / source_height;
if (psw != sw)
dw = (dw * sw) / psw;
if (psh != sh)
dh = (dh * sh) / psh;
if ((dw <= 0) || (dh <= 0) || (sw <= 0) || (sh <= 0))
return;
psx = dx;
psy = dy;
psw = dw;
psh = dh;
x2 = sx;
y2 = sy;
CLIP(dx, dy, dw, dh, 0, 0, im_dst->w, im_dst->h);
if ((dw <= 0) || (dh <= 0) || (sw <= 0) || (sh <= 0))
return;
if (psx != dx)
sx += ((dx - psx) * source_width) / destination_width;
if (psy != dy)
sy += ((dy - psy) * source_height) / destination_height;
if (psw != dw)
sw = (sw * dw) / psw;
if (psh != dh)
sh = (sh * dh) / psh;
dxx = dx - psx;
dyy = dy - psy;
dxx += (x2 * destination_width) / source_width;
dyy += (y2 * destination_width) / source_width;
/* do a second check to see if we now have invalid coords */
/* dont do anything if we have a 0 widht or height image to render */
/* if the input rect size < 0 dont render either */
if ((dw <= 0) || (dh <= 0) || (sw <= 0) || (sh <= 0))
return;
/* if the output is too big (8k arbitary limit here) dont bother */
if ((dw > 8192) || (dh > 8192))
return;
/* calculate the scaling factors of width and height for a whole image */
scw = (destination_width * im_src->w) / source_width;
sch = (destination_height * im_src->h) / source_height;
/* if we are scaling the image at all make a scaling buffer */
if (!((sw == dw) && (sh == dh)))
{
/* need to calculate ypoitns and xpoints array */
ypoints = __imlib_CalcYPoints(im_src->data, im_src->w, im_src->h,
sch, im_src->border.top,
im_src->border.bottom);
if (!ypoints)
return;
xpoints = __imlib_CalcXPoints(im_src->w, scw,
im_src->border.left,
im_src->border.right);
if (!xpoints)
{
free(ypoints);
return;
}
/* calculate aliasing counts */
if (anitalias)
{
yapoints = __imlib_CalcApoints(im_src->h, sch,
im_src->border.top,
im_src->border.bottom);
if (!yapoints)
{
free(ypoints);
free(xpoints);
return;
}
xapoints = __imlib_CalcApoints(im_src->w, scw,
im_src->border.left,
im_src->border.right);
if (!xapoints)
{
free(yapoints);
free(ypoints);
free(xpoints);
return;
}
}
}
/* if we are scaling the image at all make a scaling buffer */
/* allocate a buffer to render scaled RGBA data into */
buf = malloc(dw * LINESIZE * sizeof(DATA32));
if (!buf)
{
if (anitalias)
{
free(xapoints);
free(yapoints);
}
free(ypoints);
free(xpoints);
return;
}
/* setup h */
h = dh;
/* set our scaling up in x / y dir flags */
if (dw > sw)
xup = 1;
if (dh > sh)
yup = 1;
/* scale in LINESIZE Y chunks and convert to depth*/
for (y = 0; y < dh; y += LINESIZE)
{
hh = LINESIZE;
if (h < LINESIZE)
hh = h;
/* scale the imagedata for this LINESIZE lines chunk of image data */
if (anitalias)
{
if (IMAGE_HAS_ALPHA(im_src))
__imlib_ScaleAARGBA(ypoints, xpoints, buf, xapoints,
yapoints, xup, yup, dxx, dyy + y,
0, 0, dw, hh, dw, im_src->w);
else
__imlib_ScaleAARGB(ypoints, xpoints, buf, xapoints,
yapoints, xup, yup, dxx, dyy + y,
0, 0, dw, hh, dw, im_src->w);
}
else
__imlib_ScaleSampleRGBA(ypoints, xpoints, buf, dxx, dyy + y,
0, 0, dw, hh, dw);
if (IMAGE_HAS_ALPHA(im_src))
{
if (IMAGE_HAS_ALPHA(im_dst))
__imlib_BlendRGBAToData(buf, dw, hh,
im_dst->data, im_dst->w, im_dst->h,
0, 0, dx, dy + y, dw, dh, 1);
else
__imlib_BlendRGBAToData(buf, dw, hh,
im_dst->data, im_dst->w, im_dst->h,
0, 0, dx, dy + y, dw, dh, 0);
}
else
__imlib_BlendRGBAToData(buf, dw, hh,
im_dst->data, im_dst->w, im_dst->h,
0, 0, dx, dy + y, dw, dh, 2);
/* FIXME: have to add code to generate mask if asked for */
h -= LINESIZE;
}
/* free up our buffers and poit tables */
if (buf)
{
free(buf);
free(ypoints);
free(xpoints);
}
if (anitalias)
{
free(yapoints);
free(xapoints);
}
}
}
Imlib_Image

73
blend.c
View File

@ -1,6 +1,58 @@
#include "common.h"
#include "blend.h"
void
__imlib_BlendRGBAToData(DATA32 *src, int src_w, int src_h, DATA32 *dst,
int dst_w, int dst_h, int sx, int sy, int dx, int dy,
int w, int h, char dalpha)
{
if (sx < 0)
{
w += sx;
dx -= sx;
sx = 0;
}
if (sy < 0)
{
h += sy;
dy -= sy;
sy = 0;
}
if (dx < 0)
{
w += dx;
sx -= dx;
dx = 0;
}
if (dy < 0)
{
h += dy;
sy -= dy;
dy = 0;
}
if ((w <= 0) || (h <= 0))
return;
if ((sx + w) > src_w)
w = src_w - sx;
if ((sy + h) > src_h)
h = src_h - sy;
if ((dx + w) > dst_w)
w = dst_w - dx;
if ((dy + h) > dst_h)
h = dst_h - dy;
if ((w <= 0) || (h <= 0))
return;
if (dalpha == 1)
__imlib_BlendRGBAToRGBA(src + (sy * src_w) + sx, src_w - w,
dst + (dy * dst_w) + dx, dst_w - w, w, h);
else if (dalpha == 0)
__imlib_BlendRGBAToRGB(src + (sy * src_w) + sx, src_w - w,
dst + (dy * dst_w) + dx, dst_w - w, w, h);
else if (dalpha == 2)
__imlib_CopyRGBAToRGBA(src + (sy * src_w) + sx, src_w - w,
dst + (dy * dst_w) + dx, dst_w - w, w, h);
}
void
__imlib_BlendRGBAToRGB(DATA32 *src, int src_jump, DATA32 *dst, int dst_jump,
int w, int h)
@ -22,6 +74,7 @@ __imlib_BlendRGBAToRGB(DATA32 *src, int src_jump, DATA32 *dst, int dst_jump,
{
/* funny - i cant tell much of a speed diff between these 2 */
#if 0
/* this one over time leads to rounding errors :( */
r = 255 - a;
*p2 =
((((*p1 & 0x00ff00ff) * a) >> 8) & 0x00ff00ff) +
@ -29,6 +82,7 @@ __imlib_BlendRGBAToRGB(DATA32 *src, int src_jump, DATA32 *dst, int dst_jump,
((((*p2 & 0x00ff00ff) * r) >> 8) & 0x00ff00ff) +
((((*p2 >> 8) & 0x00ff00ff) * r) & 0xff00ff00);
#else
/* this is more accurate - but slower ? doesnt seem to be :) */
b = (*p1 ) & 0xff;
g = (*p1 >> 8 ) & 0xff;
r = (*p1 >> 16) & 0xff;
@ -100,3 +154,22 @@ __imlib_BlendRGBAToRGBA(DATA32 *src, int src_jump, DATA32 *dst, int dst_jump,
}
}
}
void
__imlib_CopyRGBAToRGBA(DATA32 *src, int src_jump, DATA32 *dst, int dst_jump,
int w, int h)
{
int x, y;
DATA32 *p1, *p2;
for (y = 0; y < h; y++)
{
DATA8 a, nr, ng, nb, r, g, b, rr, gg, bb, aa, na;
int tmp;
p1 = src + (y * (w + src_jump));
p2 = dst + (y * (w + dst_jump));
for (x = 0; x < w; x++)
*p2++ = *p1++;
}
}

View File

@ -1,9 +1,17 @@
#ifndef __BLEND
#define __BLEND 1
void
__imlib_BlendRGBAToData(DATA32 *src, int src_w, int src_h, DATA32 *dst,
int dst_w, int dst_h, int sx, int sy, int dx, int dy,
int w, int h, char dalpha);
void
__imlib_BlendRGBAToRGB(DATA32 *src, int src_jump, DATA32 *dst, int dst_jump,
int w, int h);
void
__imlib_BlendRGBAToRGBA(DATA32 *src, int src_jump, DATA32 *dst, int dst_jump,
int w, int h);
void
__imlib_CopyRGBAToRGBA(DATA32 *src, int src_jump, DATA32 *dst, int dst_jump,
int w, int h);
#endif

View File

@ -23,7 +23,7 @@
#define PNG_BYTES_TO_CHECK 4
static void *
_load_PNG (int *ww, int *hh, FILE *f)
_load_PNG (int *ww, int *hh, FILE *f, char *hasa)
{
png_structp png_ptr;
png_infop info_ptr;
@ -63,14 +63,19 @@ _load_PNG (int *ww, int *hh, FILE *f)
png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *)(&w), (png_uint_32 *)(&h),
&bit_depth, &color_type, &interlace_type,
NULL, NULL);
/* Palette -> RGB */
if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
png_set_expand(png_ptr);
/* Palette -> RGB */
if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
{
png_set_expand(png_ptr);
*hasa = 1;
}
else
*hasa = 0;
/* we want ARGB */
png_set_bgr(png_ptr);
/* 16bit color -> 8bit color */
png_set_strip_16(png_ptr);
/* pack all pixels to byte boundaires */
png_set_strip_16(png_ptr);
/* pack all pixels to byte boundaires */
png_set_packing(png_ptr);
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
png_set_expand(png_ptr);
@ -89,13 +94,13 @@ _load_PNG (int *ww, int *hh, FILE *f)
}
DATA32 *
RGBA_Load(char *file, int *w, int *h)
RGBA_Load(char *file, int *w, int *h, char *hasa)
{
FILE *f;
DATA32 *data;
f = fopen(file, "r" FOPEN_BINARY_FLAG);
data = (DATA32 *)_load_PNG(w, h, f);
data = (DATA32 *)_load_PNG(w, h, f, hasa);
fclose(f);
return data;
}
@ -109,6 +114,7 @@ load (ImlibImage *im,
{
int w, h;
DATA32 *data;
char hasa = 0;
/* if immediate_load is 1, then dont delay image laoding as below, or */
/* already data in this image - dont load it again */
@ -131,11 +137,14 @@ load (ImlibImage *im,
/* should be decoded on the first phase. The loader, if it does this */
/* shoudl ignore the image laod if the data memebr is not NULL */
/* the below code for now just does a one phase load */
data = RGBA_Load(im->file, &w, &h);
data = RGBA_Load(im->file, &w, &h, &hasa);
if (data)
{
im->data = data;
SET_FLAG(im->flags, F_HAS_ALPHA);
if (hasa)
SET_FLAG(im->flags, F_HAS_ALPHA);
else
UNSET_FLAG(im->flags, F_HAS_ALPHA);
/* setting the width to somthign > 0 means you managed to load */
/* the image */
im->w = w;

12
main.c
View File

@ -136,13 +136,15 @@ int main (int argc, char **argv)
XQueryPointer(disp, win, &rt, &rt, &x, &y,
&dum, &dum, &dui);
imlib_copy_drawable_to_image(im2, disp, win, 0, vis,
DefaultColormap(disp, DefaultScreen(disp)),
depth, x - (w / 2), y - (h / 2), w, h,
x - w, y - h, 0);
imlib_blend_image_onto_image(im, im2,
0, 0, w, h,
x - (w / 2), y - (h / 2),
x * 2, y * 2);
imlib_render_image_on_drawable(im2, disp, win, vis,
DefaultColormap(disp, DefaultScreen(disp)),
depth, dith, 0, 1700, 100, NULL);
depth, dith, 1, 1700, 100, NULL);
}
}
else

3
rend.c
View File

@ -167,7 +167,7 @@ __imlib_RenderImage(Display *d, ImlibImage *im,
if (!((sw == dw) && (sh == dh)))
{
/* allocate a buffer to render scaled RGBA data into */
buf = malloc(dw * LINESIZE * sizeof(int));
buf = malloc(dw * LINESIZE * sizeof(DATA32));
if (!buf)
{
__imlib_ConsumeXImage(d, xim);
@ -377,7 +377,6 @@ __imlib_RenderImage(Display *d, ImlibImage *im,
(mxim->bytes_per_line) - (dw >> 3),
dw, hh, dx, dy + y);
}
/* FIXME: have to add code to generate mask if asked for */
h -= LINESIZE;
}
/* free up our buffers and poit tables */