ftp.nice.ch/pub/next/graphics/viewer/ToyViewer.2.6a.s.tar.gz#/ToyViewer2.6a/src/getpixel.c

This is getpixel.c in view mode; [Download] [Up]

#include <stdlib.h>
#include "common.h"
#include "getpixel.h"

static commonInfo *comInfo;
static unsigned char *rr, *gg, *bb, *aa;

static int cs0, cs1, elems, alpx, palp;
static BOOL ismono;
static int bufp, yline;
static unsigned char *buffer[MAXPLANE];
static int had_alpha, buffer_size = 0;

static int _cc;
static short _pp[] = { 0, 0x55, 0xaa, 0xff };
#define pigment(c)	(((_cc = ((c) & 0xf0)) == 0xf0) ? 0xff : _cc)
#define pigment2(c)	(_pp[((c) & 0xc0) >> 6])
/*
    static int pigment(int cc)
    {
	int n = cc & 0xf0;
	if (n == 0xf0) n = 0xff;
	return n;
    }

    static int pigment2(int cc)
    {
	static unsigned char tone[] = { 0, 0x55, 0xaa, 0xff };
	return tone[cc >> 6];
    }
*/


int initGetPixel(commonInfo *cinf)
{
	comInfo = cinf;
	if (comInfo->cspace == NX_OneIsBlackColorSpace)
		cs0 = 0xff, cs1 = 0;
	else
		cs0 = 0, cs1 = 0xff;
	ismono = (comInfo->numcolors == 1);
	palp = 0;
	if (comInfo->alpha) {
		elems = 4;
		alpx = ismono ? 1 : 3;
	}else {
		elems = 3;
		alpx = 0;
	}
	if (comInfo->width > buffer_size) {
		int i;
		unsigned char *p;
		if (comInfo->width > MAXWidth)
			return Err_SAV_IMPL;
		if (buffer_size > 0) free((void *)buffer[0]);
		buffer_size = (comInfo->width + 7) & 0xfff8;
		p = (unsigned char *)malloc(buffer_size * 4);
		if (p == NULL) {
			buffer_size = 0;
			return Err_MEMORY;
		}
		for (i = 0; i < 4; i++) {
			buffer[i] = p;
			p += buffer_size;
		}
	}
	return 0;
}

void resetPixel(unsigned char **planes, int y)
{
	had_alpha = 0;
	rr = planes[0];
	if (!comInfo->isplanar)
		aa = gg = bb = rr;
	else if (ismono) {
		gg = bb = rr;
		aa = planes[alpx];
	}else {
		gg = planes[1];
		bb = planes[2];
		aa = planes[alpx];
	}
	if (y > 0) {
		int w = comInfo->xbytes * y;
		rr += w;
		gg += w;
		bb += w;
		aa += w;
	}
	yline = y;
	bufp = MAXWidth;
}

static int alphaToWhite(int c, int a)
{
	int n;
	if (a == AlphaOpaque) return c;
	n = 255 - a + ((c * a) >> 8);	/* (256-c)*((256-a)/256)+c */
	return (n >= 255) ? 255 : n;
}

void compositeColors(int clr[], const int bkg[], int a)
{
	int i, d, n;
	float ratio;

	if (a == AlphaOpaque) return;	/* Do Nothing */
	if (a == AlphaTransp) {
		for (i = 0; i < 3; i++)
			clr[i] = bkg[i];
		return;
	}
	ratio = (255 - a) / 255.0;
	for (i = 0; i < 3; i++) {
		if ((d = bkg[i] - clr[i]) == 0) continue;
		n = d * ratio + clr[i];
		clr[i] = (n <= 0) ? 0 : ((n >= 255) ? 255 : n);
	}
}

int getPalPixel(int *r, int *g, int *b)
{
	unsigned char *p;

	if (palp >= comInfo->palsteps)
		return -1;
	p = comInfo->palette[palp++];
	switch (comInfo->bits) {
	case 1:
		*r = p[RED] ? 0xff : 0;
		*g = p[GREEN] ? 0xff : 0;
		*b = p[BLUE] ? 0xff : 0;
		break;
	case 2:
		*r = pigment2(p[RED]);
		*g = pigment2(p[GREEN]);
		*b = pigment2(p[BLUE]);
		break;
	case 4:
		*r = pigment(p[RED]);
		*g = pigment(p[GREEN]);
		*b = pigment(p[BLUE]);
		break;
	case 8:
	default:
		*r = p[RED];
		*g = p[GREEN];
		*b = p[BLUE];
		break;
	}
	return 0;
}

static int getNextLine(void)
{
	int i, x, mask, xbytes;

	if (++yline > comInfo->height)
	    return -1;	/* End of Image */
	bufp = 0;
	xbytes = comInfo->xbytes;

	if (comInfo->isplanar) {
	    if (comInfo->bits == 1) {
		for (x = 0; x < xbytes; x++) {
		    for (mask = 0x80; mask; mask >>= 1) {
			buffer[RED][bufp]   = (*rr & mask)? cs1 : cs0;
			buffer[GREEN][bufp] = (*gg & mask)? cs1 : cs0;
			buffer[BLUE][bufp]  = (*bb & mask)? cs1 : cs0;
			bufp++;
		    }
		    rr++, gg++, bb++;
		}
		if (alpx) {
		    bufp = 0;
		    for (x = 0; x < xbytes; x++) {
			for (mask = 0x80; mask; mask >>= 1)
			    buffer[ALPHA][bufp++]  = (*aa & mask)? 0xff : 0;
			aa++;
		    }
		}
	    }else if (comInfo->bits == 2) {
		for (x = 0; x < xbytes; x++) {
		    for (i = 0; i < 8; i += 2) {
			buffer[RED][bufp]   = pigment2(*rr << i);
			buffer[GREEN][bufp] = pigment2(*gg << i);
			buffer[BLUE][bufp]  = pigment2(*bb << i);
			bufp++;
		    }
		    rr++, gg++, bb++;
		}
		if (alpx) {
		    bufp = 0;
		    for (x = 0; x < xbytes; x++) {
			for (i = 0; i < 8; i += 2)
			    buffer[ALPHA][bufp++] = pigment2(*aa << i);
			aa++;
		    }
		}
	    }else if (comInfo->bits == 4) {
		for (x = 0; x < xbytes; x++) {
		    buffer[RED][bufp]   = pigment(*rr);
		    buffer[GREEN][bufp] = pigment(*gg);
		    buffer[BLUE][bufp]  = pigment(*bb);
		    bufp++;
		    buffer[RED][bufp]   = pigment(*rr++ << 4);
		    buffer[GREEN][bufp] = pigment(*gg++ << 4);
		    buffer[BLUE][bufp]  = pigment(*bb++ << 4);
		    bufp++;
		}
		if (alpx) {
		    bufp = 0;
		    for (x = 0; x < xbytes; x++) {
			buffer[ALPHA][bufp++]  = pigment(*aa);
			buffer[ALPHA][bufp++]  = pigment(*aa++ << 4);
		    }
		}
	    }else /* 8 */ {
		for (x = 0; x < xbytes; x++) {
		    buffer[RED][x]   = *rr++;
		    buffer[GREEN][x] = *gg++;
		    buffer[BLUE][x]  = *bb++;
		}
		if (alpx) {
		    for (x = 0; x < xbytes; x++)
			buffer[ALPHA][x]  = *aa++;
		}
	    }
	}else if (ismono) { /* meshed mono */
	    if (comInfo->bits == 1) {
		for (x = 0; x < xbytes; x++) {
		    for (mask = 0x80; mask; mask >>= 1) {
			buffer[0][bufp] = buffer[1][bufp] = buffer[2][bufp]
				= (*rr & mask)? cs1 : cs0;
			if (alpx) {
			    mask >>= 1;
			    buffer[ALPHA][bufp] = (*rr & mask)? cs1 : cs0;
			}
			bufp++;
		    }
		    rr++;
		}
	    }else if (comInfo->bits == 2) {
		for (x = 0; x < xbytes; x++) {
		    for (i = 0; i < 8; i += 2) {
			buffer[0][bufp] = buffer[1][bufp] = buffer[2][bufp]
				= pigment2(*rr << i);
			if (alpx) {
			    i += 2;
			    buffer[ALPHA][bufp] = pigment2(*rr << i);
			}
			bufp++;
		    }
		    rr++;
		}
	    }else if (comInfo->bits == 4) {
		if (alpx) {
		    for (bufp = 0; bufp < xbytes; bufp++) {
			buffer[0][bufp] = buffer[1][bufp] = buffer[2][bufp]
					= pigment(*rr);
			buffer[ALPHA][bufp] = pigment(*rr++ << 4);
		    }
		}else {
		    int sft = 0;
		    x = 0;
		    for (bufp = 0; ; bufp++) {
			buffer[0][bufp] = buffer[1][bufp] = buffer[2][bufp]
					= pigment(sft ? (*rr << 4) : *rr);
			if (sft) {
			    sft = 0, rr++;
			    if (++x >= xbytes) break;
			}else
			    sft = 1;
		    }
		}
	    }else /* 8 */ {
		for (bufp = 0; bufp < xbytes; bufp++) {
		    buffer[0][bufp] = buffer[1][bufp]
					= buffer[2][bufp] = *rr++;
		    if (alpx) buffer[ALPHA][bufp] = *rr++;
		}
	    }
	}else { /* meshed color */
	    if (comInfo->bits == 1) {
		i = x = 0;
		mask = 0x80;
		for ( ; ; ) {
		    buffer[i][bufp] = (*rr & mask)? cs1 : cs0;
		    if (++i >= elems)
			i = 0, bufp++;
		    if ((mask >>= 1) == 0) {
			mask = 0x80, rr++;
			if (++x >= xbytes) break;
		    }
		}
	    }else if (comInfo->bits == 2) {
		i = x = 0;
		mask = 0;
		for ( ; ; ) {
		    buffer[i][bufp] = pigment2(*rr << mask);
		    if (++i >= elems)
			i = 0, bufp++;
		    if ((mask += 2) == 8) {
			mask = 0, rr++;
			if (++x >= xbytes) break;
		    }
		}
	    }else if (comInfo->bits == 4) {
		int sft = 0;
		i = x = 0;
		for ( ; ; ) {
		    buffer[i][bufp] = pigment(sft ? (*rr << 4) : *rr);
		    if (++i >= elems)
			i = 0, bufp++;
		    if (sft) {
		    	sft = 0, rr++;
			if (++x >= xbytes) break;
		    }else
		    	sft = 1;
		}
	    }else /* 8 */ {
		for (x = 0; x < xbytes; x += elems) {
		    for (i = 0; i < elems; i++)
			buffer[i][bufp] = *rr++;
		    bufp++;
		}
	    }
	}
	bufp = 0;
	return 0;
}

int getPixel(int *r, int *g, int *b, int *a)
{
	int av;

	if (bufp >= comInfo->width) {
		if (getNextLine() != 0)
			return -1;
	}
	if (alpx && (av = buffer[ALPHA][bufp]) < AlphaOpaque) {
		had_alpha = 1;
		if (av == AlphaTransp)
			*r = *g = *b = 255;	/* white */
		else {
			*r = alphaToWhite(buffer[RED][bufp], av);
			*g = alphaToWhite(buffer[GREEN][bufp], av);
			*b = alphaToWhite(buffer[BLUE][bufp], av);
		}
		*a = av;
	}else {
		*r = buffer[RED][bufp];
		*g = buffer[GREEN][bufp];
		*b = buffer[BLUE][bufp];
		*a = AlphaOpaque;
	}
	if (++bufp >= comInfo->width)
		return 1;
	return 0;
}

int getPixelA(int *elm)
{
	if (bufp >= comInfo->width) {
		if (getNextLine() != 0)
			return -1;
	}
	elm[RED]   = buffer[RED][bufp];
	elm[GREEN] = buffer[GREEN][bufp];
	elm[BLUE]  = buffer[BLUE][bufp];
	if (alpx) {
		if ((elm[ALPHA] = buffer[ALPHA][bufp]) < AlphaOpaque)
			had_alpha = 1;
	}else
		elm[ALPHA] = AlphaOpaque;
	if (++bufp >= comInfo->width)
		return 1;
	return 0;
}

int hadAlpha(void)
{
	return had_alpha;
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.