コード例 #1
0
ファイル: cjb2.cpp プロジェクト: tau0/djvulibre
void 
cjb2(const GURL &urlin, const GURL &urlout, cjb2opts &opts)
{
  GP<ByteStream> ibs=ByteStream::create(urlin, "rb");
  CCImage rimg;

#if HAVE_TIFF
  if (is_tiff(ibs))
    read_tiff(rimg, ibs, opts);
  else
#endif
    {
      GP<GBitmap> input=GBitmap::create(*ibs);
      rimg.init(input->columns(), input->rows(), opts.dpi);
      rimg.add_bitmap_runs(*input); 
    }
  if (opts.verbose)
    DjVuFormatErrorUTF8( "%s\t%d", ERR_MSG("cjb2.runs"), 
                         rimg.runs.size() );
  
  // Component analysis
  rimg.make_ccids_by_analysis(); // obtain ccids
  rimg.make_ccs_from_ccids();    // compute cc descriptors
  if (opts.verbose)
    DjVuFormatErrorUTF8( "%s\t%d", ERR_MSG("cjb2.ccs_before"), 
                         rimg.ccs.size());
  if (opts.losslevel > 0) 
    rimg.erase_tiny_ccs();       // clean
  rimg.merge_and_split_ccs();    // reorganize weird ccs
  rimg.sort_in_reading_order();  // sort cc descriptors
  if (opts.verbose)
    DjVuFormatErrorUTF8( "%s\t%d", ERR_MSG("cjb2.ccs_after"), 
                         rimg.ccs.size());
  
  // Pattern matching
  GP<JB2Image> jimg = rimg.get_jb2image();          // get ``raw'' jb2image
  rimg.runs.empty();                                // save memory
  rimg.ccs.empty();                                 // save memory
  if (opts.losslevel>1)
    tune_jb2image_lossy(jimg, opts.dpi, opts.losslevel);
  else
    tune_jb2image_lossless(jimg);
  if (opts.verbose)
    {
      int nshape=0, nrefine=0;
      for (int i=0; i<jimg->get_shape_count(); i++) {
        if (!jimg->get_shape(i).bits) continue;
        if (jimg->get_shape(i).parent >= 0) nrefine++; 
        nshape++; 
      }
      DjVuFormatErrorUTF8( "%s\t%d\t%d", ERR_MSG("cjb2.shapes"), 
                           nshape, nrefine);
    }
  
  // Code
  GP<ByteStream> obs=ByteStream::create(urlout, "wb");
  GP<IFFByteStream> giff=IFFByteStream::create(obs);
  IFFByteStream &iff=*giff;
  // -- main composite chunk
  iff.put_chunk("FORM:DJVU", 1);
  // -- ``INFO'' chunk
  GP<DjVuInfo> ginfo=DjVuInfo::create();
  DjVuInfo &info=*ginfo;
  info.height = rimg.height;
  info.width = rimg.width;
  info.dpi = opts.dpi;
  iff.put_chunk("INFO");
  info.encode(*iff.get_bytestream());
  iff.close_chunk();
  // -- ``Sjbz'' chunk
  iff.put_chunk("Sjbz");
  jimg->encode(iff.get_bytestream());
  iff.close_chunk();
  // -- terminate main composite chunk
  iff.close_chunk();
  // Finished!
}
コード例 #2
0
ファイル: cjb2.cpp プロジェクト: tau0/djvulibre
static void
read_tiff(CCImage &rimg, ByteStream *bs, cjb2opts &opts)
{
  TIFF *tiff = TIFFClientOpen("libtiff", "rm", (thandle_t)bs,
                              readproc, writeproc, seekproc,
                              closeproc, sizeproc, 
                              mapproc, unmapproc );
  // bitonal
  uint16 bps = 0, spp = 0;
  TIFFGetFieldDefaulted(tiff, TIFFTAG_BITSPERSAMPLE, &bps);
  TIFFGetFieldDefaulted(tiff, TIFFTAG_SAMPLESPERPIXEL, &spp);
  if (bps != 1 || spp != 1)
    G_THROW("Tiff image is not bitonal");
  // photometric
  uint16 photo = PHOTOMETRIC_MINISWHITE;
  TIFFGetFieldDefaulted(tiff, TIFFTAG_PHOTOMETRIC, &photo);
  // image size
  uint32 w, h;
  if (!TIFFGetFieldDefaulted(tiff, TIFFTAG_IMAGEWIDTH, &w) ||
      !TIFFGetFieldDefaulted(tiff, TIFFTAG_IMAGELENGTH, &h) )
    G_THROW("Tiff image size is not defined");
  // resolution
  float xres, yres;
  if (TIFFGetFieldDefaulted(tiff, TIFFTAG_XRESOLUTION, &xres) &&
      TIFFGetFieldDefaulted(tiff, TIFFTAG_YRESOLUTION, &yres) ) 
    {
      if (xres != yres)
        DjVuPrintErrorUTF8( "cjb2: X- and Y-resolution do not match\n");
      if (! opts.forcedpi)
        opts.dpi = (int) (xres + yres) / 2;
    }
  // init rimg
  rimg.init(w, h, opts.dpi);
  // allocate scanline
  tsize_t scanlinesize = TIFFScanlineSize(tiff);
  scanlinesize = MAX(scanlinesize,1);
  unsigned char *scanline = 0;
  GPBuffer<unsigned char> gscanline(scanline, scanlinesize);
  // iterate on rows
  for (int y=0; y<(int)h; y++)
    {
      int yy = h - y - 1;
      if (TIFFReadScanline(tiff, (tdata_t)scanline, y) < 0)
        G_THROW("Tiff file is corrupted (TIFFReadScanline)");
      if (photo != PHOTOMETRIC_MINISWHITE)
        for (int i=0; i<(int)scanlinesize; i++)
          scanline[i] ^= 0xff;
      int lastx=0, off=0;
      unsigned char mask=0, c=0, b=0;
      for (int x=0; x<(int)w; x++)
        {
          if (! mask) 
            {
              b = scanline[off++];
              while (b==c && x+8<(int)w )
                {
                  x = x + 8;  // speedup
                  b = scanline[off++];
                }
              mask = 0x80;
            }
          if ( (b ^ c) & mask ) 
            {
              c ^= 0xff;
              if (c)
                lastx = x;
              else
                rimg.add_single_run(yy, lastx, x-1);
            }
          mask >>= 1;
        }
      if (c)
        rimg.add_single_run(yy, lastx, w-1);
    }
  // close
  TIFFClose(tiff);
}