forked from old/legacy-imlib2
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:
parent
bc0b2d2f28
commit
bc86f38d1a
237
api.c
237
api.c
|
@ -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
73
blend.c
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
|
8
blend.h
8
blend.h
|
@ -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
|
||||
|
|
29
loader_png.c
29
loader_png.c
|
@ -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
12
main.c
|
@ -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
3
rend.c
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue