Skip to content

Commit

Permalink
-changed image! datatype to use "standard" alpha channel values (ie. …
Browse files Browse the repository at this point in the history
…0 = transparent, 255 = opaque)

-change BMP, JPG, GIF and PNG codecs to reflect the alpha channel changes
-added misc useful pixel/tuple related macros
  • Loading branch information
Richard Smolak committed Apr 2, 2013
1 parent fc51038 commit 472c106
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 56 deletions.
1 change: 1 addition & 0 deletions src/core/t-gob.c
Expand Up @@ -68,6 +68,7 @@ const REBCNT Gob_Flag_Words[] = {
CLEAR(gob, sizeof(REBGOB));
GOB_W(gob) = 100;
GOB_H(gob) = 100;
GOB_ALPHA(gob) = 255;
return gob;
}

Expand Down
39 changes: 21 additions & 18 deletions src/core/t-image.c
Expand Up @@ -26,17 +26,16 @@
** Notes:
**
***********************************************************************/
/*
** It's a bit of a shame that alpha channels are represented with
** an inverted level compared to many standards. Alpha zero must
** be opaque in order for RGB tuples to be equal RGBA tuples.
** That is: 10.20.30 = 10.20.30.0
*/

#include "sys-core.h"

#define CLEAR_IMAGE(p, x, y) memset(p, 0, x * y * sizeof(long))

#define RESET_IMAGE(p, l) do { \
REBCNT *start = (REBCNT*)p; \
REBCNT *stop = start + l; \
while (start < stop) *start++ = 0xff000000; \
} while(0)

/***********************************************************************
**
Expand Down Expand Up @@ -91,7 +90,10 @@
dp[C_R] = tup[0];
dp[C_G] = tup[1];
dp[C_B] = tup[2];
if (VAL_TUPLE_LEN(tuple) > 3) dp[C_A] = tup[3];
if (VAL_TUPLE_LEN(tuple) > 3)
dp[C_A] = tup[3];
else
dp[C_A] = 0xff;
}


Expand Down Expand Up @@ -119,9 +121,10 @@
/*
***********************************************************************/
{
if (only) // only RGB, do not touch Alpha
if (only) {// only RGB, do not touch Alpha
color &= 0xffffff;
for (; len > 0; len--, ip++) *ip = (*ip & 0xff000000) | color;
else
} else
for (; len > 0; len--) *ip++ = color;
}

Expand Down Expand Up @@ -416,7 +419,7 @@ INLINE REBCNT ARGB_To_BGR(REBCNT i)

img = Make_Series(w * h + 1, sizeof(REBINT), FALSE);
img->tail = w * h;
CLEAR(img->data, (img->tail + 1) * sizeof(REBINT));
RESET_IMAGE(img->data, img->tail); //length in 'pixels'
IMG_WIDE(img) = w;
IMG_HIGH(img) = h;
return img;
Expand Down Expand Up @@ -485,7 +488,7 @@ INLINE REBCNT ARGB_To_BGR(REBCNT i)
}
}
else if (IS_TUPLE(block)) {
Fill_Rect((REBCNT *)ip, TO_COLOR_TUPLE(block), w, w, h, TRUE);
Fill_Rect((REBCNT *)ip, TO_PIXEL_TUPLE(block), w, w, h, TRUE);
block++;
if (IS_INTEGER(block)) {
Fill_Alpha_Rect((REBCNT *)ip, (REBYTE)VAL_INT32(block), w, w, h);
Expand Down Expand Up @@ -627,7 +630,7 @@ INLINE REBCNT ARGB_To_BGR(REBCNT i)
if (action == A_INSERT) {
if (index > tail) index = tail;
Expand_Series(VAL_SERIES(value), index, dup * part);
CLEAR(VAL_BIN(value) + (index * 4), dup * part * 4);
RESET_IMAGE(VAL_BIN(value) + (index * 4), dup * part); //length in 'pixels'
Reset_Height(value);
tail = VAL_TAIL(value);
only = 0;
Expand All @@ -647,9 +650,9 @@ INLINE REBCNT ARGB_To_BGR(REBCNT i)
Fill_Alpha_Line(ip, (REBYTE)n, dup);
} else if (IS_TUPLE(arg)) { // RGB
if (IS_PAIR(count)) // rectangular fill
Fill_Rect((REBCNT *)ip, TO_COLOR_TUPLE(arg), w, dupx, dupy, only);
Fill_Rect((REBCNT *)ip, TO_PIXEL_TUPLE(arg), w, dupx, dupy, only);
else
Fill_Line((REBCNT *)ip, TO_COLOR_TUPLE(arg), dup, only);
Fill_Line((REBCNT *)ip, TO_PIXEL_TUPLE(arg), dup, only);
}
} else if (IS_IMAGE(arg)) {
Copy_Rect_Data(value, x, y, partx, party, arg, 0, 0); // dst dx dy w h src sx sy
Expand Down Expand Up @@ -718,7 +721,7 @@ INLINE REBCNT ARGB_To_BGR(REBCNT i)
if (IS_TUPLE(arg)) {
only = (REBOOL)(VAL_TUPLE_LEN(arg) < 4);
if (D_REF(5)) only = TRUE; // /only flag
p = Find_Color(ip, TO_COLOR_TUPLE(arg), len, only);
p = Find_Color(ip, TO_PIXEL_TUPLE(arg), len, only);
} else if (IS_INTEGER(arg)) {
n = VAL_INT32(arg);
if (n < 0 || n > 255) Trap_Range(arg);
Expand Down Expand Up @@ -761,7 +764,7 @@ INLINE REBCNT ARGB_To_BGR(REBCNT i)
p = (REBCNT *)VAL_IMAGE_HEAD(v);
i = VAL_IMAGE_WIDE(v)*VAL_IMAGE_HIGH(v);
for(; i > 0; i--) {
if (*p++ & 0xff000000) {
if (~*p++ & 0xff000000) {
// if (save) VAL_IMAGE_TRANSP(v) = VITT_ALPHA;
return TRUE;
}
Expand Down Expand Up @@ -1228,11 +1231,11 @@ INLINE REBCNT ARGB_To_BGR(REBCNT i)

case SYM_RGB:
if (IS_TUPLE(val)) {
Fill_Line((REBCNT *)src, TO_COLOR_TUPLE(val), len, 1);
Fill_Line((REBCNT *)src, TO_PIXEL_TUPLE(val), len, 1);
} else if (IS_INTEGER(val)) {
n = VAL_INT32(val);
if (n < 0 || n > 255) return PE_BAD_RANGE;
Fill_Line((REBCNT *)src, TO_COLOR(n,n,n,0), len, 1);
Fill_Line((REBCNT *)src, TO_PIXEL_COLOR(n,n,n,0xFF), len, 1);
} else if (IS_BINARY(val)) {
Bin_To_RGB(src, len, VAL_BIN_DATA(val), VAL_LEN(val) / 3);
} else return PE_BAD_SET;
Expand Down
18 changes: 9 additions & 9 deletions src/core/u-bmp.c
Expand Up @@ -365,7 +365,7 @@ void Unmap_Bytes(void *srcp, REBYTE **dstp, char *map) {
c = *cp++ & 0xff;
}
color = &ctab[(c&x) != 0];
*dp++ = ((int)color->rgbRed << 16) |
*dp++ = 0xff000000 | ((int)color->rgbRed << 16) |
((int)color->rgbGreen << 8) | color->rgbBlue;
x >>= 1;
}
Expand All @@ -385,7 +385,7 @@ void Unmap_Bytes(void *srcp, REBYTE **dstp, char *map) {
goto error;
}
color = &ctab[x];
*dp++ = ((int)color->rgbRed << 16) |
*dp++ = 0xff000000 | ((int)color->rgbRed << 16) |
((int)color->rgbGreen << 8) | color->rgbBlue;
}
i = (w+1) / 2;
Expand All @@ -399,17 +399,17 @@ void Unmap_Bytes(void *srcp, REBYTE **dstp, char *map) {
goto error;
}
color = &ctab[c];
*dp++ = ((int)color->rgbRed << 16) |
*dp++ = 0xff000000 | ((int)color->rgbRed << 16) |
((int)color->rgbGreen << 8) | color->rgbBlue;
}
break;

case 24:
for (i = 0; i<w; i++) {
#ifdef ENDIAN_BIG
*dp++=cp[0]|(cp[1]<<8)|(cp[2]<<16);
*dp++=cp[0]|(cp[1]<<8)|(cp[2]<<16)|0xff000000;
#else
*dp++ = (*(int *)cp) & 0xffffffL;
*dp++ = (*(int *)cp) | 0xff000000;
#endif
cp += 3;
}
Expand Down Expand Up @@ -446,7 +446,7 @@ void Unmap_Bytes(void *srcp, REBYTE **dstp, char *map) {
}
else
color = &ctab[x&0x0f];
*dp++ = ((int)color->rgbRed << 16) |
*dp++ = 0xff000000 | ((int)color->rgbRed << 16) |
((int)color->rgbGreen << 8) | color->rgbBlue;
}
j = (c+1) / 2;
Expand All @@ -464,7 +464,7 @@ void Unmap_Bytes(void *srcp, REBYTE **dstp, char *map) {
color = &ctab[x&0x0f];
else
color = &ctab[x>>4];
*dp++ = ((int)color->rgbRed << 16) |
*dp++ = 0xff000000 | ((int)color->rgbRed << 16) |
((int)color->rgbGreen << 8) | color->rgbBlue;
}
}
Expand All @@ -487,7 +487,7 @@ void Unmap_Bytes(void *srcp, REBYTE **dstp, char *map) {
for (j = 0; j<c; j++) {
x = *cp++ & 0xff;
color = &ctab[x];
*dp++ = ((int)color->rgbRed << 16) |
*dp++ = 0xff000000 | ((int)color->rgbRed << 16) |
((int)color->rgbGreen << 8) | color->rgbBlue;
}
while (j++ % 2)
Expand All @@ -497,7 +497,7 @@ void Unmap_Bytes(void *srcp, REBYTE **dstp, char *map) {
x = *cp++ & 0xff;
for (j = 0; j<c; j++) {
color = &ctab[x];
*dp++ = ((int)color->rgbRed << 16) |
*dp++ = 0xff000000 | ((int)color->rgbRed << 16) |
((int)color->rgbGreen << 8) | color->rgbBlue;
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/core/u-gif.c
Expand Up @@ -179,7 +179,7 @@ void Chrom_Key_Alpha(REBVAL *v,REBCNT col,REBINT blitmode) {
}
top_stack--;
rp = colortab + 3 * *top_stack;
*dp++ = rp[2] | (rp[1] << 8) | (rp[0] << 16);
*dp++ = rp[2] | (rp[1] << 8) | (rp[0] << 16) | 0xff000000;
x++;
}
if (interlaced) {
Expand Down Expand Up @@ -285,7 +285,8 @@ void Chrom_Key_Alpha(REBVAL *v,REBCNT col,REBINT blitmode) {
cp += 3 * colors;
}
cp += 9;


//note: animated GIFs support needs to be added!!!
/*
if (image_count == 2) {
VAL_SERIES(Temp2_Value) = Make_Block(0, 0);
Expand Down
4 changes: 2 additions & 2 deletions src/core/u-jpg.c
Expand Up @@ -271,7 +271,7 @@ void jpeg_load( char *buffer, int nbytes, char *output )
output = ( char * )dp;
for ( j=0; j<cinfo.image_width; j++ ) {
cp -= 3;
*--dp = cp[ 2 ] | ( cp[ 1 ] << 8 ) | ( ( uinteger32 )cp[ 0 ] << 16 );
*--dp = cp[ 2 ] | ( cp[ 1 ] << 8 ) | ( ( uinteger32 )cp[ 0 ] << 16 ) | 0xff000000;
}
}
else
Expand All @@ -285,7 +285,7 @@ void jpeg_load( char *buffer, int nbytes, char *output )
output = ( char * )dp;
for ( j=0; j<cinfo.image_width; j++ ) {
c = *--cp;
*--dp = c | (c << 8) | (c << 16);
*--dp = c | (c << 8) | (c << 16) | 0xff000000;
}
}

Expand Down
41 changes: 20 additions & 21 deletions src/core/u-png.c
Expand Up @@ -194,35 +194,34 @@ static void process_chunk(char *type,unsigned char *p,int length) {

static unsigned int calc_color(unsigned int color,unsigned short alpha) {
if(alpha==65535)
return color;
return 0xff000000|color;
else if(alpha==0) {
hasalpha=TRUE;
return 0xff000000;
return 0x00000000;
} else {
unsigned int red,green,blue;
hasalpha=TRUE;
red=color>>16;
green=(color>>8)&255;
blue=color&255;
return (((65535-alpha)/255)<<24)|(red<<16)|(green<<8)|blue;
return ((alpha/255)<<24)|(red<<16)|(green<<8)|blue;
}
}

static void process_row_0_1(unsigned char *p,int width,int r,int hoff,int hskip) {
int c;
unsigned char m;
unsigned int v,*imgp;

imgp=img_output+r*png_ihdr.width+hoff;
for(c=0;c<width;c++) {
if(!(c&7))
m=*p++;
v=m>>7;
if(v==transparent_gray) {
hasalpha=TRUE;
*imgp=0xff000000;
*imgp=0x00000000;
} else
*imgp=(v?0xffffff:0);
*imgp=(v?0xffffffff:0xff000000);
imgp+=hskip;
m<<=1;
}
Expand All @@ -240,10 +239,10 @@ static void process_row_0_2(unsigned char *p,int width,int r,int hoff,int hskip)
v=m>>6;
if(v==transparent_gray) {
hasalpha=TRUE;
*imgp=0xff000000;
*imgp=0x00000000;
} else {
v=bytetab2[v];
v|=(v<<8)|(v<<16);
v|=(v<<8)|(v<<16)|0xff000000;
*imgp=v;
}
imgp+=hskip;
Expand All @@ -263,10 +262,10 @@ static void process_row_0_4(unsigned char *p,int width,int r,int hoff,int hskip)
v=m>>4;
if(v==transparent_gray) {
hasalpha=TRUE;
*imgp=0xff000000;
*imgp=0x00000000;
} else {
v|=(v<<4);
v|=(v<<8)|(v<<16);
v|=(v<<8)|(v<<16)|0xff000000;
*imgp=v;
}
imgp+=hskip;
Expand All @@ -283,9 +282,9 @@ static void process_row_0_8(unsigned char *p,int width,int r,int hoff,int hskip)
v=*p++;
if(v==transparent_gray) {
hasalpha=TRUE;
*imgp=0xff000000;
*imgp=0x00000000;
} else {
v|=(v<<8)|(v<<16);
v|=(v<<8)|(v<<16)|0xff000000;
*imgp=v;
}
imgp+=hskip;
Expand All @@ -302,10 +301,10 @@ static void process_row_0_16(unsigned char *p,int width,int r,int hoff,int hskip
p+=2;
if(v==transparent_gray) {
hasalpha=TRUE;
*imgp=0xff000000;
*imgp=0x00000000;
} else {
v>>=8;
v|=(v<<8)|(v<<16);
v|=(v<<8)|(v<<16)|0xff000000;
*imgp=v;
}
imgp+=hskip;
Expand All @@ -324,9 +323,9 @@ static void process_row_2_8(unsigned char *p,int width,int r,int hoff,int hskip)
p+=3;
if((red==transparent_red)&&(green==transparent_green)&&(blue==transparent_blue)) {
hasalpha=TRUE;
*imgp=0xff000000;
*imgp=0x00000000;
} else
*imgp=(red<<16)|(green<<8)|blue;
*imgp=0xff000000|(red<<16)|(green<<8)|blue;
imgp+=hskip;
}
}
Expand All @@ -343,9 +342,9 @@ static void process_row_2_16(unsigned char *p,int width,int r,int hoff,int hskip
p+=6;
if((red==transparent_red)&&(green==transparent_green)&&(blue==transparent_blue)) {
hasalpha=TRUE;
*imgp=0xff000000;
*imgp=0x00000000;
} else
*imgp=((red>>8)<<16)|(green&0xff00)|(blue>>8);
*imgp=0xff000000|((red>>8)<<16)|(green&0xff00)|(blue>>8);
imgp+=hskip;
}
}
Expand Down Expand Up @@ -483,7 +482,7 @@ static int paeth_predictor(int a,int b,int c) {

static void process_image(int width,int height,int cwidth,int hoff,int hskip,
int voff,int vskip) {
int r,c;
int r,c;
unsigned char *p,filter;
//printf("process_image: w: %d, h: %d, cw: %d, ho: %d, hs: %d, vo: %d, vs: %d\r\n",
// width,height,cwidth,hoff,hskip,voff,vskip);
Expand Down Expand Up @@ -555,7 +554,7 @@ void png_load(unsigned char *buffer, int nbytes, char *output, REBOOL *alpha) {
nbytes-=33;
haspalette=0;
hasalpha=0;
transparent_gray=transparent_red=transparent_green=transparent_blue=0xffffffff;
transparent_gray=transparent_red=transparent_green=transparent_blue=0x00ffffff;
while(1) {
p=get_chunk(&buffer,&nbytes,type,&length);
if(!memcmp(type,"IEND",4))
Expand Down Expand Up @@ -734,7 +733,7 @@ static void emitchunk(unsigned char **cpp,char *type,char *data,int length) {
*cp++=cv>>8;
*cp++=cv;
if(hasalpha)
*cp++=255-(cv>>24);
*cp++=(cv>>24);
}
zstream.next_in=linebuf;
zstream.avail_in=(hasalpha?(4*w+1):(3*w+1));
Expand Down
8 changes: 8 additions & 0 deletions src/include/reb-c.h
Expand Up @@ -274,3 +274,11 @@ typedef void(*CFUNC)(void *);
#define MAKE_STR(n) (REBCHR*)(malloc((n) * sizeof(REBCHR))) // OS chars!

#define ROUND_TO_INT(d) (REBINT)(floor((d) + 0.5))

#ifdef ENDIAN_BIG
#define TO_RGBA_COLOR(r,g,b,a) (REBCNT)((r)<<24 | (g)<<16 | (b)<<8 | (a))
#define TO_PIXEL_COLOR(r,g,b,a) (REBCNT)((b)<<24 | (g)<<16 | (r)<<8 | (a))
#else
#define TO_RGBA_COLOR(r,g,b,a) (REBCNT)((a)<<24 | (b)<<16 | (g)<<8 | (r))
#define TO_PIXEL_COLOR(r,g,b,a) (REBCNT)((a)<<24 | (r)<<16 | (g)<<8 | (b))
#endif

0 comments on commit 472c106

Please sign in to comment.