ftp.nice.ch/pub/next/graphics/viewer/pCD.0.34.N.bs.tar.gz#/pCD0.3.4/Photo_CD.subproj/pcd.c

This is pcd.c in view mode; [Download] [Up]

/* hpcdtoppm (Hadmut's pcdtoppm) v0.2
*  Copyright (c) 1992 by Hadmut Danisch (danisch@ira.uka.de).
*  Permission to use and distribute this software and its
*  documentation for noncommercial use and without fee is hereby granted,
*  provided that the above copyright notice appear in all copies and that
*  both that copyright notice and this permission notice appear in
*  supporting documentation. It is not allowed to sell this software in 
*  any way. This software is not public domain.
*/


/* define DEBUG for some debugging informations, just remove the x from xDEBUG */
#define xDEBUG

/* define MELDUNG if you want to see what is happening and what takes time,
   just remove the x from xMeldung */
#define xMELDUNG


/* define OWN_WRITE either here or by compiler-option if you don't want to use
   the pbmplus-routines for writing */
#define OWN_WRITE

/* If the own routines are used, this is the size of the buffer in bytes.
   You can shrink if needed. */
#define own_BUsize 50000






#include <stdlib.h>		//  on NeXT, at least
#include <string.h>		//  on NeXT, at least
#include <stdio.h>
#ifndef OWN_WRITE
#include "ppm.h"
#else

/* The header for the ppm-files */
#define PPM_Header "P6\n%d %d\n255\n"


#endif



typedef unsigned char uBYTE;
typedef unsigned long dim;

#define BaseW ((dim)768)
#define BaseH ((dim)512)

#define SECSIZE 0x800



#define SeHead   2
#define L_Head   (1+SeHead)

#define SeBase16 18
#define L_Base16 (1+SeBase16)

#define SeBase4  72
#define L_Base4  (1+SeBase4)

#define SeBase   288
#define L_Base   (1+SeBase)






enum ERRORS { E_NONE,E_READ,E_WRITE,E_INTERN,E_ARG,E_OPT,E_MEM,E_HUFF,
             E_SEQ,E_SEQ1,E_SEQ2,E_SEQ3,E_SEQ4,E_SEQ5,E_SEQ6,E_SEQ7,E_POS,E_IMP };

enum TURNS  { T_NONE,T_RIGHT,T_LEFT };

enum SIZES  { S_UNSPEC,S_Base16,S_Base4,S_Base,S_4Base,S_16Base,S_Over };

/* Default taken when no size parameter given */
#define S_DEFAULT S_Base16

struct _implane
 {dim  mwidth,mheight,
       iwidth,iheight;
  uBYTE *im;
 };
typedef struct _implane implane;



enum ERRORS readplain();
void interpolate();
// static void writepicture();
void readhqt();
void decode();

static FILE *fin=0,*fout=0;
static char *ppmname=0;
static uBYTE sbuffer[SECSIZE];




/* Using preprocessor for inline-procs */
#ifdef DEBUG
#define SEEK(x) { if (fseek(fin,((x) * SECSIZE),0)) error(E_READ);\
                  fprintf(stderr,"S-Position %x\n",ftell(fin)); }
#else
#define SEEK(x) { if (fseek(fin,((x) * SECSIZE),0)) error(E_READ);}
#endif


#define SKIP(n)  { if (fseek(fin,(n),1)) error(E_READ);}
#define SKIPr(n) { if (fseek(fin,(n),1)) return(E_READ);}

#define READBUF   fread(sbuffer,sizeof(sbuffer),1,fin)
#define READBUF_NeXT   fread(sbuffer,sizeof(sbuffer),1,NeXT_fin)

#define xTRIF(x,u,o,a,b,c) ((x)<(u)? (a) : ( (x)>(o)?(c):(b)  ))
#define xNORM(x) x=TRIF(x,0,255,0,x,255)
#define NORM(x) { if(x<0) x=0; else if (x>255) x=255;}

#ifdef MELDUNG
#define melde(x) fprintf(stderr,x)
#else
#define melde(x)
#endif




void error(e)
  enum ERRORS e;
 {
  
  switch(e)
   {case E_NONE:   return;
    case E_IMP:    fprintf(stderr,"Sorry, Not yet implemented.\n"); break;
    case E_READ:   fprintf(stderr,"Error while reading.\n"); break;
    case E_WRITE:  fprintf(stderr,"Error while writing.\n"); break;
    case E_INTERN: fprintf(stderr,"Internal error.\n"); break;
    case E_ARG:    fprintf(stderr,"Arguments !\n"); 
                   fprintf(stderr,"Usage: hpcdtoppm [options] pcd-file [ppm-file]\n");
                   fprintf(stderr,"Opts:\n");
                   fprintf(stderr,"     -i Give some (buggy) informations from fileheader\n");
                   fprintf(stderr,"     -s Apply simple sharpness-operator on the Luma-channel\n");
                   fprintf(stderr,"     -d Show differential picture only \n");
                   fprintf(stderr,"     -r Rotate clockwise for portraits\n");
                   fprintf(stderr,"     -l Rotate counter-clockwise for portraits\n");
                   fprintf(stderr,"     -0 Extract thumbnails from Overview file\n");
                   fprintf(stderr,"     -1 Extract  128x192  from Image file\n");
                   fprintf(stderr,"     -2 Extract  256x384  from Image file\n");
                   fprintf(stderr,"     -3 Extract  512x768  from Image file\n");
                   fprintf(stderr,"     -4 Extract 1024x1536 from Image file\n");
                   fprintf(stderr,"     -5 Extract 2048x3072 from Image file\n");
                   break;
    case E_OPT:    fprintf(stderr,"These Options are not allowed together.\n");break;
    case E_MEM:    fprintf(stderr,"Not enough memory !\n"); break;
    case E_HUFF:   fprintf(stderr,"Error in Huffman-Code-Table\n"); break;
    case E_SEQ:    fprintf(stderr,"Error in Huffman-Sequence\n"); break;
    case E_SEQ1:    fprintf(stderr,"Error1 in Huffman-Sequence\n"); break;
    case E_SEQ2:    fprintf(stderr,"Error2 in Huffman-Sequence\n"); break;
    case E_SEQ3:    fprintf(stderr,"Error3 in Huffman-Sequence\n"); break;
    case E_SEQ4:    fprintf(stderr,"Error4 in Huffman-Sequence\n"); break;
    case E_SEQ5:    fprintf(stderr,"Error5 in Huffman-Sequence\n"); break;
    case E_SEQ6:    fprintf(stderr,"Error6 in Huffman-Sequence\n"); break;
    case E_SEQ7:    fprintf(stderr,"Error7 in Huffman-Sequence\n"); break;
    case E_POS:    fprintf(stderr,"Error in file-position\n"); break;
    default:       fprintf(stderr,"Unknown error %d ???\n",e);break;
   }
  if(fin) fclose(fin);
  if(fout && ppmname) fclose(fout);
  exit(9);
 }

void planealloc(p,width,height)
  implane *p;
  dim width,height;
 {
  p->iwidth=p->iheight=0;
  p->mwidth=width;
  p->mheight=height;

  p->im = ( uBYTE * ) malloc  (width*height*sizeof(uBYTE));
  if(!(p->im)) error(E_MEM);
 }

enum ERRORS readplain(w,h,l,c1,c2,fin)
  FILE *fin;
  dim w,h;
  implane *l,*c1,*c2;
 {dim i;
  uBYTE *pl=0,*pc1=0,*pc2=0;
  melde("readplain\n");

  if(l)
   { if ((l->mwidth<w) || (l->mheight<h) || (!l->im)) error(E_INTERN);
     l->iwidth=w;
     l->iheight=h;
     pl=l->im;
   }

  if(c1)
   { if ((c1->mwidth<w/2) || (c1->mheight<h/2) || (!c1->im)) error(E_INTERN);
     c1->iwidth=w/2;
     c1->iheight=h/2;
     pc1=c1->im;
   }

  if(c2)
   { if ((c2->mwidth<w/2) || (c2->mheight<h/2) || (!c2->im)) error(E_INTERN);
     c2->iwidth=w/2;
     c2->iheight=h/2;
     pc2=c2->im;
   }

  for(i=0;i<h/2;i++)
   {
    if(pl)
     { 
       if(fread(pl,w,1,fin)<1) return(E_READ);
       pl+= l->mwidth;

       if(fread(pl,w,1,fin)<1) return(E_READ);
       pl+= l->mwidth;
     }
    else SKIPr(2*w);
     
    if(pc1)
     { if(fread(pc1,w/2,1,fin)<1) return(E_READ);
       pc1+= c1->mwidth;
     }
    else SKIPr(w/2);
     
    if(pc2)
     { if(fread(pc2,w/2,1,fin)<1) return(E_READ);
       pc2+= c2->mwidth;
     }
    else SKIPr(w/2);


   }
#ifdef DEBUG_EXTRA
fprintf(stderr,"R-Position %x\n",ftell(fin));
#endif
  return E_NONE;
 }


void interpolate(p)
  implane *p;
 {dim w,h,x,y,yi;
  uBYTE *optr,*nptr,*uptr;

  melde("interpolate\n");
  if ((!p) || (!p->im)) error(E_INTERN);

  w=p->iwidth;
  h=p->iheight;

  if(p->mwidth  < 2*w ) error(E_INTERN);
  if(p->mheight < 2*h ) error(E_INTERN);


  p->iwidth=2*w;
  p->iheight=2*h;


  for(y=0;y<h;y++)
   {yi=h-1-y;
    optr=p->im+  yi*p->mwidth + (w-1);
    nptr=p->im+2*yi*p->mwidth + (2*w - 2);

    nptr[0]=nptr[1]=optr[0];

    for(x=1;x<w;x++)
     { optr--; nptr-=2;
       nptr[0]=optr[0];
       nptr[1]=(((int)optr[0])+((int)optr[1])+1)>>1;
     }
    }

  for(y=0;y<h-1;y++)
   {optr=p->im + 2*y*p->mwidth;
    nptr=optr+p->mwidth;
    uptr=nptr+p->mwidth;

    for(x=0;x<w-1;x++)
     {
      nptr[0]=(((int)optr[0])+((int)uptr[0])+1)>>1;
      nptr[1]=(((int)optr[0])+((int)optr[2])+((int)uptr[0])+((int)uptr[2])+2)>>2;
      nptr+=2; optr+=2; uptr+=2;
     }
    *(nptr++)=(((int)*(optr++))+((int)*(uptr++))+1)>>1;
    *(nptr++)=(((int)*(optr++))+((int)*(uptr++))+1)>>1;
   }

  bcopy(p->im + (2*h-2)*p->mwidth,
        p->im + (2*h-1)*p->mwidth,
        2*w);

 }


struct ph1 
 {char id1[8];
  char ww1[14];
  char id2[20];
  char id3[4*16+4];
  short ww2;
  char id4[20];
  char ww3[2*16+1];
  char id5[4*16];
  char idx[11*16];
 } ;



struct pcdword
 { uBYTE high,low;
 };

struct pcdquad { uBYTE len,highseq,lowseq,key;};
struct pcdhqt  { uBYTE entries; struct pcdquad entry[256];};
struct myhqt { unsigned long seq,mask,len; uBYTE key; };


#define E ((unsigned long) 1)


static void readhqtsub(source,ziel,anzahl)
  struct pcdhqt *source;
  struct myhqt *ziel;
  int *anzahl;
 {int i;
  struct pcdquad *sub;
  struct myhqt *help;
  *anzahl=(source->entries)+1;

  for(i=0;i<*anzahl;i++)
   {sub = (struct pcdquad *)(((uBYTE *)source)+1+i*sizeof(*sub));
    help=ziel+i;

    help->seq = (((unsigned long) sub->highseq) << 24) |(((unsigned long) sub->lowseq) << 16);
    help->len = ((unsigned long) sub->len) +1;
    help->key = sub->key;

#ifdef DEBUGhuff
   fprintf(stderr," Anz: %d A1: %08x  A2: %08x X:%02x %02x %02x %02x Seq:  %08x   Laenge:  %d %d\n",
          *anzahl,sbuffer,sub,((uBYTE *)sub)[0],((uBYTE *)sub)[1],((uBYTE *)sub)[2],((uBYTE *)sub)[3],
          help->seq,help->len,sizeof(uBYTE));
#endif

    if(help->len > 16) error(E_HUFF);

    help->mask = ~ ( (E << (32-help->len)) -1); 

  }
#ifdef DEBUG_EXTRA
  for(i=0;i<*anzahl;i++)
   {help=ziel+i;
    fprintf(stderr,"H: %3d  %08lx & %08lx (%2d) = %02x = %5d  %8x\n",
        i, help->seq,help->mask,help->len,help->key,(signed char)help->key,
        help->seq & (~help->mask));
   }
#endif

}

static struct myhqt myhuffl[256],myhuff1[256],myhuff2[256];
static int          myhufflenl=0,myhufflen1=0,myhufflen2=0;

void readhqt(w,h,n, NeXT_fin)
  dim w,h;
  int n;
  FILE *NeXT_fin;
 {
  uBYTE *ptr;

  melde("readhqt\n");
  if(READBUF_NeXT < 1) error(E_READ);
  ptr = sbuffer;

  readhqtsub((struct pcdhqt *)ptr,myhuffl,&myhufflenl);

  if(n<2) return;
  ptr+= 1 + 4* myhufflenl;
  readhqtsub((struct pcdhqt *)ptr,myhuff1,&myhufflen1);

  if(n<3) return;
  ptr+= 1 + 4* myhufflen1;
  readhqtsub((struct pcdhqt *)ptr,myhuff2,&myhufflen2);

}





void decode(w,h,f,f1,f2, autosync, NeXT_fin)
  dim w,h;
  implane *f,*f1,*f2;
  int autosync;
  FILE *NeXT_fin;
 {int i,htlen,sum;
  unsigned long sreg,maxwidth;
  unsigned int inh,n,zeile,segment,ident;
  struct myhqt *htptr,*hp;

  uBYTE *nptr;
  uBYTE *lptr;

  melde("decode\n");
#define nextbuf  {  nptr=sbuffer;  if(READBUF_NeXT < 1) error(E_READ); }
#define checkbuf { if (nptr >= sbuffer + sizeof(sbuffer)) nextbuf; }
#define shiftout(n){ sreg<<=n; inh-=n; \
                     while (inh<=24) \
                      {checkbuf; \
                       sreg |= ((unsigned long)(*(nptr++)))<<(24-inh);\
                       inh+=8;\
                      }\
                    }  


  if((!f) || (!f->im)) error(E_INTERN);
  if((f->iheight < h) || (f->iwidth<w)) error(E_INTERN);

  htlen=sreg=maxwidth=0;
  htptr=0;
  nextbuf;
  inh=32;
  lptr=0;
  shiftout(16);
  shiftout(16);

  n=0;
  for(;;)
   {
    if((sreg & 0xffffff00) == 0xfffffe00)
     {shiftout(24);
      ident=sreg>>16;
      shiftout(16);

      zeile=(ident>>1) & 0x1fff;
      segment=ident>>14;

#ifdef DEBUG_EXTRA
      fprintf(stderr,"Ident %4x Zeile:  %6d  Segment %3d Pixels bisher: %d\n",
          ident,zeile,segment,n);
#endif
      if(lptr && (n!=maxwidth)) error(E_SEQ1);
      n=0;


      if(zeile==h) return;
      if(zeile > h) error(E_SEQ2);

      switch(segment)
       {
        case 0: if(!f) error(E_SEQ7);
                lptr=f->im + zeile*f->mwidth;
                maxwidth=f->iwidth;
                htlen=myhufflenl;
                htptr=myhuffl;
                break;

        case 2: if(!f1) error(E_SEQ7);
                lptr=f1->im + (zeile>>1)*f1->mwidth;
                maxwidth=f1->iwidth;
                htlen=myhufflen1;
                htptr=myhuff1;
                break;
 
        case 3: if(!f2) error(E_SEQ7);
                lptr=f2->im + (zeile>>1)*f2->mwidth;
                maxwidth=f2->iwidth;
                htlen=myhufflen2;
                htptr=myhuff2;
                break;

        default:error(E_SEQ3);
	}
     }
    else
     {
/*      if((!lptr) || (n>maxwidth)) error(E_SEQ4);*/
      if(!lptr)      error(E_SEQ6);
      if(n>maxwidth) error(E_SEQ4);
      for(i=0,hp=htptr;(i<htlen) && ((sreg & hp->mask)!= hp->seq); i++,hp++);
      if(i>=htlen) error(E_SEQ5);

      sum=((int)(*lptr)) + ((char)hp->key);
      NORM(sum);
      *(lptr++) = sum;

      n++; 
      shiftout(hp->len);

     }

   }



 }

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.