home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / zip / program / gempp15b.zoo / src / img.cc < prev    next >
C/C++ Source or Header  |  1993-04-25  |  5KB  |  248 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. //  This file is Copyright 1992,1993 by Warwick W. Allison.
  4. //  This file is part of the gem++ library.
  5. //  You are free to copy and modify these sources, provided you acknowledge
  6. //  the origin by retaining this notice, and adhere to the conditions
  7. //  described in the file COPYING.LIB.
  8. //
  9. /////////////////////////////////////////////////////////////////////////////
  10.  
  11. #include "img.h"
  12.  
  13. #include <stdio.h>
  14. #include <builtin.h>
  15.  
  16. #define SEEK_CUR 1
  17.  
  18. inline int Bpad(int x) { return (x+7)>>3; }
  19.  
  20.  
  21. static void readIMG(unsigned char*,int patlen,int bW,int H,FILE*);
  22.  
  23. struct IMGfileheader
  24. {
  25.     short version;
  26.     short length;
  27.     short planes;
  28.     short patternlen;
  29.     short uW,uH;
  30.     short W,H;
  31. };
  32.  
  33. IMG::IMG(int w,int h,int d) :
  34.     W(w), H(h), D(d),
  35.     bW(Bpad(w)), uW(85), uH(85),
  36.     data(new unsigned char[H*bW]),
  37.     Cursor(0),
  38.     bit(TOPBIT),
  39.     External(FALSE)
  40. { }
  41.  
  42. IMG::IMG(unsigned char* At,int w,int h,int d) :
  43.     W(w), H(h), D(d),
  44.     bW(Bpad(w)), uW(85), uH(85),
  45.     data(At),
  46.     Cursor(0),
  47.     bit(TOPBIT),
  48.     External(TRUE)
  49. { }
  50.  
  51. IMG::IMG(const char *fn) :
  52.     Cursor(0),
  53.     data(0),
  54.     bit(TOPBIT),
  55.     External(FALSE)
  56. {
  57.     FILE *f=fopen(fn,"rb");
  58.  
  59.     if (!f) return;
  60.  
  61.     IMGfileheader header;
  62.     fread(&header,sizeof(header),1,f);
  63.  
  64.     if (header.length*sizeof(short)!=sizeof(header))
  65.         fseek(f,header.length*sizeof(short)-sizeof(header),SEEK_CUR);
  66.  
  67.     W=header.W;
  68.     H=header.H;
  69.     D=header.planes;
  70.     bW=Bpad(W);
  71.     uW=header.uW;
  72.     uH=header.uH;
  73.     data=new unsigned char[H*bW];
  74.  
  75.     readIMG(data,header.patternlen,bW,uH,f);
  76.  
  77.     fclose(f);
  78. }
  79.  
  80. IMG::~IMG()
  81. {
  82.     if (!External) delete data;
  83. }
  84.  
  85.  
  86. static
  87. void readIMG(unsigned char* bitmap,int patlen,int bW,int H,FILE* f)
  88. {
  89.     int c;
  90.     int linerep=0;
  91.     int thisln=bW;
  92.  
  93.     while (EOF!=(c=fgetc(f))) {
  94.         switch (c) {
  95.             case 0:
  96.                 int n;
  97.                 if (EOF!=(n=fgetc(f))) {
  98.                     if (n) { // Repeating pattern
  99.                         fread(bitmap,patlen,1,f);
  100.                         bitmap+=patlen;
  101.                         thisln-=patlen;
  102.                         while (--n) {
  103.                             unsigned char *from=bitmap-patlen;
  104.                             for (int pn=patlen; pn; pn--) *bitmap++=*from++;
  105.                             thisln-=patlen;
  106.                         }
  107.                     } else { // Next scanline repeats
  108.                         n=fgetc(f); // Should be 0xff
  109.                         n=fgetc(f);
  110.                         linerep+=n-1; // REPEATs, not total number
  111.                     }
  112.                 }
  113.         break;    case 0x80: // Literal
  114.                 int nl;
  115.                 if (EOF!=(nl=fgetc(f))) {
  116.                     fread(bitmap,nl,1,f);
  117.                     bitmap+=nl;
  118.                     thisln-=nl;
  119.                 }
  120.         break;    default: // Solid run
  121.                 unsigned char pat=((c&0x80) ? 0xff : 0);
  122.                 int nsol=c&0x7f;
  123.                 thisln-=nsol;
  124.                 while (nsol--) *bitmap++=pat;
  125.         }
  126.         while (thisln<=0) {
  127.             thisln+=bW;
  128.             H--;
  129.             while (linerep) {
  130.                 unsigned char *from=bitmap-bW;
  131.                 for (int lineb=0; lineb<bW; lineb++) *bitmap++ = *from++;
  132.                 H--;
  133.                 linerep--;
  134.             }
  135.         }
  136.     }
  137. }
  138.  
  139.  
  140. int IMG::Save(const char *fn,int PatLen=2)
  141. {
  142. #define REPEATLINE(n) fputc(0,f); fputc(0,f); fputc(0xFF,f); fputc(n,f); //printf("%d repeated lines\n",n);
  143. #define BLACK(n) fputc(n|0x80,f); //printf("%d bytes all black\n",n);
  144. #define WHITE(n) fputc(n,f); //printf("%d bytes all white\n",n);
  145. #define LITERAL(n) fputc(0x80,f); fputc(n,f); for (int l=n; l; l--) fputc(From[lineb++],f); //printf("%d literal bytes\n",n);
  146. #define PATTERN(n) fputc(0,f); fputc(n,f); for (int p=0; p<PatLen; p++) fputc(From[lineb+p],f); //printf("%d byte pattern x %d\n",PatLen,n);
  147.  
  148.     FILE *f=fopen(fn,"wb");
  149.  
  150.     if (!f) return 0;
  151.  
  152.     IMGfileheader header;
  153.  
  154.     header.version=1;
  155.     header.length=8;
  156.     header.planes=1;
  157.     header.patternlen=PatLen;
  158.     header.uW=uW;
  159.     header.uH=uH;
  160.     header.W=W;
  161.     header.H=H;
  162.     fwrite(&header,sizeof(header),1,f);
  163.  
  164.     unsigned char *From=data;
  165.  
  166.     for (int h=0; h<H; h++) {
  167.         //printf("byte %d\n",From-data);
  168.  
  169.         unsigned char *Next;
  170.         int i=0;
  171.  
  172.         //Check for repeats of this line.
  173.         Next=From+bW;
  174.         int rep=0;
  175.         while (h+rep<H && From[i]==Next[i]) {
  176.             i=bW-1;
  177.             while (i && From[i]==Next[i]) i--;
  178.             if (From[i]==Next[i]) {
  179.                 rep++;
  180.                 Next=Next+bW;
  181.             }
  182.         }
  183.  
  184.         if (rep) {
  185.             h+=rep;
  186.             REPEATLINE(rep+1);
  187.         }
  188.  
  189.         int lineb=0;
  190.         while (lineb<bW) {
  191.             if (From[lineb]) {
  192.                 if (From[lineb]==0xFF) {
  193.                     for (i=0; lineb<bW && i<127 && From[lineb]==0xFF; i++) lineb++;
  194.                     BLACK(i);
  195.                 } else {
  196.                     unsigned char *NextPat=From;
  197.                     int pat=0;
  198.                     int nlineb=lineb;
  199.                     while (pat<127 && nlineb+PatLen<=bW && From[lineb]==NextPat[nlineb]) {
  200.                         //printf("Pattern? (nlineb=%d lineb=%d)\n",nlineb,lineb);
  201.                         NextPat=NextPat+PatLen;
  202.                         i=PatLen-1;
  203.                         while (i && From[i+lineb]==NextPat[i+nlineb]) i--;
  204.                         if (From[i+lineb]==NextPat[i]+nlineb) {
  205.                             pat++;
  206.                             nlineb+=PatLen;
  207.                         }
  208.                     }
  209.                     if (pat) {
  210.                         PATTERN(pat);
  211.                         lineb=nlineb;
  212.                     } else {
  213.                         for (int nlit=0;
  214.  
  215.                             nlit<=255 &&
  216.                             lineb+nlit<bW &&
  217.                             (From[lineb+nlit] || lineb+nlit+1==bW || From[lineb+nlit+1]) &&
  218.                             (From[lineb+nlit]!=0xFF || lineb+nlit+1==bW || From[lineb+nlit+1]!=0xFF);
  219.  
  220.                             nlit++);
  221.                         LITERAL(nlit);
  222.                     }
  223.                 }
  224.             } else {
  225.                 for (i=0; lineb<bW && i<127 && !From[lineb]; i++) lineb++;
  226.                 WHITE(i);
  227.             }
  228.         }
  229.         From=Next;
  230.     }
  231.  
  232.     return 1;
  233. }
  234.  
  235. void IMG::operator|= (const IMG& other)
  236. // Assumes same size
  237. {
  238.     int size=bW*H;
  239.     while (size--) data[size]|=other.data[size];
  240. }
  241.  
  242. void IMG::Clear(int colour=0)
  243. {
  244.     int b=colour ? 0xFF : 0;
  245.     int size=bW*H;
  246.     while (size--) data[size]=b;
  247. }
  248.