Logo Search packages:      
Sourcecode: c2esp version File versions  Download package

myopldecode.c

/*b
 * Copyright (C) 2003-2006  Rick Richardson
 * Modified by Paul Newall 2010
 * To decode the file for Kodak ESP nnnn AOI printers
 * -
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * Authors: Rick Richardson <rick.richardson@comcast.net>
 * and Paul Newall
b*/

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

#include "jbig.h"

/*
 * Global option flags
 */
int   Debug = 0;
char  *DecFile;
int   PrintOffset = 0;
int   PrintHexOffset = 0;

      int   Stripe; //counts the stripes

void
debug(int level, char *fmt, ...)
{
    va_list ap;

    if (Debug < level)
      return;

    va_start(ap, fmt);
    vfprintf(stderr, fmt, ap);
    va_end(ap);
}

int
error(int fatal, char *fmt, ...)
{
      va_list ap;

      fprintf(stderr, fatal ? "Error: " : "Warning: ");
      if (errno)
          fprintf(stderr, "%s: ", strerror(errno));
      va_start(ap, fmt);
      vfprintf(stderr, fmt, ap);
      va_end(ap);
      if (fatal > 0)
          exit(fatal);
      else
      {
          errno = 0;
          return (fatal);
      }
}

void
usage(void)
{
    fprintf(stderr,
"Usage:\n"
"     myopldecode [options] < opl-file\n"
"\n"
"     Decode a Kodak Raster Object (opl) stream into human readable form.\n"
"\n"
"     A Kodak Raster Object stream is the printer langauge used by some Kodak\n"
"     printers, such as the ESP 5250.\n"
"\n"
"\n"
"Options:\n"
"       -d basename Basename of .pbm file for saving decompressed planes\n"
"       -o          Print file offsets\n"
"       -h          Print hex file offsets\n"
"       -D lvl      Set Debug level [%d]\n"
    , Debug
    );

    exit(1);
}

void
print_bih(unsigned char bih[20])
{
    unsigned int i, xd, yd, l0;
    char hdr[] = "\n\t\t\t\t";

    if (!PrintOffset && !PrintHexOffset) hdr[strlen(hdr)-1] = 0;

    xd = (bih[4] << 24) | (bih[5] << 16) | (bih[6] << 8) | (bih[7] << 0);
    yd = (bih[8] << 24) | (bih[9] << 16) | (bih[10] << 8) | (bih[11] << 0);
    l0 = (bih[12] << 24) | (bih[13] << 16) | (bih[14] << 8) | (bih[15] << 0);
    for(i=0;i<20;++i)
    {
      printf("%3x",bih[i]);
    }

    printf("%sDL = %d, D = %d, P = %d, - = %d, XY = %d x %d",
       hdr, bih[0], bih[1], bih[2], bih[3], xd, yd);

    printf("%sL0 = %d, MX = %d, MY = %d",
       hdr, l0, bih[16], bih[17]);

    printf("%sOrder   = %d %s%s%s%s%s", hdr, bih[18],
      bih[18] & JBG_HITOLO ? " HITOLO" : "",
      bih[18] & JBG_SEQ ? " SEQ" : "",
      bih[18] & JBG_ILEAVE ? " ILEAVE" : "",
      bih[18] & JBG_SMID ? " SMID" : "",
      bih[18] & 0xf0 ? " other" : "");

    printf("%sOptions = %d %s%s%s%s%s%s%s%s", hdr, bih[19],
      bih[19] & JBG_LRLTWO ? " LRLTWO" : "",
      bih[19] & JBG_VLENGTH ? " VLENGTH" : "",
      bih[19] & JBG_TPDON ? " TPDON" : "",
      bih[19] & JBG_TPBON ? " TPBON" : "",
      bih[19] & JBG_DPON ? " DPON" : "",
      bih[19] & JBG_DPPRIV ? " DPPRIV" : "",
      bih[19] & JBG_DPLAST ? " DPLAST" : "",
      bih[19] & 0x80 ? " other" : "");
    printf("%s%u stripes, %d layers, %d planes",
      hdr,
      ((yd >> bih[1]) +  ((((1UL << bih[1]) - 1) & xd) != 0) + l0 - 1) / l0,
      bih[1] - bih[0], bih[2]);
}

void
print_config(unsigned char *c)
{
    char hdr[] = "\n\t\t\t\t";

    if (!PrintOffset && !PrintHexOffset) hdr[strlen(hdr)-1] = 0;

    if (c[1] == 1)
    {
      printf("%sfmt=%d np=%d",
          hdr, c[0], c[1]);
      printf("%sBLACK:  X=%d, Y=%d, unk=%d, #=%d(%d)",
          hdr, (c[2]<<8) + c[3], (c[4]<<8) + c[5], c[6], 1 << c[7], c[7]);
    }
    else if (c[1] == 4)
    {
      printf("%sfmt=%d np=%d",
          hdr, c[0], c[1]);
      printf("%sYEL:    X=%d, Y=%d, unk=%d, #=%d(%d)",
          hdr, (c[2]<<8) + c[3], (c[4]<<8) + c[5], c[6], 1 << c[7], c[7]);
      printf("%sMAG:    X=%d, Y=%d, unk=%d, #=%d(%d)",
          hdr, (c[8]<<8) + c[9], (c[10]<<8) + c[11], c[12], 1 << c[13], c[13]);
      printf("%sCYA:    X=%d, Y=%d, unk=%d, #=%d(%d)",
          hdr, (c[14]<<8) + c[15], (c[16]<<8) + c[17], c[18], 1 << c[19], c[19]);
      printf("%sBLK:    X=%d, Y=%d, unk=%d, #=%d(%d)",
          hdr, (c[20]<<8) + c[21], (c[22]<<8) + c[23], c[24], 1 << c[25], c[25]);
    }
    else
      error(1, "config image data is not 8 or 26 bytes!\n");
}

void
proff(int curOff)
{
    if (PrintOffset)
      printf("%d: ", curOff);
    else if (PrintHexOffset)
      printf("%6x:      ", curOff);
}

char *
fgetcomma(char *s, int size, int *datalen, FILE *stream)
{
      //get a string terminated by ; or ? from stream
      //the string is returned in  s
      //size is not used?
      //if the string has an integer delimited by # and =, datalen returns the integer (length of the data)
      //extents might be 10 chars per line, so s should be > 12800 chars
    int     c;
    char *os = s;

    *datalen = 0;
    while ((c = fgetc(stream)) != EOF)
    {
      *s++ = c;
      if (c == ';' || c == '?')
          break;
      if (c == '#') //expect an int next, terminated by =, that gives the no of bytes in the following JBIG
      {
          while ((c = fgetc(stream)) != EOF)
          {
            *s++ = c;
            if (c == '=')
                break;
            else
            {
                *datalen *= 10;
                *datalen += c - '0';
            }
          }
          break;
      }
    }
    if (c == EOF)
      return (NULL);
    *s++ = 0;
    return (os);
}

int
jbig_write_file( int pn, int page, struct jbg_dec_state *pstate, FILE *dfp)
//attempts to write image, finished or not
{
            printf("<jbig_write_file starts>");
   // size_t      cnt;
    int           rc;
      
      int     h, w, x1, x2, y, wBytes, len;
      unsigned char *image=NULL;

      //h = jbg_dec_getheight(pstate);
      h=pstate->l0 * (Stripe); //band height may not be right with multiple stripes
      w = jbg_dec_getwidth(pstate);
      image = jbg_dec_getimage(pstate, 0); //is the first plane 1 or 0?
      //len = jbg_dec_getsize(pstate);
      wBytes=(w+7)/8;
      len = ((w+7)/8)*h; 
      if (image !=NULL)
      {
          char        buf[512];
          sprintf(buf, "%s-%02d-%d.pbm", DecFile, page, Stripe);
            printf("<\nwrite_file writing raster to %s...>\n", buf);
          dfp = fopen(buf, "w");
          if (dfp)
          {
                fprintf(dfp, "P4\n%8d %8d\n", w, h);
            rc = fwrite(image, 1, len, dfp);
            fclose(dfp);
          }
            else return (1);
      //look for zone widths
            printf("<seeking zones>\n");
            for(y=0;y<h;y+=10)
            {
                  for(x1=0;image[wBytes*y+x1]==0 && x1<wBytes;++x1);
                  for(x2=x1+wBytes/5;image[wBytes*y+x2]==0 && x2<wBytes;++x2);
                  printf("%d,",x2-x1);
            }
            printf("\n");

      }
      else   
      {
            debug(0, "Missing image %dx%d!\n", w, h);
            printf("<s.d = %d, s.ii[0] = %d>\n", pstate->d, (int) pstate->ii[0]);         

      }
      jbg_dec_free(pstate);
      return (0);
    
}

int
jbig_zone_widths( int pn, int page, struct jbg_dec_state *pstate, FILE *dfp)
//attempts to detect the colour zone widths 
{
            printf("<jbig_zone_widths starts>");
   // size_t      cnt;
    //int         rc;
      
      int     h, w, x1, x2, y,wBytes;
      unsigned char *image=NULL;

      h=pstate->l0 * (Stripe); //band height may not be right with multiple stripes
      w = jbg_dec_getwidth(pstate);
      image = jbg_dec_getimage(pstate, 0);
      wBytes=(w+7)/8;
      //len = ((w+7)/8)*h; 
      if (image !=NULL)
      {
            printf("<image found - seeking zones>\n");
            for(y=0;y<h;y+=10)
            {
                  for(x1=0;image[wBytes*y+x1]==0 && x1<wBytes;++x1);
                  for(x2=x1+wBytes/5;image[wBytes*y+x2]==0 && x2<wBytes;++x2);
                  printf("%d,",x2-x1);
            }
            printf("\n");
            
      }
      else   
      {
            debug(0, "Missing image! wxh= %dx%d!\n", w, h);
            printf("<s.d = %d, s.ii[0] = %d>\n", pstate->d, (int) pstate->ii[0]);         

      }
      jbg_dec_free(pstate);
      return (0);
}

int
jbig_decode1(unsigned char ch, int pn, int page, struct jbg_dec_state *pstate, FILE *dfp)
//called for every char in the JBIG
{
    size_t  cnt;
    int           rc;
//    printf(".");
      rc = jbg_dec_in(pstate, &ch, 1, &cnt);
      if (rc == JBG_EOK || rc == JBG_EOK_INTR) //the image is finished
      {
            int     h, w, len;
            unsigned char *image=NULL;
            printf("\n<complete image found>\n");

            //debug(0, "JBG_EOK: %d\n", pn);
            h = jbg_dec_getheight(pstate);
            w = jbg_dec_getwidth(pstate);
            image = jbg_dec_getimage(pstate, 0); //is the first plane 1 or 0?
            len = jbg_dec_getsize(pstate);
            if (image !=NULL)
            {
                  char        buf[512];
                  sprintf(buf, "%s-%02d-%d.pbm", DecFile, page, pn);
                  printf("<\ndecode1 writing raster to %s...>\n", buf);
                  dfp = fopen(buf, "w");
                  if (dfp)
                  {
                        fprintf(dfp, "P4\n%8d %8d\n", w, h);
                        rc = fwrite(image, 1, len, dfp);
                        fclose(dfp);
                  }
            }
            else debug(0, "Missing image %dx%d!\n", h, w);

            ++Stripe;
            printf("<Start new stripe no %d>\n",Stripe);
//    jbg_dec_free(pstate);
      }
      else //its a data byte
      {
            if(rc == JBG_EAGAIN) printf("%3x",ch);
            else printf("<PROBLEM IN DECODING %s>\n", jbg_strerror(rc)); //add some error message 
      }
            return (rc);
    
}
void
decode(FILE *fp)
{
    int           h,w,c,i;
    int           rc;
      int   FirstData; //the position of the first data byte in JBIG data (The first stripe has a 20 bytes header)
    FILE    *dfp = NULL;
    int           pageNum = 1;
    int           curOff = 0;
    struct jbg_dec_state      s[5];
    unsigned char bih[20];
    int                 bihlen = 0;
    int           pn = 1;//was 0 but I took out the ++pn
    int                 totSize = 0;
    //char        buf[1024];
      char        buf[15000];
      int         datalen; //size of image , size of BIE

    Stripe = 0;
    while (fgetcomma(buf, sizeof(buf), &datalen, fp))       //get a string in buf terminated by ; or ? and return datalen
    {
      proff(curOff); curOff += strlen(buf);
      printf("%s\n", buf);
      if (0) {
      }
      else if (strncmp(buf, "LockPrinter", 11) == 0) {
      }
      else if (strncmp(buf, "Event=StartOfJob", 16) == 0) {
      }
      else if (strncmp(buf, "DeviceStatus", 12) == 0) {
      }
      else if (strncmp(buf, "DeviceSettings.System", 21) == 0) {
      }
      else if (strncmp(buf, "DeviceSettings", 14) == 0) {
      }
      else if (strncmp(buf, "DeviceStatus", 11) == 0) {
      }
      else if (strncmp(buf, "Event=EndOfPage", 15) == 0) {
          //pn = 0;
          ++pageNum;
      }
      else if (strncmp(buf, "RasterObject.BitsPerPixel", 26) == 0) {
      }
      else if (strncmp(buf, "RasterObject.Planes", 19) == 0) {
          int pl;
          sscanf(buf+20, "%x", &pl);
          debug(1, "planes=%x\n", pl);
      }
      else if (strncmp(buf, "RasterObject.Width", 18) == 0) {
         // int w;
          sscanf(buf+19, "%d", &w);
          debug(1, "width=%d\n", w);
      }
      else if (strncmp(buf, "RasterObject.Height", 19) == 0) {
          //int h;
          sscanf(buf+20, "%d", &h);
          debug(1, "height=%d\n", h);
      }
      else if (strncmp(buf, "RasterObject.Extent=true", 19) == 0) {
          int Commas = 0;
            for(i=0;i<sizeof(buf) && buf[i] != 0;++i) 
            { 
                  if(buf[i] == ',') 
                  {
                        ++Commas;
                        //printf("X");
                  }
            }
            printf("<Extents = %d, Height = %d>\n",(Commas)/2,h);
      }
      else if (strncmp(buf, "RasterObject.Data", 17) == 0) {
          curOff += datalen + 1;
          totSize += datalen;
printf("<Stripe %d>\n",Stripe);
            // In Kodak files the header is the first 20 bytes in the data of the first stripe.
                  //++pn;//we don't have planes
                  if(Stripe == 0)
                  {
                        rc = fread(bih, bihlen = sizeof(bih), 1, fp);
                        print_bih(bih);
                        printf("\n");
            //          getc(fp); //is this for the ; at the end of the header?
                        if (DecFile)
                        {
                              //initialize the JBIG decode
                              size_t      cnt;

                              jbg_dec_init(&s[pn]);

                              rc = jbg_dec_in(&s[pn], bih, bihlen, &cnt);
                              if (rc == JBG_EIMPL) error(1, "JBIG uses unimpl feature\n");
                              h = jbg_dec_getheight(&s[pn]);
                              w = jbg_dec_getwidth(&s[pn]);
printf("<initialised decode and read header, image is %dx%d>\n",w,h);
                        }
                  }
                  //in kodak files there's data following the header
            if (datalen > 20 && Stripe == 0) FirstData = 21;
            else FirstData = 1;
                unsigned char ch;
//jbg_dec_maxsize(&s[pn], s[pn].xd, s[pn].l0); //set the size to the size of one stripe
printf("<decoding JBIG stripe start %d datalen %d>\n",FirstData, datalen);
      h = jbg_dec_getheight(&s[pn]);
      w = jbg_dec_getwidth(&s[pn]);

            for(i=FirstData;i<=datalen;++i)
                {
                        c = getc(fp);
                        ch = c;
if(i==FirstData) 
{
printf("<First byte has been read>\n");
printf("<DecFile=%s ch=%d pn=%d pageNum=%d >\n",DecFile,ch,pn,pageNum);
}
                        if (DecFile)  jbig_decode1(ch, pn, pageNum, &s[pn], dfp);
                }
                getc(fp); //is this for the ; at the end of the data?
printf("<Data has been read>\n");
//jbig_write_file(pn, pageNum, &s[pn], dfp);
      ++Stripe;
printf("<Start new stripe no %d>\n",Stripe);

      }
    }
//try to identify the width of the colour zones
//jbig_zone_widths(pn, pageNum, &s[pn], dfp);
//try to write the file
jbig_write_file(pn, pageNum, &s[pn], dfp);
jbg_dec_free(&s[pn]);
}

int
main(int argc, char *argv[])
{
      extern int  optind;
      extern char *optarg;
      int         c;

      while ( (c = getopt(argc, argv, "d:hoD:?h")) != EOF)
            switch (c)
            {
            case 'd': DecFile = optarg; 
            printf("<will write raster to %s....>\n", DecFile);
            break;
            case 'o': PrintOffset = 1; break;
            case 'h': PrintHexOffset = 1; break;
            case 'D': Debug = atoi(optarg); break;
            default: usage(); exit(1);
            }

      argc -= optind;
      argv += optind;

        if (argc > 0)
        {
            FILE        *fp;

            fp = fopen(argv[0], "r");
            if (!fp)
                error(1, "file '%s' doesn't exist\n", argv[0]);
            for (;;)
            {
                decode(fp);
                c = getc(fp); ungetc(c, fp);
                if (feof(fp))
                    break;
            }
            fclose(fp);
        }
        else
        {
          for(;;)
          {
            decode(stdin);
            c = getc(stdin); ungetc(c, stdin);
            if (feof(stdin))
                break;
          }
      }
      printf("\n");

      exit(0);
}

Generated by  Doxygen 1.6.0   Back to index