home *** CD-ROM | disk | FTP | other *** search
- /* This source file is part of the LynxLib miscellaneous library by
- Robert Fischer, and is Copyright 1990 by Robert Fischer. It costs no
- money, and you may not make money off of it, but you may redistribute
- it. It comes with ABSOLUTELY NO WARRANTY. See the file LYNXLIB.DOC
- for more details.
- To contact the author:
- Robert Fischer \\80 Killdeer Rd \\Hamden, CT 06517 USA
- (203) 288-9599 fischer-robert@cs.yale.edu */
-
- /* for loading & dicompressing pictures */
- /* This file is missing stuff about printing pictures from the pascal code */
-
- /* Will load a NEO or D*E*G*A*S picture from disk
- Structure of a NEO file:
- 2 words: unused
- 16 words: color palette, hardware format
- 46 words: unknown (rotation info, unused, etc)
- 32000 bytes: the picture, hardware format
-
- Structure of a DEGAS file:
- 1 word: resolution
- 16 words: palette
- 32000 bytes: the picture
-
- You can only tell the difference by size. Degas files are 32033 bytes long,
- and NEO files are 32128 bytes long.
-
- Structure of a DOODLE file:
-
- */
-
- #include <stddef.h>
- #include <e_osbind.h>
- #include <picture.h>
- #include <vfile.h>
-
- /* -------------------------------------------------------- */
- pic_type find_pictype(name) /* Figures out the type of a picture file */
- char *name; /* The name */
- {
- TRANS_BUF *old_trans_p;
- TRANS_BUF trans;
- pic_type out;
- GFILE h;
- WORD first_2; /* First 2 bytes of SPC file. It's an SPC file */
- /* if the WORD contains $5350 */
- char ext[5]; /* Extender of file name */
- int i;
-
- old_trans_p = (TRANS_BUF *)Fgetdta();
- Fsetdta(&trans);
-
- out = ERROR;
- if (Fsfirst(name, NO_ATTRIB) != E_OK) goto err;
- if (trans.size == DEGAS_SIZE) out = DEGAS;
- else if (trans.size == NEO_SIZE) out = NEO;
- else if (trans.size == DOODLE_SIZE) out = DOODLE;
- else if (trans.size == SPU_SIZE) out = SPU;
- else if (trans.size == SCR_SIZE) out = PLAIN_SCREEN;
- else { /* We think it's SPC or COMPRESS. Look in it to find out */
- if ((h = Fopen(name, G_READ)) <= 0) goto err;
- if (Fread(h, 2, &first_2) == 2)
- if (first_2 == 0x5350) out = SPC;
- #if 0
- else if (first_2 == 0x9310) out = SPLAY;
- else if (first_2 == 0x1f9d) out = COMPRESS;
- #endif
- Fclose(h);
-
- /* It may still be unidentified, in which case we look @ name */
- /* To tell if it's a TINY picture */
- if (out == ERROR) {
- for (i = 0; name[i] != '.'; i++) ; /* Find dot */
- strncpy(ext, &name[i+1], 4);
- pstrupper(ext);
- if (ext[2] >= '1' && ext[2] <= '3') ext[2] = 'Y';
- if (strcmp(ext, "TNY") == 0) out = TINY;
- }
- }
- err:
- Fsetdta(old_trans_p);
- return out;
- }
- /* -------------------------------------------------------- */
- raster_convert(pic, atari, ci, bi)
- /* Convert one scanline from DOODLE to NEO */
- DOODLE_PIC *pic;
- PLANE_ARRAY atari; /* Current color place in NEO picture */
- int ci,bi; /* Color index & raster byte index */
- {
- int ai,b,i,j,ai_base;
- int color;
- BOOLEAN for_bool, bak_bool;
- register BYTE *k;
- for (i = 0, ai_base = 0; i < 20; i++, ai_base += 8) {
- for (b = 0; b < 2; b++, ci++, bi += 8) {
- ai = ai_base + b;
- color = pic->c[ci];
- for (j = 0; j < 4; j++) {
- bak_bool = (color >> j) & 1;
- for_bool = (color >> (j+4)) & 1;
-
- k = &atari[ai + (j<<1)];
- if (for_bool) {
- if (bak_bool) *k = 0xFF;
- else *k = pic->b[bi];
- } else {
- if (bak_bool) *k = ~(pic->b[bi]);
- else *k = 0;
- }
- } /* for j */
- } /* for b */
- } /* for i, ai_base */
- }
- /* --------------------------------------------------------------- */
- BOOLEAN read_degas(in, res, pal, pic)
- /* Reads a DEGAS picture from in */
- VFILE *in; /* File to read from */
- WORD *res; /* Resolution */
- char *pal; /* Palette to read to */
- char *pic; /* Picture data to read to */
- {
- read_bytes(in, 2L, res); /* Read res word */
- read_bytes(in, (LONG)PAL_SIZE, pal); /* Read palette */
- read_bytes(in, (LONG)SCR_SIZE, pic);
- }
- /* -------------------------------------------------------- */
- BOOLEAN read_neo(in, res, pal, pic)
- /* Reads a DEGAS picture from in */
- VFILE *in; /* File to read from */
- WORD *res; /* Resolution */
- char *pal; /* Palette to read to */
- char *pic; /* Picture data to read to */
- {
- *res = LOW_RES;
- read_bytes(in, 4L, pic); /* Read unused bytes */
- read_bytes(in, (LONG)PAL_SIZE, pal); /* Read palette */
- read_bytes(in, 92L, pic); /* Read unused bytes */
- read_bytes(in, (LONG)SCR_SIZE, pic); /* Read the picture data */
- }
- /* -------------------------------------------------------- */
- BOOLEAN read_doodle(in, res, pal, pic)
- /* Reads a DEGAS picture from in */
- VFILE *in; /* File to read from */
- WORD *res; /* Resolution */
- PALETTE pal; /* Palette to read to */
- char *pic; /* Picture data to read to */
- {
- static WORD doodle_pal[] = { /* Commodore's palette */
- 0x0000, 0x0777, 0x0700, 0x0066, 0x0527, 0x0160, 0x0007, 0x0771,
- 0x0740, 0x0530, 0x0745, 0x0333, 0x0555, 0x0573, 0x0467, 0x0666
- };
- DOODLE_PIC *dpic; /* Doodle picture pointer */
- int row; /* current row we're converting */
- int color_index, raster_index;
- BYTE *cur_neo; /* Current place in neo picture */
-
- *res = LOW_RES;
-
- /* Load the picture */
- dpic = malloc(sizeof(*dpic));
- read_bytes(in, (LONG)DOODLE_SIZE, dpic);
- if (dpic->load_addr != 92) {
- free(dpic);
- return FALSE;
- }
-
- /* Convert the data from Doodle to Neochrome format */
- cur_neo = pic;
- for (row = 0; row < 200; row++) {
- color_index = (row >> 3) * 40;
- raster_index = (color_index << 3) + (row & 0x7);
- raster_convert(dpic, cur_neo, color_index, raster_index);
- cur_neo += 160;
- }
-
- /* Copy the palette */
- for (row = 0; row < 16; row++)
- pal[row] = doodle_pal[row];
-
- /* Free memory and leave */
- free(dpic);
- return TRUE;
- }
- /* -------------------------------------------------------- */
- BOOLEAN read_plainscr(in, res, pal, pic)
- /* Reads a DEGAS picture from in */
- VFILE *in; /* File to read from */
- WORD *res; /* Resolution */
- PALETTE pal; /* Palette to read to */
- char *pic; /* Picture data to read to */
- {
- int i;
- read_bytes(in, (LONG)SCR_SIZE, pic);
-
- /* No palette or resolution is provided -- use current */
- for (i = 0; i < 16; i++) pal[i] = Setcolor(i, -1);
- *res = Getres();
- }
- /* -------------------------------------------------------- */
- BOOLEAN read_spec(in, pt, res, pal, pic)
- /* Reads a SPEC picture from in */
- VFILE *in; /* File to read from */
- pic_type pt; /* Either SPC or SPU */
- WORD *res; /* Resolution */
- PALETTE pal; /* Palette to read to */
- char *pic; /* Picture data to read to */
- {
- char *spec_pic, *spec_color;
- BOOLEAN out;
- /* Allocate memory for spectrum picture */
- spec_pic = malloc(SCR_SIZE);
- spec_color = malloc(SPEC_PAL_SIZE);
-
- if (pt == SPC) out = load_spc(in, spec_pic, spec_color);
- else out = load_spu(in, spec_pic, spec_color);
- if (out) {
- spu_to_degas(spec_pic, spec_color, pic, pal);
- }
-
- free(spec_pic);
- free(spec_color);
- *res = LOW_RES;
- return out;
- }
- /* -------------------------------------------------------- */
- BOOLEAN read_tiny(in, res, pal, pic)
- /* Reads a TINY picture */
- VFILE *in; /* File to read from */
- WORD *res; /* Resolution */
- PALETTE pal; /* Palette to read to */
- char *pic; /* Picture data to read to */
- {
- WORD numctrl; /* # control bytes */
- WORD numdata; /* # data bytes */
- BYTE *ctrl_buf; /* Buffer of control bytes */
- VFILE *c; /* VFILES for ctrl_buf & pic, respectively */
- VFILE *p;
-
- BYTE dum[4];
- BOOLEAN out = FALSE;
- WORD b;
- register BYTE q, r;
-
- /* Read resolution and possible color rotation data */
- *res = vgetc(in);
- if (*res > HIGH_RES) { /* This could be wrong, but I haven't */
- *res -= 3; /* found a counterexample */
- read_bytes(in, 4L, dum);
- }
-
- /* Read the rest of header */
- read_bytes(in, (LONG)PAL_SIZE, pal);
- read_bytes(in, 2L, &numctrl);
- read_bytes(in, 2L, &numdata);
- numdata <<= 1;
- if (veof(in)) return FALSE;
-
- /* Allocate memory for control bytes & read it in */
- if ((ctrl_buf = malloc(numctrl)) == NULL) return FALSE;
- read_bytes(in, (LONG)numctrl, ctrl_buf);
- if (veof(in)) {
- free(ctrl_buf);
- return FALSE;
- }
-
- c = open_mfile(ctrl_buf, (LONG)numctrl);
- p = open_mfile(pic, (LONG)SCR_SIZE);
-
- /* Convert the data */
- for (b = (WORD)vgetc(c); !veof(c); b = (WORD)vgetc(c)) {
- if (b > 127) { /* Short copy-word */
- b = (256-b) << 1;
- for (; b > 0; b--) vputc(vgetc(in), p);
- } else if (b == 0) { /* Long repeat-word */
- read_bytes(c, 2L, &b);
- read_bytes(in, 2L, dum);
- q = dum[0];
- r = dum[1];
- for (; b > 0; b--) {
- vputc(q, p);
- vputc(r, p);
- }
- } else if (b == 1) { /* Long copy-word */
- read_bytes(c, 2L, &b);
- b <<= 1;
- for (; b > 0; b--) vputc(vgetc(in), p);
- } else { /* Short repeat-word */
- read_bytes(in, 2L, dum);
- q = dum[0];
- r = dum[1];
- for (; b > 0; b--) {
- vputc(q, p);
- vputc(r, p);
- }
- }
- }
-
- free(ctrl_buf);
- vclose(c);
- vclose(p);
- }
- /* -------------------------------------------------------- */
- #if 0
- my_uncompress(v)
- VFILE_REC *v;
- {
- decompress(v->in, v->out);
- vclose(v->in);
- vclose(v->out);
- }
- /* -------------------------------------------------------- */
- my_unsplay(v)
- VFILE_REC *v;
- {
- unsplay(v->in, v->out);
- vclose(v->in);
- vclose(v->out);
- }
- #endif
- /* -------------------------------------------------------- */
- BOOLEAN load_pic(pic, name) /* Loads a picture from disk */
- register pic_rec *pic; /* The place to load it to */
- char *name; /* The name of the picture to load */
- /* Returns TRUE if the picture loaded OK */
- {
- GFILE h;
- pic_type pt;
- char *pic_buf; /* The buffer that the picture file is read into */
- LONG dum;
- long size; /* Size of picture */
- VFILE *in; /* Input file */
- #if 0
- VFILE_REC vrec; /* Arguments to uncompress */
- #endif
- BOOLEAN b;
- BOOLEAN out = FALSE;
- /* Find first useable byte in picture array */
- pic->p_start = (char *)(((LONG)(pic->p) + 255) & 0xFFFFFF00L);
-
- /* Figure out picture type */
- pt = find_pictype(name);
- if (pt == ERROR) return FALSE;
-
- /* Read picture file image into memory & set up a memory VFILE */
- g_file_attrib(name, &dum, &dum, &size);
-
- pic_buf = lmalloc(size);
- h = Fopen(name, READ_MODE);
- if (h <= 0) goto err;
- if (Fread(h, size, pic_buf) != size) {
- Fclose(h);
- goto err;
- }
- if (Fclose(h) != E_OK) goto vclose_err;
- in = open_mfile(pic_buf, size);
-
- /* in = open_ffile(name, "rb");*/
- #if 0
- /* Change in to a cofile handle on uncompress(), if pic is compressed */
- if (pt == SPLAY) {
- /* Rearrange file handles */
- vrec.in = in;
- in = open_cofile(&my_unsplay, &vrec, 2000L, &vrec.out);
-
- /* Find size and type */
- pt = vgetc(in);
- read_bytes(in, 4L, &size);
- }
-
- if (pt == COMPRESS) {
- /* Rearrange file handles */
- vrec.in = in;
- in = open_cofile(&my_uncompress, &vrec, 2000L, &vrec.out);
-
- /* Find size and type */
- pt = vgetc(in);
- read_bytes(in, 4L, &size);
- }
- #endif
- /* Read in the file to appropriate data structure */
- switch(pt) {
- case SPC :
- case SPU :
- b = read_spec(in, pt, &(pic->rez), pic->pal, pic->p_start);
- break;
- case DEGAS :
- b = read_degas(in, &(pic->rez), pic->pal, pic->p_start);
- break;
- case NEO :
- b = read_neo(in, &(pic->rez), pic->pal, pic->p_start);
- break;
- case DOODLE :
- b = read_doodle(in, &(pic->rez), pic->pal, pic->p_start);
- break;
- case TINY :
- b = read_tiny(in, &(pic->rez), pic->pal, pic->p_start);
- break;
- case PLAIN_SCREEN : /* No data other than bit image */
- b = read_plainscr(in, &(pic->rez), pic->pal, pic->p_start);
- break;
- } /* Switch */
-
- out = TRUE;
- vclose_err:
- vclose(in);
- err:
- free(pic_buf);
-
- return out;
- }
- /* -------------------------------------------------------- */
- setres(res) /* Sets the current resolution to res, if possible */
- /* This needs 32256 bytes in malloc'able memory, if the resolution changes */
- int res;
- {
- int ores;
- char *pic;
- char *p;
- char *old_phys, *old_log;
-
- /* Try to save effort */
- ores = Getres();
- if (res == HIGH_RES || ores == HIGH_RES) return;
- if (res == ores) return;
-
- /* Now, really do it! */
- pic = malloc(32256);
- p = (char *)(((LONG)(pic) + 255) & 0xFFFFFF00L);
- old_phys = Physbase();
- old_log = Logbase();
- Setscreen(p, -1, -1);
- Setscreen(-1, p, -1);
- Setscreen(-1, -1, res);
- Setscreen(old_log, -1, -1);
- Setscreen(-1, old_phys, -1);
- free(pic);
- }
- /* -------------------------------------------------------- */
- switch_pic(pic) /* Switches screen to the specified picture */
- register pic_rec *pic; /* The picture to switch to */
- {
- int i;
-
- /* Take care of resolution */
- pic->old_rez = Getres();
- setres(pic->rez);
-
- /* Take care of screen location */
- pic->old_phys = Physbase();
- pic->old_log = Logbase();
- Setscreen(pic->p_start, pic->p_start, -1);
-
- /* Take care of palette */
- for (i = 0; i <= 15; i++) {
- pic->old_pal[i] = Setcolor(i, pic->pal[i]);
- }
- }
- /* -------------------------------------------------------- */
- switch_norm(pic) /* Switches back to the normal screen */
- register pic_rec *pic; /* The picture to switch from */
- {
- setres(pic->old_rez);
- Setscreen(pic->old_log, pic->old_phys, -1);
-
- /* Take care of pallette */
- Setpalette(pic->old_pal);
- }
- /* -------------------------------------------------------- */
- BOOLEAN save_neo(pic, name)
- register pic_rec *pic; /* The place to load it to */
- char *name; /* The name of the picture to load */
- /* Returns TRUE if the picture saved OK */
- {
- int h; /* File handle */
- WORD filler[46]; /* Zeros to write in neo file */
- if (pic->rez != LOW_RES) return FALSE; /* NEO format only low resolution */
-
- for (h = 0; h < 46; h++)
- filler[h] = 0;
-
- h = Fcreate(name, 0);
- if (h <= 0) return FALSE;
- if (Fwrite(h, (LONG)(2*sizeof(WORD)), filler) != 2*sizeof(WORD)) goto err;
- if (Fwrite(h, (LONG)sizeof(PALETTE), pic->pal) != sizeof(PALETTE)) goto err;
- if (Fwrite(h, (LONG)(46*sizeof(WORD)), filler) != 46*sizeof(WORD)) goto err;
- if (Fwrite(h, (LONG)SCR_SIZE, pic->p_start) != SCR_SIZE) goto err;
-
- Fclose(h);
- return TRUE;
- err:
- Fclose(h);
- return FALSE;
- }
- /* -------------------------------------------------------- */
- /* Picture conversion routines -- usually, convert between resolutions */
- /* -------------------------------------------------------- */
- /* -------------------------------------------------------- */
- /* Convert a low-res picture to a high-res picture */
- /* This great-o routine was created by Roland Lieger in 1988. */
- /* He was so gratious to let Robert Fischer steal it while */
- /* only including this little message */
- ltoh(pic)
- pic_rec *pic;
- {
- register WORD l1,l2,l3,l4;
- WORD temp1,temp2,temp3,temp4;
- WORD *p1,*p2,*p3,*p4;
- LONG *line1,*line2;
- WORD buffer[80];
- int curcol;
- int red,green,blue,brightness;
- int grayscale[16];
- int code[16];
- register int currcol;
- int i,j,k,line;
- int lev1,lev2,lev3;
- LONG long1,long2;
-
- static BYTE data[]={0x09,0x03,0x0a,0x06,0x0c,0x05,0x09,0x03,0x0a,
- 0x06,0x0c,0x05,0x09,0x03,0x06,0x0a};
- /* different patterns of 2 bits in 4 in a good order */
-
- /* ----------- Calculate the palette ----------- */
- for (i=0;i<16;i++) {
- curcol=pic->pal[i];
- red=(curcol>>8)&7;
- green=(curcol>>4)&7;
- blue=curcol&7;
- brightness=red*red+green*green+blue*blue;
- if (brightness>108) grayscale[i]=0;
- else if (brightness>70) grayscale[i]=1;
- else if (brightness>43) grayscale[i]=2;
- else if (brightness>7) grayscale[i]=3;
- else grayscale[i]=4;
- }
- lev1=0;
- lev2=0;
- lev3=0;
-
- for (i=0;i<16;i++) {
-
- for (j=0;j<i;j++) {
- if (pic->pal[i]==pic->pal[j]) {
- code[i]=code[j];
- break;
- }
- }
-
- if (i==j) {
- if (grayscale[i]==0) {
- code[i]=0;
- } else if (grayscale[i]==4) {
- code[i]=0xf;
- } else if (grayscale[i]==1) {
- code[i]=1<<(lev1&3);
- lev1++;
- } else if (grayscale[i]==2) {
- lev2++;
- code[i]=data[lev2];
- } else {
- code[i]=(0xee>>(lev3&3)&0xf);
- lev3++;
- }
- }
- }
-
- /*---------------- Process the picture -----------------*/
-
- p1=((WORD*)(pic->p_start))+3;
- p2=((WORD*)(pic->p_start))+2;
- p3=((WORD*)(pic->p_start))+1;
- p4=((WORD*)(pic->p_start));
-
- line1=((LONG*)pic->p_start);
- line2=((LONG*)pic->p_start)+20; /* 20 LONGs make up a 640 dot line */
-
- for (line=0;line<200;line++) {
- j=0;
- for (i=0;i<20;i++) {
- l1=*p1;
- l2=*p2;
- l3=*p3;
- l4=*p4;
-
- temp1=(l1&0x5555)<<1; /* Flip all the bits around to be able to */
- temp2=(l2&0xaaaa)>>1; /* Get the colors out */
- l1=(l1&0xaaaa)+temp2;
- l2=(l2&0x5555)+temp1;
- temp3=(l3&0x5555)<<1;
- temp4=(l4&0xaaaa)>>1;
- l3=(l3&0xaaaa)+temp4;
- l4=(l4&0x5555)+temp3;
- temp1=l1&0x3333;
- temp2=l2&0x3333;
- temp3=l3&0xcccc;
- temp4=l4&0xcccc;
- l1=(l1&0xcccc)+(temp3>>2);
- l2=(l2&0xcccc)+(temp4>>2);
- l3=(l3&0x3333)+(temp1<<2);
- l4=(l4&0x3333)+(temp2<<2);
-
- buffer[j++]=l1;
- buffer[j++]=l2;
- buffer[j++]=l3;
- buffer[j++]=l4;
-
- p1+=4;
- p2+=4;
- p3+=4;
- p4+=4;
- } /* end of the for loop - one color (= 2 monochrome )pictureline done */
- for (i=0;i<80;i+=4) {
- l1=buffer[i];
- l2=buffer[i+1];
- l3=buffer[i+2];
- l4=buffer[i+3];
-
- for (k=0;k<4;k++) {
- currcol=code[((l1&0xf000)>>12)];
- l1<<=4;
- long1<<=2;
- long2<<=2;
- long1+=((currcol&0x0c)>>2);
- long2+=(currcol&0x03);
-
- currcol=code[((l2&0xf000)>>12)];
- l2<<=4;
- long1<<=2;
- long2<<=2;
- long1+=((currcol&0x0c)>>2);
- long2+=(currcol&0x03);
-
- currcol=code[((l3&0xf000)>>12)];
- l3<<=4;
- long1<<=2;
- long2<<=2;
- long1+=((currcol&0x0c)>>2);
- long2+=(currcol&0x03);
-
- currcol=code[((l4&0xf000)>>12)];
- l4<<=4;
- long1<<=2;
- long2<<=2;
- long1+=((currcol&0x0c)>>2);
- long2+=(currcol&0x03);
- }
- *line1=long1;
- *line2=long2;
- line1++;
- line2++;
- }
- line1+=20; /* One 640 dot line has 20 LONGs */
- line2+=20; /* line1 and line 2 each skip over each others screenlines */
- } /* end of for (line... */
-
- /* Change the palette so it's the "standard" for B&W: */
- /* White backround, black forground */
- pic->pal[0] = 1;
- } /* end of ltoh */
- /* -------------------------------------------------------- */
- BOOLEAN change_res(pic, dest_res)
- /* Converts a picture from its current resolution to the destination res */
- pic_rec *pic; /* Picture to convert */
- int dest_res; /* Destination resolution */
- {
- if (pic->rez == dest_res) return TRUE;
- if (pic->rez == LOW_RES && dest_res == HIGH_RES) {
- ltoh(pic);
- pic->rez = HIGH_RES;
- return TRUE;
- }
- return FALSE;
- }
- /* -------------------------------------------------------- */
-