home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DOS/V Power Report 1997 March
/
VPR9703A.ISO
/
VPR_DATA
/
DOGA
/
SOURCES
/
REND.LZH
/
PIC1600
/
REDUCE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-06-18
|
5KB
|
173 lines
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "piclib.h"
PicReduceData *PicColorReduceOpen(int sizex, int mode)
{
PicReduceData *data;
if ((data = malloc(sizeof(PicReduceData))) == NULL) {
return NULL;
}
data->mode = mode;
data->y = 0;
data->x = sizex;
data->nowbuf = data->nextbuf = NULL;
switch (mode) {
case REDUCE_NORMAL:
break;
case REDUCE_DITHER_ORDERED:
break;
case REDUCE_DITHER_RANDOM:
break;
case REDUCE_DITHER_ERROR:
case REDUCE_DITHER_ERROR216:
if ((data->nowbuf = malloc(sizeof(Pixel)*(sizex+2))) == NULL) {
free(data);
return NULL;
}
if ((data->nextbuf = malloc(sizeof(Pixel)*(sizex+2))) == NULL) {
free(data->nowbuf);
free(data);
return NULL;
}
memset(data->nowbuf, 0, sizeof(Pixel)*(sizex+2));
memset(data->nextbuf, 0, sizeof(Pixel)*(sizex+2));
break;
}
return data;
}
int PicColorReduce(PicReduceData *data, Pixel *dst, Pixel *p)
{
static const int dither_map[2][2] = {{0,6}, {4,2}};
int r, g, b, x;
switch (data->mode) {
case REDUCE_DITHER_ORDERED:
for (x = 0; x < data->x; ++x) {
g = (int)((p[x]>>24) & 0xff); g = g - g/32 + dither_map[x&1][data->y&1];
r = (int)((p[x]>>16) & 0xff); r = r - r/32 + dither_map[x&1][data->y&1];
b = (int)((p[x]>> 8) & 0xff); b = b - b/32 + dither_map[x&1][data->y&1];
dst[x] = (g << 24) + (r << 16) + (b << 8) + (p[x]&0xff);
}
data->y++;
break;
case REDUCE_DITHER_RANDOM:
{
int diff;
for (x = 0; x < data->x; ++x) {
diff = (rand()>>12)%8;
g = (int)((p[x] >> 24) & 0xff); g = g - g/32 + diff;
r = (int)((p[x] >> 16) & 0xff); r = r - r/32 + diff;
b = (int)((p[x] >> 8) & 0xff); b = b - b/32 + diff;
dst[x] = (g << 24) + (r << 16) + (b << 8) + (p[x]&0xff);
}
}
break;
case REDUCE_DITHER_ERROR:
{
int x;
int er = 0, eg = 0, eb = 0, ee;
int tmp;
Pixel *now, *next;
now = data->nowbuf;
next = data->nextbuf;
data->nowbuf = next;
data->nextbuf = now;
memset(next, 0, sizeof(Pixel)*data->x);
for (x = 0; x < data->x; ++x) {
tmp = (int)((p[x] >> 24) & 0xff); tmp = tmp - (tmp/32);
g = tmp & 0xf8;
ee = (tmp & 7) * 8+ eg + (int)((now[x] >> 24) & 0xff);
/*printf("(%3d):%3d:%3d=%3d+%3d+%3d", x, g, ee, (tmp&7)*8, eg, ((now[x] >> 24) & 0xff));*/
if (ee > 64) {ee = 0; g += 8;}
eg = (ee * 3 + 4)/8;
/*printf("-> %3d:%3d\n", g, eg);*/
next[x ] += eg << 24;
next[x+1] += (ee-eg*2) << 24;
tmp = (int)((p[x] >> 16) & 0xff); tmp = tmp - (tmp/32);
r = tmp & 0xf8;
ee = (tmp & 7) * 8 + er + (int)((now[x] >> 16) & 0xff);
if (ee > 64) {ee = 0; r+=8;}
er = (ee * 3 + 4)/8;
next[x ] += er << 16;
next[x+1] += (ee-er*2) << 16;
tmp = (int)((p[x] >> 8) & 0xff); tmp = tmp - (tmp/32);
b = tmp & 0xf8;
ee = (tmp & 7) * 8 + eb + (int)((now[x] >> 8) & 0xff);
if (ee > 64) {ee = 0; b+=8;}
eb = (ee * 3 + 4)/8;
next[x ] += eb << 8;
next[x+1] += (ee-eb*2) << 8;
dst[x] = (g << 24) + (r << 16) + (b << 8) + (p[x]&0xff);
}
}
break;
case REDUCE_DITHER_ERROR216:
{
int x;
int er = 0, eg = 0, eb = 0, ee;
Pixel *now, *next;
now = data->nowbuf;
next = data->nextbuf;
data->nowbuf = next;
data->nextbuf = now;
memset(next, 0, sizeof(Pixel)*data->x);
for (x = 0; x < data->x; ++x) {
ee = (int)((p[x] >> 24) & 0xff) + eg + (int)((now[x] >> 24) & 0xff);
g = ee / 32; ee = ee % 32;
eg = (ee * 3 + 4) / 8;
next[x ] += eg << 24;
next[x+1] += (ee-eg*2) << 24;
ee = (int)((p[x] >> 16) & 0xff) + er + (int)((now[x] >> 16) & 0xff);
r = ee / 32; ee = ee % 32;
er = (ee * 3 + 4) / 8;
next[x ] += er << 16;
next[x+1] += (ee-er*2) << 16;
ee = (int)((p[x] >> 8) & 0xff) + eb + (int)((now[x] >> 8) & 0xff);
b = ee / 32; ee = ee % 32;
eb = (ee * 3 + 4) / 8;
next[x ] += eb << 8;
next[x+1] += (ee-eb*2) << 8;
if (--r < 0) r = 0;
if (r > 5) r = 5;
if (--g < 0) g = 0;
if (g > 5) g = 5;
if (--b < 0) b = 0;
if (b > 5) b = 5;
dst[x] = ((g * 51) << 24)
+ ((r * 51) << 16)
+ ((b * 51) << 8) + (p[x]&0xff);
}
}
break;
default:
if (dst != p) {
memcpy(dst, p, sizeof(Pixel) * data->x);
}
break;
}
return TRUE;
}
int PicColorReduceClose(PicReduceData *data)
{
if (data != NULL) {
if (data->nowbuf != NULL) {
free(data->nowbuf);
}
if (data->nextbuf != NULL) {
free(data->nextbuf);
}
}
return TRUE;
}