1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-19 04:20:27 +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

@@ -2,7 +2,7 @@
*
* 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
* modify it under the terms of the GNU Library General Public
@@ -35,12 +35,13 @@ char *WRasterLibVersion="0.9";
int RErrorCode=RERR_NONE;
#define HAS_ALPHA(I) ((I)->format == RRGBAFormat)
RImage*
RCreateImage(unsigned width, unsigned height, int alpha)
{
RImage *image=NULL;
int i;
assert(width>0 && height>0);
@@ -53,22 +54,22 @@ RCreateImage(unsigned width, unsigned height, int alpha)
memset(image, 0, sizeof(RImage));
image->width = width;
image->height = height;
for (i=0; i<3+(alpha?1:0); i++) {
image->data[i] = malloc(width*height);
if (!image->data[i])
goto error;
if (alpha) {
image->format = RRGBAFormat;
} else {
image->format = RRGBFormat;
}
/* 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
*/
image->data = malloc(width * height * (alpha ? 4 : 3) + 4);
if (!image->data) {
RErrorCode = RERR_NOMEMORY;
free(image);
image = NULL;
}
return image;
error:
for (i=0; i<4; i++) {
if (image->data[i])
free(image->data[i]);
}
if (image)
free(image);
RErrorCode = RERR_NOMEMORY;
return NULL;
return image;
}
@@ -80,16 +81,13 @@ RCloneImage(RImage *image)
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)
return NULL;
new_image->background = image->background;
memcpy(new_image->data[0], image->data[0], image->width*image->height);
memcpy(new_image->data[1], image->data[1], image->width*image->height);
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);
memcpy(new_image->data, image->data,
image->width*image->height*(HAS_ALPHA(image) ? 4 : 3));
return new_image;
}
@@ -100,8 +98,7 @@ RGetSubImage(RImage *image, int x, int y, unsigned width, unsigned height)
{
int i, ofs;
RImage *new_image;
unsigned char *sr, *sg, *sb, *sa;
unsigned char *dr, *dg, *db, *da;
unsigned total_line_size, line_size;
assert(image!=NULL);
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)
height = image->height-y;
new_image = RCreateImage(width, height, image->data[3]!=NULL);
new_image = RCreateImage(width, height, HAS_ALPHA(image));
if (!new_image)
return NULL;
new_image->background = image->background;
ofs = image->width*y+x;
sr = image->data[0]+ofs;
sg = image->data[1]+ofs;
sb = image->data[2]+ofs;
sa = image->data[3]+ofs;
dr = new_image->data[0];
dg = new_image->data[1];
db = new_image->data[2];
da = new_image->data[3];
total_line_size = image->width * (HAS_ALPHA(image) ? 4 : 3);
line_size = width * (HAS_ALPHA(image) ? 4 : 3);
ofs = x*(HAS_ALPHA(image) ? 4 : 3);
for (i=0; i<height; i++) {
memcpy(dr, sr, width);
memcpy(dg, sg, width);
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;
}
memcpy(&new_image->data[i*line_size],
&image->data[i*total_line_size+ofs], line_size);
}
return new_image;
}
@@ -152,14 +132,9 @@ RGetSubImage(RImage *image, int x, int y, unsigned width, unsigned height)
void
RDestroyImage(RImage *image)
{
int i;
assert(image!=NULL);
for (i=0; i<4; i++) {
if (image->data[i])
free(image->data[i]);
}
free(image->data);
free(image);
}
@@ -174,41 +149,60 @@ RDestroyImage(RImage *image)
void
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->height == src->height);
dr = image->data[0];
dg = image->data[1];
db = image->data[2];
da = image->data[3];
sr = src->data[0];
sg = src->data[1];
sb = src->data[2];
sa = src->data[3];
if (!sa) {
memcpy(dr, sr, image->height*image->width);
memcpy(dg, sg, image->height*image->width);
memcpy(db, sb, image->height*image->width);
if (!HAS_ALPHA(src)) {
if (!HAS_ALPHA(image)) {
memcpy(image->data, src->data, image->height*image->width*3);
} else {
int x, y;
unsigned char *d, *s;
d = image->data;
s = src->data;
for (y = 0; y < image->height; y++) {
for (x = 0; x < image->width; x++) {
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
d++;
}
}
}
} else {
for (i=0; i<image->height*image->width; i++) {
alpha = *sa;
calpha = 255 - *sa;
*dr = (((int)*dr * calpha) + ((int)*sr * alpha))/256;
*dg = (((int)*dg * calpha) + ((int)*sg * alpha))/256;
*db = (((int)*db * calpha) + ((int)*sb * alpha))/256;
if (image->data[3])
*da++ |= *sa;
dr++; dg++; db++;
sr++; sg++; sb++;
sa++;
register int i;
unsigned char *d;
unsigned char *s;
int alpha, calpha;
d = image->data;
s = src->data;
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 {
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++;
*d++ |= *s++;
}
}
}
}
@@ -220,62 +214,58 @@ void
RCombineImagesWithOpaqueness(RImage *image, RImage *src, int opaqueness)
{
register int i;
unsigned char *dr, *dg, *db, *da;
unsigned char *sr, *sg, *sb, *sa;
unsigned char *d;
unsigned char *s;
int c_opaqueness;
assert(image->width == src->width);
assert(image->height == src->height);
dr = image->data[0];
dg = image->data[1];
db = image->data[2];
da = image->data[3];
sr = src->data[0];
sg = src->data[1];
sb = src->data[2];
sa = src->data[3];
d = image->data;
s = src->data;
c_opaqueness = 255 - opaqueness;
#define OP opaqueness
if (!src->data[3]) {
if (!HAS_ALPHA(src)) {
int dalpha = HAS_ALPHA(image);
#define COP c_opaqueness
for (i=0; i<image->width*image->height; i++) {
*dr = (((int)*dr *(int)COP) + ((int)*sr *(int)OP))/256;
*dg = (((int)*dg *(int)COP) + ((int)*sg *(int)OP))/256;
*db = (((int)*db *(int)COP) + ((int)*sb *(int)OP))/256;
dr++; dg++; db++;
sr++; sg++; sb++;
for (i=0; i < image->width*image->height; i++) {
*d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256;
d++; s++;
*d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256;
d++; s++;
*d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256;
d++; s++;
if (dalpha) {
d++;
}
}
#undef COP
} else {
int tmp;
if (image->data[3]) {
if (!HAS_ALPHA(image)) {
for (i=0; i<image->width*image->height; i++) {
tmp = (*sa * opaqueness)/256;
*dr = (((int)*dr * (255-tmp)) + ((int)*sr * tmp))/256;
*dg = (((int)*dg * (255-tmp)) + ((int)*sg * tmp))/256;
*db = (((int)*db * (255-tmp)) + ((int)*sb * tmp))/256;
*da |= tmp;
dr++; dg++; db++;
sr++; sg++; sb++;
sa++;
da++;
tmp = (*(s+3) * opaqueness)/256;
*d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256;
d++; s++;
*d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256;
d++; s++;
*d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256;
d++; s++;
s++;
}
} else {
for (i=0; i<image->width*image->height; i++) {
tmp = (*sa * opaqueness)/256;
*dr = (((int)*dr * (255-tmp)) + ((int)*sr * tmp))/256;
*dg = (((int)*dg * (255-tmp)) + ((int)*sg * tmp))/256;
*db = (((int)*db * (255-tmp)) + ((int)*sb * tmp))/256;
dr++; dg++; db++;
sr++; sg++; sb++;
sa++;
tmp = (*(s+3) * opaqueness)/256;
*d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256;
d++; s++;
*d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256;
d++; s++;
*d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256;
d++; s++;
*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)
{
int x, y, dwi, swi;
unsigned char *dr, *dg, *db;
unsigned char *sr, *sg, *sb, *sa;
unsigned char *d;
unsigned char *s;
int alpha, calpha;
@@ -299,46 +289,70 @@ RCombineArea(RImage *image, RImage *src, int sx, int sy, unsigned width,
assert(sy + height <= src->height);
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)
height = image->height - dy;
if (!src->data[3]) {
for (y=sy; y<height+sy; y++) {
for (x=sx; x<width+sx; x++) {
*(dr++) = *(sr++);
*(dg++) = *(sg++);
*(db++) = *(sb++);
if (!HAS_ALPHA(src)) {
if (!HAS_ALPHA(image)) {
swi = (src->width - width) * 3;
dwi = (image->width - width) * 3;
d = image->data + dy*(int)image->width*3 + dx;
s = src->data + sy*(int)src->width*3 + sx;
for (y=0; y < height; y++) {
memcpy(d, s, width*3);
d += dwi;
s += swi;
}
} else {
swi = (src->width - width) * 3;
dwi = (image->width - width) * 4;
d = image->data + dy*(int)image->width*4 + dx;
s = src->data + sy*(int)src->width*3 + sx;
for (y=0; y < height; y++) {
for (x=0; x < width; x++) {
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
d++;
}
d += dwi;
s += swi;
}
dr += dwi; dg += dwi; db += dwi;
sr += swi; sg += swi; sb += swi;
}
} else {
for (y=sy; y<height+sy; y++) {
for (x=sx; x<width+sx; x++) {
alpha = *sa;
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;
*dr = (((int)*dr * calpha) + ((int)*sr * alpha))/256;
*dg = (((int)*dg * calpha) + ((int)*sg * alpha))/256;
*db = (((int)*db * calpha) + ((int)*sb * alpha))/256;
dr++; dg++; db++;
sr++; sg++; sb++;
sa++;
*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++;
}
dr += dwi; dg += dwi; db += dwi;
sr += swi; sg += swi; sb += swi;
sa += swi;
d += dwi;
s += swi;
}
}
}
@@ -351,8 +365,9 @@ RCombineAreaWithOpaqueness(RImage *image, RImage *src, int sx, int sy,
{
int x, y, dwi, swi;
int c_opaqueness;
unsigned char *dr, *dg, *db;
unsigned char *sr, *sg, *sb, *sa;
unsigned char *d;
unsigned char *s;
int dalpha = HAS_ALPHA(image);
assert(dy <= image->height);
assert(dx <= image->width);
@@ -360,17 +375,6 @@ RCombineAreaWithOpaqueness(RImage *image, RImage *src, int sx, int sy,
assert(sy <= height);
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 */
width -= sx;
@@ -381,36 +385,51 @@ RCombineAreaWithOpaqueness(RImage *image, RImage *src, int sx, int sy,
c_opaqueness = 255 - opaqueness;
#define OP opaqueness
if (!src->data[3]) {
if (!HAS_ALPHA(src)) {
#define COP c_opaqueness
for (y=0; y<height; y++) {
for (x=0; x<width; x++) {
*dr = (((int)*dr *(int)COP) + ((int)*sr *(int)OP))/256;
*dg = (((int)*dg *(int)COP) + ((int)*sg *(int)OP))/256;
*db = (((int)*db *(int)COP) + ((int)*sb *(int)OP))/256;
dr++; dg++; db++;
sr++; sg++; sb++;
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 (x=0; x < width; x++) {
*d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256;
s++; d++;
*d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256;
s++; d++;
*d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256;
s++; d++;
if (dalpha)
d++;
}
dr += dwi; dg += dwi; db += dwi;
sr += swi; sg += swi; sb += swi;
d += dwi; s += swi;
}
#undef COP
} else {
int tmp;
for (y=0; y<height; y++) {
for (x=0; x<width; x++) {
tmp= (*sa * opaqueness)/256;
*dr = (((int)*dr *(int)(255-tmp)) + ((int)*sr *(int)tmp))/256;
*dg = (((int)*dg *(int)(255-tmp)) + ((int)*sg *(int)tmp))/256;
*db = (((int)*db *(int)(255-tmp)) + ((int)*sb *(int)tmp))/256;
dr++; dg++; db++;
sr++; sg++; sb++;
sa++;
for (y=0; y < height; y++) {
for (x=0; x < width; x++) {
tmp= (*(s+3) * opaqueness)/256;
*d = (((int)*d *(int)(255-tmp)) + ((int)*s *(int)tmp))/256;
d++; s++;
*d = (((int)*d *(int)(255-tmp)) + ((int)*s *(int)tmp))/256;
d++; s++;
*d = (((int)*d *(int)(255-tmp)) + ((int)*s *(int)tmp))/256;
d++; s++;
s++;
if (dalpha)
d++;
}
dr += dwi; dg += dwi; db += dwi;
sr += swi; sg += swi; sb += swi;
sa += swi;
d += dwi; s += swi;
}
}
#undef OP
@@ -423,34 +442,37 @@ void
RCombineImageWithColor(RImage *image, RColor *color)
{
register int i;
unsigned char *dr, *dg, *db, *da;
unsigned char *d;
int alpha, nalpha, r, g, b;
dr = image->data[0];
dg = image->data[1];
db = image->data[2];
da = image->data[3];
d = image->data;
if (!da) {
/* Image has no alpha channel, so we consider it to be all 255 */
if (!HAS_ALPHA(image)) {
/* Image has no alpha channel, so we consider it to be all 255.
* Thus there are no transparent parts to be filled. */
return;
}
r = color->red;
g = color->green;
b = color->blue;
for (i=0; i<image->width*image->height; i++) {
alpha = *da;
for (i=0; i < image->width*image->height; i++) {
alpha = *(d+3);
nalpha = 255 - alpha;
*dr = (((int)*dr * alpha) + (r * nalpha))/256;
*dg = (((int)*dg * alpha) + (g * nalpha))/256;
*db = (((int)*db * alpha) + (b * nalpha))/256;
dr++; dg++; db++; da++;
*d = (((int)*d * alpha) + (r * nalpha))/256;
d++;
*d = (((int)*d * alpha) + (g * nalpha))/256;
d++;
*d = (((int)*d * alpha) + (b * nalpha))/256;
d++;
d++;
}
}
RImage*
RMakeTiledImage(RImage *tile, unsigned width, unsigned height)
{
@@ -458,47 +480,36 @@ RMakeTiledImage(RImage *tile, unsigned width, unsigned height)
unsigned w;
unsigned long tile_size = tile->width * tile->height;
unsigned long tx = 0;
int have_alpha = (tile->data[3]!=NULL);
RImage *image;
unsigned char *sr, *sg, *sb, *sa;
unsigned char *dr, *dg, *db, *da;
unsigned char *s, *d;
if (width == tile->width && height == tile->height)
image = RCloneImage(tile);
else if (width <= tile->width && height <= tile->height)
image = RGetSubImage(tile, 0, 0, width, height);
else {
int has_alpha = HAS_ALPHA(tile);
image = RCreateImage(width, height, have_alpha);
image = RCreateImage(width, height, has_alpha);
dr = image->data[0];
dg = image->data[1];
db = image->data[2];
da = image->data[3];
sr = tile->data[0];
sg = tile->data[1];
sb = tile->data[2];
sa = tile->data[3];
d = image->data;
s = tile->data;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x += tile->width) {
w = (width - x < tile->width) ? width - x : tile->width;
memcpy(dr, sr+tx, w);
memcpy(dg, sg+tx, w);
memcpy(db, sb+tx, w);
if (have_alpha) {
memcpy(da, sa+tx, w);
da += w;
}
dr += w;
dg += w;
db += w;
if (has_alpha) {
w *= 3;
memcpy(d, s+tx*3, w);
} else {
w *= 4;
memcpy(d, s+tx*4, w);
}
d += w;
}
tx = (tx + tile->width) % tile_size;
}
}