aboutsummaryrefslogtreecommitdiff
path: root/Src/Winamp/plush/READ_PCX.C
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Winamp/plush/READ_PCX.C
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Winamp/plush/READ_PCX.C')
-rw-r--r--Src/Winamp/plush/READ_PCX.C162
1 files changed, 162 insertions, 0 deletions
diff --git a/Src/Winamp/plush/READ_PCX.C b/Src/Winamp/plush/READ_PCX.C
new file mode 100644
index 00000000..e1de3825
--- /dev/null
+++ b/Src/Winamp/plush/READ_PCX.C
@@ -0,0 +1,162 @@
+/******************************************************************************
+Plush Version 1.2
+read_pcx.c
+PCX Texture Reader
+Copyright (c) 1996-2000, Justin Frankel
+******************************************************************************/
+
+#include "plush.h"
+
+static pl_uInt _plHiBit(pl_uInt16);
+static pl_uInt _plOptimizeImage(pl_uChar *, pl_uChar *, pl_uInt32);
+static pl_sInt _plReadPCX(char *filename, pl_uInt16 *width, pl_uInt16 *height,
+ pl_uChar **pal, pl_uChar **data);
+static void _plRescaleImage(pl_uChar *in, pl_uChar *out, pl_uInt inx,
+ pl_uInt iny, pl_uInt outx, pl_uInt outy);
+
+pl_Texture *plReadPCXTex(char *fn, pl_Bool rescale, pl_Bool optimize) {
+ pl_uChar *data, *pal;
+ pl_uInt16 x, y;
+ pl_Texture *t;
+ if (_plReadPCX(fn,&x,&y,&pal,&data) < 0) return 0;
+ t = (pl_Texture *) malloc(sizeof(pl_Texture));
+ if (!t) return 0;
+ t->Width = _plHiBit(x);
+ t->Height = _plHiBit(y);
+ if (rescale && (1 << t->Width != x || 1 << t->Height != y)) {
+ pl_uChar nx, ny, *newdata;
+ nx = t->Width;
+ if ((1 << t->Width) != x) nx++;
+ ny = t->Height;
+ if ((1 << t->Height) != y) ny++;
+ newdata = (pl_uChar *) malloc((1<<nx)*(1<<ny));
+ if (!newdata) {
+ free(t);
+ free(data);
+ free(pal);
+ return 0;
+ }
+ _plRescaleImage(data,newdata,x,y,1<<nx,1<<ny);
+ free(data);
+ data = newdata;
+ t->Width = nx;
+ t->Height = ny;
+ x = 1<<nx; y = 1<<ny;
+ }
+ t->iWidth = x;
+ t->iHeight = y;
+ t->uScale = (pl_Float) (1<<t->Width);
+ t->vScale = (pl_Float) (1<<t->Height);
+ if (optimize) t->NumColors = _plOptimizeImage(pal, data,x*y);
+ else t->NumColors = 256;
+ t->Data = data;
+ t->PaletteData = pal;
+ return t;
+}
+
+
+static pl_uInt _plHiBit(pl_uInt16 x) {
+ pl_uInt i = 16, mask = 1<<15;
+ while (mask) {
+ if (x & mask) return i;
+ mask >>= 1; i--;
+ }
+ return 0;
+}
+
+static pl_uInt _plOptimizeImage(pl_uChar *pal, pl_uChar *data, pl_uInt32 len) {
+ pl_uChar colors[256], *dd = data;
+ pl_uChar remap[256];
+ pl_sInt32 lastused, firstunused;
+ pl_uInt32 x;
+ memset(colors,0,256);
+ for (x = 0; x < len; x ++) colors[(pl_uInt) *dd++] = 1;
+ lastused = -1;
+ for (x = 0; x < 256; x ++) remap[x] = (pl_uChar)x;
+ lastused = 255;
+ firstunused = 0;
+ for (;;) {
+ while (firstunused < 256 && colors[firstunused]) firstunused++;
+ if (firstunused > 255) break;
+ while (lastused >= 0 && !colors[lastused]) lastused--;
+ if (lastused < 0) break;
+ if (lastused <= firstunused) break;
+ pal[firstunused*3] = pal[lastused*3];
+ pal[firstunused*3+1] = pal[lastused*3+1];
+ pal[firstunused*3+2] = pal[lastused*3+2];
+ colors[lastused] = 0;
+ colors[firstunused] = 1;
+ remap[lastused] = (pl_uChar) firstunused;
+ }
+ x = len;
+ while (x--) *data++ = remap[(pl_uInt) *data];
+ return (lastused+1);
+}
+
+static pl_sInt _plReadPCX(char *filename, pl_uInt16 *width, pl_uInt16 *height,
+ pl_uChar **pal, pl_uChar **data) {
+ pl_uInt16 sx, sy, ex, ey;
+ FILE *fp = fopen(filename,"rb");
+ pl_uChar *data2;
+ if (!fp) return -1;
+ fgetc(fp);
+ if (fgetc(fp) != 5) { fclose(fp); return -2; }
+ if (fgetc(fp) != 1) { fclose(fp); return -2; }
+ if (fgetc(fp) != 8) { fclose(fp); return -3; }
+ sx = fgetc(fp); sx |= fgetc(fp)<<8;
+ sy = fgetc(fp); sy |= fgetc(fp)<<8;
+ ex = fgetc(fp); ex |= fgetc(fp)<<8;
+ ey = fgetc(fp); ey |= fgetc(fp)<<8;
+ *width = ex - sx + 1;
+ *height = ey - sy + 1;
+ fseek(fp,128,SEEK_SET);
+ if (feof(fp)) { fclose(fp); return -4; }
+ *data = (pl_uChar *) malloc((*width) * (*height));
+ if (!*data) { fclose(fp); return -128; }
+ sx = *height;
+ data2 = *data;
+ do {
+ int xpos = 0;
+ do {
+ char c = fgetc(fp);
+ if ((c & 192) == 192) {
+ char oc = fgetc(fp);
+ c &= ~192;
+ do {
+ *(data2++) = oc;
+ xpos++;
+ } while (--c && xpos < *width);
+ } else {
+ *(data2++) = c;
+ xpos++;
+ }
+ } while (xpos < *width);
+ } while (--sx);
+ if (feof(fp)) { fclose(fp); free(*data); return -5; }
+ fseek(fp,-769,SEEK_END);
+ if (fgetc(fp) != 12) { fclose(fp); free(*data); return -6; }
+ *pal = (pl_uChar *) malloc(768);
+ if (!*pal) { fclose(fp); free(*data); return -7; }
+ fread(*pal,3,256,fp);
+ fclose(fp);
+ return 0;
+}
+
+static void _plRescaleImage(pl_uChar *in, pl_uChar *out, pl_uInt inx,
+ pl_uInt iny, pl_uInt outx, pl_uInt outy) {
+ pl_uInt x;
+ pl_uInt32 X, dX, dY, Y;
+ dX = (inx<<16) / outx;
+ dY = (iny<<16) / outy;
+ Y = 0;
+ do {
+ pl_uChar *ptr = in + inx*(Y>>16);
+ X = 0;
+ Y += dY;
+ x = outx;
+ do {
+ *out++ = ptr[X>>16];
+ X += dX;
+ } while (--x);
+ } while (--outy);
+}