1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-19 12:28:22 +01:00

changed format of RImage, added x86 speicfic optimized code

This commit is contained in:
kojima
2000-01-14 16:39:15 +00:00
parent f2de1c9dcf
commit a30475fc0f
23 changed files with 1527 additions and 1324 deletions

View File

@@ -4,7 +4,7 @@ AUTOMAKE_OPTIONS = no-dependencies
lib_LTLIBRARIES = libwraster.la lib_LTLIBRARIES = libwraster.la
libwraster_la_LDFLAGS = -version-info 4:0:3 libwraster_la_LDFLAGS = -version-info 5:0:0
bin_SCRIPTS = get-wraster-flags bin_SCRIPTS = get-wraster-flags
@@ -28,6 +28,7 @@ libwraster_la_SOURCES = \
gradient.c \ gradient.c \
xpixmap.c \ xpixmap.c \
convert.c \ convert.c \
x86_specific.c \
context.c \ context.c \
misc.c \ misc.c \
scale.c \ scale.c \
@@ -42,6 +43,17 @@ libwraster_la_SOURCES = \
gif.c gif.c
# cant compile asm stuff with optimizations
x86_specific.lo: x86_specific.c
$(LTCOMPILE) -O0 -c $<
x86_specific.o: x86_specific.c
$(COMPILE) -O0 -c $<
INCLUDES = @DFLAGS@ @HEADER_SEARCH_PATH@ INCLUDES = @DFLAGS@ @HEADER_SEARCH_PATH@
LIBLIST = $(top_builddir)/wrlib/libwraster.la @LIBRARY_SEARCH_PATH@ @GFXLIBS@ @XLIBS@ -lm LIBLIST = $(top_builddir)/wrlib/libwraster.la @LIBRARY_SEARCH_PATH@ @GFXLIBS@ @XLIBS@ -lm

View File

@@ -97,7 +97,7 @@ AUTOMAKE_OPTIONS = no-dependencies
lib_LTLIBRARIES = libwraster.la lib_LTLIBRARIES = libwraster.la
libwraster_la_LDFLAGS = -version-info 4:0:3 libwraster_la_LDFLAGS = -version-info 5:0:0
bin_SCRIPTS = get-wraster-flags bin_SCRIPTS = get-wraster-flags
@@ -106,7 +106,7 @@ noinst_PROGRAMS = testgrad testdraw view
EXTRA_DIST = test.png tile.xpm ballot_box.xpm EXTRA_DIST = test.png tile.xpm ballot_box.xpm
include_HEADERS = wraster.h include_HEADERS = wraster.h
libwraster_la_SOURCES = LookupCmap.c StdCmap.c StdCmap.h CrCmap.c DelCmap.c CmapAlloc.c raster.c draw.c color.c load.c save.c gradient.c xpixmap.c convert.c context.c misc.c scale.c convolve.c nxpm.c xpm.c xutil.c ppm.c png.c jpeg.c tiff.c gif.c libwraster_la_SOURCES = LookupCmap.c StdCmap.c StdCmap.h CrCmap.c DelCmap.c CmapAlloc.c raster.c draw.c color.c load.c save.c gradient.c xpixmap.c convert.c x86_specific.c context.c misc.c scale.c convolve.c nxpm.c xpm.c xutil.c ppm.c png.c jpeg.c tiff.c gif.c
INCLUDES = @DFLAGS@ @HEADER_SEARCH_PATH@ INCLUDES = @DFLAGS@ @HEADER_SEARCH_PATH@
@@ -142,8 +142,9 @@ X_PRE_LIBS = @X_PRE_LIBS@
libwraster_la_DEPENDENCIES = @ALLOCA@ libwraster_la_DEPENDENCIES = @ALLOCA@
libwraster_la_OBJECTS = LookupCmap.lo StdCmap.lo CrCmap.lo DelCmap.lo \ libwraster_la_OBJECTS = LookupCmap.lo StdCmap.lo CrCmap.lo DelCmap.lo \
CmapAlloc.lo raster.lo draw.lo color.lo load.lo save.lo gradient.lo \ CmapAlloc.lo raster.lo draw.lo color.lo load.lo save.lo gradient.lo \
xpixmap.lo convert.lo context.lo misc.lo scale.lo convolve.lo nxpm.lo \ xpixmap.lo convert.lo x86_specific.lo context.lo misc.lo scale.lo \
xpm.lo xutil.lo ppm.lo png.lo jpeg.lo tiff.lo gif.lo convolve.lo nxpm.lo xpm.lo xutil.lo ppm.lo png.lo jpeg.lo tiff.lo \
gif.lo
PROGRAMS = $(noinst_PROGRAMS) PROGRAMS = $(noinst_PROGRAMS)
testgrad_OBJECTS = testgrad.o testgrad_OBJECTS = testgrad.o
@@ -434,6 +435,13 @@ mostlyclean-generic distclean-generic clean-generic \
maintainer-clean-generic clean mostlyclean distclean maintainer-clean maintainer-clean-generic clean mostlyclean distclean maintainer-clean
# cant compile asm stuff with optimizations
x86_specific.lo: x86_specific.c
$(LTCOMPILE) -O0 -c $<
x86_specific.o: x86_specific.c
$(COMPILE) -O0 -c $<
# Tell versions [3.59,3.63) of GNU make to not export all variables. # Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded. # Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT: .NOEXPORT:

View File

@@ -448,6 +448,8 @@ setupPseudoColorColormap(RContext *context)
*context->std_rgb_map = maps[theMap]; *context->std_rgb_map = maps[theMap];
context->cmap = context->std_rgb_map->colormap;
XFree(maps); XFree(maps);
return True; return True;
@@ -510,6 +512,14 @@ gatherconfig(RContext *context, int screen_n)
context->attribs->colors_per_channel = i; context->attribs->colors_per_channel = i;
} }
} }
ptr = mygetenv("WRASTER_OPTIMIZE_FOR_SPEED", screen_n);
if (ptr) {
context->flags.optimize_for_speed = 1;
} else {
context->flags.optimize_for_speed = 0;
}
} }
@@ -601,9 +611,9 @@ RCreateContext(Display *dpy, int screen_number, RContextAttributes *attribs)
/* get configuration from environment variables */ /* get configuration from environment variables */
gatherconfig(context, screen_number); gatherconfig(context, screen_number);
#ifndef BENCH
_wraster_change_filter(context->attribs->scaling_filter); _wraster_change_filter(context->attribs->scaling_filter);
#endif
if ((context->attribs->flags & RC_VisualID)) { if ((context->attribs->flags & RC_VisualID)) {
XVisualInfo *vinfo, templ; XVisualInfo *vinfo, templ;
int nret; int nret;

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
/* /*
* Raster graphics library * Raster graphics library
* *
* Copyright (c) 1997 Alfredo K. Kojima * Copyright (c) 1997-2000 Alfredo K. Kojima
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public
@@ -20,23 +20,6 @@
#include <config.h> #include <config.h>
/* AIX requires this to be the first thing in the file. */
#ifdef __GNUC__
# define alloca __builtin_alloca
#else
# if HAVE_ALLOCA_H
# include <alloca.h>
# else
# ifdef _AIX
# pragma alloca
# else
# ifndef alloca /* predefined by HP cc +Olibcalls */
char *alloca ();
# endif
# endif
# endif
#endif
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
@@ -57,84 +40,92 @@ int
RBlurImage(RImage *image) RBlurImage(RImage *image)
{ {
register int x, y; register int x, y;
register int w, tmp; register int tmp;
unsigned char *r, *g, *b, *a; unsigned char *ptr, *nptr;
unsigned char *pr=NULL, *pg=NULL, *pb=NULL, *pa=NULL; unsigned char *pptr=NULL, *tmpp;
int ch = image->format == RRGBAFormat ? 4 : 3;
#define MASK(c,pc,p) ((*c+ *c + *(c-1) + *(c+1) + pc[p] + pc[p-1] + pc[p+1] \ pptr = malloc(image->width * ch);
+ *(c+w) + *(c+w-1) + *(c+w+1))/10) if (!pptr) {
RErrorCode = RERR_NOMEMORY;
pr = (unsigned char*)alloca(image->width*sizeof(char)); return False;
if (!pr)
goto outofmem;
pg = (unsigned char*)alloca(image->width*sizeof(char));
if (!pg)
goto outofmem;
pb = (unsigned char*)alloca(image->width*sizeof(char));
if (!pb)
goto outofmem;
pa = (unsigned char*)alloca(image->width*sizeof(char));
if (!pa)
goto outofmem;
r = image->data[0];
g = image->data[1];
b = image->data[2];
a = image->data[3];
for (x=0; x<image->width; x++) {
pr[x] = *(r++);
pg[x] = *(g++);
pb[x] = *(b++);
} }
w = image->width; #define MASK(prev, cur, next, ch)\
(*(prev-ch) + *prev + *(prev+ch)\
+*(cur-ch) + 2 * *cur + *(cur+ch)\
+*(next-ch) + *next + *(next+ch)) / 10
memcpy(pptr, image->data, image->width * ch);
ptr = image->data;
nptr = ptr + image->width*ch;
tmpp = pptr;
if (ch == 3) {
ptr+=3;
nptr+=3;
pptr+=3;
for (y = 1; y < image->height-1; y++) { for (y = 1; y < image->height-1; y++) {
pr[w-1] = r[w-1];
pg[w-1] = g[w-1];
pb[w-1] = b[w-1];
pr[0] = *(r++);
pg[0] = *(g++);
pb[0] = *(b++);
for (x = 1; x < image->width-1; x++) { for (x = 1; x < image->width-1; x++) {
tmp = *r; tmp = *ptr;
*(r++) = MASK(r,pr,x); *ptr = MASK(pptr, ptr, nptr, 3);
pr[x] = tmp; *pptr = tmp;
ptr++; nptr++; pptr++;
tmp = *g; tmp = *ptr;
*(g++) = MASK(g,pg,x); *ptr = MASK(pptr, ptr, nptr, 3);
pg[x] = tmp; *pptr = tmp;
ptr++; nptr++; pptr++;
tmp = *b; tmp = *ptr;
*(b++) = MASK(b,pb,x); *ptr = MASK(pptr, ptr, nptr, 3);
pb[x] = tmp; *pptr = tmp;
ptr++; nptr++; pptr++;
}
pptr = tmpp;
ptr+=6;
nptr+=6;
pptr+=6;
}
} else {
ptr+=4;
nptr+=4;
pptr+=4;
for (y = 1; y < image->height-1; y++) {
for (x = 1; x < image->width-1; x++) {
tmp = *ptr;
*ptr = MASK(pptr, ptr, nptr, 4);
*pptr = tmp;
ptr++; nptr++; pptr++;
tmp = *ptr;
*ptr = MASK(pptr, ptr, nptr, 4);
*pptr = tmp;
ptr++; nptr++; pptr++;
tmp = *ptr;
*ptr = MASK(pptr, ptr, nptr, 4);
*pptr = tmp;
ptr++; nptr++; pptr++;
tmp = *ptr;
*ptr = MASK(pptr, ptr, nptr, 4);
*pptr = tmp;
ptr++; nptr++; pptr++;
}
pptr = tmpp;
ptr+=8;
nptr+=8;
pptr+=8;
} }
r++;
g++;
b++;
} }
#undef MASK
#ifdef C_ALLOCA
alloca(0);
#endif
return True; return True;
outofmem:
RErrorCode = RERR_NOMEMORY;
#ifdef C_ALLOCA
alloca(0);
#endif
return False;
} }
@@ -273,47 +264,45 @@ RSmoothImage(RImage *image)
{ {
register int x, y; register int x, y;
register int v, w; register int v, w;
unsigned char *r, *g, *b, *a; unsigned char *ptr;
int ch = image->format == RRGBAFormat;
r = image->data[0]; ptr = image->data;
g = image->data[1];
b = image->data[2];
a = image->data[3];
w = image->width;
w = image->width*ch;
for (y=0; y<image->height - 1; y++) { for (y=0; y<image->height - 1; y++) {
for (x=0; x<image->width - 1; x++) { for (x=0; x<image->width - 1; x++) {
v = *r + 2 * *(r + 1) + 2 * *(r + w) + *(r + w + 1); v = *ptr + 2 * *(ptr + ch) + 2 * *(ptr + w) + *(ptr + w + ch);
*(r++) = v/6; *ptr = v/6;
v = *(ptr+1) + 2 * *(ptr+1 + ch) + 2 * *(ptr+1 + w) + *(ptr+1 + w + ch);
*(ptr+1) = v/6;
v = *ptr + 2 * *(ptr+2 + ch) + 2 * *(ptr+2 + w) + *(ptr+2 + w + ch);
*(ptr+2) = v/6;
v = *g + 2 * *(g + 1) + 2 * *(g + w) + *(g + w + 1); ptr+= ch;
*(g++) = v/6;
v = *b + 2 * *(b + 1) + 2 * *(b + w) + *(b + w + 1);
*(b++) = v/6;
} }
/* last column */ /* last column */
v = 3 * *r + 3 * *(r + w); v = 3 * *ptr + 3 * *(ptr + w);
*(r++) = v/6; *ptr = v/6;
v = 3 * *ptr + 3 * *(ptr+1 + w);
*(ptr+1) = v/6;
v = 3 * *ptr + 3 * *(ptr+2 + w);
*(ptr+2) = v/6;
v = 3 * *g + 3 * *(g + w); ptr+= ch;
*(g++) = v/6;
v = 3 * *b + 3 * *(b + w);
*(b++) = v/6;
} }
/* last line */ /* last line */
for (x=0; x<image->width - 1; x++) { for (x=0; x<image->width - 1; x++) {
v = 3 * *r + 3 * *(r + 1); v = 3 * *ptr + 3 * *(ptr + ch);
*(r++) = v/6; *ptr = v/6;
v = 3 * *(ptr+1) + 3 * *(ptr+1 + ch);
*(ptr+1) = v/6;
v = 3 * *(ptr+2) + 3 * *(ptr+2 + ch);
*(ptr+2) = v/6;
v = 3 * *g + 3 * *(g + 1); ptr+= ch;
*(g++) = v/6;
v = 3 * *b + 3 * *(b + 1);
*(b++) = v/6;
} }
return True; return True;

View File

@@ -3,6 +3,7 @@
* Raster graphics library * Raster graphics library
* *
* Copyright (c) 1998 Dan Pascu * Copyright (c) 1998 Dan Pascu
* Copyright (c) 2000 Alfredo K. Kojima
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public
@@ -46,15 +47,20 @@ RGetPixel(RImage *image, int x, int y, RColor *color)
|| y < 0 || y >= image->height) || y < 0 || y >= image->height)
return False; return False;
ofs = y*image->width + x; if (image->format == RRGBAFormat) {
color->red = image->data[0][ofs]; ofs = (y*image->width + x) * 4;
color->green = image->data[1][ofs]; color->red = image->data[ofs];
color->blue = image->data[2][ofs]; color->green = image->data[ofs++];
color->blue = image->data[ofs++];
color->alpha = image->data[ofs];
} else {
ofs = (y*image->width + x) * 3;
color->red = image->data[ofs++];
color->green = image->data[ofs++];
color->blue = image->data[ofs++];
/* If the image does not have alpha channel, we consider alpha 255 */ /* If the image does not have alpha channel, we consider alpha 255 */
if (image->data[3])
color->alpha = image->data[3][ofs];
else
color->alpha = 255; color->alpha = 255;
}
return True; return True;
} }
@@ -63,26 +69,26 @@ RGetPixel(RImage *image, int x, int y, RColor *color)
void void
RPutPixel(RImage *image, int x, int y, RColor *color) RPutPixel(RImage *image, int x, int y, RColor *color)
{ {
int ofs; unsigned char *ptr;
unsigned char *sr, *sg, *sb, *sa;
assert(image!=NULL); assert(image!=NULL);
assert(color!=NULL); assert(color!=NULL);
if (x < 0 || x >= image->width || y < 0 || y >= image->height) if (x < 0 || x >= image->width || y < 0 || y >= image->height)
return; return;
ofs = y*image->width + x; if (image->format == RRGBAFormat) {
sr = image->data[0] + ofs; ptr = image->data + (y*image->width + x) * 4;
sg = image->data[1] + ofs; } else {
sb = image->data[2] + ofs; ptr = image->data + (y*image->width + x) * 3;
sa = image->data[3] + ofs; }
if (color->alpha==255) { if (color->alpha==255) {
*sr = color->red; *ptr++ = color->red;
*sg = color->green; *ptr++ = color->green;
*sb = color->blue; *ptr++ = color->blue;
if (image->data[3]) if (image->format == RRGBAFormat) {
*sa = 255; *ptr = 255;
}
} else { } else {
register int alpha, nalpha, r, g, b; register int alpha, nalpha, r, g, b;
@@ -92,11 +98,12 @@ RPutPixel(RImage *image, int x, int y, RColor *color)
alpha = color->alpha; alpha = color->alpha;
nalpha = 255 - alpha; nalpha = 255 - alpha;
*sr = (((int)*sr * nalpha) + (r * alpha))/256; *ptr++ = (((int)*ptr * nalpha) + (r * alpha))/256;
*sg = (((int)*sg * nalpha) + (g * alpha))/256; *ptr++ = (((int)*ptr * nalpha) + (g * alpha))/256;
*sb = (((int)*sb * nalpha) + (b * alpha))/256; *ptr++ = (((int)*ptr * nalpha) + (b * alpha))/256;
if (image->data[3]) if (image->format == RRGBAFormat) {
*sa = alpha + ((int)*sa * nalpha)/256; *ptr = alpha + ((int)*ptr * nalpha)/256;
}
} }
} }
@@ -106,15 +113,15 @@ operatePixel(RImage *image, int ofs, int operation, RColor *color)
{ {
unsigned char *sr, *sg, *sb, *sa; unsigned char *sr, *sg, *sb, *sa;
register int alpha, nalpha, tmp; register int alpha, nalpha, tmp;
int hasAlpha = image->data[3]!=NULL; int hasAlpha = image->format == RRGBAFormat;
alpha = color->alpha; alpha = color->alpha;
nalpha = 255 - alpha; nalpha = 255 - alpha;
sr = image->data[0] + ofs; sr = image->data + ofs*(hasAlpha ? 4 : 3);
sg = image->data[1] + ofs; sg = image->data + ofs*(hasAlpha ? 4 : 3) + 1;
sb = image->data[2] + ofs; sb = image->data + ofs*(hasAlpha ? 4 : 3) + 2;
sa = image->data[3] + ofs; sa = image->data + ofs*(hasAlpha ? 4 : 3) + 3;
switch (operation) { switch (operation) {
case RClearOperation: case RClearOperation:
@@ -335,31 +342,35 @@ genericLine(RImage *image, int x0, int y0, int x1, int y1, RColor *color,
last = (polyline) ? du-1 : du; last = (polyline) ? du-1 : du;
if (color->alpha==255 || operation==RCopyOperation) { if (color->alpha==255 || operation==RCopyOperation) {
unsigned char *sr, *sg, *sb, *sa; unsigned char *ptr;
i = y0*image->width + x0; if (image->format == RRGBAFormat)
sr = image->data[0] + i; i = (y0*image->width + x0) * 4;
sg = image->data[1] + i; else
sb = image->data[2] + i; i = (y0*image->width + x0) * 3;
sa = image->data[3] + i; ptr = image->data + i;
for (i=0; i<=last; i++) { for (i=0; i<=last; i++) {
/* Draw the pixel */ /* Draw the pixel */
*sr = color->red; *ptr = color->red;
*sg = color->green; *(ptr+1) = color->green;
*sb = color->blue; *(ptr+2) = color->blue;
if (image->data[3]) if (image->format == RRGBAFormat)
*sa = 255; *(ptr+3) = 255;
/* Compute error for NeXT Step */ /* Compute error for NeXT Step */
err += dv2; err += dv2;
if (err >= du) { if (err >= du) {
sr += vofs; sg += vofs; if (image->format == RRGBAFormat)
sb += vofs; sa += vofs; ptr += vofs*4;
else
ptr += vofs*3;
err -= du2; err -= du2;
} }
sr += uofs; sg += uofs; if (image->format == RRGBAFormat)
sb += uofs; sa += uofs; ptr += uofs*4;
else
ptr += uofs*3;
} }
} else { } else {
register int ofs = y0*image->width + x0; register int ofs = y0*image->width + x0;
@@ -592,4 +603,3 @@ ROperateSegments(RImage *image, int operation, RSegment *segs,
} }
} }

View File

@@ -44,6 +44,7 @@ RImage*
RLoadGIF(RContext *context, char *file, int index) RLoadGIF(RContext *context, char *file, int index)
{ {
RImage *image = NULL; RImage *image = NULL;
#if 0
GifFileType *gif = NULL; GifFileType *gif = NULL;
GifPixelType *buffer = NULL; GifPixelType *buffer = NULL;
int i, j, k, ofs = 0; int i, j, k, ofs = 0;
@@ -208,7 +209,7 @@ did_not_get_any_errors:
if (gif) if (gif)
DGifCloseFile(gif); DGifCloseFile(gif);
#endif
return image; return image;
} }

View File

@@ -2,7 +2,7 @@
* *
* Raster graphics library * Raster graphics library
* *
* Copyright (c) 1997 Alfredo K. Kojima * Copyright (c) 1997-2000 Alfredo K. Kojima
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public
@@ -116,15 +116,13 @@ renderHGradient(unsigned width, unsigned height, int r0, int g0, int b0,
int i; int i;
unsigned long r, g, b, dr, dg, db; unsigned long r, g, b, dr, dg, db;
RImage *image; RImage *image;
unsigned char *rp, *gp, *bp; unsigned char *ptr;
image = RCreateImage(width, height, False); image = RCreateImage(width, height, False);
if (!image) { if (!image) {
return NULL; return NULL;
} }
rp = image->data[0]; ptr = image->data;
gp = image->data[1];
bp = image->data[2];
r = r0 << 16; r = r0 << 16;
g = g0 << 16; g = g0 << 16;
@@ -135,20 +133,17 @@ renderHGradient(unsigned width, unsigned height, int r0, int g0, int b0,
db = ((bf-b0)<<16)/(int)width; db = ((bf-b0)<<16)/(int)width;
/* render the first line */ /* render the first line */
for (i=0; i<width; i++) { for (i=0; i<width; i++) {
*(rp++) = (unsigned char)(r>>16); *(ptr++) = (unsigned char)(r>>16);
*(gp++) = (unsigned char)(g>>16); *(ptr++) = (unsigned char)(g>>16);
*(bp++) = (unsigned char)(b>>16); *(ptr++) = (unsigned char)(b>>16);
r += dr; r += dr;
g += dg; g += dg;
b += db; b += db;
} }
/* copy the first line to the other lines */ /* copy the first line to the other lines */
for (i=1; i<height; i++) { for (i=1; i<height; i++) {
memcpy(&(image->data[0][i*width]), image->data[0], width); memcpy(&(image->data[i*width*3]), image->data, width*3);
memcpy(&(image->data[1][i*width]), image->data[1], width);
memcpy(&(image->data[2][i*width]), image->data[2], width);
} }
return image; return image;
} }
@@ -170,18 +165,18 @@ static RImage*
renderVGradient(unsigned width, unsigned height, int r0, int g0, int b0, renderVGradient(unsigned width, unsigned height, int r0, int g0, int b0,
int rf, int gf, int bf) int rf, int gf, int bf)
{ {
int i; int i, j;
unsigned long r, g, b, dr, dg, db; unsigned long r, g, b, dr, dg, db;
RImage *image; RImage *image;
unsigned char *rp, *gp, *bp; unsigned char *ptr;
unsigned int *iptr;
unsigned char rr, gg, bb;
image = RCreateImage(width, height, False); image = RCreateImage(width, height, False);
if (!image) { if (!image) {
return NULL; return NULL;
} }
rp = image->data[0]; iptr = (unsigned int*)ptr = image->data;
gp = image->data[1];
bp = image->data[2];
r = r0<<16; r = r0<<16;
g = g0<<16; g = g0<<16;
@@ -191,13 +186,22 @@ renderVGradient(unsigned width, unsigned height, int r0, int g0, int b0,
dg = ((gf-g0)<<16)/(int)height; dg = ((gf-g0)<<16)/(int)height;
db = ((bf-b0)<<16)/(int)height; db = ((bf-b0)<<16)/(int)height;
for (i=0; i<height; i++) { for (i=0; i<height; i++) {
memset(rp, (unsigned char)(r>>16), width); rr = r>>16;
memset(gp, (unsigned char)(g>>16), width); gg = g>>16;
memset(bp, (unsigned char)(b>>16), width); bb = b>>16;
rp+=width; for (j=0; j<width/4; j++) {
gp+=width; *ptr++ = rr; *ptr++ = gg; *ptr++ = bb;
bp+=width; *ptr++ = rr; *ptr++ = gg; *ptr++ = bb;
*ptr++ = rr; *ptr++ = gg; *ptr++ = bb;
*ptr++ = rr; *ptr++ = gg; *ptr++ = bb;
}
switch (width%4) {
case 3: *ptr++ = rr; *ptr++ = gg; *ptr++ = bb;
case 2: *ptr++ = rr; *ptr++ = gg; *ptr++ = bb;
case 1: *ptr++ = rr; *ptr++ = gg; *ptr++ = bb;
}
r+=dr; r+=dr;
g+=dg; g+=dg;
b+=db; b+=db;
@@ -219,67 +223,6 @@ renderVGradient(unsigned width, unsigned height, int r0, int g0, int b0,
* None * None
*---------------------------------------------------------------------- *----------------------------------------------------------------------
*/ */
#if 0
/* This version is slower then the one below. It uses more operations,
* most of them multiplication of floats. Dan.
*/
static RImage*
renderDGradient(unsigned width, unsigned height, int r0, int g0, int b0,
int rf, int gf, int bf)
{
int x, y;
float from_red,from_green,from_blue;
float to_red,to_green,to_blue;
float dr,dg,db,dx,dy,w,h,xred,yred,xgreen,ygreen,xblue,yblue;
RImage *image;
unsigned char *rp, *gp, *bp;
image = RCreateImage(width, height, False);
if (!image) {
return NULL;
}
rp = image->data[0];
gp = image->data[1];
bp = image->data[2];
from_red = (float)r0;
from_green = (float)g0;
from_blue = (float)b0;
to_red = (float)rf;
to_green = (float)gf;
to_blue = (float)bf;
w = (float) width;
h = (float) height;
dr = (to_red - from_red);
dg = (to_green - from_green);
db = (to_blue - from_blue);
for (y=0; y<height; y++) {
dy = y / h;
yred = dr * dy + from_red;
ygreen = dg * dy + from_green;
yblue = db * dy + from_blue;
for (x=0; x<width; x++) {
dx = x / w;
xred = dr * dx + from_red;
xgreen = dg * dx + from_green;
xblue = db * dx + from_blue;
*(rp++) = (unsigned char)((xred + yred)/2);
*(gp++) = (unsigned char)((xgreen + ygreen)/2);
*(bp++) = (unsigned char)((xblue + yblue)/2);
}
}
return image;
}
#endif
static RImage* static RImage*
@@ -287,8 +230,8 @@ renderDGradient(unsigned width, unsigned height, int r0, int g0, int b0,
int rf, int gf, int bf) int rf, int gf, int bf)
{ {
RImage *image, *tmp; RImage *image, *tmp;
float a; unsigned long a;
int i, offset; int i, j, offset;
if (width == 1) if (width == 1)
return renderVGradient(width, height, r0, g0, b0, rf, gf, bf); return renderVGradient(width, height, r0, g0, b0, rf, gf, bf);
@@ -306,14 +249,13 @@ renderDGradient(unsigned width, unsigned height, int r0, int g0, int b0,
return NULL; return NULL;
} }
a = ((float)(width - 1))/((float)(height - 1)); a = (((width - 1)<<16) / ((height - 1)<<16)) * 3;
width *= 3;
/* copy the first line to the other lines with corresponding offset */ /* copy the first line to the other lines with corresponding offset */
for (i=0; i<height; i++) { for (i=0, j=0, offset = 0; i<height; i++, j+= width) {
offset = (int)(a*i+0.5); offset += a;
memcpy(&(image->data[0][i*width]), &(tmp->data[0][offset]), width); memcpy(&(image->data[j]), &(tmp->data[(offset>>16)]), width);
memcpy(&(image->data[1][i*width]), &(tmp->data[1][offset]), width);
memcpy(&(image->data[2][i*width]), &(tmp->data[2][offset]), width);
} }
RDestroyImage(tmp); RDestroyImage(tmp);
return image; return image;
@@ -326,7 +268,7 @@ renderMHGradient(unsigned width, unsigned height, RColor **colors, int count)
int i, j, k; int i, j, k;
unsigned long r, g, b, dr, dg, db; unsigned long r, g, b, dr, dg, db;
RImage *image; RImage *image;
unsigned char *rp, *gp, *bp; unsigned char *ptr;
unsigned width2; unsigned width2;
@@ -336,9 +278,7 @@ renderMHGradient(unsigned width, unsigned height, RColor **colors, int count)
if (!image) { if (!image) {
return NULL; return NULL;
} }
rp = image->data[0]; ptr = image->data;
gp = image->data[1];
bp = image->data[2];
if (count > width) if (count > width)
count = width; count = width;
@@ -360,9 +300,9 @@ renderMHGradient(unsigned width, unsigned height, RColor **colors, int count)
dg = ((int)(colors[i]->green - colors[i-1]->green)<<16)/(int)width2; dg = ((int)(colors[i]->green - colors[i-1]->green)<<16)/(int)width2;
db = ((int)(colors[i]->blue - colors[i-1]->blue) <<16)/(int)width2; db = ((int)(colors[i]->blue - colors[i-1]->blue) <<16)/(int)width2;
for (j=0; j<width2; j++) { for (j=0; j<width2; j++) {
*(rp++) = (unsigned char)(r>>16); *ptr++ = (unsigned char)(r>>16);
*(gp++) = (unsigned char)(g>>16); *ptr++ = (unsigned char)(g>>16);
*(bp++) = (unsigned char)(b>>16); *ptr++ = (unsigned char)(b>>16);
r += dr; r += dr;
g += dg; g += dg;
b += db; b += db;
@@ -373,16 +313,14 @@ renderMHGradient(unsigned width, unsigned height, RColor **colors, int count)
b = colors[i]->blue << 16; b = colors[i]->blue << 16;
} }
for (j=k; j<width; j++) { for (j=k; j<width; j++) {
*(rp++) = (unsigned char)(r>>16); *ptr++ = (unsigned char)(r>>16);
*(gp++) = (unsigned char)(g>>16); *ptr++ = (unsigned char)(g>>16);
*(bp++) = (unsigned char)(b>>16); *ptr++ = (unsigned char)(b>>16);
} }
/* copy the first line to the other lines */ /* copy the first line to the other lines */
for (i=1; i<height; i++) { for (i=1; i<height; i++) {
memcpy(&(image->data[0][i*width]), image->data[0], width); memcpy(&(image->data[i*width*3]), image->data, width*3);
memcpy(&(image->data[1][i*width]), image->data[1], width);
memcpy(&(image->data[2][i*width]), image->data[2], width);
} }
return image; return image;
} }
@@ -396,8 +334,10 @@ renderMVGradient(unsigned width, unsigned height, RColor **colors, int count)
int i, j, k; int i, j, k;
unsigned long r, g, b, dr, dg, db; unsigned long r, g, b, dr, dg, db;
RImage *image; RImage *image;
unsigned char *rp, *gp, *bp; unsigned char *ptr, *tmp;
unsigned height2; unsigned height2;
int x;
unsigned char rr, gg, bb;
assert(count > 2); assert(count > 2);
@@ -406,9 +346,7 @@ renderMVGradient(unsigned width, unsigned height, RColor **colors, int count)
if (!image) { if (!image) {
return NULL; return NULL;
} }
rp = image->data[0]; ptr = image->data;
gp = image->data[1];
bp = image->data[2];
if (count > height) if (count > height)
count = height; count = height;
@@ -428,13 +366,23 @@ renderMVGradient(unsigned width, unsigned height, RColor **colors, int count)
dr = ((int)(colors[i]->red - colors[i-1]->red) <<16)/(int)height2; dr = ((int)(colors[i]->red - colors[i-1]->red) <<16)/(int)height2;
dg = ((int)(colors[i]->green - colors[i-1]->green)<<16)/(int)height2; dg = ((int)(colors[i]->green - colors[i-1]->green)<<16)/(int)height2;
db = ((int)(colors[i]->blue - colors[i-1]->blue) <<16)/(int)height2; db = ((int)(colors[i]->blue - colors[i-1]->blue) <<16)/(int)height2;
for (j=0; j<height2; j++) { for (j=0; j<height2; j++) {
memset(rp, (unsigned char)(r>>16), width); rr = r>>16;
memset(gp, (unsigned char)(g>>16), width); gg = g>>16;
memset(bp, (unsigned char)(b>>16), width); bb = b>>16;
rp+=width;
gp+=width; for (x=0; x<width/4; x++) {
bp+=width; *ptr++ = rr; *ptr++ = gg; *ptr++ = bb;
*ptr++ = rr; *ptr++ = gg; *ptr++ = bb;
*ptr++ = rr; *ptr++ = gg; *ptr++ = bb;
*ptr++ = rr; *ptr++ = gg; *ptr++ = bb;
}
switch (width%4) {
case 3: *ptr++ = rr; *ptr++ = gg; *ptr++ = bb;
case 2: *ptr++ = rr; *ptr++ = gg; *ptr++ = bb;
case 1: *ptr++ = rr; *ptr++ = gg; *ptr++ = bb;
}
r += dr; r += dr;
g += dg; g += dg;
b += db; b += db;
@@ -444,13 +392,27 @@ renderMVGradient(unsigned width, unsigned height, RColor **colors, int count)
g = colors[i]->green << 16; g = colors[i]->green << 16;
b = colors[i]->blue << 16; b = colors[i]->blue << 16;
} }
for (j=k; j<height; j++) {
memset(rp, (unsigned char)(r>>16), width); rr = r>>16;
memset(gp, (unsigned char)(g>>16), width); gg = g>>16;
memset(bp, (unsigned char)(b>>16), width); bb = b>>16;
rp+=width;
gp+=width; tmp = ptr;
bp+=width; for (x=0; x<width/4; x++) {
*ptr++ = rr; *ptr++ = gg; *ptr++ = bb;
*ptr++ = rr; *ptr++ = gg; *ptr++ = bb;
*ptr++ = rr; *ptr++ = gg; *ptr++ = bb;
*ptr++ = rr; *ptr++ = gg; *ptr++ = bb;
}
switch (width%4) {
case 3: *ptr++ = rr; *ptr++ = gg; *ptr++ = bb;
case 2: *ptr++ = rr; *ptr++ = gg; *ptr++ = bb;
case 1: *ptr++ = rr; *ptr++ = gg; *ptr++ = bb;
}
for (j=k+1; j<width; j++) {
memcpy(ptr, tmp, width*3);
ptr += width*3;
} }
return image; return image;
@@ -498,10 +460,8 @@ renderMDGradient(unsigned width, unsigned height, RColor **colors, int count)
/* copy the first line to the other lines with corresponding offset */ /* copy the first line to the other lines with corresponding offset */
for (i=0; i<height; i++) { for (i=0; i<height; i++) {
offset = (int)(a*i+0.5); offset = (int)(a*i+0.5)*3;
memcpy(&(image->data[0][i*width]), &(tmp->data[0][offset]), width); memcpy(&(image->data[i*width*3]), &(tmp->data[offset]), width*3);
memcpy(&(image->data[1][i*width]), &(tmp->data[1][offset]), width);
memcpy(&(image->data[2][i*width]), &(tmp->data[2][offset]), width);
} }
RDestroyImage(tmp); RDestroyImage(tmp);
return image; return image;

View File

@@ -77,7 +77,7 @@ typedef struct my_error_mgr * my_error_ptr;
* Here's the routine that will replace the standard error_exit method: * Here's the routine that will replace the standard error_exit method:
*/ */
void static void
my_error_exit(j_common_ptr cinfo) my_error_exit(j_common_ptr cinfo)
{ {
/* cinfo->err really points to a my_error_mgr struct, so coerce pointer */ /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
@@ -97,9 +97,9 @@ RLoadJPEG(RContext *context, char *file_name, int index)
{ {
RImage *image = NULL; RImage *image = NULL;
struct jpeg_decompress_struct cinfo; struct jpeg_decompress_struct cinfo;
int i, j; int i;
unsigned char *r, *g, *b; unsigned char *ptr;
JSAMPROW buffer[1]; JSAMPROW buffer[1], bptr;
FILE *file; FILE *file;
/* We use our private extension JPEG error handler. /* We use our private extension JPEG error handler.
* Note that this struct must live as long as the main JPEG parameter * Note that this struct must live as long as the main JPEG parameter
@@ -131,7 +131,7 @@ RLoadJPEG(RContext *context, char *file_name, int index)
jpeg_read_header(&cinfo, TRUE); jpeg_read_header(&cinfo, TRUE);
buffer[0] = (JSAMPROW)malloc(cinfo.image_width*cinfo.num_components); bptr = buffer[0] = (JSAMPROW)malloc(cinfo.image_width*cinfo.num_components);
if (!buffer[0]) { if (!buffer[0]) {
RErrorCode = RERR_NOMEMORY; RErrorCode = RERR_NOMEMORY;
goto bye; goto bye;
@@ -145,26 +145,47 @@ RLoadJPEG(RContext *context, char *file_name, int index)
cinfo.do_fancy_upsampling = FALSE; cinfo.do_fancy_upsampling = FALSE;
cinfo.do_block_smoothing = FALSE; cinfo.do_block_smoothing = FALSE;
jpeg_calc_output_dimensions(&cinfo); jpeg_calc_output_dimensions(&cinfo);
if (context->flags.optimize_for_speed)
image = RCreateImage(cinfo.image_width, cinfo.image_height, True);
else
image = RCreateImage(cinfo.image_width, cinfo.image_height, False); image = RCreateImage(cinfo.image_width, cinfo.image_height, False);
if (!image) { if (!image) {
RErrorCode = RERR_NOMEMORY; RErrorCode = RERR_NOMEMORY;
goto bye; goto bye;
} }
jpeg_start_decompress(&cinfo); jpeg_start_decompress(&cinfo);
r = image->data[0]; ptr = image->data;
g = image->data[1];
b = image->data[2];
if (cinfo.out_color_space==JCS_RGB) {
if (context->flags.optimize_for_speed) {
while (cinfo.output_scanline < cinfo.output_height) { while (cinfo.output_scanline < cinfo.output_height) {
jpeg_read_scanlines(&cinfo, buffer,(JDIMENSION) 1); jpeg_read_scanlines(&cinfo, buffer,(JDIMENSION) 1);
for (i=0,j=0; i<cinfo.image_width; i++) { bptr = buffer[0];
if (cinfo.out_color_space==JCS_RGB) { for (i=0; i<cinfo.image_width; i++) {
*(r++) = buffer[0][j++]; *ptr++ = *bptr++;
*(g++) = buffer[0][j++]; *ptr++ = *bptr++;
*(b++) = buffer[0][j++]; *ptr++ = *bptr++;
ptr++; /* skip alpha channel */
}
}
} else { } else {
*(r++) = *(g++) = *(b++) = buffer[0][j++]; while (cinfo.output_scanline < cinfo.output_height) {
jpeg_read_scanlines(&cinfo, buffer,(JDIMENSION) 1);
bptr = buffer[0];
memcpy(ptr, bptr, cinfo.image_width*3);
ptr += cinfo.image_width*3;
}
}
} else {
while (cinfo.output_scanline < cinfo.output_height) {
jpeg_read_scanlines(&cinfo, buffer,(JDIMENSION) 1);
bptr = buffer[0];
for (i=0; i<cinfo.image_width; i++) {
*ptr++ = *ptr++ = *ptr++ = *bptr++;
} }
} }
} }

View File

@@ -1,7 +1,7 @@
/* /*
* Raster graphics library * Raster graphics library
* *
* Copyright (c) 1997 Alfredo K. Kojima * Copyright (c) 1997-2000 Alfredo K. Kojima
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public
@@ -17,7 +17,6 @@
* License along with this library; if not, write to the Free * License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#include <config.h> #include <config.h>
#include <stdlib.h> #include <stdlib.h>
@@ -92,24 +91,40 @@ RBevelImage(RImage *image, int bevel_type)
void void
RClearImage(RImage *image, RColor *color) RClearImage(RImage *image, RColor *color)
{ {
int bytes;
bytes = image->width*image->height;
if (color->alpha==255) { if (color->alpha==255) {
memset(image->data[0], color->red, bytes); if (image->format == RRGBAFormat) {
memset(image->data[1], color->green, bytes); unsigned char *d = image->data;
memset(image->data[2], color->blue, bytes); int i;
if (image->data[3])
memset(image->data[3], 0xff, bytes); for (i = 0; i < image->width; i++) {
*d++ = color->red;
*d++ = color->green;
*d++ = color->blue;
*d++ = 0xff;
}
for (i = 1; i < image->height; i++, d += image->width*4) {
memcpy(d, image->data, image->width*4);
}
} else { } else {
register int i; unsigned char *d = image->data;
unsigned char *dr, *dg, *db; int i;
for (i = 0; i < image->width; i++) {
*d++ = color->red;
*d++ = color->green;
*d++ = color->blue;
}
for (i = 1; i < image->height; i++, d += image->width*3) {
memcpy(d, image->data, image->width*3);
}
}
} else {
int bytes = image->width*image->height;
int i;
unsigned char *d;
int alpha, nalpha, r, g, b; int alpha, nalpha, r, g, b;
dr = image->data[0]; d = image->data;
dg = image->data[1];
db = image->data[2];
alpha = color->alpha; alpha = color->alpha;
r = color->red * alpha; r = color->red * alpha;
@@ -118,14 +133,18 @@ RClearImage(RImage *image, RColor *color)
nalpha = 255 - alpha; nalpha = 255 - alpha;
for (i=0; i<bytes; i++) { for (i=0; i<bytes; i++) {
*dr = (((int)*dr * nalpha) + r)/256; *d = (((int)*d * nalpha) + r)/256;
*dg = (((int)*dg * nalpha) + g)/256; d++;
*db = (((int)*db * nalpha) + b)/256; *d = (((int)*d * nalpha) + g)/256;
dr++; dg++; db++; d++;
*d = (((int)*d * nalpha) + b)/256;
d++;
if (image->format == RRGBAFormat) {
d++;
}
} }
} }
} }
const char* const char*
RMessageForError(int errorCode) RMessageForError(int errorCode)
@@ -172,4 +191,3 @@ RMessageForError(int errorCode)
return "internal error"; return "internal error";
} }
} }

View File

@@ -156,10 +156,13 @@ RGetImageFromXPMData(RContext *context, char **data)
return NULL; return NULL;
} }
r = image->data[0]; r = image->data;
g = image->data[1]; g = image->data+1;
b = image->data[2]; b = image->data+2;
a = image->data[3]; if (image->format == RRGBAFormat)
a = image->data+3;
else
a = NULL;
for (i=0; i<h; i++) { for (i=0; i<h; i++) {
if (csize==1) { if (csize==1) {
@@ -332,10 +335,13 @@ RLoadXPM(RContext *context, char *file, int index)
return NULL; return NULL;
} }
r = image->data[0]; r = image->data;
g = image->data[1]; g = image->data+1;
b = image->data[2]; b = image->data+2;
a = image->data[3]; if (image->format == RRGBAFormat)
a = image->data+3;
else
a = NULL;
for (i=0; i<h; i++) { for (i=0; i<h; i++) {
if (!fgets(buffer, bsize, f)) if (!fgets(buffer, bsize, f))
@@ -557,10 +563,13 @@ RSaveXPM(RImage *image, char *filename)
fprintf(file, "static char *image[] = {\n"); fprintf(file, "static char *image[] = {\n");
r = image->data[0]; r = image->data;
g = image->data[1]; g = image->data+1;
b = image->data[2]; b = image->data+2;
a = image->data[3]; if (image->format == RRGBAFormat)
a = image->data+3;
else
a = NULL;
/* first pass: make colormap for the image */ /* first pass: make colormap for the image */
if (a) if (a)
@@ -595,11 +604,14 @@ RSaveXPM(RImage *image, char *filename)
i = 0; i = 0;
outputcolormap(file, colormap, charsPerPixel); outputcolormap(file, colormap, charsPerPixel);
r = image->data[0];
g = image->data[1];
b = image->data[2];
a = image->data[3];
r = image->data;
g = image->data+1;
b = image->data+2;
if (image->format == RRGBAFormat)
a = image->data+3;
else
a = NULL;
/* write data */ /* write data */
for (y = 0; y < image->height; y++) { for (y = 0; y < image->height; y++) {

View File

@@ -65,7 +65,7 @@ RLoadPNG(RContext *context, char *file, int index)
png_uint_32 width, height; png_uint_32 width, height;
int depth, junk, color_type; int depth, junk, color_type;
png_bytep *png_rows; png_bytep *png_rows;
unsigned char *r, *g, *b, *a; unsigned char *ptr;
f = fopen(file, "r"); f = fopen(file, "r");
if (!f) { if (!f) {
@@ -207,27 +207,19 @@ RLoadPNG(RContext *context, char *file, int index)
fclose(f); fclose(f);
r = image->data[0]; ptr = image->data;
g = image->data[1];
b = image->data[2];
a = image->data[3];
/* convert to RImage */ /* convert to RImage */
if (alpha) { if (alpha) {
for (y=0; y<height; y++) { for (y=0; y<height; y++) {
for (x=0, i=0; x<width; x++) { for (x=0, i=width*4; x<i; x++, ptr++) {
*(r++) = *(png_rows[y]+i++); *ptr = *(png_rows[y]+x);
*(g++) = *(png_rows[y]+i++);
*(b++) = *(png_rows[y]+i++);
*(a++) = *(png_rows[y]+i++);
} }
} }
} else { } else {
for (y=0; y<height; y++) { for (y=0; y<height; y++) {
for (x=0, i=0; x<width; x++) { for (x=0, i=width*3; x<i; x++, ptr++) {
*(r++) = *(png_rows[y]+i++); *ptr = *(png_rows[y]+x);
*(g++) = *(png_rows[y]+i++);
*(b++) = *(png_rows[y]+i++);
} }
} }
} }

View File

@@ -43,10 +43,27 @@ load_graymap(char *file_name, FILE *file, int w, int h, int max, int raw)
} else { } else {
if (max<256) { if (max<256) {
if (!fgets(image->data[0], w*h, file)) int x, y;
char *buf, *ptr;
buf = malloc(w);
if (!buf) {
return NULL;
}
ptr = image->data;
for (y = 0; y < h; y++) {
if (!fgets(buf, w, file)) {
free(buf);
goto short_file; goto short_file;
memcpy(image->data[0], image->data[1], w*h); }
memcpy(image->data[0], image->data[2], w*h); for (x = 0; x < w; x++) {
*(ptr++) = buf[x];
*(ptr++) = buf[x];
*(ptr++) = buf[x];
}
}
free(buf);
} else { } else {
} }
@@ -66,15 +83,13 @@ load_pixmap(char *file_name, FILE *file, int w, int h, int max, int raw)
RImage *image; RImage *image;
int i; int i;
char buf[3]; char buf[3];
char *r, *g, *b; char *ptr;
image = RCreateImage(w, h, 0); image = RCreateImage(w, h, 0);
if (!image) { if (!image) {
return NULL; return NULL;
} }
r = image->data[0]; ptr = image->data;
g = image->data[1];
b = image->data[2];
if (!raw) { if (!raw) {
} else { } else {
@@ -83,9 +98,9 @@ load_pixmap(char *file_name, FILE *file, int w, int h, int max, int raw)
while (i < w*h) { while (i < w*h) {
if (fread(buf, 1, 3, file)!=3) if (fread(buf, 1, 3, file)!=3)
goto short_file; goto short_file;
*(r++) = buf[0]; *(ptr++) = buf[0];
*(g++) = buf[1]; *(ptr++) = buf[1];
*(b++) = buf[2]; *(ptr++) = buf[2];
i++; i++;
} }
} else { } else {

View File

@@ -2,7 +2,7 @@
* *
* Raster graphics library * Raster graphics library
* *
* Copyright (c) 1997 Alfredo K. Kojima * Copyright (c) 1997-2000 Alfredo K. Kojima
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public
@@ -35,12 +35,13 @@ char *WRasterLibVersion="0.9";
int RErrorCode=RERR_NONE; int RErrorCode=RERR_NONE;
#define HAS_ALPHA(I) ((I)->format == RRGBAFormat)
RImage* RImage*
RCreateImage(unsigned width, unsigned height, int alpha) RCreateImage(unsigned width, unsigned height, int alpha)
{ {
RImage *image=NULL; RImage *image=NULL;
int i;
assert(width>0 && height>0); assert(width>0 && height>0);
@@ -53,22 +54,22 @@ RCreateImage(unsigned width, unsigned height, int alpha)
memset(image, 0, sizeof(RImage)); memset(image, 0, sizeof(RImage));
image->width = width; image->width = width;
image->height = height; image->height = height;
for (i=0; i<3+(alpha?1:0); i++) { if (alpha) {
image->data[i] = malloc(width*height); image->format = RRGBAFormat;
if (!image->data[i]) } else {
goto error; image->format = RRGBFormat;
} }
return image; /* the +4 is to give extra bytes at the end of the buffer,
* so that we can optimize image conversion for MMX(tm).. see convert.c
error: */
for (i=0; i<4; i++) { image->data = malloc(width * height * (alpha ? 4 : 3) + 4);
if (image->data[i]) if (!image->data) {
free(image->data[i]);
}
if (image)
free(image);
RErrorCode = RERR_NOMEMORY; RErrorCode = RERR_NOMEMORY;
return NULL; free(image);
image = NULL;
}
return image;
} }
@@ -80,16 +81,13 @@ RCloneImage(RImage *image)
assert(image!=NULL); assert(image!=NULL);
new_image = RCreateImage(image->width, image->height, image->data[3]!=NULL); new_image = RCreateImage(image->width, image->height, HAS_ALPHA(image));
if (!new_image) if (!new_image)
return NULL; return NULL;
new_image->background = image->background; new_image->background = image->background;
memcpy(new_image->data[0], image->data[0], image->width*image->height); memcpy(new_image->data, image->data,
memcpy(new_image->data[1], image->data[1], image->width*image->height); image->width*image->height*(HAS_ALPHA(image) ? 4 : 3));
memcpy(new_image->data[2], image->data[2], image->width*image->height);
if (image->data[3])
memcpy(new_image->data[3], image->data[3], image->width*image->height);
return new_image; return new_image;
} }
@@ -100,8 +98,7 @@ RGetSubImage(RImage *image, int x, int y, unsigned width, unsigned height)
{ {
int i, ofs; int i, ofs;
RImage *new_image; RImage *new_image;
unsigned char *sr, *sg, *sb, *sa; unsigned total_line_size, line_size;
unsigned char *dr, *dg, *db, *da;
assert(image!=NULL); assert(image!=NULL);
assert(x>=0 && y>=0); assert(x>=0 && y>=0);
@@ -113,37 +110,20 @@ RGetSubImage(RImage *image, int x, int y, unsigned width, unsigned height)
if (y+height > image->height) if (y+height > image->height)
height = image->height-y; height = image->height-y;
new_image = RCreateImage(width, height, image->data[3]!=NULL); new_image = RCreateImage(width, height, HAS_ALPHA(image));
if (!new_image) if (!new_image)
return NULL; return NULL;
new_image->background = image->background; new_image->background = image->background;
ofs = image->width*y+x;
sr = image->data[0]+ofs; total_line_size = image->width * (HAS_ALPHA(image) ? 4 : 3);
sg = image->data[1]+ofs; line_size = width * (HAS_ALPHA(image) ? 4 : 3);
sb = image->data[2]+ofs;
sa = image->data[3]+ofs;
dr = new_image->data[0]; ofs = x*(HAS_ALPHA(image) ? 4 : 3);
dg = new_image->data[1];
db = new_image->data[2];
da = new_image->data[3];
for (i=0; i<height; i++) { for (i=0; i<height; i++) {
memcpy(dr, sr, width); memcpy(&new_image->data[i*line_size],
memcpy(dg, sg, width); &image->data[i*total_line_size+ofs], line_size);
memcpy(db, sb, width);
sr += image->width;
sg += image->width;
sb += image->width;
dr += width;
dg += width;
db += width;
if (da) {
memcpy(da, sa, width);
sa += image->width;
da += width;
}
} }
return new_image; return new_image;
} }
@@ -152,14 +132,9 @@ RGetSubImage(RImage *image, int x, int y, unsigned width, unsigned height)
void void
RDestroyImage(RImage *image) RDestroyImage(RImage *image)
{ {
int i;
assert(image!=NULL); assert(image!=NULL);
for (i=0; i<4; i++) { free(image->data);
if (image->data[i])
free(image->data[i]);
}
free(image); free(image);
} }
@@ -174,41 +149,60 @@ RDestroyImage(RImage *image)
void void
RCombineImages(RImage *image, RImage *src) RCombineImages(RImage *image, RImage *src)
{ {
register int i;
unsigned char *dr, *dg, *db, *da;
unsigned char *sr, *sg, *sb, *sa;
int alpha, calpha;
assert(image->width == src->width); assert(image->width == src->width);
assert(image->height == src->height); assert(image->height == src->height);
dr = image->data[0]; if (!HAS_ALPHA(src)) {
dg = image->data[1]; if (!HAS_ALPHA(image)) {
db = image->data[2]; memcpy(image->data, src->data, image->height*image->width*3);
da = image->data[3]; } else {
int x, y;
unsigned char *d, *s;
sr = src->data[0]; d = image->data;
sg = src->data[1]; s = src->data;
sb = src->data[2]; for (y = 0; y < image->height; y++) {
sa = src->data[3]; for (x = 0; x < image->width; x++) {
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
d++;
}
}
}
} else {
register int i;
unsigned char *d;
unsigned char *s;
int alpha, calpha;
if (!sa) { d = image->data;
memcpy(dr, sr, image->height*image->width); s = src->data;
memcpy(dg, sg, image->height*image->width);
memcpy(db, sb, image->height*image->width); if (!HAS_ALPHA(image)) {
for (i=0; i<image->height*image->width; i++) {
alpha = *(s+3);
calpha = 255 - alpha;
*d = (((int)*d * calpha) + ((int)*s * alpha))/256;
d++; s++;
*d = (((int)*d * calpha) + ((int)*s * alpha))/256;
d++; s++;
*d = (((int)*d * calpha) + ((int)*s * alpha))/256;
d++; s++;
s++;
}
} else { } else {
for (i=0; i<image->height*image->width; i++) { for (i=0; i<image->height*image->width; i++) {
alpha = *sa; alpha = *(s+3);
calpha = 255 - *sa; calpha = 255 - alpha;
*dr = (((int)*dr * calpha) + ((int)*sr * alpha))/256; *d = (((int)*d * calpha) + ((int)*s * alpha))/256;
*dg = (((int)*dg * calpha) + ((int)*sg * alpha))/256; d++; s++;
*db = (((int)*db * calpha) + ((int)*sb * alpha))/256; *d = (((int)*d * calpha) + ((int)*s * alpha))/256;
if (image->data[3]) d++; s++;
*da++ |= *sa; *d = (((int)*d * calpha) + ((int)*s * alpha))/256;
dr++; dg++; db++; d++; s++;
sr++; sg++; sb++; *d++ |= *s++;
sa++; }
} }
} }
} }
@@ -220,62 +214,58 @@ void
RCombineImagesWithOpaqueness(RImage *image, RImage *src, int opaqueness) RCombineImagesWithOpaqueness(RImage *image, RImage *src, int opaqueness)
{ {
register int i; register int i;
unsigned char *dr, *dg, *db, *da; unsigned char *d;
unsigned char *sr, *sg, *sb, *sa; unsigned char *s;
int c_opaqueness; int c_opaqueness;
assert(image->width == src->width); assert(image->width == src->width);
assert(image->height == src->height); assert(image->height == src->height);
dr = image->data[0]; d = image->data;
dg = image->data[1]; s = src->data;
db = image->data[2];
da = image->data[3];
sr = src->data[0];
sg = src->data[1];
sb = src->data[2];
sa = src->data[3];
c_opaqueness = 255 - opaqueness; c_opaqueness = 255 - opaqueness;
#define OP opaqueness #define OP opaqueness
if (!src->data[3]) { if (!HAS_ALPHA(src)) {
int dalpha = HAS_ALPHA(image);
#define COP c_opaqueness #define COP c_opaqueness
for (i=0; i < image->width*image->height; i++) { for (i=0; i < image->width*image->height; i++) {
*dr = (((int)*dr *(int)COP) + ((int)*sr *(int)OP))/256; *d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256;
*dg = (((int)*dg *(int)COP) + ((int)*sg *(int)OP))/256; d++; s++;
*db = (((int)*db *(int)COP) + ((int)*sb *(int)OP))/256; *d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256;
dr++; dg++; db++; d++; s++;
sr++; sg++; sb++; *d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256;
d++; s++;
if (dalpha) {
d++;
}
} }
#undef COP #undef COP
} else { } else {
int tmp; int tmp;
if (image->data[3]) { if (!HAS_ALPHA(image)) {
for (i=0; i<image->width*image->height; i++) { for (i=0; i<image->width*image->height; i++) {
tmp = (*sa * opaqueness)/256; tmp = (*(s+3) * opaqueness)/256;
*dr = (((int)*dr * (255-tmp)) + ((int)*sr * tmp))/256; *d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256;
*dg = (((int)*dg * (255-tmp)) + ((int)*sg * tmp))/256; d++; s++;
*db = (((int)*db * (255-tmp)) + ((int)*sb * tmp))/256; *d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256;
*da |= tmp; d++; s++;
*d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256;
dr++; dg++; db++; d++; s++;
sr++; sg++; sb++; s++;
sa++;
da++;
} }
} else { } else {
for (i=0; i<image->width*image->height; i++) { for (i=0; i<image->width*image->height; i++) {
tmp = (*sa * opaqueness)/256; tmp = (*(s+3) * opaqueness)/256;
*dr = (((int)*dr * (255-tmp)) + ((int)*sr * tmp))/256; *d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256;
*dg = (((int)*dg * (255-tmp)) + ((int)*sg * tmp))/256; d++; s++;
*db = (((int)*db * (255-tmp)) + ((int)*sb * tmp))/256; *d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256;
d++; s++;
dr++; dg++; db++; *d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256;
sr++; sg++; sb++; d++; s++;
sa++; *d |= tmp;
d++; s++;
} }
} }
} }
@@ -288,8 +278,8 @@ RCombineArea(RImage *image, RImage *src, int sx, int sy, unsigned width,
unsigned height, int dx, int dy) unsigned height, int dx, int dy)
{ {
int x, y, dwi, swi; int x, y, dwi, swi;
unsigned char *dr, *dg, *db; unsigned char *d;
unsigned char *sr, *sg, *sb, *sa; unsigned char *s;
int alpha, calpha; int alpha, calpha;
@@ -299,46 +289,70 @@ RCombineArea(RImage *image, RImage *src, int sx, int sy, unsigned width,
assert(sy + height <= src->height); assert(sy + height <= src->height);
assert(sx + width <= src->width); assert(sx + width <= src->width);
dr = image->data[0] + dy*(int)image->width + dx;
dg = image->data[1] + dy*(int)image->width + dx;
db = image->data[2] + dy*(int)image->width + dx;
sr = src->data[0] + sy*(int)src->width + sx;
sg = src->data[1] + sy*(int)src->width + sx;
sb = src->data[2] + sy*(int)src->width + sx;
sa = src->data[3] + sy*(int)src->width + sx;
swi = src->width - width;
dwi = image->width - width;
if (height > image->height - dy) if (height > image->height - dy)
height = image->height - dy; height = image->height - dy;
if (!src->data[3]) { if (!HAS_ALPHA(src)) {
for (y=sy; y<height+sy; y++) { if (!HAS_ALPHA(image)) {
for (x=sx; x<width+sx; x++) { swi = (src->width - width) * 3;
*(dr++) = *(sr++); dwi = (image->width - width) * 3;
*(dg++) = *(sg++);
*(db++) = *(sb++); d = image->data + dy*(int)image->width*3 + dx;
} s = src->data + sy*(int)src->width*3 + sx;
dr += dwi; dg += dwi; db += dwi;
sr += swi; sg += swi; sb += swi; for (y=0; y < height; y++) {
memcpy(d, s, width*3);
d += dwi;
s += swi;
} }
} else { } else {
for (y=sy; y<height+sy; y++) { swi = (src->width - width) * 3;
for (x=sx; x<width+sx; x++) { dwi = (image->width - width) * 4;
alpha = *sa;
calpha = 255 - alpha; d = image->data + dy*(int)image->width*4 + dx;
*dr = (((int)*dr * calpha) + ((int)*sr * alpha))/256; s = src->data + sy*(int)src->width*3 + sx;
*dg = (((int)*dg * calpha) + ((int)*sg * alpha))/256;
*db = (((int)*db * calpha) + ((int)*sb * alpha))/256; for (y=0; y < height; y++) {
dr++; dg++; db++; for (x=0; x < width; x++) {
sr++; sg++; sb++; *d++ = *s++;
sa++; *d++ = *s++;
*d++ = *s++;
d++;
} }
dr += dwi; dg += dwi; db += dwi; d += dwi;
sr += swi; sg += swi; sb += swi; s += swi;
sa += swi; }
}
} else {
int dalpha = HAS_ALPHA(image);
swi = (src->width - width) * 4;
s = src->data + sy*(int)src->width*4 + sx;
if (!HAS_ALPHA(image)) {
dwi = (image->width - width) * 3;
d = image->data + (dy*(int)image->width+dx)*3;
} else {
dwi = (image->width - width) * 4;
d = image->data + (dy*(int)image->width+dx)*4;
}
for (y=0; y < height; y++) {
for (x=0; x < width; x++) {
alpha = *(s+3);
calpha = 255 - alpha;
*d = (((int)*d * calpha) + ((int)*s * alpha))/256;
s++; d++;
*d = (((int)*d * calpha) + ((int)*s * alpha))/256;
s++; d++;
*d = (((int)*d * calpha) + ((int)*s * alpha))/256;
s++; d++;
s++;
if (dalpha)
d++;
}
d += dwi;
s += swi;
} }
} }
} }
@@ -351,8 +365,9 @@ RCombineAreaWithOpaqueness(RImage *image, RImage *src, int sx, int sy,
{ {
int x, y, dwi, swi; int x, y, dwi, swi;
int c_opaqueness; int c_opaqueness;
unsigned char *dr, *dg, *db; unsigned char *d;
unsigned char *sr, *sg, *sb, *sa; unsigned char *s;
int dalpha = HAS_ALPHA(image);
assert(dy <= image->height); assert(dy <= image->height);
assert(dx <= image->width); assert(dx <= image->width);
@@ -360,17 +375,6 @@ RCombineAreaWithOpaqueness(RImage *image, RImage *src, int sx, int sy,
assert(sy <= height); assert(sy <= height);
assert(sx <= width); assert(sx <= width);
dr = image->data[0] + dy*image->width + dx;
dg = image->data[1] + dy*image->width + dx;
db = image->data[2] + dy*image->width + dx;
sr = src->data[0] + sy*src->width;
sg = src->data[1] + sy*src->width;
sb = src->data[2] + sy*src->width;
sa = src->data[3] + sy*src->width;
swi = src->width - width;
dwi = image->width - width;
/* clip */ /* clip */
width -= sx; width -= sx;
@@ -381,18 +385,32 @@ RCombineAreaWithOpaqueness(RImage *image, RImage *src, int sx, int sy,
c_opaqueness = 255 - opaqueness; c_opaqueness = 255 - opaqueness;
#define OP opaqueness #define OP opaqueness
if (!src->data[3]) { if (!HAS_ALPHA(src)) {
#define COP c_opaqueness #define COP c_opaqueness
s = src->data + sy*src->width*3;
swi = (src->width - width) * 3;
if (dalpha) {
d = image->data + dy*image->width*4 + dx;
dwi = (image->width - width)*4;
} else {
d = image->data + dy*image->width*3 + dx;
dwi = (image->width - width)*3;
}
for (y=0; y < height; y++) { for (y=0; y < height; y++) {
for (x=0; x < width; x++) { for (x=0; x < width; x++) {
*dr = (((int)*dr *(int)COP) + ((int)*sr *(int)OP))/256; *d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256;
*dg = (((int)*dg *(int)COP) + ((int)*sg *(int)OP))/256; s++; d++;
*db = (((int)*db *(int)COP) + ((int)*sb *(int)OP))/256; *d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256;
dr++; dg++; db++; s++; d++;
sr++; sg++; sb++; *d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256;
s++; d++;
if (dalpha)
d++;
} }
dr += dwi; dg += dwi; db += dwi; d += dwi; s += swi;
sr += swi; sg += swi; sb += swi;
} }
#undef COP #undef COP
} else { } else {
@@ -400,17 +418,18 @@ RCombineAreaWithOpaqueness(RImage *image, RImage *src, int sx, int sy,
for (y=0; y < height; y++) { for (y=0; y < height; y++) {
for (x=0; x < width; x++) { for (x=0; x < width; x++) {
tmp= (*sa * opaqueness)/256; tmp= (*(s+3) * opaqueness)/256;
*dr = (((int)*dr *(int)(255-tmp)) + ((int)*sr *(int)tmp))/256; *d = (((int)*d *(int)(255-tmp)) + ((int)*s *(int)tmp))/256;
*dg = (((int)*dg *(int)(255-tmp)) + ((int)*sg *(int)tmp))/256; d++; s++;
*db = (((int)*db *(int)(255-tmp)) + ((int)*sb *(int)tmp))/256; *d = (((int)*d *(int)(255-tmp)) + ((int)*s *(int)tmp))/256;
dr++; dg++; db++; d++; s++;
sr++; sg++; sb++; *d = (((int)*d *(int)(255-tmp)) + ((int)*s *(int)tmp))/256;
sa++; d++; s++;
s++;
if (dalpha)
d++;
} }
dr += dwi; dg += dwi; db += dwi; d += dwi; s += swi;
sr += swi; sg += swi; sb += swi;
sa += swi;
} }
} }
#undef OP #undef OP
@@ -423,16 +442,14 @@ void
RCombineImageWithColor(RImage *image, RColor *color) RCombineImageWithColor(RImage *image, RColor *color)
{ {
register int i; register int i;
unsigned char *dr, *dg, *db, *da; unsigned char *d;
int alpha, nalpha, r, g, b; int alpha, nalpha, r, g, b;
dr = image->data[0]; d = image->data;
dg = image->data[1];
db = image->data[2];
da = image->data[3];
if (!da) { if (!HAS_ALPHA(image)) {
/* Image has no alpha channel, so we consider it to be all 255 */ /* Image has no alpha channel, so we consider it to be all 255.
* Thus there are no transparent parts to be filled. */
return; return;
} }
r = color->red; r = color->red;
@@ -440,17 +457,22 @@ RCombineImageWithColor(RImage *image, RColor *color)
b = color->blue; b = color->blue;
for (i=0; i < image->width*image->height; i++) { for (i=0; i < image->width*image->height; i++) {
alpha = *da; alpha = *(d+3);
nalpha = 255 - alpha; nalpha = 255 - alpha;
*dr = (((int)*dr * alpha) + (r * nalpha))/256; *d = (((int)*d * alpha) + (r * nalpha))/256;
*dg = (((int)*dg * alpha) + (g * nalpha))/256; d++;
*db = (((int)*db * alpha) + (b * nalpha))/256; *d = (((int)*d * alpha) + (g * nalpha))/256;
dr++; dg++; db++; da++; d++;
*d = (((int)*d * alpha) + (b * nalpha))/256;
d++;
d++;
} }
} }
RImage* RImage*
RMakeTiledImage(RImage *tile, unsigned width, unsigned height) RMakeTiledImage(RImage *tile, unsigned width, unsigned height)
{ {
@@ -458,47 +480,36 @@ RMakeTiledImage(RImage *tile, unsigned width, unsigned height)
unsigned w; unsigned w;
unsigned long tile_size = tile->width * tile->height; unsigned long tile_size = tile->width * tile->height;
unsigned long tx = 0; unsigned long tx = 0;
int have_alpha = (tile->data[3]!=NULL);
RImage *image; RImage *image;
unsigned char *sr, *sg, *sb, *sa; unsigned char *s, *d;
unsigned char *dr, *dg, *db, *da;
if (width == tile->width && height == tile->height) if (width == tile->width && height == tile->height)
image = RCloneImage(tile); image = RCloneImage(tile);
else if (width <= tile->width && height <= tile->height) else if (width <= tile->width && height <= tile->height)
image = RGetSubImage(tile, 0, 0, width, height); image = RGetSubImage(tile, 0, 0, width, height);
else { else {
int has_alpha = HAS_ALPHA(tile);
image = RCreateImage(width, height, have_alpha); image = RCreateImage(width, height, has_alpha);
dr = image->data[0]; d = image->data;
dg = image->data[1]; s = tile->data;
db = image->data[2];
da = image->data[3];
sr = tile->data[0];
sg = tile->data[1];
sb = tile->data[2];
sa = tile->data[3];
for (y = 0; y < height; y++) { for (y = 0; y < height; y++) {
for (x = 0; x < width; x += tile->width) { for (x = 0; x < width; x += tile->width) {
w = (width - x < tile->width) ? width - x : tile->width; w = (width - x < tile->width) ? width - x : tile->width;
memcpy(dr, sr+tx, w); if (has_alpha) {
memcpy(dg, sg+tx, w); w *= 3;
memcpy(db, sb+tx, w); memcpy(d, s+tx*3, w);
if (have_alpha) { } else {
memcpy(da, sa+tx, w); w *= 4;
da += w; memcpy(d, s+tx*4, w);
}
d += w;
} }
dr += w;
dg += w;
db += w;
}
tx = (tx + tile->width) % tile_size; tx = (tx + tile->width) % tile_size;
} }
} }

View File

@@ -55,8 +55,8 @@ RScaleImage(RImage *image, unsigned new_width, unsigned new_height)
int px, py; int px, py;
register int x, y, t; register int x, y, t;
int dx, dy; int dx, dy;
unsigned char *sr, *sg, *sb, *sa; unsigned char *s;
unsigned char *dr, *dg, *db, *da; unsigned char *d;
RImage *img; RImage *img;
assert(new_width >= 0 && new_height >= 0); assert(new_width >= 0 && new_height >= 0);
@@ -64,7 +64,7 @@ RScaleImage(RImage *image, unsigned new_width, unsigned new_height)
if (new_width == image->width && new_height == image->height) if (new_width == image->width && new_height == image->height)
return RCloneImage(image); return RCloneImage(image);
img = RCreateImage(new_width, new_height, image->data[3]!=NULL); img = RCreateImage(new_width, new_height, image->format==RRGBAFormat);
if (!img) if (!img)
return NULL; return NULL;
@@ -76,21 +76,15 @@ RScaleImage(RImage *image, unsigned new_width, unsigned new_height)
py = 0; py = 0;
dr = img->data[0]; d = img->data;
dg = img->data[1];
db = img->data[2];
da = img->data[3];
if (image->data[3]!=NULL) { if (image->format == RRGBAFormat) {
int ot; int ot;
ot = -1; ot = -1;
for (y=0; y<new_height; y++) { for (y=0; y<new_height; y++) {
t = image->width*(py>>16); t = image->width*(py>>16);
sr = image->data[0]+t; s = image->data+t;
sg = image->data[1]+t;
sb = image->data[2]+t;
sa = image->data[3]+t;
ot = t; ot = t;
ox = 0; ox = 0;
@@ -98,18 +92,15 @@ RScaleImage(RImage *image, unsigned new_width, unsigned new_height)
for (x=0; x<new_width; x++) { for (x=0; x<new_width; x++) {
px += dx; px += dx;
*(dr++) = *sr; *(d++) = *(s);
*(dg++) = *sg; *(d++) = *(s+1);
*(db++) = *sb; *(d++) = *(s+2);
*(da++) = *sa; *(d++) = *(s+3);
t = (px - ox)>>16; t = (px - ox)>>16;
ox += t<<16; ox += t<<16;
sr += t; s += t<<2; /* t*4 */
sg += t;
sb += t;
sa += t;
} }
py += dy; py += dy;
} }
@@ -119,9 +110,7 @@ RScaleImage(RImage *image, unsigned new_width, unsigned new_height)
for (y=0; y<new_height; y++) { for (y=0; y<new_height; y++) {
t = image->width*(py>>16); t = image->width*(py>>16);
sr = image->data[0]+t; s = image->data+t;
sg = image->data[1]+t;
sb = image->data[2]+t;
ot = t; ot = t;
ox = 0; ox = 0;
@@ -129,16 +118,14 @@ RScaleImage(RImage *image, unsigned new_width, unsigned new_height)
for (x=0; x<new_width; x++) { for (x=0; x<new_width; x++) {
px += dx; px += dx;
*(dr++) = *sr; *(d++) = *(s);
*(dg++) = *sg; *(d++) = *(s+1);
*(db++) = *sb; *(d++) = *(s+2);
t = (px-ox)>>16; t = (px-ox)>>16;
ox += t<<16; ox += t<<16;
sr += t; s += (t<<1)+t; /* t*3 */
sg += t;
sb += t;
} }
py += dy; py += dy;
} }
@@ -431,6 +418,9 @@ CLIST *contrib; /* array of contribution lists */
#define CLAMP(v,l,h) ((v)<(l) ? (l) : (v) > (h) ? (h) : v) #define CLAMP(v,l,h) ((v)<(l) ? (l) : (v) > (h) ? (h) : v)
#include "bench.h"
RImage* RImage*
RSmoothScaleImage(RImage *src, unsigned new_width, unsigned new_height) RSmoothScaleImage(RImage *src, unsigned new_width, unsigned new_height)
{ {
@@ -442,8 +432,10 @@ RSmoothScaleImage(RImage *src, unsigned new_width, unsigned new_height)
double width, fscale; /* filter calculation variables */ double width, fscale; /* filter calculation variables */
double rweight, gweight, bweight; double rweight, gweight, bweight;
RImage *dst; RImage *dst;
unsigned char *rp, *gp, *bp; unsigned char *p;
unsigned char *rsp, *gsp, *bsp; unsigned char *sp;
int sch = src->format == RRGBAFormat ? 4 : 3;
dst = RCreateImage(new_width, new_height, False); dst = RCreateImage(new_width, new_height, False);
@@ -475,11 +467,12 @@ RSmoothScaleImage(RImage *src, unsigned new_width, unsigned new_height)
n = j; n = j;
} }
k = contrib[i].n++; k = contrib[i].n++;
contrib[i].p[k].pixel = n; contrib[i].p[k].pixel = n*sch;
contrib[i].p[k].weight = rweight; contrib[i].p[k].weight = rweight;
} }
} }
} else { } else {
for(i = 0; i < new_width; ++i) { for(i = 0; i < new_width; ++i) {
contrib[i].n = 0; contrib[i].n = 0;
contrib[i].p = (CONTRIB *)calloc((int) (fwidth * 2 + 1), contrib[i].p = (CONTRIB *)calloc((int) (fwidth * 2 + 1),
@@ -498,32 +491,29 @@ RSmoothScaleImage(RImage *src, unsigned new_width, unsigned new_height)
n = j; n = j;
} }
k = contrib[i].n++; k = contrib[i].n++;
contrib[i].p[k].pixel = n; contrib[i].p[k].pixel = n*sch;
contrib[i].p[k].weight = rweight; contrib[i].p[k].weight = rweight;
} }
} }
} }
/* apply filter to zoom horizontally from src to tmp */ /* apply filter to zoom horizontally from src to tmp */
rp = tmp->data[0]; p = tmp->data;
gp = tmp->data[1];
bp = tmp->data[2];
for(k = 0; k < tmp->height; ++k) { for(k = 0; k < tmp->height; ++k) {
rsp = src->data[0] + src->width*k; sp = src->data + src->width*k*sch;
gsp = src->data[1] + src->width*k;
bsp = src->data[2] + src->width*k;
for(i = 0; i < tmp->width; ++i) { for(i = 0; i < tmp->width; ++i) {
rweight = gweight = bweight = 0.0; rweight = gweight = bweight = 0.0;
for(j = 0; j < contrib[i].n; ++j) { for(j = 0; j < contrib[i].n; ++j) {
rweight += rsp[contrib[i].p[j].pixel] * contrib[i].p[j].weight; rweight += sp[contrib[i].p[j].pixel] * contrib[i].p[j].weight;
gweight += gsp[contrib[i].p[j].pixel] * contrib[i].p[j].weight; gweight += sp[contrib[i].p[j].pixel+1] * contrib[i].p[j].weight;
bweight += bsp[contrib[i].p[j].pixel] * contrib[i].p[j].weight; bweight += sp[contrib[i].p[j].pixel+2] * contrib[i].p[j].weight;
} }
*rp++ = CLAMP(rweight, 0, 255); *p++ = CLAMP(rweight, 0, 255);
*gp++ = CLAMP(gweight, 0, 255); *p++ = CLAMP(gweight, 0, 255);
*bp++ = CLAMP(bweight, 0, 255); *p++ = CLAMP(bweight, 0, 255);
} }
} }
@@ -556,7 +546,7 @@ RSmoothScaleImage(RImage *src, unsigned new_width, unsigned new_height)
n = j; n = j;
} }
k = contrib[i].n++; k = contrib[i].n++;
contrib[i].p[k].pixel = n; contrib[i].p[k].pixel = n*3;
contrib[i].p[k].weight = rweight; contrib[i].p[k].weight = rweight;
} }
} }
@@ -579,61 +569,45 @@ RSmoothScaleImage(RImage *src, unsigned new_width, unsigned new_height)
n = j; n = j;
} }
k = contrib[i].n++; k = contrib[i].n++;
contrib[i].p[k].pixel = n; contrib[i].p[k].pixel = n*3;
contrib[i].p[k].weight = rweight; contrib[i].p[k].weight = rweight;
} }
} }
} }
/* apply filter to zoom vertically from tmp to dst */ /* apply filter to zoom vertically from tmp to dst */
rsp = malloc(tmp->height); sp = malloc(tmp->height*3);
gsp = malloc(tmp->height);
bsp = malloc(tmp->height);
for(k = 0; k < new_width; ++k) { for(k = 0; k < new_width; ++k) {
rp = dst->data[0] + k; p = dst->data + k*3;
gp = dst->data[1] + k;
bp = dst->data[2] + k;
/* copy a column into a row */ /* copy a column into a row */
{ {
int i; int i;
unsigned char *p, *d; unsigned char *p, *d;
d = rsp; d = sp;
for(i = tmp->height, p = tmp->data[0] + k; i-- > 0; for(i = tmp->height, p = tmp->data + k*3; i-- > 0;
p += tmp->width) { p += tmp->width*3) {
*d++ = *p;
}
d = gsp;
for(i = tmp->height, p = tmp->data[1] + k; i-- > 0;
p += tmp->width) {
*d++ = *p;
}
d = bsp;
for(i = tmp->height, p = tmp->data[2] + k; i-- > 0;
p += tmp->width) {
*d++ = *p; *d++ = *p;
*d++ = *(p+1);
*d++ = *(p+2);
} }
} }
for(i = 0; i < new_height; ++i) { for(i = 0; i < new_height; ++i) {
rweight = gweight = bweight = 0.0; rweight = gweight = bweight = 0.0;
for(j = 0; j < contrib[i].n; ++j) { for(j = 0; j < contrib[i].n; ++j) {
rweight += rsp[contrib[i].p[j].pixel] * contrib[i].p[j].weight; rweight += sp[contrib[i].p[j].pixel] * contrib[i].p[j].weight;
gweight += gsp[contrib[i].p[j].pixel] * contrib[i].p[j].weight; gweight += sp[contrib[i].p[j].pixel+1] * contrib[i].p[j].weight;
bweight += bsp[contrib[i].p[j].pixel] * contrib[i].p[j].weight; bweight += sp[contrib[i].p[j].pixel+2] * contrib[i].p[j].weight;
} }
*rp = CLAMP(rweight, 0, 255); *p = CLAMP(rweight, 0, 255);
*gp = CLAMP(gweight, 0, 255); *(p+1) = CLAMP(gweight, 0, 255);
*bp = CLAMP(bweight, 0, 255); *(p+2) = CLAMP(bweight, 0, 255);
rp += new_width; p += new_width*3;
gp += new_width;
bp += new_width;
} }
} }
free(rsp); free(sp);
free(gsp);
free(bsp);
/* free the memory allocated for vertical filter weights */ /* free the memory allocated for vertical filter weights */
for(i = 0; i < dst->height; ++i) { for(i = 0; i < dst->height; ++i) {

View File

@@ -10,6 +10,7 @@
#include <time.h> #include <time.h>
#endif #endif
Display *dpy; Display *dpy;
Window win; Window win;
RContext *ctx; RContext *ctx;
@@ -192,11 +193,12 @@ int main(int argc, char **argv)
imgh = RRenderMultiGradient(250, 250, colors, RGRD_HORIZONTAL); imgh = RRenderMultiGradient(250, 250, colors, RGRD_HORIZONTAL);
imgv = RRenderMultiGradient(250, 250, colors, RGRD_VERTICAL); imgv = RRenderMultiGradient(250, 250, colors, RGRD_VERTICAL);
imgd = RRenderMultiGradient(250, 250, colors, RGRD_DIAGONAL); imgd = RRenderMultiGradient(250, 250, colors, RGRD_DIAGONAL);
RConvertImage(ctx, imgh, &pix); RConvertImage(ctx, imgh, &pix);
XCopyArea(dpy, pix, win, ctx->copy_gc, 0, 0, 250, 250, 0, 0); XCopyArea(dpy, pix, win, ctx->copy_gc, 0, 0, 250, 250, 0, 0);
RConvertImage(ctx, imgv, &pix); RConvertImage(ctx, imgv, &pix);
XCopyArea(dpy, pix, win, ctx->copy_gc, 0, 0, 250, 250, 250, 0); XCopyArea(dpy, pix, win, ctx->copy_gc, 0, 0, 250, 250, 250, 0);
RConvertImage(ctx, imgd, &pix); RConvertImage(ctx, imgd, &pix);
XCopyArea(dpy, pix, win, ctx->copy_gc, 0, 0, 250, 250, 500, 0); XCopyArea(dpy, pix, win, ctx->copy_gc, 0, 0, 250, 250, 500, 0);

View File

@@ -47,6 +47,7 @@ RLoadTIFF(RContext *context, char *file, int index)
uint32 *data, *ptr; uint32 *data, *ptr;
uint16 extrasamples; uint16 extrasamples;
uint16 *sampleinfo; uint16 *sampleinfo;
int ch;
tif = TIFFOpen(file, "r"); tif = TIFFOpen(file, "r");
@@ -94,13 +95,18 @@ RLoadTIFF(RContext *context, char *file, int index)
/* convert data */ /* convert data */
image = RCreateImage(width, height, alpha); image = RCreateImage(width, height, alpha);
if (alpha)
ch = 4;
else
ch = 3;
if (image) { if (image) {
int x, y; int x, y;
r = image->data[0]; r = image->data;
g = image->data[1]; g = image->data+1;
b = image->data[2]; b = image->data+2;
a = image->data[3]; a = image->data+3;
/* data seems to be stored upside down */ /* data seems to be stored upside down */
data += width * (height-1); data += width * (height-1);
@@ -120,10 +126,10 @@ RLoadTIFF(RContext *context, char *file, int index)
*b = (*b * 255) / *(a); *b = (*b * 255) / *(a);
} }
a++; a+=4;
} }
r++; g++; b++; r+=ch; g+=ch; b+=ch;
data++; data++;
} }
data -= 2*width; data -= 2*width;

View File

@@ -1,121 +1,125 @@
/* XPM */ /* XPM */
static char *image_name[] = { static char *image_name[] = {
/* width height num_colors chars_per_pixel */
" 64 64 54 1", " 64 64 54 1",
" c white", /* colors */
". c #000000000000", ". c #ffffff",
"X c #514461856185", "# c #000000",
"o c #A289A289B2CA", "a c #516161",
"O c #A289A289A289", "b c #a2a2b2",
"+ c #A2899248B2CA", "c c #a2a2a2",
"@ c #9248A289A289", "d c #a292b2",
"# c #A2899248A289", "e c #92a2a2",
"$ c #92489248A289", "f c #a292a2",
"% c #924892489248", "g c #9292a2",
"& c #92488207A289", "h c #929292",
"* c #820792489248", "i c #9282a2",
"= c #924882079248", "j c #829292",
"- c #820782079248", "k c #928292",
"; c #820782078207", "l c #828292",
": c #820771C69248", "m c #828282",
"> c #618551446185", "n c #827192",
", c #9248A289B2CA", "o c #615161",
"< c #92489248B2CA", "p c #92a2b2",
"1 c #82079248A289", "q c #9292b2",
"2 c #82078207A289", "r c #8292a2",
"3 c #71C682079248", "s c #8282a2",
"4 c #71C682078207", "t c #718292",
"5 c #514451446185", "u c #718282",
"6 c #514451445144", "v c #515161",
"7 c #820771C68207", "w c #515151",
"8 c #410351445144", "x c #827182",
"9 c #514441035144", "y c #415151",
"0 c #71C671C69248", "z c #514151",
"q c #71C671C68207", "A c #717192",
"w c #71C671C671C6", "B c #717182",
"e c #410341035144", "C c #717171",
"r c #71C661858207", "D c #414151",
"t c #618571C68207", "E c #716182",
"y c #410351444103", "F c #617182",
"u c #410341034103", "G c #415141",
"i c #618571C671C6", "H c #414141",
"p c #410330C24103", "I c #617171",
"a c #30C241034103", "J c #413041",
"s c #71C6618571C6", "K c #304141",
"d c #6185618571C6", "L c #716171",
"f c #618561858207", "M c #616171",
"g c #30C230C230C2", "N c #616182",
"h c #618561856185", "O c #303030",
"j c #30C230C24103", "P c #616161",
"k c #5144618571C6", "Q c #303041",
"l c #30C2410330C2", "R c #516171",
"z c #6185514471C6", "S c #304130",
"x c #208130C230C2", "T c #615171",
"c c #30C2208130C2", "U c #203030",
"v c #5144514471C6", "V c #302030",
"b c #2081208130C2", "W c #515171",
"n c #208120812081", "X c #202030",
"m c #410330C25144", "Y c #202020",
" .", "Z c #413051",
" X.", /* pixels */
" oOoO+O+O+O+@#$+@#$#$#$$$#$$%&%&%&%&*&*&*=-=*=-=-=--;---;:;:;>.", "...............................................................#",
" oo@o,o@o@o@+@+@<@$@$@$@$@$1$$$*$*$*&*&*2*&*2*-*-*-----3-3-4-X.", "..............................................................a#",
" oO+OoO#O+@#@#@#$#@#$#%#$$%$%$%&%&*=%&*=*=*=-=-=--;-;-;:;:;:;5.", "..bcbcdcdcdcdefgdefgfgfgggfgghihihihijijijklkjklklkllmlllmnmnmo#",
" ,ooo@+@+@+@+@<@#@<@$$$$$$$$$*$1$*&*&*&*&*2*---*-----3---4:4:6.", "..bbebpbebebededeqegegegegegrgggjgjgjijijsjijsjljljllllltltlula#",
" +O+O+O+@#$#@#$#$#$$%$$$%&%&%&%&*=*&*=-=*=---=--;---;:;:4:;:45.", "..bcdcbcfcdefefefgfefgfhfgghghghihijkhijkjkjklklkllmlmlmnmnmnmv#",
" @o@o@o@+@+@<@$@$@$$$@$1$1$*$*$*&*&*2*=*2*-*-*-----4-3-4:4-4:6.", "..pbbbededededeqefeqegggggggggjgrgjijijijijsjllljllllltlllununw#",
" +O#O+@#@#@#$#$#$#%#%$%&%$%&%&*=*&*=*=*=-=-=--;-;-;:;:;:;:4745.", "..dcdcdcdefgfefgfgfgghggghihihihijkjijklkjklllkllmlllmnmnunmnuv#",
" @+@+@+@+@<@#@$@$$$$$$$$$*$*$*&*&*&*&*2*---*-----3---4:4:4:4:8.", "..ebebebededeqegegegggegrgrgjgjgjijijsjkjsjljljlllllultlunulunw#",
" #O+@#$#@#$#$#$$%$$$%&%&%&%&*=*&*=-=-=---=--;:;-;:;:4:4:474:49.", "..dcfcdefefefgfgfgfhfhghihghihijkjijkjkjklklkllmlmlmnmnmnmnuxuv#",
" @o@<@+@<@$@$@$$$$$1$1$*$*$*&*&*2*=*2*-*-*-----4-4-4:4:4:4:408.", "..ededededeqefegegggggggggjgjgjijijijijsjllljllllltlllununununy#",
" +@#@#@#$#$#$$%#%$%&%$%&%&*=*&*=*=*=-=-=--;-;-;:;:;:;:474747q9.", "..fcdefgfefgfgfgghggghihihihijkjijklklklllkllmnmlmnmnununuxunuz#",
" @+@+@<@$$$@$$$$$1$$$*&*$*&*&*&*&*2*---------3-3-4:4:4:4:404q8.", "..ebeqedeqegegegggggrgrgjgjgjijijsjkjsjljljlllllululununununuAy#",
" #$#@#$#$#$$%$$$%&%&%&%&*=-&*=-=-=---=--;:;:;:;:4:4:474:47q7q9.", "..defefefgfgfgghfhghihghihijkjijkjkjklklkllmlmlmnmnmnmnuxuxuxBz#",
" @#@<@$@$@$$$$$*$1$*$*$*&*&*2*-*2*-*-*-3---4-4-4:4:4:4:404q4q8.", "..ededeqegggegggggrgggjijgjijijijijsjllllllllltltlununununuAuBy#",
" #@#$#$#$$%$%$%&%$%&%&*=*=*=-=*=-=;=--;-;-;:;:47;:474747q7q7q9.", "..fgfefgfgfgghggghihihihijklijklklklllkllmnmnmnmnununuxunuxBxBz#",
" @<@$$$@$$$$$1$$$*&*&*&*&*&*=*2*---------4-3-4:4:4:4:404qq04q8.", "..efeqegegegggggjgrgjgjgjijijsjljsjljljltlllululununununuAuBuBy#",
" #$#$#$$%$%$%&%&%&%&*=-&*=-=-=------;:;:;:;:4:4:47q747qqq7qqq9.", "..fefgfgfgghghghihghihijkjkjklkjklkmkllmlmlmnmnuxmnuxuxuxBxBxBz#",
" @$@$@$$$$$*$1$*$*$*&*&*2*-*-*---*-3-3-4-4-4:4:4:4:404q4q4qqq8.", "..eqegggegggggrgggjijijijijijkjsjlllllllllultlununununuAuBBAuBy#",
" #$#$$%$%$%&%&%&%&*=*=*=-=-=-=;=--;:;-;:;:474:474747q7q7qqwqw9.", "..fgfgfgghghghihihihijklijklklkllllllmnmnmnmnununuxBxuxBBBxBBBz#",
" $$@$$$$$*$$$*&*&*&*&*2*=*2*---------4-3-4:4:4:4:404qqq4qqqqqe.", "..egegegggggjgrgjgjgjijijsjljljllljltltlululununununuAuBuBuBBBy#",
" #$$%$%$%&%&*&%&*=-&*=-=-=------;:;:;:;:4:4:47q7q7qqq7qqwrqqw9.", "..fgfgghghghihihihijkjkjklklklkmkllmnmlmnmnuxunuxuxuxBxBxBBCBCz#",
" @$$$$$*$1$*&*$*2*&*2*-*-*-----3-3-4-4-4:4:404:404q4q4qqqqqtqy.", "..ggegggggjgggjijijijijsjkjsjlllllllllultlununununuAuBBBuBBBBBD#",
" $%$%$%&%&%=%&*=*=*=-=-=--;=--;:;-;:;:474:474747q7q7qqwqwqwrwe.", "..fgghghghihijihijklijklklkllllllmnmnmnmnununuxBxBxBBBxBBCEBBCz#",
" $$$$*$1$*&*&*&*&*2*--2*-----3---4:3-4:4:4:4:404qqqqqqqqqtqtqu.", "..egggggjgrgjijgjsjijsjljljllllltltlululununuAunuAuBuBuBBBBBFBG#",
" &%$%&%&*&*&*=-=*=-=-=--;---;:;:;:;:4:4:47q7q7qqq7qqwrqrwrwrip.", "..ghghghihihkhijkjkjklklkllmkllmnmlmnmnuxunuxuxuxBxBxBBCBCBCECD#",
" $$*$*$*&*&*2*&*2*-*-*-----3-3-4-4-4:4:404q404q4q4qtqqqiqtqiru.", "..ggggjgrgjijijijijsjllsjllllltllluntlununununuAuBBBBBBBBBFBFBH#",
" $%&%&*=%&*=*=*=-=-=--;-;-;:;-;:;:474:47q747q7q7qqwqwqwrwrirwu.", "..ihghihijijijklkjklklkllmlllmnmnmnmnununuxBxBxBBBxBBCEBECECEIJ#",
" *$1$*&*&*&*&*2*---*-----3---4:4:4:4:4:4:404qqqqqqqqqtqtqirira.", "..ggjgjgjijijsjijsjljljllllltltlululununuAuBuAuBuBuBFBBBIBFBIEH#",
" &%&*=*&*=-=*=-=-=--;---;:;:;:;:4:4:47q7q7qqqqqqwrqrwrwriririp.", "..ghihijkhijkjkjklklkllmlmlmnmlmnmnuxunuxBxuxBxBxBBCBCBCECEIECH#",
" *$*&*&*2*&*2*-*-*-----3-3-4-4-4:4:404q4q4qqq4qtqtqiqiqiriqira.", "..jgrgjijijijijsjllljllllltlllununununununuAuBBBBBBBBBFBFBIEIEK#",
" &*=*&*=*=*=-=-=--;-;-;:;:;:;:474:47q7q7q7q7qqwrwqwrwrirwrisip.", "..ihijkjijklkjklklkllmlllmnmnmnmnununuxBxBxBBBBBBCEBECECEIEIEIJ#",
" *&*&*&*&*2*---*-----3---4:4:4:4:404:404qqqqqqqqqtqtqiriririra.", "..jgjijijsjijsjljljllllltltlululununuAuBuBuBBBuBFBFBIBIBIEIBIEK#",
" =*&*=-=*=---=--;---;:;:4:;:474:47q7q7qqqqqqwrwrwrwriririsdrdp.", "..ijkjijkjkjklklkllmlmlmnmnmnmnuxunuxBxBxBxBxBBCECBCECEIECEILIJ#",
" *&*2*=*2*-*-*-----4-3-4:4-4:4:404q4q4qqqqqtqtqiqiqiriqifirifa.", "..jijijijijsjllljllllltlllununununuAunuAuBBBBBBBBBFBFBIEIEIEIEK#",
" &*=*=*=-=-=--;-;-;:;:;:;:474747q7q7qqq7qqwrwqwrwrirwrisisisdp.", "..kjijklkjklllkllmlllmnmnunmnuxunuxBxBxBBBBBBCECECECEIEIEILMEMJ#",
" *&*&*2*---*-----3-3-4:4:4:4:404qq04qqqqqtqqqirtqiririririfida.", "..jijsjkjsjljljlllllultlunulununuAuBuBuBBBBBFBFBIBIBIEIBINIEINK#",
" =-=-=---=--;:;-;:;:4:4:474:47q7q7qqqqqqwrwrwrwriririsdrdsdddp.", "..ijkjkjklklkllmlmlmnmnmnmnuxuxuxBxBxBBBxBBCECBCECEIECEILILILMJ#",
" *=*2*-*-*-----4-4-4:4:4:4:404q4q4qqqqqtqtqiqiqiriqifififidida.", "..jijijsjllljllllltltlununununuAuBBAuBBBBBFBBBIEFBIEIEIEIEINIMK#",
" =*=-=-=--;-;-;:;:4:;:474747q7q7qqwqwqwrwqwrwrirwrisdsisdsdsdp.", "..klklklllkllmnmlmnmnununuxunuxBxBxBBBBBBCECECECEIEIEILMEMLMMMJ#",
" *2*---------4-3-4:4:4:4:404qq04qqqqqtqqqiririririririfidddddg.", "..jkjsjljljlllllululununununuAuBuBuBBBBBFBFBIBIBIEIBINININIMIMK#",
" =---=--;:;:;:;:4:4:474:47q7q7qqqqqqwrwrwrwriririsdsdsddddddhj.", "..kjklklkllmlmlmnmnunmnuxuxuxBxBxBBCBCBCECBCECEIECEILMLILMLMLMJ#",
" *---*-3---4-4-4:4:4:4:404q4q4qqqqqtqtqiqiqiririfififidddidkdl.", "..jsjlllllllllultlununununuAuBBAuBBBBBFBBBIEIEIEIEIEIEINIMMMMMO#",
" =;=--;:;-;:;:474:474747q7q7qqwqwqwrwrwrwrirwrisdsdsdsdsddhzhj.", "..klllkllmnmnmnmnununuxunuxBxBxBBBBBBCECECECEIEIEILMLMLMMMMMMPQ#",
" --------4-3-4:4:4:4:404qq04qqqqqtqqqiririririfirifidddddddddx.", "..jllljltlllululununununuAuBuBuBBBBBFBFBIBIBIEIEINININIMMMIMRMS#",
" ---;:;:;:;:4:4:47q747qqq7qqwqqqwrwrirwriririsdsdsddddddhzhzhc.", "..kmkllmnmlmnmnuxunuxuxuxBxBxBBCBCBCECECECEIECEILMLMLMLMLMMPTPQ#",
" --3-3-4-4-4:4:4:4:404q4q4qqqqqtqtqiriqiririfififidddddkdkdXdx.", "..llllllllultlununununuAuBBAuBBBBBFBBBIEIEIEIEINIEINIMMMMMMMMMU#",
" -;:;-;:;:474:474747q7q7qqwqwqwrwrwrwrisisisdsdsdddsddhzhdhzhg.", "..lllmnmnmnmnununuxBxuxBBBxBBCBBBCECEIECEIEIEILMLMLMMMMMMPTPTPV#",
" ----4-3-4:4:4:4:404qqq4qqqqqtqtqiriririrififdfidddddkdddkzkdx.", "..lltltlululununununuAuBuBuBBBBBFBFBIEIBIEIEINININIMMMMMRMRMaMU#",
" :;:;:;:4:4:47q7q7qqq7qqwrqqwrwriririririsdsdsddddddhzhzhzhzXc.", "..lmnmlmnmnuxunuxuxuxBxBxBBCBCBCECECECEILILILMLMLMMMLMMPTPMPTPO#",
" 3-4-4-4:4:404:404q4q4qqqqqtqtqiriqiririfidididddddkdkdXdXdXzx.", "..llllultlununununuAuBBBuBBBBBFBFBIEIEIEIEININMNIMMMMMRMMMRTRMU#",
" -;:;:474:47q747q7q7qqwqwqwrwrirwrisisisdsdsddddddhzhdhzhzXzhc.", "..nmnmnmnununuxBxBxBBBxBBCEBBCECEIEIEIEIEILMLMLMMMMMMPTPTPTPTaV#",
" 4:4-4:4:4:4:404qqqqqqqqqtqtqiriririrififdfidddddkdddkzkdXzXzx.", "..tlululununuAunuAuBuBuBBBBBFBFBIEIBIEIEINIMIMIMMMMMRMRMaMaMaTU#",
" :;:4:4:47q7q7qqq7qqwrqrwrwriririsirisdsdsddddddhzhzhzhzXzXzXc.", "..lmnmnuxunuxBxuxBxBxBBCBCBCECEIECEILILILMLMLMMMMMMPTPMPTPTaTPV#",
" 4-4:4:404q404qqq4qtqqqiqtqiriqiririfidididddddkdkdXdXdXzXzXvx.", "..unulununununuAuBBBBBBBBBFBFBIEIEIEIEININMNIMMMMMRMMMRTRMaTaTU#",
" :474:47q7q7q7q7qqwrwqwrwrirwrisisisdsdsddddddhzhzhzhzXzhzX>5c.", "..nmnununuxBxBxBBBxBBCEBECECEIEIEILIEILMLMLMMMMMMPTPTPTPTaTaTaV#",
" 4:4:4:4:404qqqqqqqqqtqtqiririririfiddfidddddkdddXzkdXzXzXvXzx.", "..ulununuAuBuAuBBBuBFBBBIBFBIEIBIEIEINIMIMIMMMMMRMRMaMaMaTaTaWU#",
" :4:47q7q7qqqqqqwrwrwrwriririsdrisdddsddddddhzhzXzhzXzXzX>5>5c.", "..nuxunuxBxBxBxBxBBCECBCECEIECEILILILMLMLMMMMMMPTPTPTPTaTPTaovV#",
" 4:404q4q4qqqqqtqtqiqiqiriqiririfidididddddkdkdXzXdXzXzXvXvXvx.", "..ununununuAuBBBBBBBBBFBFBIEIEIEIEINIMMNIMMMMMRMMMaTRMaTaTaWaTU#",
" :47q7q7q7q7qqwrwqwrwrirwrisisisdsdsddhdddhzhzhzhzXzXzX>5>5>5b.", "..nunuxBxBxBBBBBBCECECECEIEIEILMEILMMMLMMMMMMPTPTaTPTaTaTaovovV#",
" 404:404qqqqqqqqqiqtqiririririfidddidddddkdkdXzkzXzXzXvXv5vX5n.", "..unuAuBuBuBBBBBFBFBIBIBIEIBIEIEINIMIMIMMMMMRMRMaTaMaTaTaWaWaWU#",
" >65656569698989y9e9u9ueumueupupapaplpgjgjgjgcgcgcgcxcbcncnbnb.", "..nuxBxBxBxBxBBCECBCECEIECEILILILMLMLMMPMMMPTPTPTPTaTaTaovovovX#",
" ..............................................................."}; "..uAunuAuBBBBBBBBBIBFBIEIEIEIEINIMMMIMMMMMRMRMaTRTaTaTaWaWvWavY#",
"..owvwvwvwzwzyzyzGzDzHzHDHZHDHJHJKJKJSJOQOQOQOVOVOVOVUVXVYVYXYX#",
".###############################################################"
};

View File

@@ -20,12 +20,12 @@ int main(int argc, char **argv)
puts("cant open display"); puts("cant open display");
exit(1); exit(1);
} }
attr.flags = RC_RenderMode | RC_ColorsPerChannel; attr.flags = RC_RenderMode | RC_ColorsPerChannel;
attr.render_mode = RDitheredRendering; attr.render_mode = RDitheredRendering;
attr.colors_per_channel = 4; attr.colors_per_channel = 4;
ctx = RCreateContext(dpy, DefaultScreen(dpy), &attr); ctx = RCreateContext(dpy, DefaultScreen(dpy), &attr);
if (argc<2) if (argc<2)
img = RGetImageFromXPMData(ctx, image_name); img = RGetImageFromXPMData(ctx, image_name);
else else
@@ -54,15 +54,17 @@ int main(int argc, char **argv)
exit(1); exit(1);
} }
printf("%ix%i\n", img->width, img->height);
win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 10, 10, win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 10, 10,
img->width, img->width,
img->height, 0, 0, 0); img->height, 0, 0, 0);
RDestroyImage(img);
XSetWindowBackgroundPixmap(dpy, win, pix); XSetWindowBackgroundPixmap(dpy, win, pix);
XClearWindow(dpy, win); XClearWindow(dpy, win);
XMapRaised(dpy, win); XMapRaised(dpy, win);
XFlush(dpy); XFlush(dpy);
getchar(); getchar();
exit(0); exit(0);
} }

View File

@@ -39,8 +39,8 @@
#define RLRASTER_H_ #define RLRASTER_H_
/* version of the header for the library: 0.16 */ /* version of the header for the library: 0.20 */
#define WRASTER_HEADER_VERSION 16 #define WRASTER_HEADER_VERSION 20
#include <X11/Xlib.h> #include <X11/Xlib.h>
@@ -145,6 +145,7 @@ typedef struct RContext {
struct { struct {
unsigned int use_shared_pixmap:1; unsigned int use_shared_pixmap:1;
unsigned int optimize_for_speed:1;
} flags; } flags;
} RContext; } RContext;
@@ -175,13 +176,22 @@ typedef struct RSegment {
} RSegment; } RSegment;
/* image formats */
enum RImageFormat {
RRGBFormat,
RRGBAFormat
};
/* /*
* internal 24bit+alpha image representation * internal 24bit+alpha image representation
*/ */
typedef struct RImage { typedef struct RImage {
unsigned char *data; /* image data RGBA or RGB */
unsigned width, height; /* size of the image */ unsigned width, height; /* size of the image */
enum RImageFormat format;
RColor background; /* background color */ RColor background; /* background color */
unsigned char *data[4]; /* image data (R,G,B,A) */
} RImage; } RImage;
@@ -199,7 +209,6 @@ typedef struct RXImage {
} RXImage; } RXImage;
/* image display modes */ /* image display modes */
enum { enum {
RDitheredRendering = 0, RDitheredRendering = 0,
@@ -313,7 +322,7 @@ RImage *RLoadImage(RContext *context, char *file, int index);
void RDestroyImage(RImage *image); void RDestroyImage(RImage *image);
RImage *RGetImageFromXPMData(RContext *context, char **data); RImage *RGetImageFromXPMData(RContext *context, char **xpmData);
/* /*
* RImage storing * RImage storing

285
wrlib/x86_specific.c Normal file
View File

@@ -0,0 +1,285 @@
/* x86_convert.c - convert RImage to XImage with x86 optimizations
*
* Raster graphics library
*
* Copyright (c) 2000 Alfredo K. Kojima
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <config.h>
#ifdef ASM_X86_MMX
int
x86_check_mmx()
{
static int result = 1;
if (result >= 0)
return result;
result = 0;
#if 0
asm volatile
("pushfl \n" // check whether cpuid supported
"pop %%eax \n"
"movl %%eax, %%ebx \n"
"xorl 1<<21, %%eax \n"
"pushfl %%eax \n"
"popfd \n"
"pushfl \n"
"popl %%eax \n"
"xorl %%eax, %%ebx \n"
"andl 1<<21, %%eax \n"
"jz .NotPentium \n"
"xorl %%eax, %%eax \n"
"movl $1, %%eax \n"
"cpuid \n"
"test 1<<23, %%edx \n"
"jz .NotMMX \n"
"movl $1, %%0 \n"
".NotMMX: \n"
".Bye: \n"
".NotPentium: \n"
: "=rm" (result));
#endif
return result;
}
void
x86_TrueColor_32_to_16(unsigned char *image, // 8
unsigned short *ximage, // 12
short *err, // 16
short *nerr, // 20
short *rtable, // 24
short *gtable, // 28
short *btable, // 32
int dr, // 36
int dg, // 40
int db, // 44
unsigned int roffs, // 48
unsigned int goffs, // 52
unsigned int boffs, // 56
int width, // 60
int height, // 64
int line_offset) // 68
{
/*
int x; //-4
long long rrggbbaa;// -16
long long pixel; //-24
short *tmp_err; //-32
short *tmp_nerr; //-36
*/
asm volatile
(
"subl $64, %esp \n" // alloc some more stack
"pusha \n"
// pack dr, dg and db into mm6
"movl 36(%ebp), %eax \n"
"movl 40(%ebp), %ebx \n"
"movw %ax, -16(%ebp) \n"
"movw %bx, -14(%ebp) \n"
"movl 44(%ebp), %eax \n"
"movw $0, -10(%ebp) \n"
"movw %ax, -12(%ebp) \n"
"movq -16(%ebp), %mm6 \n" // dr dg db 0
// pack 4|4|4|4 into mm7, for shifting (/16)
"movl $0x00040004, -16(%ebp) \n"
"movl $0x00040004, -12(%ebp) \n"
"movq -16(%ebp), %mm7 \n"
// store constant values for using with mmx when dithering
"movl $0x00070007, -16(%ebp) \n"
"movl $0x00070007, -12(%ebp) \n"
"movq -16(%ebp), %mm5 \n"
"movl $0x00050005, -16(%ebp) \n"
"movl $0x00050005, -12(%ebp) \n"
"movq -16(%ebp), %mm4 \n"
"movl $0x00030003, -16(%ebp) \n"
"movl $0x00030003, -12(%ebp) \n"
"movq -16(%ebp), %mm3 \n"
// process 1 pixel / cycle, each component treated as 16bit
"movl 8(%ebp), %esi \n" // esi = image->data
".LoopY: \n"
"movl 60(%ebp), %eax \n"
"movl %eax, -4(%ebp) \n" // x = width
"movl 64(%ebp), %eax \n"
"decl %eax \n" // y--
"movl %eax, 64(%ebp) \n"
"js .End \n" // if y < 0, goto end
"andl $1, %eax \n"
"jz .LoopY_1 \n" // if (y&1) goto LoopY_1
".LoopY_0: \n"
"movl 16(%ebp), %ebx \n" // ebx = err
"movl %ebx, -36(%ebp) \n" // [-36] = err
"movl 20(%ebp), %eax \n" //
"movl %eax, -32(%ebp) \n" // [-32] = nerr
"jmp .LoopX \n"
".LoopY_1: \n"
"movl 20(%ebp), %ebx \n" // ebx = nerr
"movl %ebx, -36(%ebp) \n" // [-36] = nerr
"movl 16(%ebp), %eax \n" //
"movl %eax, -32(%ebp) \n" // [-32] = eerr
".LoopX: \n"
// calculate errors and pixel components
// depend on ebx, esi, mm6
"movq (%ebx), %mm1 \n" // mm1 = error[0..3]
"punpcklbw (%esi), %mm0 \n" // mm0 = image->data[0..3]
"psrlw $8, %mm0 \n" // fixup mm0
"paddusb %mm1, %mm0 \n" // mm0 = mm0 + mm1 (sat. to 255)
"movq %mm0, -24(%ebp) \n" // save the pixel
"movzwl -24(%ebp), %ecx \n" // ecx = pixel.red
"movl 24(%ebp), %edi \n" // edi = rtable
"leal (%edi, %ecx, 2), %eax \n" // eax = &rtable[pixel.red]
"movl (%eax), %edx \n" // edx = rtable[pixel.red]
"movw %dx, -16(%ebp) \n" // save rr
"movzwl -22(%ebp), %ecx \n" // ecx = pixel.green
"movl 28(%ebp), %edi \n" // edi = gtable
"leal (%edi, %ecx, 2), %eax \n" // eax = &gtable[pixel.green]
"movl (%eax), %edx \n" // ebx = gtable[pixel.green]
"movw %dx, -14(%ebp) \n" // save gg
"movzwl -20(%ebp), %ecx \n" // ecx = pixel.blue
"movl 32(%ebp), %edi \n" // ebx = btable
"leal (%edi, %ecx, 2), %eax \n" // eax = &btable[pixel.blue]
"movl (%eax), %edx \n" // ecx = btable[pixel.blue]
"movw %dx, -12(%ebp) \n" // save bb
"movw $0, -10(%ebp) \n" // save dummy aa
"movq -16(%ebp), %mm1 \n" // load mm1 with rrggbbaa
"pmullw %mm6, %mm1 \n" // mm1 = rr*dr|...
"psubsw %mm1, %mm0 \n" // error = pixel - mm1
// distribute the error
// depend on mm0, mm7, mm3, mm4, mm5
"movl -36(%ebp), %ebx \n"
"movq %mm0, %mm1 \n"
"pmullw %mm5, %mm1 \n" // mm1 = mm1*7
"psrlw %mm7, %mm1 \n" // mm1 = mm1/16
"paddw 8(%ebx), %mm1 \n"
"movq %mm1, 8(%ebx) \n" // err[x+1,y] = rer*7/16
"movl -32(%ebp), %ebx \n"
"movq %mm0, %mm1 \n"
"pmullw %mm4, %mm1 \n" // mm1 = mm1*5
"psrlw %mm7, %mm1 \n" // mm1 = mm1/16
"paddw -8(%ebx), %mm1 \n"
"movq %mm1, -8(%ebx) \n" // err[x-1,y+1] += rer*3/16
"movq %mm0, %mm1 \n"
"pmullw %mm3, %mm1 \n" // mm1 = mm1*3
"psrlw %mm7, %mm1 \n" // mm1 = mm1/16
"paddw 8(%ebx), %mm1 \n"
"movq %mm1, (%ebx) \n" // err[x,y+1] += rer*5/16
"psrlw %mm7, %mm0 \n" // mm0 = mm0/16
"movq %mm0, 8(%ebx) \n" // err[x+1,y+1] = rer/16
// calculate final pixel value and store
"movl 48(%ebp), %ecx \n"
"movw -16(%ebp), %ax \n"
"shlw %cl, %ax \n" //NP* ax = r<<roffs
"movl 52(%ebp), %ecx \n"
"movw -14(%ebp), %bx \n"
"shlw %cl, %bx \n" //NP*
"orw %bx, %ax \n"
"movl 56(%ebp), %ecx \n"
"movw -12(%ebp), %bx \n"
"shlw %cl, %bx \n" //NP*
"orw %bx, %ax \n"
"movl 12(%ebp), %edx \n"
"movw %ax, (%edx) \n"
"addl $2, %edx \n" // increment ximage
"movl %edx, 12(%ebp) \n"
// prepare for next iteration on X
"addl $8, -32(%ebp) \n" // nerr += 8
"movl -36(%ebp), %ebx \n"
"addl $8, %ebx \n"
"movl %ebx, -36(%ebp) \n" // ebx = err += 8
// Note: in the last pixel, this would cause an invalid memory access
// because, punpcklbw is used (which reads 8 bytes) and the last
// pixel is only 4 bytes. This is no problem because the image data
// was allocated with extra 4 bytes when created.
"addl $4, %esi \n" // image->data += 4
"decl -4(%ebp) \n" // x--
"jnz .LoopX \n" // if x>0, goto .LoopX
// depend on edx
"addl 68(%ebp), %edx \n" // add extra offset to ximage
"movl %edx, 12(%ebp) \n"
"jmp .LoopY \n"
".End: \n" // THE END
"emms \n"
"popa \n"
);
}
#endif /* ASM_X86_MMX */

View File

@@ -52,7 +52,7 @@ RCreateImageFromXImage(RContext *context, XImage *image, XImage *mask)
RImage *img; RImage *img;
int x, y; int x, y;
unsigned long pixel; unsigned long pixel;
unsigned char *r, *g, *b, *a; unsigned char *data;
int rshift, gshift, bshift; int rshift, gshift, bshift;
int rmask, gmask, bmask; int rmask, gmask, bmask;
@@ -84,10 +84,7 @@ RCreateImageFromXImage(RContext *context, XImage *image, XImage *mask)
gshift = get_shifts(gmask) - 8; gshift = get_shifts(gmask) - 8;
bshift = get_shifts(bmask) - 8; bshift = get_shifts(bmask) - 8;
r = img->data[0]; data = img->data;
g = img->data[1];
b = img->data[2];
a = img->data[3];
#define NORMALIZE_RED(pixel) ((rshift>0) ? ((pixel) & rmask) >> rshift \ #define NORMALIZE_RED(pixel) ((rshift>0) ? ((pixel) & rmask) >> rshift \
: ((pixel) & rmask) << -rshift) : ((pixel) & rmask) << -rshift)
@@ -101,9 +98,13 @@ RCreateImageFromXImage(RContext *context, XImage *image, XImage *mask)
for (x = 0; x < image->width; x++) { for (x = 0; x < image->width; x++) {
pixel = XGetPixel(image, x, y); pixel = XGetPixel(image, x, y);
if (pixel) { if (pixel) {
*(r++) = *(g++) = *(b++) = 0; *data++ = 0;
*data++ = 0;
*data++ = 0;
} else { } else {
*(r++) = *(g++) = *(b++) = 0xff; *data++ = 0xff;
*data++ = 0xff;
*data++ = 0xff;
} }
} }
} }
@@ -111,20 +112,20 @@ RCreateImageFromXImage(RContext *context, XImage *image, XImage *mask)
for (y = 0; y < image->height; y++) { for (y = 0; y < image->height; y++) {
for (x = 0; x < image->width; x++) { for (x = 0; x < image->width; x++) {
pixel = XGetPixel(image, x, y); pixel = XGetPixel(image, x, y);
*(r++) = NORMALIZE_RED(pixel); *(data++) = NORMALIZE_RED(pixel);
*(g++) = NORMALIZE_GREEN(pixel); *(data++) = NORMALIZE_GREEN(pixel);
*(b++) = NORMALIZE_BLUE(pixel); *(data++) = NORMALIZE_BLUE(pixel);
} }
} }
} }
if (mask && a) { if (mask) {
for (y = 0; y < mask->height; y++) { for (y = 0; y < mask->height; y++) {
for (x = 0; x < mask->width; x++) { for (x = 0; x < mask->width; x++) {
if (XGetPixel(mask, x, y)) { if (XGetPixel(mask, x, y)) {
*(a++) = 0xff; *(data++) = 0xff;
} else { } else {
*(a++) = 0; *(data++) = 0;
} }
} }
} }

View File

@@ -33,18 +33,18 @@
#include "wraster.h" #include "wraster.h"
RImage* RImage*
RGetImageFromXPMData(RContext *context, char **data) RGetImageFromXPMData(RContext *context, char **xpmData)
{ {
Display *dpy = context->dpy; Display *dpy = context->dpy;
Colormap cmap = context->cmap; Colormap cmap = context->cmap;
RImage *image; RImage *image;
XpmImage xpm; XpmImage xpm;
unsigned char *color_table[4]; unsigned char *color_table[4];
unsigned char *r, *g, *b, *a; unsigned char *data;
int *p; int *p;
int i; int i;
i = XpmCreateXpmImageFromData(data, &xpm, (XpmInfo *)NULL); i = XpmCreateXpmImageFromData(xpmData, &xpm, (XpmInfo *)NULL);
if (i!=XpmSuccess) { if (i!=XpmSuccess) {
switch (i) { switch (i) {
case XpmOpenFailed: case XpmOpenFailed:
@@ -136,18 +136,14 @@ RGetImageFromXPMData(RContext *context, char **data)
color_table[3][i] = 0xff; color_table[3][i] = 0xff;
} }
} }
memset(image->data[3], 255, xpm.width*xpm.height);
/* convert pixmap to RImage */ /* convert pixmap to RImage */
p = (int*)xpm.data; p = (int*)xpm.data;
r = image->data[0]; data = image->data;
g = image->data[1];
b = image->data[2];
a = image->data[3];
for (i=0; i<xpm.width*xpm.height; i++) { for (i=0; i<xpm.width*xpm.height; i++) {
*(r++)=color_table[0][*p]; *(data++)=color_table[0][*p];
*(g++)=color_table[1][*p]; *(data++)=color_table[1][*p];
*(b++)=color_table[2][*p]; *(data++)=color_table[2][*p];
*(a++)=color_table[3][*p]; *(data++)=color_table[3][*p];
p++; p++;
} }
for(i=0; i<4; i++) { for(i=0; i<4; i++) {
@@ -167,7 +163,7 @@ RLoadXPM(RContext *context, char *file, int index)
RImage *image; RImage *image;
XpmImage xpm; XpmImage xpm;
unsigned char *color_table[4]; unsigned char *color_table[4];
unsigned char *r, *g, *b, *a; unsigned char *data;
int *p; int *p;
int i; int i;
@@ -265,16 +261,12 @@ RLoadXPM(RContext *context, char *file, int index)
} }
/* convert pixmap to RImage */ /* convert pixmap to RImage */
p = (int*)xpm.data; p = (int*)xpm.data;
r = image->data[0]; data = image->data;
g = image->data[1]; for (i=0; i<xpm.width*xpm.height; i++, p++) {
b = image->data[2]; *(data++)=color_table[0][*p];
a = image->data[3]; *(data++)=color_table[1][*p];
for (i=0; i<xpm.width*xpm.height; i++) { *(data++)=color_table[2][*p];
*(r++)=color_table[0][*p]; *(data++)=color_table[3][*p];
*(g++)=color_table[1][*p];
*(b++)=color_table[2][*p];
*(a++)=color_table[3][*p];
p++;
} }
for(i=0; i<4; i++) { for(i=0; i<4; i++) {
free(color_table[i]); free(color_table[i]);