Category : Recently Uploaded Files
Archive   : PL192SRC.ZIP
Filename : PLPOINT.C
** point processes just update the array lookup[][], pending a TRANSFORM
** command. This enables these operations to be stacked up without any disk
** I/O until all are complete. Commands here include HISTOGRAM, GRAY, COLOR,
** NEGATE, BRIGHTEN/DARKEN, CONTRAST, GAMMA, EQUALIZE, and TRANSFORM.
*/
#include
#include
#include
#ifdef MSDOS
#include
#endif
#include "piclab.h"
#include "yiq"
static char msg1[] = "Point transformation pending.\r\n",
*pn[] = { "RED", "GREEN", "BLUE", NULL },
unimp[] = "Sorry, this function is currently unimplemented.\r\n";
static int pf[3];
static int loadhist(void);
/* Utility routine to load histogram. Nothing terribly mysterious here.
*/
static int loadhist()
{
U32 mem, *hp;
int i;
U8 *sp;
U16 lines, x;
struct _plane *ip;
if (histvalid) return 0;
mem = mark();
if (new->planes == 0) return 7;
for (i=0; i<256; ++i) hist[0][i] = hist[1][i] = hist[2][i] = 0L;
pl_printf(working);
for (i=0; i < new->planes; ++i) {
hp = hist[i];
if ((ip = openplane(i, new, READ)) == NULL) return 3;
for (lines=0; lines < new->height; ++lines) {
if (getline(ip) == 0) return 4;
sp = ip->linebuf;
if (new->flags & 2) {
for (x=0; x < new->width; ++x) {
++hist[0][gcmap[0][*sp]];
++hist[1][gcmap[1][*sp]];
++hist[2][gcmap[2][*sp]];
++sp;
}
} else for (x=0; x < new->width; ++x) ++hp[*sp++];
pl_trace(lines);
}
closeplane(ip);
release(mem);
}
pl_printf(crlf);
histvalid = 1;
return 0;
}
/* Handler for HISTOGRAM command. If no arguments are given, histograms are
** plotted for all planes; if one or more arguments are given, a histogram is
** plotted for each plane specified.
*/
int histogram(int ac, argument *av)
{
U32 hmax, hv, *hp, h2[64];
int i, j, k, r, nh, np;
char temp[80];
U8 *lp;
double lhm;
if (new->planes == 0) return 7;
if (new->flags & 2) np = 3; else np = new->planes;
if ((r = loadhist()) != 0) return r;
pf[0] = pf[1] = pf[2] = (ac == 1);
while (--ac > 0) {
if ((i = pl_match((*++av).cval, pn)) != 0) pf[i-1] = 1;
}
nh = 0;
for (i=0; i < np; ++i) {
if (!pf[i]) continue;
#ifdef MSDOS
if (interactive && ++nh > 1) {
pl_printf("\r\nPress any key for next graph.\r");
getch();
}
#endif
strcpy(temp, " ");
hmax = 0L;
for (j=0; j<64; ++j) h2[j] = 0L;
hp = hist[i];
lp = lookup[i];
for (j=0; j<256; ++j) h2[(*lp++)>>2] += *hp++;
for (j=0; j<64; ++j) if (hmax < h2[j]) hmax = h2[j];
lhm = log((double)hmax);
for (j=20; j>0; --j) {
hv = (U32)exp((lhm * j) / 20.0);
for (k=0; k<64; ++k)
if (h2[k] >= hv) temp[k+6] = 'X'; else temp[k+6] = ' ';
temp[70] = '\r';
temp[71] = '\n';
temp[72] = '\0';
pl_printf(temp);
}
pl_sprintf(temp, "%-6.6s----------------------------------------------------------------\r\n",
(np == 3) ? pn[i] : "GRAY");
pl_printf(temp);
pl_printf(" 0 1 2 3 4 5 6 7 8 9 A B C D E F \r\n");
pl_printf(" 048C048C048C048C048C048C048C048C048C048C048C048C048C048C048C048C\r\n");
}
return 0;
}
/* Create negative of NEW. Arguments are handled as in histogram().
*/
int negate(int ac, argument *av)
{
U8 *lp;
U32 temp, *hp;
int i, j;
pf[0] = pf[1] = pf[2] = (ac == 1);
while (--ac > 0) {
if ((i = pl_match((*++av).cval, pn)) != 0) pf[i-1] = 1;
}
for (i=0; i<3; ++i) {
if (!pf[i]) continue;
lp = lookup[i];
hp = hist[i];
for (j=0; j<256; ++j) lp[j] ^= 0xFF;
for (j=0; j<128; ++j) {
temp = hp[j]; hp[j] = hp[255-j]; hp[255-j] = temp;
}
}
pl_printf(msg1);
transpend = 1;
return 0;
}
/* Handler for BRIGHTEN and DARKEN commands. Add or subtract a fixed amount
** from each color value. If only one argument is given, all planes are
** brightened by that amount. Otherwise, arguments are interpreted in order,
** and any arguments which specify planes determine which plane to next
** numerical argument effects. E.g., BRIGHTEN RED 10 BLUE 15 would add 10
** to the values in the red plane and 15 to the blue.
*/
int brightness(int ac, argument *av)
{
U8 *lp;
int i, j, a[3], a1, v, lost = 1, sign;
lost = a[0] = a[1] = a[2] = 0;
if (*av[0].cval == 'D') sign = -1; else sign = 1;
if (ac == 1) {
pl_printf("Syntax is %s
return 0;
} else if (ac == 2) {
a1 = sign * (int)(av[1].fval);
a[0] = a[1] = a[2] = a1;
} else {
i = 0;
while (--ac > 0) {
if ((j = pl_match((*++av).cval, pn)) != 0) i = j-1;
else a[i++] = sign * (int)(av->fval);
}
}
for (i=0; i<3; ++i) if (a[i] < -255 || a[i] > 255) return 9;
for (i=0; i < 3; ++i) {
lp = lookup[i];
if ((a1 = a[i]) == 0) continue;
for (j=0; j<256; ++j) {
v = (int)*lp + a1;
if (v < 0) v = 0;
if (v > 255) v = 255;
*lp++ = (U8)v;
}
}
if (lost) pl_warn(3);
pl_printf(msg1);
transpend = 1;
return 0;
}
/* Handler for GAMMA command. Arguments are handled as in brightness(). If
** argument is negative, value is taken to be reciprocal of absolute value,
** i.e., GAMMA -2.0 is the same as GAMMA 0.5.
*/
int gamma(int ac, argument *av)
{
U8 *lp, lu2[256];
int i, j, v;
double g[3], g1, d;
g[0] = g[1] = g[2] = 0.0;
if (ac == 1) {
pl_printf("Syntax is %s
return 0;
} else if (ac == 2) {
g1 = av[1].fval;
g[0] = g[1] = g[2] = g1;
} else {
i = 0;
while (--ac > 0) {
if ((j = pl_match((*++av).cval, pn)) != 0) i = j-1;
else g[i++] = av->fval;
}
}
for (i=0; i<3; ++i) {
if (g[i] < 0.0) g[i] = 1.0 / (-g[i]);
}
for (i=0; i < 3; ++i) {
if ((g1 = g[i]) <= 0.0) continue;
d = pow(255.0, g1-1.0);
lp = lu2;
*lp++ = 0;
for (j=1; j<256; ++j) {
v = (int)(pow((double)j, g1) / d);
if (v < 0) v = 0; else if (v > 255) v = 255;
*lp++ = (U8)v;
}
lp = lookup[i];
for (j=0; j<256; ++j) {
v = lu2[*lp];
*lp++ = (U8)v;
}
}
/* It is very hard to determine whether information was lost with this
** function, but it almost always is, so we just always print the
** 'info lost' warning.
*/
pl_warn(3);
pl_printf(msg1);
transpend = 1;
return 0;
}
/* Handler for CONTRAST command Stretches or squeezes contrast of image.
** Arguments are handled as in brightness().
*/
int contrast(int ac, argument *av)
{
U8 *lp;
int i, j, c1, c[3], r, v, lost = 1;
lost = c[0] = c[1] = c[2] = 0;
if (ac == 1) {
pl_printf("Syntax is %s
return 0;
} else if (ac == 2) {
c1 = (int)(av[1].fval);
c[0] = c[1] = c[2] = c1;
} else {
i = 0;
while (--ac > 0) {
if ((j = pl_match((*++av).cval, pn)) != 0) i = j-1;
else c[i++] = (int)(av->fval);
}
}
for (i=0; i<3; ++i) if (c[i] < -127 || c[i] > 127) return 9;
for (i=0; i<3; ++i) {
if ((c1 = c[i]) == 0) continue;
lp = lookup[i];
r = 255 - (c1 << 1);
for (j=0; j<256; ++j) {
v = (int)((((int)*lp - c1) * 256L) / r);
if (v < 0) v = 0;
else if (v > 255) v = 255;
*lp++ = (U8)v;
}
}
if (lost) pl_warn(3);
pl_printf(msg1);
transpend = 1;
return 0;
}
/* Convert grayscale image to color-mapped.
*/
int color(int ac, argument *av)
{
int i;
if (new->planes != 1 || (new->flags & 2)) {
pl_printf("Image is already color.\r\n");
return 0;
}
new->flags |= 2;
for (i=0; i<256; ++i) gcmap[0][i] = gcmap[1][i] = gcmap[2][i] = (U8)i;
pl_printf(done);
return 0;
}
/* Convert whole image to grayscale. Uses lookup tables from the file YIQ
** to perform the NTSC formula. No arguments.
*/
int grayscale(int ac, argument *av)
{
int r, i, v;
U8 *rp, *gp, *bp, *dp;
U16 lines, x;
struct _plane *ip[3], *op;
if (new->planes == 1 && ((new->flags & 2) == 0)) {
pl_printf("Image is already grayscale.\r\n");
return 0;
}
if (ac != 1) pl_warn(1);
if ((r = begintransform()) != 0) return r;
new->planes = 1;
new->flags &= ~2;
if (old->planes == 1) {
for (i=0; i<256; ++i) {
v = ry[gcmap[0][i]] + gy[gcmap[1][i]] + by[gcmap[2][i]];
gcmap[0][i] = gcmap[1][i] = gcmap[2][i] = (U8)v;
}
}
for (i=0; i
if ((op = openplane(0, new, WRITE)) == NULL) return 3;
pl_printf(working);
for (lines=0; lines < new->height; ++lines) {
for (i=0; i
rp = ip[0]->linebuf;
if (old->planes > 1) {
gp = ip[1]->linebuf;
bp = ip[2]->linebuf;
}
dp = op->linebuf;
if (old->planes == 1) {
for (x=0; x < new->width; ++x) {
*dp++ = gcmap[0][*rp++];
}
} else {
for (x=0; x < new->width; ++x) {
*dp++ = ry[*rp++] + gy[*gp++] + by[*bp++];
}
}
if (putline(op) == 0) return 3;
pl_trace(lines);
}
for (i=0; i
closeplane(op);
pl_printf(done);
return 0;
}
/* Write any pending point transformations to disk. No arguments.
*/
int transform(int ac, argument *av)
{
U32 mem;
int r, i;
U8 *sp, *dp, *lp;
U16 lines, x;
struct _plane *ip, *op;
if (!transpend) {
pl_printf("No transformation pending.\r\n");
return 0;
} else transpend = 0;
if (new->flags & 2) {
for (i=0; i<256; ++i) {
gcmap[0][i] = lookup[0][gcmap[0][i]];
gcmap[1][i] = lookup[1][gcmap[1][i]];
gcmap[2][i] = lookup[2][gcmap[2][i]];
}
} else {
mem = mark();
if ((r = begintransform()) != 0) return r;
pl_printf(working);
for (i=0; i < new->planes; ++i) {
lp = lookup[i];
if ((ip = openplane(i, old, READ)) == NULL) return 3;
if ((op = openplane(i, new, WRITE)) == NULL) return 3;
for (lines=0; lines < new->height; ++lines) {
if (getline(ip) == 0) return 4;
sp = ip->linebuf;
dp = op->linebuf;
for (x=0; x < new->width; ++x) *dp++ = lp[*sp++];
if (putline(op) == 0) return 3;
pl_trace(lines);
}
closeplane(ip);
closeplane(op);
release(mem);
}
}
for (i=0; i<256; ++i) lookup[0][i] = lookup[1][i] = lookup[2][i] = (U8)i;
pl_printf(done);
return 0;
}
int equalize(int ac, argument *av)
{
U8 *lp;
int i;
if (new->planes != 3 || (new->flags & 2)) {
pl_printf("Image is not true-color.\r\n");
return 0;
}
pl_printf(done);
return 0;
}
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/