1 /* Zgv v3.0 - GIF, JPEG and PBM/PGM/PPM viewer, for VGA PCs running Linux.
2  * Copyright (C) 1993-1998 Russell Marks. See README for license details.
3  *
4  * readmrf.c - read the 1-bit mono `mrf' format. based on my `mrftopbm'.
5  */
6 
7 #include <stdio.h>
8 #include <string.h>
9 #include <stdlib.h>
10 #include "zgv.h"
11 #include "readmrf.h"
12 
13 
14 /* for aborted_file_mrf_cleanup() */
15 static unsigned char *work_bmap,*work_pal;
16 static FILE *work_in;
17 
18 static int bitbox,bitsleft;
19 
20 
21 
bit_init()22 void bit_init()
23 {
24 bitbox=0; bitsleft=0;
25 }
26 
27 
bit_input(FILE * in)28 int bit_input(FILE *in)
29 {
30 if(bitsleft==0)
31   {
32   bitbox=fgetc(in);
33   bitsleft=8;
34   }
35 
36 bitsleft--;
37 return((bitbox&(1<<bitsleft))?1:0);
38 }
39 
40 
do_square(FILE * in,unsigned char * image,int ox,int oy,int w,int size)41 void do_square(FILE *in,unsigned char *image,int ox,int oy,int w,int size)
42 {
43 int x,y,c;
44 
45 /* is it all black or white? */
46 
47 if(size==1 || bit_input(in))
48   {
49   /* yes, next bit says which. */
50   c=bit_input(in);
51   for(y=0;y<size;y++)
52     for(x=0;x<size;x++)
53       image[(oy+y)*w+ox+x]=c;
54   }
55 else
56   {
57   /* not all one colour, so recurse. */
58   size>>=1;
59   do_square(in,image,ox,oy,w,size);
60   do_square(in,image,ox+size,oy,w,size);
61   do_square(in,image,ox,oy+size,w,size);
62   do_square(in,image,ox+size,oy+size,w,size);
63   }
64 }
65 
66 
67 
read_mrf_file(char * filename,hffunc howfarfunc,unsigned char ** bmap,unsigned char ** pal,int * output_type,PICINFO * pp)68 int read_mrf_file(char *filename,hffunc howfarfunc,unsigned char **bmap,
69                   unsigned char **pal,int *output_type,PICINFO *pp)
70 {
71 FILE *in;
72 int w,h,w64,h64,x,y;
73 unsigned char buf[13],*image;
74 int totalsq;
75 
76 *bmap=NULL;
77 *pal=NULL;
78 
79 if((in=fopen(filename,"rb"))==NULL)
80   return(_PICERR_NOFILE);
81 
82 fread(buf,1,13,in);
83 
84 if(strncmp(buf,"MRF1",4)!=0)
85   CLOSE_AND_RET(_PICERR_CORRUPT);
86 
87 if(buf[12]!=0)
88   CLOSE_AND_RET(_PICERR_UNSUPPORTED);
89 
90 w=((buf[4]<<24)|(buf[5]<<16)|(buf[6]<<8)|buf[7]);
91 h=((buf[8]<<24)|(buf[9]<<16)|(buf[10]<<8)|buf[11]);
92 
93 if(w==0 || h==0)
94   CLOSE_AND_RET(_PICERR_CORRUPT);
95 
96 if((*pal=calloc(768,1))==NULL)
97   CLOSE_AND_RET(_PICERR_NOMEM);
98 
99 (*pal)[0]=(*pal)[256]=(*pal)[512]=0;
100 (*pal)[1]=(*pal)[257]=(*pal)[513]=255;
101 
102 /* w64 is units-of-64-bits width, h64 same for height */
103 w64=(w+63)/64;
104 h64=(h+63)/64;
105 
106 if(WH_BAD(w64*64,h64*64) || WH_BAD(w,h) ||
107    (*bmap=malloc(w*h))==NULL ||
108    (image=calloc(w64*h64*64*64,1))==NULL)
109   CLOSE_AND_RET(_PICERR_NOMEM);
110 
111 /* save stuff in case of abort */
112 work_in=in; work_bmap=(*bmap); work_pal=*pal;
113 
114 /* now recursively input squares. */
115 
116 /* init bit input */
117 bit_init();
118 
119 totalsq=w64*h64;
120 
121 for(y=0;y<h64;y++)
122   for(x=0;x<w64;x++)
123     {
124     /* difficult to do meaningful howfar for this, but we give it a go... */
125     /* the icky *10 stuff is to defeat %10 in zgv.c's showhowfar */
126     if(howfarfunc!=NULL) howfarfunc((y*w64+x)*10,totalsq*10);
127     do_square(in,image,x*64,y*64,w64*64,64);
128     }
129 
130 fclose(in);
131 
132 /* write real image */
133 for(y=0;y<h;y++)
134   memcpy(*bmap+y*w,image+y*w64*64,w);
135 
136 free(image);
137 
138 pp->width=w;
139 pp->height=h;
140 pp->numcols=2;
141 
142 *output_type=1;
143 
144 return(_PIC_OK);
145 }
146 
147 
aborted_file_mrf_cleanup()148 void aborted_file_mrf_cleanup()
149 {
150 free(work_bmap);
151 free(work_pal);
152 fclose(work_in);
153 }
154