PageRenderTime 27ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/1997-11-rbz/rbz.c

http://github.com/ricbit/Oldies
C | 470 lines | 434 code | 36 blank | 0 comment | 53 complexity | 3d1f11618ddda51529ba1b77b6face6e MD5 | raw file
Possible License(s): GPL-2.0
  1. #include <stdio.h>
  2. #include <allegro.h>
  3. #include <fcntl.h>
  4. #include <math.h>
  5. #include <unistd.h>
  6. #include <conio.h>
  7. #include <go32.h>
  8. #include <sys/stat.h>
  9. #include <sys/movedata.h>
  10. #include <sys/segments.h>
  11. typedef unsigned char byte;
  12. typedef unsigned short word;
  13. typedef byte RGBA[4];
  14. typedef struct pcx {
  15. byte Manufacturer;
  16. byte Version;
  17. byte Encoding;
  18. byte BitsPerPixel;
  19. word XMin,YMin,XMax,YMax;
  20. word Hdpi;
  21. word Vdpi;
  22. byte Colormap[48];
  23. byte Reserved;
  24. byte NPlanes;
  25. word BytesPerLine;
  26. word PaletteInfo;
  27. word HScreenSize;
  28. word VScreenSize;
  29. byte Filler[54];
  30. } PCX_header;
  31. typedef struct {
  32. PCX_header header;
  33. RGBA *buffer;
  34. } PCX_image;
  35. typedef struct {
  36. int xmax,ymax;
  37. int size;
  38. byte *buffer;
  39. int app[256];
  40. double entropy;
  41. } image_t;
  42. typedef struct {
  43. byte root[3];
  44. byte *buffer[3];
  45. int xmax,ymax;
  46. int size;
  47. int app[256][3];
  48. int bits[3];
  49. int mask[3];
  50. double entropy[3];
  51. } split_image_t;
  52. int fullinfo=0;
  53. byte uniformRGB (byte r, byte g, byte b) {
  54. return ((b&0xc0)>>6)+((g&0xe0)>>3)+(r&0xe0);
  55. }
  56. PCX_image *read_pcx (char *name) {
  57. int file;
  58. PCX_image *image;
  59. int rx,ry;
  60. struct stat sbuf;
  61. int tempsize;
  62. byte *tempbuffer;
  63. byte **colorbuffer;
  64. int i,j,k,l;
  65. byte *pbuffer,*pfile;
  66. byte *pbufr,*pbufg,*pbufb;
  67. RGBA *pimage;
  68. byte value,value2;
  69. int normal=0,compressed=0;
  70. image=(PCX_image *) malloc (sizeof (PCX_image));
  71. stat (name,&sbuf);
  72. file=open (name,O_BINARY|O_RDONLY);
  73. read (file,&(image->header),sizeof (PCX_header));
  74. rx=image->header.XMax+1;
  75. ry=image->header.YMax+1;
  76. image->buffer=(RGBA *) malloc (rx*ry*sizeof (RGBA));
  77. tempsize=sbuf.st_size-sizeof (PCX_header);
  78. tempbuffer=(byte *) malloc (tempsize);
  79. read (file,tempbuffer,tempsize);
  80. close (file);
  81. colorbuffer=(byte **) malloc (image->header.NPlanes);
  82. for (i=0; i<image->header.NPlanes; i++)
  83. colorbuffer[i]=(byte *) malloc (image->header.BytesPerLine);
  84. pfile=tempbuffer;
  85. pimage=image->buffer;
  86. for (j=0; j<=image->header.YMax; j++) {
  87. for (k=0; k<image->header.NPlanes; k++) {
  88. pbuffer=colorbuffer[k];
  89. for (i=0; i<image->header.BytesPerLine;) {
  90. value=*pfile++;
  91. if (value>0xc0) {
  92. value2=*pfile++;
  93. compressed++;
  94. for (l=0; l<value-0xc0; l++) {
  95. *pbuffer++=value2;
  96. i++;
  97. }
  98. }
  99. else {
  100. *pbuffer++=value;
  101. i++;
  102. normal++;
  103. }
  104. }
  105. }
  106. pbufr=colorbuffer[0];
  107. pbufg=colorbuffer[1];
  108. pbufb=colorbuffer[2];
  109. for (i=0; i<=image->header.XMax; i++) {
  110. (*pimage)[0]=*pbufr++;
  111. (*pimage)[1]=*pbufg++;
  112. (*pimage++)[2]=*pbufb++;
  113. }
  114. }
  115. return image;
  116. }
  117. image_t *quantize_pcx (PCX_image *pcx) {
  118. image_t *image;
  119. int i;
  120. byte *p;
  121. RGBA *prgb;
  122. image=(image_t *) malloc (sizeof (image_t));
  123. image->xmax=pcx->header.XMax+1;
  124. image->ymax=pcx->header.YMax+1;
  125. image->size=image->xmax*image->ymax;
  126. image->buffer=(byte *) malloc (image->size);
  127. p=image->buffer;
  128. prgb=pcx->buffer;
  129. for (i=0; i<image->size; i++) {
  130. *p++=uniformRGB ((*prgb)[0],(*prgb)[1],(*prgb)[2]);
  131. prgb++;
  132. }
  133. return image;
  134. }
  135. void display (image_t *image) {
  136. RGB rgb[256];
  137. int i;
  138. for (i=0; i<256; i++) {
  139. rgb[i].r=(i&0xe0)>>2;
  140. rgb[i].g=(i&0x1c)<<1;
  141. rgb[i].b=(i&0x03)<<4;
  142. }
  143. set_gfx_mode (GFX_VGA,320,200,320,200);
  144. set_palette (rgb);
  145. for (i=0; i<image->ymax; i++) {
  146. movedata (_my_ds(),(int)(image->buffer+i*image->xmax),
  147. _dos_ds,0xa0000+i*320,image->xmax);
  148. }
  149. getch ();
  150. set_gfx_mode (GFX_TEXT,80,25,80,25);
  151. }
  152. void stats (image_t *image) {
  153. int i;
  154. byte *p;
  155. double prob,accprob;
  156. printf ("uncompressed size=%d\n",image->size);
  157. p=image->buffer;
  158. for (i=0; i<256; i++)
  159. image->app[i]=0;
  160. for (i=0; i<image->size; i++)
  161. image->app[*p++]++;
  162. image->entropy=0.0;
  163. accprob=0.0;
  164. for (i=0; i<256; i++) {
  165. prob=(double)image->app[i]/(double)image->size;
  166. accprob+=prob;
  167. if (prob>0.0)
  168. image->entropy+=prob*log(prob);
  169. }
  170. image->entropy/=-log(2.0)*8.0;
  171. printf ("entropy = %f\n",image->entropy);
  172. printf ("accumulated probability=%f\n",accprob);
  173. printf ("minimum size after ideal compression = %d\n",
  174. (int)(image->entropy*image->size));
  175. }
  176. split_image_t *split_image (image_t *image) {
  177. split_image_t *split;
  178. int i;
  179. split=(split_image_t *) malloc (sizeof (split_image_t));
  180. split->xmax=image->xmax;
  181. split->ymax=image->ymax;
  182. split->size=image->size;
  183. split->bits[0]=split->bits[1]=3;
  184. split->bits[2]=2;
  185. split->mask[0]=split->mask[1]=7;
  186. split->mask[2]=3;
  187. for (i=0; i<3; i++)
  188. split->buffer[i]=(byte *) malloc (image->size);
  189. for (i=0; i<image->size; i++) {
  190. split->buffer[0][i]=(image->buffer[i]&0x1c)>>2;
  191. split->buffer[1][i]=(image->buffer[i]&0xe0)>>5;
  192. split->buffer[2][i]=(image->buffer[i]&0x03);
  193. }
  194. return split;
  195. }
  196. void linear_dpcm (split_image_t *split) {
  197. int i,j;
  198. byte value,last;
  199. for (j=0; j<3; j++) {
  200. split->root[j]=split->buffer[j][0];
  201. value=split->root[j];
  202. for (i=0; i<split->size; i++) {
  203. last=value;
  204. value=split->buffer[j][i];
  205. split->buffer[j][i]=(split->buffer[j][i]-last)&split->mask[j];
  206. }
  207. }
  208. }
  209. void blocked_dpcm (split_image_t *split, int bsize) {
  210. int channel;
  211. int i,j,bi,bj;
  212. byte value,last;
  213. int offset;
  214. for (channel=0; channel<3; channel++) {
  215. split->root[channel]=split->buffer[channel][0];
  216. value=split->root[channel];
  217. for (j=0; j<split->ymax/bsize; j++) {
  218. for (i=0; i<split->xmax/bsize; i++) {
  219. for (bj=0; bj<bsize; bj++) {
  220. for (bi=0; bi<bsize; bi++) {
  221. last=value;
  222. offset=bi+i*bsize+j*split->xmax*bsize+bj*split->xmax;
  223. value=split->buffer[channel][offset];
  224. split->buffer[channel][offset]=
  225. (split->buffer[channel][offset]-last)&split->mask[channel];
  226. }
  227. }
  228. }
  229. }
  230. }
  231. }
  232. void stats_split (split_image_t *image, int wsize) {
  233. int i,j,k;
  234. byte *p;
  235. double prob,accprob;
  236. int *hits;
  237. int tsize;
  238. int shift;
  239. int offset;
  240. int total=0;
  241. printf ("uncompressed size=%d\n",image->size);
  242. tsize=1;
  243. for (i=0; i<wsize; i++)
  244. tsize*=8;
  245. hits=(int *) malloc (sizeof (int)*tsize);
  246. for (j=0; j<3; j++) {
  247. p=image->buffer[j];
  248. printf ("channel %d ",j);
  249. for (i=0; i<tsize; i++)
  250. hits[i]=0;
  251. for (i=0; i<image->size; i+=wsize) {
  252. shift=1;
  253. offset=0;
  254. for (k=0; k<wsize; k++) {
  255. offset+=*p++*shift;
  256. shift*=8;
  257. }
  258. hits[offset]++;
  259. }
  260. image->entropy[j]=0.0;
  261. accprob=0.0;
  262. for (i=0; i<tsize; i++) {
  263. prob=(double)hits[i]/(double)image->size*wsize;
  264. if (fullinfo) printf ("%d %d %f\n",j,i,prob);
  265. accprob+=prob;
  266. if (prob>0.0)
  267. image->entropy[j]+=prob*log(prob);
  268. }
  269. image->entropy[j]/=-log(2.0)*(double)image->bits[j]*wsize;
  270. printf ("entropy = %f\n",image->entropy[j]);
  271. if (fullinfo) {
  272. printf ("accumulated probability=%f\n",accprob);
  273. printf ("minimum size after ideal compression = %d\n",
  274. (int)(image->entropy[j]*image->size*image->bits[j]/8.0));
  275. }
  276. total+=(int)(image->entropy[j]*image->size*image->bits[j]/8.0);
  277. }
  278. printf ("total compressed size = %d\n",total);
  279. free (hits);
  280. }
  281. void oddeven_dpcm (split_image_t *split) {
  282. int i,j;
  283. byte value,last;
  284. for (j=0; j<3; j++) {
  285. split->root[j]=split->buffer[j][0];
  286. value=split->root[j];
  287. for (i=0; i<split->size; i+=2) {
  288. last=value;
  289. value=split->buffer[j][i];
  290. split->buffer[j][i]=(split->buffer[j][i]-last)&split->mask[j];
  291. }
  292. value=split->root[j];
  293. for (i=1; i<split->size; i+=2) {
  294. last=value;
  295. value=split->buffer[j][i];
  296. split->buffer[j][i]=(split->buffer[j][i]-last)&split->mask[j];
  297. }
  298. }
  299. }
  300. void linear_xpcm (split_image_t *split) {
  301. int i,j;
  302. byte value,last;
  303. for (j=0; j<3; j++) {
  304. split->root[j]=split->buffer[j][0];
  305. value=split->root[j];
  306. for (i=0; i<split->size; i++) {
  307. last=value;
  308. value=split->buffer[j][i];
  309. split->buffer[j][i]=(split->buffer[j][i]^last)&split->mask[j];
  310. }
  311. }
  312. }
  313. void oddeven_xpcm (split_image_t *split) {
  314. int i,j;
  315. byte value,last;
  316. for (j=0; j<3; j++) {
  317. split->root[j]=split->buffer[j][0];
  318. value=split->root[j];
  319. for (i=0; i<split->size; i+=2) {
  320. last=value;
  321. value=split->buffer[j][i];
  322. split->buffer[j][i]=(split->buffer[j][i]^last)&split->mask[j];
  323. }
  324. value=split->root[j];
  325. for (i=1; i<split->size; i+=2) {
  326. last=value;
  327. value=split->buffer[j][i];
  328. split->buffer[j][i]=(split->buffer[j][i]^last)&split->mask[j];
  329. }
  330. }
  331. }
  332. void linear2_dpcm (split_image_t *split) {
  333. int i,j;
  334. byte value,last;
  335. for (j=0; j<3; j++) {
  336. split->root[j]=split->buffer[j][0];
  337. value=split->root[j];
  338. for (i=0; i<split->size; i++) {
  339. last=value;
  340. value=split->buffer[j][i];
  341. split->buffer[j][i]=(split->buffer[j][i]-last)&split->mask[j];
  342. }
  343. }
  344. for (j=0; j<3; j++) {
  345. split->root[j]=split->buffer[j][0];
  346. value=split->root[j];
  347. for (i=0; i<split->size; i++) {
  348. last=value;
  349. value=split->buffer[j][i];
  350. split->buffer[j][i]=(split->buffer[j][i]-last)&split->mask[j];
  351. }
  352. }
  353. }
  354. void single_xpcm (image_t *split) {
  355. int i,j;
  356. byte value,last;
  357. for (j=0; j<3; j++) {
  358. value=split->buffer[0];
  359. for (i=0; i<split->size; i++) {
  360. last=value;
  361. value=split->buffer[i];
  362. split->buffer[i]=(split->buffer[i]^last);
  363. }
  364. }
  365. }
  366. void main (int argc, char **argv) {
  367. PCX_image *image;
  368. image_t *quantized,*singlex;
  369. split_image_t *split,*blocked,*oddeven,*linearx,*oddevenx,*linear2;
  370. int disp=0;
  371. if (argc<2) {
  372. printf ("missing argument\n");
  373. exit (1);
  374. }
  375. if (argc>2 && !strcmp (argv[2],"full"))
  376. fullinfo=1;
  377. if (argc>2 && !strcmp (argv[2],"display"))
  378. disp=1;
  379. allegro_init ();
  380. image=read_pcx (argv[1]);
  381. printf ("-- Quantized image\n");
  382. quantized=quantize_pcx (image);
  383. if (disp) display (quantized);
  384. stats (quantized);
  385. printf ("-- Split image\n");
  386. split=split_image (quantized);
  387. stats_split (split,1);
  388. printf ("-- blocked DPCM image (block size=4)\n");
  389. blocked=split_image (quantized);
  390. blocked_dpcm (blocked,4);
  391. stats_split (blocked,1);
  392. printf ("-- blocked DPCM image (block size=8)\n");
  393. blocked=split_image (quantized);
  394. blocked_dpcm (blocked,8);
  395. stats_split (blocked,1);
  396. printf ("-- blocked DPCM image (block size=16)\n");
  397. blocked=split_image (quantized);
  398. blocked_dpcm (blocked,16);
  399. stats_split (blocked,1);
  400. printf ("-- linear DPCM image (word size=1) \n");
  401. linear_dpcm (split);
  402. stats_split (split,1);
  403. printf ("-- linear DPCM image (word size=2) \n");
  404. stats_split (split,2);
  405. printf ("-- linear DPCM image (word size=3) \n");
  406. stats_split (split,3);
  407. printf ("-- linear DPCM image (word size=4) \n");
  408. stats_split (split,4);
  409. printf ("-- odd/even DPCM image (word size=1) \n");
  410. oddeven=split_image (quantized);
  411. oddeven_dpcm (oddeven);
  412. stats_split (oddeven,1);
  413. printf ("-- linear XPCM image (word size=1) \n");
  414. linearx=split_image (quantized);
  415. linear_xpcm (linearx);
  416. stats_split (linearx,1);
  417. printf ("-- odd/even XPCM image (word size=1) \n");
  418. oddevenx=split_image (quantized);
  419. oddeven_xpcm (oddevenx);
  420. stats_split (oddevenx,1);
  421. printf ("-- odd/even XPCM image (word size=2) \n");
  422. stats_split (oddevenx,2);
  423. printf ("-- second order DPCM image (word size=1) \n");
  424. linear2=split_image (quantized);
  425. linear2_dpcm (linear2);
  426. stats_split (linear2,1);
  427. printf ("-- second order DPCM image (word size=2) \n");
  428. stats_split (linear2,2);
  429. printf ("-- single XPCM image (word size=1) \n");
  430. singlex=quantize_pcx (image);
  431. single_xpcm (singlex);
  432. stats (singlex);
  433. allegro_exit ();
  434. }