Blame tools/ddjvu.cpp

Packit df99a1
//C-  -*- C++ -*-
Packit df99a1
//C- -------------------------------------------------------------------
Packit df99a1
//C- DjVuLibre-3.5
Packit df99a1
//C- Copyright (c) 2002  Leon Bottou and Yann Le Cun.
Packit df99a1
//C- Copyright (c) 2001  AT&T
Packit df99a1
//C-
Packit df99a1
//C- This software is subject to, and may be distributed under, the
Packit df99a1
//C- GNU General Public License, either Version 2 of the license,
Packit df99a1
//C- or (at your option) any later version. The license should have
Packit df99a1
//C- accompanied the software or you may obtain a copy of the license
Packit df99a1
//C- from the Free Software Foundation at http://www.fsf.org .
Packit df99a1
//C-
Packit df99a1
//C- This program is distributed in the hope that it will be useful,
Packit df99a1
//C- but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit df99a1
//C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit df99a1
//C- GNU General Public License for more details.
Packit df99a1
//C- 
Packit df99a1
//C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library from
Packit df99a1
//C- Lizardtech Software.  Lizardtech Software has authorized us to
Packit df99a1
//C- replace the original DjVu(r) Reference Library notice by the following
Packit df99a1
//C- text (see doc/lizard2002.djvu and doc/lizardtech2007.djvu):
Packit df99a1
//C-
Packit df99a1
//C-  ------------------------------------------------------------------
Packit df99a1
//C- | DjVu (r) Reference Library (v. 3.5)
Packit df99a1
//C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
Packit df99a1
//C- | The DjVu Reference Library is protected by U.S. Pat. No.
Packit df99a1
//C- | 6,058,214 and patents pending.
Packit df99a1
//C- |
Packit df99a1
//C- | This software is subject to, and may be distributed under, the
Packit df99a1
//C- | GNU General Public License, either Version 2 of the license,
Packit df99a1
//C- | or (at your option) any later version. The license should have
Packit df99a1
//C- | accompanied the software or you may obtain a copy of the license
Packit df99a1
//C- | from the Free Software Foundation at http://www.fsf.org .
Packit df99a1
//C- |
Packit df99a1
//C- | The computer code originally released by LizardTech under this
Packit df99a1
//C- | license and unmodified by other parties is deemed "the LIZARDTECH
Packit df99a1
//C- | ORIGINAL CODE."  Subject to any third party intellectual property
Packit df99a1
//C- | claims, LizardTech grants recipient a worldwide, royalty-free, 
Packit df99a1
//C- | non-exclusive license to make, use, sell, or otherwise dispose of 
Packit df99a1
//C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the 
Packit df99a1
//C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU 
Packit df99a1
//C- | General Public License.   This grant only confers the right to 
Packit df99a1
//C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to 
Packit df99a1
//C- | the extent such infringement is reasonably necessary to enable 
Packit df99a1
//C- | recipient to make, have made, practice, sell, or otherwise dispose 
Packit df99a1
//C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to 
Packit df99a1
//C- | any greater extent that may be necessary to utilize further 
Packit df99a1
//C- | modifications or combinations.
Packit df99a1
//C- |
Packit df99a1
//C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
Packit df99a1
//C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
Packit df99a1
//C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
Packit df99a1
//C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Packit df99a1
//C- +------------------------------------------------------------------
Packit df99a1
Packit df99a1
Packit df99a1
/* Program ddjvu has been rewritten to use the ddjvuapi only.
Packit df99a1
 * This file should compile both as C and C++. 
Packit df99a1
 */
Packit df99a1
Packit df99a1
#ifdef HAVE_CONFIG_H
Packit df99a1
# include "config.h"
Packit df99a1
#endif
Packit df99a1
Packit df99a1
#include <stddef.h>
Packit df99a1
#include <stdlib.h>
Packit df99a1
#include <stdio.h>
Packit df99a1
#include <stdarg.h>
Packit df99a1
#include <string.h>
Packit df99a1
#include <locale.h>
Packit df99a1
#include <fcntl.h>
Packit df99a1
#include <errno.h>
Packit df99a1
Packit df99a1
#ifdef UNIX
Packit df99a1
# include <sys/time.h>
Packit df99a1
# include <sys/types.h>
Packit df99a1
# include <unistd.h>
Packit df99a1
#endif
Packit df99a1
#if defined(_WIN32) || defined(__CYGWIN32__)
Packit df99a1
# include <io.h>
Packit df99a1
#endif
Packit df99a1
#if defined(_WIN32) && !defined(__CYGWIN32__)
Packit df99a1
# include <mbctype.h>
Packit df99a1
#endif
Packit df99a1
Packit df99a1
#include "libdjvu/ddjvuapi.h"
Packit df99a1
#include "tiff2pdf.h"
Packit df99a1
Packit df99a1
Packit df99a1
#if HAVE_PUTC_UNLOCKED
Packit df99a1
# undef putc
Packit df99a1
# define putc putc_unlocked
Packit df99a1
#endif
Packit df99a1
Packit df99a1
#if HAVE_TIFF
Packit df99a1
# include <tiff.h>
Packit df99a1
# include <tiffio.h>
Packit df99a1
# include <tiffconf.h>
Packit df99a1
#endif
Packit df99a1
Packit df99a1
/* Some day we'll redo i18n right. */
Packit df99a1
#ifndef i18n
Packit df99a1
# define i18n(x) (x)
Packit df99a1
# define I18N(x) (x)
Packit df99a1
#endif
Packit df99a1
Packit df99a1
Packit df99a1
unsigned long 
Packit df99a1
ticks(void)
Packit df99a1
{
Packit df99a1
#ifdef UNIX
Packit df99a1
  struct timeval tv;
Packit df99a1
  if (gettimeofday(&tv, NULL) >= 0)
Packit df99a1
    return (unsigned long)(((tv.tv_sec & 0xfffff)*1000)+(tv.tv_usec/1000));
Packit df99a1
#endif
Packit df99a1
  return 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
ddjvu_context_t *ctx;
Packit df99a1
ddjvu_document_t *doc;
Packit df99a1
Packit df99a1
unsigned long timingdata[4];
Packit df99a1
Packit df99a1
double       flag_scale = -1;
Packit df99a1
int          flag_size = -1;
Packit df99a1
int          flag_aspect = -1;
Packit df99a1
int          flag_subsample = -1;
Packit df99a1
int          flag_segment = 0;
Packit df99a1
int          flag_verbose = 0;
Packit df99a1
char         flag_mode = 0;     /* 'c', 'k', 's', 'f','b' */
Packit df99a1
char         flag_format = 0;   /* '4','5','6','p','r','t', 'f' */
Packit df99a1
int          flag_quality = -1; /* 1-100 jpg, 900 zip, 901 lzw, 1000 raw */
Packit df99a1
int          flag_skipcorrupted = 0;
Packit df99a1
int          flag_eachpage = 0;
Packit df99a1
const char  *flag_pagespec = 0; 
Packit df99a1
ddjvu_rect_t info_size;
Packit df99a1
ddjvu_rect_t info_segment;
Packit df99a1
const char  *programname = 0;
Packit df99a1
const char  *inputfilename = 0;
Packit df99a1
const char  *outputfilename = 0;
Packit df99a1
Packit df99a1
char *pagefilename = 0;
Packit df99a1
#if HAVE_TIFF2PDF
Packit df99a1
char *tempfilename = 0;
Packit df99a1
int tiffd = -1;
Packit df99a1
#endif
Packit df99a1
#if HAVE_TIFF
Packit df99a1
TIFF *tiff = 0;
Packit df99a1
#endif
Packit df99a1
FILE *fout = 0;
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
/* Djvuapi events */
Packit df99a1
Packit df99a1
void
Packit df99a1
handle(int wait)
Packit df99a1
{
Packit df99a1
  const ddjvu_message_t *msg;
Packit df99a1
  if (!ctx)
Packit df99a1
    return;
Packit df99a1
  if (wait)
Packit df99a1
    msg = ddjvu_message_wait(ctx);
Packit df99a1
  while ((msg = ddjvu_message_peek(ctx)))
Packit df99a1
    {
Packit df99a1
      switch(msg->m_any.tag)
Packit df99a1
        {
Packit df99a1
        case DDJVU_ERROR:
Packit df99a1
          fprintf(stderr,"ddjvu: %s\n", msg->m_error.message);
Packit df99a1
          if (msg->m_error.filename)
Packit df99a1
            fprintf(stderr,"ddjvu: '%s:%d'\n", 
Packit df99a1
                    msg->m_error.filename, msg->m_error.lineno);
Packit df99a1
        default:
Packit df99a1
          break;
Packit df99a1
        }
Packit df99a1
      ddjvu_message_pop(ctx);
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
void 
Packit df99a1
die(const char *fmt, ...)
Packit df99a1
{
Packit df99a1
  /* Handling messages might give a better error message */
Packit df99a1
  handle(FALSE);
Packit df99a1
  /* Print */
Packit df99a1
  va_list args;
Packit df99a1
  fprintf(stderr,"ddjvu: ");
Packit df99a1
  va_start(args, fmt);
Packit df99a1
  vfprintf(stderr, fmt, args);
Packit df99a1
  va_end(args);
Packit df99a1
  fprintf(stderr,"\n");
Packit df99a1
  /* Cleanup */
Packit df99a1
#if HAVE_TIFF2PDF
Packit df99a1
  if (tiffd >= 0)
Packit df99a1
    close(tiffd);
Packit df99a1
  if (tempfilename)
Packit df99a1
    remove(tempfilename);
Packit df99a1
#endif
Packit df99a1
  /* Terminates */
Packit df99a1
  exit(10);
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
void
Packit df99a1
inform(ddjvu_page_t *page, int pageno)
Packit df99a1
{
Packit df99a1
  if (flag_verbose)
Packit df99a1
    {
Packit df99a1
      const char *desctype;
Packit df99a1
      char *description = ddjvu_page_get_long_description(page);
Packit df99a1
      ddjvu_page_type_t type = ddjvu_page_get_type(page);
Packit df99a1
      fprintf(stderr,i18n("\n-------- page %d -------\n"), pageno);
Packit df99a1
      if (type == DDJVU_PAGETYPE_BITONAL)
Packit df99a1
        desctype = i18n("This is a legal Bitonal DjVu image");
Packit df99a1
      else if (type == DDJVU_PAGETYPE_PHOTO)
Packit df99a1
        desctype = i18n("This is a legal Photo DjVu image");
Packit df99a1
      else if (type == DDJVU_PAGETYPE_COMPOUND)
Packit df99a1
        desctype = i18n("This is a legal Compound DjVu image");
Packit df99a1
      else
Packit df99a1
        desctype = i18n("This is a malformed DjVu image");
Packit df99a1
      fprintf(stderr,"%s.\n", desctype);
Packit df99a1
      if (description)
Packit df99a1
        fprintf(stderr,"%s\n", description);
Packit df99a1
      if (description)
Packit df99a1
        free(description);
Packit df99a1
      if (timingdata[0] != timingdata[1])
Packit df99a1
	fprintf(stderr,"Decoding time:  %5ld ms\n",
Packit df99a1
		timingdata[1] - timingdata[0] );
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
void
Packit df99a1
render(ddjvu_page_t *page, int pageno)
Packit df99a1
{
Packit df99a1
  ddjvu_rect_t prect;
Packit df99a1
  ddjvu_rect_t rrect;
Packit df99a1
  ddjvu_format_style_t style;
Packit df99a1
  ddjvu_render_mode_t mode;
Packit df99a1
  ddjvu_format_t *fmt;
Packit df99a1
  int iw = ddjvu_page_get_width(page);
Packit df99a1
  int ih = ddjvu_page_get_height(page);
Packit df99a1
  int dpi = ddjvu_page_get_resolution(page);
Packit df99a1
  ddjvu_page_type_t type = ddjvu_page_get_type(page);
Packit df99a1
  char *image = 0;
Packit df99a1
  char white = (char)0xFF;
Packit df99a1
  int rowsize;
Packit df99a1
#if HAVE_TIFF
Packit df99a1
  int compression = COMPRESSION_NONE;
Packit df99a1
#endif
Packit df99a1
  
Packit df99a1
  /* Process size specification */
Packit df99a1
  prect.x = 0;
Packit df99a1
  prect.y = 0;
Packit df99a1
  if (flag_size > 0)
Packit df99a1
    {
Packit df99a1
      prect.w = info_size.w;
Packit df99a1
      prect.h = info_size.h;
Packit df99a1
    }
Packit df99a1
  else if (flag_subsample > 0)
Packit df99a1
    {
Packit df99a1
      prect.w = (iw + flag_subsample - 1) / flag_subsample;
Packit df99a1
      prect.h = (ih + flag_subsample - 1) / flag_subsample;
Packit df99a1
    }
Packit df99a1
  else if (flag_scale > 0)
Packit df99a1
    {
Packit df99a1
      prect.w = (unsigned int) (iw * flag_scale) / dpi;
Packit df99a1
      prect.h = (unsigned int) (ih * flag_scale) / dpi;
Packit df99a1
    }
Packit df99a1
  else if (flag_format)
Packit df99a1
    {
Packit df99a1
      prect.w = iw;
Packit df99a1
      prect.h = ih;
Packit df99a1
    }
Packit df99a1
  else
Packit df99a1
    {
Packit df99a1
      prect.w = (iw * 100) / dpi;
Packit df99a1
      prect.h = (ih * 100) / dpi;
Packit df99a1
    }
Packit df99a1
  /* Process aspect ratio */
Packit df99a1
  if (flag_aspect <= 0)
Packit df99a1
    {
Packit df99a1
      double dw = (double)iw / prect.w;
Packit df99a1
      double dh = (double)ih / prect.h;
Packit df99a1
      if (dw > dh) 
Packit df99a1
        prect.h = (int)(ih / dw);
Packit df99a1
      else
Packit df99a1
        prect.w = (int)(iw / dh);
Packit df99a1
    }
Packit df99a1
Packit df99a1
  /* Process segment specification */
Packit df99a1
  rrect = prect;
Packit df99a1
  if (flag_segment > 0)
Packit df99a1
    {
Packit df99a1
      rrect = info_segment;
Packit df99a1
      if (rrect.x < 0)
Packit df99a1
        rrect.x = prect.w - rrect.w + rrect.x;
Packit df99a1
      if (rrect.y < 0)
Packit df99a1
        rrect.y = prect.h - rrect.h + rrect.y;
Packit df99a1
    }
Packit df99a1
Packit df99a1
  /* Process mode specification */
Packit df99a1
  mode = DDJVU_RENDER_COLOR;
Packit df99a1
  if (flag_mode == 'f')
Packit df99a1
    mode = DDJVU_RENDER_FOREGROUND;
Packit df99a1
  else if (flag_mode == 'b')
Packit df99a1
    mode = DDJVU_RENDER_BACKGROUND;
Packit df99a1
  else if (flag_mode == 'c')
Packit df99a1
    mode = DDJVU_RENDER_COLOR;
Packit df99a1
  else if (flag_mode == 'k')
Packit df99a1
    mode = DDJVU_RENDER_BLACK;
Packit df99a1
  else if (flag_mode == 's')
Packit df99a1
    mode = DDJVU_RENDER_MASKONLY;
Packit df99a1
  else if (flag_format == 'r' || flag_format == '4')
Packit df99a1
    mode = DDJVU_RENDER_BLACK;
Packit df99a1
Packit df99a1
  /* Determine output pixel format and compression */
Packit df99a1
  style = DDJVU_FORMAT_RGB24;
Packit df99a1
  if (mode==DDJVU_RENDER_BLACK ||
Packit df99a1
      mode==DDJVU_RENDER_MASKONLY ||
Packit df99a1
      (mode==DDJVU_RENDER_COLOR && type==DDJVU_PAGETYPE_BITONAL))
Packit df99a1
    {
Packit df99a1
      style = DDJVU_FORMAT_GREY8;
Packit df99a1
      if ((int)prect.w == iw && (int)prect.h == ih)
Packit df99a1
        style = DDJVU_FORMAT_MSBTOLSB;
Packit df99a1
    }
Packit df99a1
  switch(flag_format)
Packit df99a1
    {
Packit df99a1
    case 'f':
Packit df99a1
    case 't':
Packit df99a1
#if HAVE_TIFF
Packit df99a1
      compression = COMPRESSION_NONE;
Packit df99a1
      if (flag_quality >= 1000)
Packit df99a1
        break;
Packit df99a1
# ifdef CCITT_SUPPORT
Packit df99a1
      if (style==DDJVU_FORMAT_MSBTOLSB 
Packit df99a1
          && TIFFFindCODEC(COMPRESSION_CCITT_T6))
Packit df99a1
        compression = COMPRESSION_CCITT_T6;
Packit df99a1
# endif
Packit df99a1
# ifdef JPEG_SUPPORT
Packit df99a1
      if (compression == COMPRESSION_NONE 
Packit df99a1
          && style!=DDJVU_FORMAT_MSBTOLSB 
Packit df99a1
          && flag_quality>0 && flag_quality<=100
Packit df99a1
          && TIFFFindCODEC(COMPRESSION_JPEG))
Packit df99a1
        compression = COMPRESSION_JPEG;
Packit df99a1
# endif
Packit df99a1
# ifdef ZIP_SUPPORT
Packit df99a1
      if (compression == COMPRESSION_NONE
Packit df99a1
          && (flag_format == 'f' || flag_quality == 900)
Packit df99a1
          && TIFFFindCODEC(COMPRESSION_DEFLATE))
Packit df99a1
        /* All pdf engines understand deflate. */
Packit df99a1
        compression = COMPRESSION_DEFLATE;
Packit df99a1
# endif
Packit df99a1
# ifdef LZW_SUPPORT
Packit df99a1
      if (compression == COMPRESSION_NONE
Packit df99a1
          && flag_quality == 901
Packit df99a1
          && TIFFFindCODEC(COMPRESSION_LZW))
Packit df99a1
        /* Because of patents that are now expired, some versions
Packit df99a1
           of libtiff only support lzw decoding and trigger an error
Packit df99a1
           condition when trying to encode. Unfortunately we cannot
Packit df99a1
           know this in advance and select another compression scheme. */
Packit df99a1
        compression = COMPRESSION_LZW;
Packit df99a1
# endif
Packit df99a1
# ifdef PACKBITS_SUPPORT
Packit df99a1
      if (compression == COMPRESSION_NONE 
Packit df99a1
          && TIFFFindCODEC(COMPRESSION_PACKBITS))
Packit df99a1
        /* This mediocre default produces the most portable tiff files. */
Packit df99a1
        compression = COMPRESSION_PACKBITS;
Packit df99a1
# endif
Packit df99a1
      break;
Packit df99a1
#endif      
Packit df99a1
    case '4':
Packit df99a1
      style = DDJVU_FORMAT_MSBTOLSB; 
Packit df99a1
      break;
Packit df99a1
    case 'r': 
Packit df99a1
    case '5':
Packit df99a1
      style = DDJVU_FORMAT_GREY8;    
Packit df99a1
      break;
Packit df99a1
    case '6':
Packit df99a1
      style = DDJVU_FORMAT_RGB24;   
Packit df99a1
      break;
Packit df99a1
    default:
Packit df99a1
      break;
Packit df99a1
    }
Packit df99a1
  if (! (fmt = ddjvu_format_create(style, 0, 0)))
Packit df99a1
    die(i18n("Cannot determine pixel style for page %d"), pageno);
Packit df99a1
  ddjvu_format_set_row_order(fmt, 1);
Packit df99a1
  /* Allocate buffer */
Packit df99a1
  if (style == DDJVU_FORMAT_MSBTOLSB) {
Packit df99a1
    white = 0x00;
Packit df99a1
    rowsize = (rrect.w + 7) / 8; 
Packit df99a1
  } else if (style == DDJVU_FORMAT_GREY8)
Packit df99a1
    rowsize = rrect.w;
Packit df99a1
  else
Packit df99a1
    rowsize = rrect.w * 3; 
Packit df99a1
  if (! (image = (char*)malloc(rowsize * rrect.h)))
Packit df99a1
    die(i18n("Cannot allocate image buffer for page %d"), pageno);
Packit df99a1
Packit df99a1
  /* Render */
Packit df99a1
  timingdata[2] = ticks();
Packit df99a1
  if (! ddjvu_page_render(page, mode, &prect, &rrect, fmt, rowsize, image))
Packit df99a1
    memset(image, white, rowsize * rrect.h);
Packit df99a1
  timingdata[3] = ticks();
Packit df99a1
  if (flag_verbose)
Packit df99a1
    if (timingdata[2] != timingdata[3])
Packit df99a1
      fprintf(stderr,"Rendering time: %5ld ms\n",
Packit df99a1
	      timingdata[3] - timingdata[2] );
Packit df99a1
Packit df99a1
  /* Output */
Packit df99a1
  switch (flag_format)
Packit df99a1
    {
Packit df99a1
      /* -------------- PNM output */
Packit df99a1
    default:
Packit df99a1
    case '4':
Packit df99a1
    case '5':
Packit df99a1
    case '6':
Packit df99a1
      {
Packit df99a1
        int i;
Packit df99a1
        char *s = image;
Packit df99a1
        if (style == DDJVU_FORMAT_MSBTOLSB) {
Packit df99a1
          if (flag_verbose) 
Packit df99a1
            fprintf(stderr,i18n("Producing PBM file.\n"));
Packit df99a1
          fprintf(fout,"P4\n%d %d\n", rrect.w, rrect.h);
Packit df99a1
        } else if (style == DDJVU_FORMAT_GREY8) {
Packit df99a1
          if (flag_verbose) 
Packit df99a1
            fprintf(stderr,i18n("Producing PGM file.\n"));
Packit df99a1
          fprintf(fout,"P5\n%d %d\n255\n", rrect.w, rrect.h);
Packit df99a1
        } else {
Packit df99a1
          if (flag_verbose) 
Packit df99a1
            fprintf(stderr,i18n("Producing PPM file.\n"));
Packit df99a1
          fprintf(fout,"P6\n%d %d\n255\n", rrect.w, rrect.h);
Packit df99a1
        }
Packit df99a1
        for (i=0; i<(int)rrect.h; i++,s+=rowsize)
Packit df99a1
          if (fwrite(s, 1, rowsize, fout) < (size_t)rowsize)
Packit df99a1
            die(i18n("writing pnm file: %s"), strerror(errno));
Packit df99a1
        break;
Packit df99a1
      }
Packit df99a1
      /* -------------- RLE output */
Packit df99a1
    case 'r':
Packit df99a1
      {
Packit df99a1
        int i;
Packit df99a1
        unsigned char *s = (unsigned char *)image;
Packit df99a1
        if (flag_verbose)
Packit df99a1
          fprintf(stderr,i18n("Producing RLE file.\n"));
Packit df99a1
        fprintf(fout,"R4\n%d %d\n", rrect.w, rrect.h);
Packit df99a1
        for (i=0; i<(int)rrect.h; i++,s+=rowsize)
Packit df99a1
          {
Packit df99a1
            int j = 0;
Packit df99a1
            int c = 0xff;
Packit df99a1
            while (j < (int)rrect.w)
Packit df99a1
              {
Packit df99a1
                int l = j;
Packit df99a1
                while ((j<(int)rrect.w) && ((s[j]^c)<128))
Packit df99a1
                  j += 1;
Packit df99a1
                c = c ^ 0xff;
Packit df99a1
                l = j - l;
Packit df99a1
                while (l > 0x3fff) {
Packit df99a1
                  putc( 0xff, fout);
Packit df99a1
                  putc( 0xff, fout);
Packit df99a1
                  putc( 0x00, fout);
Packit df99a1
                  l -= 0x3fff;
Packit df99a1
                }
Packit df99a1
                if (l > 0xbf) {
Packit df99a1
                  putc( (l >> 8) + 0xc0, fout);
Packit df99a1
                  putc( (l & 0xff), fout);
Packit df99a1
                } else {
Packit df99a1
                  putc( l, fout);
Packit df99a1
                }
Packit df99a1
              }
Packit df99a1
          }
Packit df99a1
        if (ferror(fout))
Packit df99a1
          die(i18n("writing rle file: %s"), strerror(errno));
Packit df99a1
        break;
Packit df99a1
      }
Packit df99a1
      /* -------------- TIFF or PDF output */
Packit df99a1
    case 't':
Packit df99a1
    case 'f':
Packit df99a1
      {
Packit df99a1
#if HAVE_TIFF
Packit df99a1
        int i;
Packit df99a1
        char *s = image;
Packit df99a1
        TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, (uint32)rrect.w);
Packit df99a1
        TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, (uint32)rrect.h);
Packit df99a1
        TIFFSetField(tiff, TIFFTAG_XRESOLUTION, 
Packit df99a1
		     (float)((dpi*rrect.w+iw/2)/iw));
Packit df99a1
        TIFFSetField(tiff, TIFFTAG_YRESOLUTION, 
Packit df99a1
		     (float)((dpi*rrect.h+ih/2)/ih));
Packit df99a1
        TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
Packit df99a1
        TIFFSetField(tiff, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
Packit df99a1
# ifdef CCITT_SUPPORT
Packit df99a1
        if (compression != COMPRESSION_CCITT_T6)
Packit df99a1
# endif
Packit df99a1
# ifdef JPEG_SUPPORT
Packit df99a1
          if (compression != COMPRESSION_JPEG)
Packit df99a1
# endif
Packit df99a1
# ifdef ZIP_SUPPORT
Packit df99a1
            if (compression != COMPRESSION_DEFLATE)
Packit df99a1
# endif
Packit df99a1
              TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, (uint32)64);
Packit df99a1
        if (style == DDJVU_FORMAT_MSBTOLSB) {
Packit df99a1
          TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, (uint16)1);
Packit df99a1
          TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, (uint16)1);
Packit df99a1
          TIFFSetField(tiff, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
Packit df99a1
          TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression);
Packit df99a1
          TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE);
Packit df99a1
        } else {
Packit df99a1
          TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, (uint16)8);
Packit df99a1
          if (style == DDJVU_FORMAT_GREY8) {
Packit df99a1
            TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, (uint16)1);
Packit df99a1
            TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression);
Packit df99a1
            TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
Packit df99a1
          } else {
Packit df99a1
            TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, (uint16)3);
Packit df99a1
            TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression);
Packit df99a1
# ifdef JPEG_SUPPORT
Packit df99a1
            if (compression == COMPRESSION_JPEG) {
Packit df99a1
              TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR);
Packit df99a1
              TIFFSetField(tiff, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
Packit df99a1
              TIFFSetField(tiff, TIFFTAG_JPEGQUALITY, flag_quality);
Packit df99a1
            } else 
Packit df99a1
# endif
Packit df99a1
              TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
Packit df99a1
          }
Packit df99a1
        }
Packit df99a1
        if (flag_verbose) {
Packit df99a1
          if (compression == COMPRESSION_NONE)
Packit df99a1
            fprintf(stderr,i18n("Producing uncompressed TIFF file.\n"));
Packit df99a1
# ifdef CCITT_SUPPORT
Packit df99a1
          else if (compression == COMPRESSION_CCITT_T6)
Packit df99a1
            fprintf(stderr,i18n("Producing TIFF/G4 file.\n"));
Packit df99a1
# endif
Packit df99a1
# ifdef JPEG_SUPPORT
Packit df99a1
          else if (compression == COMPRESSION_JPEG)
Packit df99a1
            fprintf(stderr,i18n("Producing TIFF/JPEG file.\n"));
Packit df99a1
# endif
Packit df99a1
# ifdef ZIP_SUPPORT
Packit df99a1
          else if (compression == COMPRESSION_DEFLATE)
Packit df99a1
            fprintf(stderr,i18n("Producing TIFF/DEFLATE file.\n"));
Packit df99a1
# endif
Packit df99a1
# ifdef PACKBITS_SUPPORT
Packit df99a1
          else if (compression == COMPRESSION_PACKBITS)
Packit df99a1
            fprintf(stderr,i18n("Producing TIFF/PACKBITS file.\n"));
Packit df99a1
# endif
Packit df99a1
          else
Packit df99a1
            fprintf(stderr,i18n("Producing TIFF file.\n"));
Packit df99a1
        }
Packit df99a1
        if (rowsize != TIFFScanlineSize(tiff))
Packit df99a1
          die("internal error (%d!=%d)", rowsize, (int)TIFFScanlineSize(tiff));
Packit df99a1
        for (i=0; i<(int)rrect.h; i++,s+=rowsize)
Packit df99a1
          TIFFWriteScanline(tiff, s, i, 0);
Packit df99a1
#else
Packit df99a1
        die(i18n("TIFF output is not compiled"));
Packit df99a1
#endif
Packit df99a1
      }
Packit df99a1
    }
Packit df99a1
Packit df99a1
  /* Free */
Packit df99a1
  ddjvu_format_release(fmt);
Packit df99a1
  free(image);
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
void 
Packit df99a1
openfile(int pageno)
Packit df99a1
{
Packit df99a1
  /* Compute filename */
Packit df99a1
  const char *filename = outputfilename;
Packit df99a1
  if (flag_eachpage)
Packit df99a1
    {
Packit df99a1
      sprintf(pagefilename, filename, pageno);
Packit df99a1
      filename = pagefilename;
Packit df99a1
    }
Packit df99a1
  
Packit df99a1
  /* Open */
Packit df99a1
  if (flag_format == 't') /* tiff file */
Packit df99a1
    { 
Packit df99a1
#if HAVE_TIFF
Packit df99a1
      if (tiff) 
Packit df99a1
        {
Packit df99a1
          if (! TIFFWriteDirectory(tiff))
Packit df99a1
            die(i18n("Problem writing TIFF directory."));
Packit df99a1
        }
Packit df99a1
      else
Packit df99a1
        {
Packit df99a1
          if (! strcmp(filename,"-"))
Packit df99a1
            die(i18n("TIFF output requires a valid output file name."));
Packit df99a1
          if (! (tiff = TIFFOpen(filename, "w")))
Packit df99a1
            die(i18n("Cannot open output tiff file '%s'."), filename);
Packit df99a1
        }
Packit df99a1
#else
Packit df99a1
      die(i18n("TIFF output is not compiled"));
Packit df99a1
#endif
Packit df99a1
    }
Packit df99a1
  else if (flag_format == 'f') /* temporary tiff, later converted to pdf */
Packit df99a1
    {
Packit df99a1
#if HAVE_TIFF2PDF
Packit df99a1
      if (tiff) 
Packit df99a1
        {
Packit df99a1
          if (! TIFFWriteDirectory(tiff))
Packit df99a1
            die(i18n("Problem writing directory in temporary TIFF file."));
Packit df99a1
        }
Packit df99a1
      else
Packit df99a1
        {
Packit df99a1
          if (! strcmp(filename,"-"))
Packit df99a1
            die(i18n("PDF output requires a valid output file name."));
Packit df99a1
          if (! (tempfilename = (char*)malloc(strlen(outputfilename) + 8)))
Packit df99a1
            die(i18n("Out of memory."));
Packit df99a1
          strcpy(tempfilename, outputfilename);
Packit df99a1
          strcat(tempfilename, ".XXXXXX");
Packit df99a1
          tiff = 0;
Packit df99a1
# ifdef _WIN32
Packit df99a1
          if (_mktemp(tempfilename))
Packit df99a1
            tiff = TIFFOpen(tempfilename,"w");
Packit df99a1
# elif HAVE_MKSTEMP
Packit df99a1
          if ((tiffd = mkstemp(tempfilename)) >= 0)
Packit df99a1
            tiff = TIFFFdOpen(tiffd, tempfilename, "w");
Packit df99a1
# else
Packit df99a1
          if (mktemp(tempfilename))
Packit df99a1
            if ((tiffd = open(tempfilename, O_RDWR|O_CREAT)) >= 0)
Packit df99a1
              tiff = TIFFFdOpen(tiffd, tempfilename, "w");
Packit df99a1
# endif
Packit df99a1
          if (! tiff)
Packit df99a1
            die(i18n("Cannot create temporary TIFF file '%s'."), tempfilename);
Packit df99a1
        }
Packit df99a1
#else
Packit df99a1
      die(i18n("PDF output is not compiled"));
Packit df99a1
#endif
Packit df99a1
    } 
Packit df99a1
  else if (! fout) /* file output */
Packit df99a1
    {
Packit df99a1
      if (! strcmp(filename,"-")) {
Packit df99a1
        fout = stdout;
Packit df99a1
#if defined(__CYGWIN32__)
Packit df99a1
        setmode(fileno(fout), O_BINARY);
Packit df99a1
#elif defined(_WIN32)
Packit df99a1
        _setmode(_fileno(fout), _O_BINARY);
Packit df99a1
#endif
Packit df99a1
      } else if (! (fout = fopen(filename, "wb")))
Packit df99a1
        die(i18n("Cannot open output file '%s'."), filename);
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
closefile(int pageno)
Packit df99a1
{
Packit df99a1
  /* Do not close when generating a single file */
Packit df99a1
  if (pageno > 0 && ! flag_eachpage)
Packit df99a1
    return;
Packit df99a1
Packit df99a1
  /* Compute filename */
Packit df99a1
  const char *filename = outputfilename;
Packit df99a1
  if (flag_eachpage && pageno > 0)
Packit df99a1
    {
Packit df99a1
      sprintf(pagefilename, filename, pageno);
Packit df99a1
      filename = pagefilename;
Packit df99a1
    }
Packit df99a1
Packit df99a1
  /* Close temporary tiff and generate pdf */
Packit df99a1
#if HAVE_TIFF2PDF
Packit df99a1
  if (tiff && tempfilename)
Packit df99a1
    {
Packit df99a1
      const char *args[3];
Packit df99a1
      if (! TIFFFlush(tiff))
Packit df99a1
        die(i18n("Error while flushing TIFF file."));
Packit df99a1
      if (flag_verbose)
Packit df99a1
        fprintf(stderr,i18n("Converting temporary TIFF to PDF.\n"));
Packit df99a1
#ifndef _WIN32
Packit df99a1
      if (tiffd >= 0)
Packit df99a1
        {
Packit df99a1
          int fd = dup(tiffd);
Packit df99a1
          TIFFClose(tiff);
Packit df99a1
          close(tiffd);
Packit df99a1
          tiffd = fd;
Packit df99a1
          lseek(tiffd, 0, SEEK_SET);
Packit df99a1
          if (! (tiff = TIFFFdOpen(tiffd, tempfilename, "r")))
Packit df99a1
            die(i18n("Cannot reopen temporary TIFF file '%s'."), tempfilename);
Packit df99a1
        }
Packit df99a1
      else
Packit df99a1
#endif
Packit df99a1
        {
Packit df99a1
          TIFFClose(tiff);
Packit df99a1
          if (!(tiff = TIFFOpen(tempfilename, "r")))
Packit df99a1
            die(i18n("Cannot reopen temporary TIFF file '%s'."), tempfilename);
Packit df99a1
        }
Packit df99a1
      // Convert
Packit df99a1
      if (! (fout = fopen(filename, "wb")))
Packit df99a1
        die(i18n("Cannot open output file '%s'."), filename);
Packit df99a1
      args[0] = programname;
Packit df99a1
      args[1] = "-o";
Packit df99a1
      args[2] = filename;
Packit df99a1
      if (tiff2pdf(tiff, fout, 3, args) != EXIT_SUCCESS)
Packit df99a1
        die(i18n("Error occured while creating PDF file."));
Packit df99a1
      TIFFClose(tiff);
Packit df99a1
      tiff = 0;
Packit df99a1
#ifndef _WIN32
Packit df99a1
      close(tiffd);
Packit df99a1
      tiffd = -1;
Packit df99a1
#endif
Packit df99a1
      remove(tempfilename);
Packit df99a1
      free(tempfilename);
Packit df99a1
      tempfilename = 0;
Packit df99a1
    }
Packit df99a1
#endif
Packit df99a1
  /* Close tiff */
Packit df99a1
#if HAVE_TIFF
Packit df99a1
  if (tiff)
Packit df99a1
    {
Packit df99a1
      if (! TIFFFlush(tiff))
Packit df99a1
        die(i18n("Error while flushing tiff file."));
Packit df99a1
      TIFFClose(tiff);
Packit df99a1
      tiff = 0;
Packit df99a1
    }
Packit df99a1
#endif
Packit df99a1
  /* Close fout */
Packit df99a1
  if (fout)
Packit df99a1
    {
Packit df99a1
      if (fflush(fout) < 0)
Packit df99a1
        die(i18n("Error while flushing output file: %s"), strerror(errno));
Packit df99a1
      fclose(fout);
Packit df99a1
      fout = 0;
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
void
Packit df99a1
dopage(int pageno)
Packit df99a1
{
Packit df99a1
  ddjvu_page_t *page;
Packit df99a1
  /* Decode page */
Packit df99a1
  timingdata[0] = ticks();
Packit df99a1
  if (! (page = ddjvu_page_create_by_pageno(doc, pageno-1)))
Packit df99a1
    die(i18n("Cannot access page %d."), pageno);
Packit df99a1
  while (! ddjvu_page_decoding_done(page))
Packit df99a1
    handle(TRUE);
Packit df99a1
  if (ddjvu_page_decoding_error(page))
Packit df99a1
    {
Packit df99a1
      handle(FALSE);
Packit df99a1
      fprintf(stderr,"ddjvu: ");
Packit df99a1
      fprintf(stderr,i18n("Cannot decode page %d."), pageno);
Packit df99a1
      fprintf(stderr,"\n");
Packit df99a1
      if (flag_skipcorrupted)
Packit df99a1
        return;
Packit df99a1
      else
Packit df99a1
        exit(10);
Packit df99a1
    }
Packit df99a1
  timingdata[1] = ticks();
Packit df99a1
  /* Create filename */
Packit df99a1
  if (flag_eachpage)
Packit df99a1
    {
Packit df99a1
      
Packit df99a1
    }
Packit df99a1
Packit df99a1
Packit df99a1
  /* Render */
Packit df99a1
  openfile(pageno);
Packit df99a1
  inform(page, pageno);
Packit df99a1
  render(page, pageno);
Packit df99a1
  ddjvu_page_release(page);
Packit df99a1
  closefile(pageno);
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
void
Packit df99a1
parse_pagespec(const char *s, int max_page, void (*dopage)(int))
Packit df99a1
{
Packit df99a1
  static const char *err = 
Packit df99a1
    I18N("invalid page specification: %s");
Packit df99a1
  int spec = 0;
Packit df99a1
  int both = 1;
Packit df99a1
  int start_page = 1;
Packit df99a1
  int end_page = max_page;
Packit df99a1
  int pageno;
Packit df99a1
  char *p = (char*)s;
Packit df99a1
  while (*p)
Packit df99a1
    {
Packit df99a1
      spec = 0;
Packit df99a1
      while (*p==' ')
Packit df99a1
        p += 1;
Packit df99a1
      if (! *p)
Packit df99a1
        break;
Packit df99a1
      if (*p>='0' && *p<='9') {
Packit df99a1
        end_page = strtol(p, &p, 10);
Packit df99a1
        spec = 1;
Packit df99a1
      } else if (*p=='$') {
Packit df99a1
        spec = 1;
Packit df99a1
        end_page = max_page;
Packit df99a1
        p += 1;
Packit df99a1
      } else if (both) {
Packit df99a1
        end_page = 1;
Packit df99a1
      } else {
Packit df99a1
        end_page = max_page;
Packit df99a1
      }
Packit df99a1
      while (*p==' ')
Packit df99a1
        p += 1;
Packit df99a1
      if (both) {
Packit df99a1
        start_page = end_page;
Packit df99a1
        if (*p == '-') {
Packit df99a1
          p += 1;
Packit df99a1
          both = 0;
Packit df99a1
          continue;
Packit df99a1
        }
Packit df99a1
      }
Packit df99a1
      both = 1;
Packit df99a1
      while (*p==' ')
Packit df99a1
        p += 1;
Packit df99a1
      if (*p && *p != ',')
Packit df99a1
        die(i18n(err), s);
Packit df99a1
      if (*p == ',')
Packit df99a1
        p += 1;
Packit df99a1
      if (! spec)
Packit df99a1
        die(i18n(err), s);
Packit df99a1
      if (end_page <= 0)
Packit df99a1
        end_page = 1;
Packit df99a1
      if (start_page <= 0)
Packit df99a1
        start_page = 1;
Packit df99a1
      if (end_page > max_page)
Packit df99a1
        end_page = max_page;
Packit df99a1
      if (start_page > max_page)
Packit df99a1
        start_page = max_page;
Packit df99a1
      if (start_page <= end_page)
Packit df99a1
        for(pageno=start_page; pageno<=end_page; pageno++)
Packit df99a1
          (*dopage)(pageno);
Packit df99a1
      else
Packit df99a1
        for(pageno=start_page; pageno>=end_page; pageno--)
Packit df99a1
          (*dopage)(pageno);
Packit df99a1
    }
Packit df99a1
  if (! spec)
Packit df99a1
    die(i18n(err), s);
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
void
Packit df99a1
parse_geometry(const char *s, ddjvu_rect_t *r)
Packit df99a1
{
Packit df99a1
  static const char *fmt = 
Packit df99a1
    I18N("syntax error in geometry specification: %s");
Packit df99a1
  char *curptr = (char*) s;
Packit df99a1
  char *endptr;
Packit df99a1
Packit df99a1
  r->w = strtol(curptr, &endptr, 10);
Packit df99a1
  if (endptr<=curptr || r->w<=0 || *endptr!='x')
Packit df99a1
    die(i18n(fmt), s);
Packit df99a1
  curptr = endptr+1;
Packit df99a1
  r->h = strtol(curptr, &endptr, 10);
Packit df99a1
  if (endptr<=curptr || r->h<=0)
Packit df99a1
    die(i18n(fmt), s);
Packit df99a1
  curptr = endptr;
Packit df99a1
  r->x = 0;
Packit df99a1
  r->y = 0;
Packit df99a1
  if (curptr[0])
Packit df99a1
    {
Packit df99a1
      if (curptr[0]=='+')
Packit df99a1
        curptr++;
Packit df99a1
      else if (curptr[0]!='-')
Packit df99a1
        die(i18n(fmt), s);
Packit df99a1
      r->x = strtol(curptr, &endptr, 10);
Packit df99a1
      curptr = endptr;
Packit df99a1
      if (curptr[0])
Packit df99a1
        {
Packit df99a1
          if (curptr[0]=='+')
Packit df99a1
            curptr++;
Packit df99a1
          else if (curptr[0]!='-')
Packit df99a1
            die(i18n(fmt), s);
Packit df99a1
          r->y = strtol(curptr, &endptr, 10);
Packit df99a1
          if (endptr[0])
Packit df99a1
            die(i18n(fmt), s);
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
void
Packit df99a1
usage()
Packit df99a1
{
Packit df99a1
#ifdef DJVULIBRE_VERSION
Packit df99a1
  fprintf(stderr, "DDJVU --- DjVuLibre-" DJVULIBRE_VERSION "\n");
Packit df99a1
#endif
Packit df99a1
  fprintf(stderr, "%s",
Packit df99a1
    i18n("DjVu decompression utility\n\n"
Packit df99a1
         "Usage: ddjvu [options] [<djvufile> [<outputfile>]]\n\n"
Packit df99a1
         "Options:\n"
Packit df99a1
         "  -verbose          Print various informational messages.\n"
Packit df99a1
         "  -format=FMT       Select output format: pbm,pgm,ppm,pnm,rle,tiff.\n"
Packit df99a1
         "  -scale=N          Select display scale.\n"
Packit df99a1
         "  -size=WxH         Select size of rendered image.\n"
Packit df99a1
         "  -subsample=N      Select direct subsampling factor.\n"
Packit df99a1
         "  -aspect=no        Authorize aspect ratio changes\n"
Packit df99a1
         "  -segment=WxH+X+Y  Select which segment of the rendered image\n"
Packit df99a1
         "  -mode=black       Render a meaningful bitonal image.\n"
Packit df99a1
         "  -mode=mask        Only render the mask layer.\n"
Packit df99a1
         "  -mode=foreground  Only render the foreground layer.\n"
Packit df99a1
         "  -mode=background  Only render the background layer.\n"
Packit df99a1
         "  -page=PAGESPEC    Select page(s) to be decoded.\n"
Packit df99a1
         "  -skip             Skip corrupted pages instead of aborting.\n"
Packit df99a1
         "  -eachpage         Produce one file per page (using %d in outputfile).\n"
Packit df99a1
         "  -quality=QUALITY  Specify jpeg quality for lossy tiff output.\n"
Packit df99a1
         "\n"
Packit df99a1
         "If <outputfile> is a single dash or omitted, the decompressed image\n"
Packit df99a1
         "is sent to the standard output.  If <djvufile> is a single dash or\n"
Packit df99a1
         "omitted, the djvu file is read from the standard input.\n\n" ));
Packit df99a1
  exit(1);
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
int 
Packit df99a1
parse_option(int argc, char **argv, int i)
Packit df99a1
{
Packit df99a1
  static const char *errarg = 
Packit df99a1
    I18N("option '-%s' needs no argument.");
Packit df99a1
  static const char *errnoarg = 
Packit df99a1
    I18N("option '-%s' needs an argument.");
Packit df99a1
  static const char *errbadarg = 
Packit df99a1
    I18N("valid arguments for option '-%s' %s.");
Packit df99a1
  static const char *errdupl = 
Packit df99a1
    I18N("option '%s' specified multiple times.");
Packit df99a1
  static const char *errconfl = 
Packit df99a1
    I18N("option '%s' conflicts with another option.");
Packit df99a1
  
Packit df99a1
  char buf[32];
Packit df99a1
  const char *s = argv[i];
Packit df99a1
  const char *opt = s;
Packit df99a1
  const char *arg = strchr(opt, '=');
Packit df99a1
  char *end;
Packit df99a1
Packit df99a1
  /* Split argument */
Packit df99a1
  if (*opt == '-')
Packit df99a1
    opt += 1;
Packit df99a1
  if (*opt == '-')
Packit df99a1
    opt += 1;
Packit df99a1
  if (arg) {
Packit df99a1
    int l = arg - opt;
Packit df99a1
    if (l > (int)sizeof(buf) - 1)
Packit df99a1
      l = sizeof(buf) - 1;
Packit df99a1
    strncpy(buf, opt, l);
Packit df99a1
    buf[l] = 0;
Packit df99a1
    opt = buf;
Packit df99a1
    arg += 1;
Packit df99a1
  }
Packit df99a1
Packit df99a1
  /* Legacy options */
Packit df99a1
  if (!strcmp(opt, "black") ||
Packit df99a1
      !strcmp(opt, "foreground") ||              
Packit df99a1
      !strcmp(opt, "background") ) 
Packit df99a1
    {
Packit df99a1
      arg = opt;
Packit df99a1
      opt = "mode";
Packit df99a1
    } 
Packit df99a1
  else if (!strcmp(opt,"rle"))
Packit df99a1
    {
Packit df99a1
      arg = opt;
Packit df99a1
      opt = "format";
Packit df99a1
    }
Packit df99a1
  else if (!strcmp(opt,"segment") ||
Packit df99a1
           !strcmp(opt,"scale") ||
Packit df99a1
           !strcmp(opt,"size") ||
Packit df99a1
           !strcmp(opt,"page") ) 
Packit df99a1
    {
Packit df99a1
      if (!arg && i
Packit df99a1
        if (argv[i+1][0]>='0' && argv[i+1][0]<='9')
Packit df99a1
          arg = argv[++i];
Packit df99a1
    }
Packit df99a1
  else if (strtol(opt,&end,10) && !*end)
Packit df99a1
    {
Packit df99a1
      arg = opt;
Packit df99a1
      opt = "subsample";
Packit df99a1
    }
Packit df99a1
  /* Parse options */
Packit df99a1
  if (!strcmp(opt,"v") ||
Packit df99a1
      !strcmp(opt,"verbose"))
Packit df99a1
    {
Packit df99a1
      if (arg) 
Packit df99a1
        die(i18n(errarg), opt);
Packit df99a1
      flag_verbose = 1;
Packit df99a1
    }
Packit df99a1
  else if (!strcmp(opt,"skip"))
Packit df99a1
    {
Packit df99a1
      if (arg) 
Packit df99a1
        die(i18n(errarg), opt);
Packit df99a1
      flag_skipcorrupted = 1;
Packit df99a1
    }
Packit df99a1
  else if (! strcmp(opt,"eachpage"))
Packit df99a1
    {
Packit df99a1
      if (arg) 
Packit df99a1
        die(i18n(errarg), opt);
Packit df99a1
      flag_eachpage = 1;
Packit df99a1
    }
Packit df99a1
  else if (!strcmp(opt,"scale"))
Packit df99a1
    {
Packit df99a1
      if (!arg) 
Packit df99a1
        die(i18n(errnoarg), opt);
Packit df99a1
      if (flag_subsample>=0 || flag_scale>=0 || flag_size>=0)
Packit df99a1
        die(i18n(errconfl), s);
Packit df99a1
      flag_scale = strtol(arg, &end, 10);
Packit df99a1
      if (*end == '%')
Packit df99a1
        end++;
Packit df99a1
      if (*end || flag_scale<1 || flag_scale>999)
Packit df99a1
        die(i18n(errbadarg), opt, i18n("range from 1% to 999%"));
Packit df99a1
    }
Packit df99a1
  else if (!strcmp(opt,"aspect"))
Packit df99a1
    {
Packit df99a1
      if (flag_aspect >= 0)
Packit df99a1
        die(i18n(errdupl), opt);
Packit df99a1
      if (!arg || !strcmp(arg,"no"))
Packit df99a1
        flag_aspect = 1;
Packit df99a1
      else if (!strcmp(arg,"yes"))
Packit df99a1
        flag_aspect = 0;
Packit df99a1
      else
Packit df99a1
        die(i18n(errbadarg), opt, i18n("are 'yes' or 'no'"));
Packit df99a1
    }
Packit df99a1
  else if (!strcmp(opt,"size"))
Packit df99a1
    {
Packit df99a1
      if (!arg) 
Packit df99a1
        die(i18n(errnoarg), opt);
Packit df99a1
      if (flag_subsample>=0 || flag_scale>=0 || flag_size>=0)
Packit df99a1
        die(i18n(errconfl), s);
Packit df99a1
      parse_geometry(arg, &info_size);
Packit df99a1
      if (info_size.x || info_size.y)
Packit df99a1
        die(i18n(errbadarg), opt, i18n("have the form <width>x<height>"));
Packit df99a1
      flag_size = 1;
Packit df99a1
    }
Packit df99a1
  else if (!strcmp(opt,"subsample"))
Packit df99a1
    {
Packit df99a1
      if (!arg) 
Packit df99a1
        die(i18n(errnoarg), opt);
Packit df99a1
      if (flag_subsample>=0 || flag_scale>=0 || flag_size>=0)
Packit df99a1
        die(i18n(errconfl), s);
Packit df99a1
      flag_subsample = strtol(arg, &end, 10);
Packit df99a1
      if (*end || flag_subsample<1)
Packit df99a1
        die(i18n(errbadarg),opt,i18n("are positive integers"));
Packit df99a1
    }
Packit df99a1
  else if (!strcmp(opt,"segment"))
Packit df99a1
    {
Packit df99a1
      if (!arg) 
Packit df99a1
        die(i18n(errnoarg), opt);
Packit df99a1
      if (flag_segment)
Packit df99a1
        die(i18n(errdupl), opt);
Packit df99a1
      parse_geometry(arg, &info_segment);
Packit df99a1
      flag_segment = 1;
Packit df99a1
    }
Packit df99a1
  else if (!strcmp(opt,"format"))
Packit df99a1
    {
Packit df99a1
      if (!arg) 
Packit df99a1
        die(i18n(errnoarg), opt);
Packit df99a1
      if (flag_format)
Packit df99a1
        die(i18n(errdupl), opt);
Packit df99a1
      if (!strcmp(arg,"pbm"))
Packit df99a1
        flag_format='4';
Packit df99a1
      else if (!strcmp(arg,"pgm"))
Packit df99a1
        flag_format='5';
Packit df99a1
      else if (!strcmp(arg,"ppm"))
Packit df99a1
        flag_format='6';
Packit df99a1
      else if (!strcmp(arg,"pnm"))
Packit df99a1
        flag_format='p';
Packit df99a1
      else if (!strcmp(arg,"rle"))
Packit df99a1
        flag_format='r';
Packit df99a1
      else if (!strcmp(arg,"tiff") || !strcmp(arg,"tif"))
Packit df99a1
        flag_format='t';
Packit df99a1
      else if (!strcmp(arg,"pdf"))
Packit df99a1
        flag_format='f';
Packit df99a1
      else
Packit df99a1
        die(i18n(errbadarg),opt,i18n("are: pbm,pgm,ppm,pnm,rle,tiff,pdf"));
Packit df99a1
    }
Packit df99a1
  else if (!strcmp(opt,"mode"))
Packit df99a1
    {
Packit df99a1
      if (!arg) 
Packit df99a1
        die(i18n(errnoarg), opt);
Packit df99a1
      if (flag_mode)
Packit df99a1
        die(i18n(errdupl), opt);
Packit df99a1
      if (!strcmp(arg,"color") )
Packit df99a1
        flag_mode = 'c';
Packit df99a1
      else if (!strcmp(arg,"black"))
Packit df99a1
        flag_mode = 'k';
Packit df99a1
      else if (!strcmp(arg,"mask") || !strcmp(arg,"stencil"))
Packit df99a1
        flag_mode = 's';
Packit df99a1
      else if (!strcmp(arg,"foreground") || !strcmp(arg,"fg"))
Packit df99a1
        flag_mode = 'f';
Packit df99a1
      else if (!strcmp(arg,"background") || !strcmp(arg,"bg"))
Packit df99a1
        flag_mode = 'b';
Packit df99a1
      else
Packit df99a1
        die(i18n(errbadarg),opt,i18n("are: color,black,mask,fg,bg"));
Packit df99a1
    }
Packit df99a1
  else if (! strcmp(opt, "page") ||
Packit df99a1
           ! strcmp(opt, "pages") )
Packit df99a1
    {
Packit df99a1
      if (!arg) 
Packit df99a1
        die(i18n(errnoarg), opt);
Packit df99a1
      if (flag_pagespec)
Packit df99a1
        die(i18n(errdupl), opt);
Packit df99a1
      flag_pagespec = arg;
Packit df99a1
    }
Packit df99a1
  else if (!strcmp(opt,"quality") ||
Packit df99a1
           !strcmp(opt,"jpeg") )
Packit df99a1
    {
Packit df99a1
      if (flag_quality >= 0)
Packit df99a1
        die(i18n(errdupl), opt);
Packit df99a1
      else if (!arg) 
Packit df99a1
        flag_quality = 100;
Packit df99a1
      else if (!strcmp(arg,"deflate") || !strcmp(arg,"zip"))
Packit df99a1
        flag_quality = 900;
Packit df99a1
      else if (!strcmp(arg,"lzw"))
Packit df99a1
        flag_quality = 901;
Packit df99a1
      else if (!strcmp(arg,"uncompressed") || !strcmp(arg,"raw"))
Packit df99a1
        flag_quality = 1000;
Packit df99a1
      else
Packit df99a1
        {
Packit df99a1
          flag_quality = strtol(arg,&end,10);
Packit df99a1
          if (*end || flag_quality<25 || flag_quality>150)
Packit df99a1
            die(i18n(errbadarg),opt,i18n("an integer between 25 and 150"));
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
  else if (! strcmp(opt, "help"))
Packit df99a1
    {
Packit df99a1
      usage();
Packit df99a1
    }
Packit df99a1
  else
Packit df99a1
    {
Packit df99a1
      die(i18n("Invalid option '%s'. Try 'ddjvu --help'."), s);
Packit df99a1
    }
Packit df99a1
  return i;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
int
Packit df99a1
check_eachpage(const char *s)
Packit df99a1
{
Packit df99a1
  const char *p = s;
Packit df99a1
  int hasd = 0;
Packit df99a1
  int size = 0;
Packit df99a1
  char c;
Packit df99a1
  while ((c = *s++))
Packit df99a1
    if (c == '%')
Packit df99a1
      {
Packit df99a1
        c = *s++;
Packit df99a1
        if (c == '%')
Packit df99a1
          continue;
Packit df99a1
        if (hasd)
Packit df99a1
          return 0;
Packit df99a1
        if (c == '-' || c == '+' || c == ' ')
Packit df99a1
          c = *s++;
Packit df99a1
        while (c >= '0' && c <= '9')
Packit df99a1
          {
Packit df99a1
            size = 10 * size + c - '0';
Packit df99a1
            c = *s++;
Packit df99a1
          }
Packit df99a1
        if (c != 'd')
Packit df99a1
          return 0;
Packit df99a1
        hasd = 1;
Packit df99a1
      }
Packit df99a1
  if (size == 0)
Packit df99a1
    size = 30;
Packit df99a1
  if (hasd == 1 && size>0 && size<1000)
Packit df99a1
    return size + s - p;
Packit df99a1
  return 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
int
Packit df99a1
main(int argc, char **argv)
Packit df99a1
{
Packit df99a1
  int i;
Packit df99a1
#if defined(_WIN32) && !defined(__CYGWIN32__)
Packit df99a1
  _setmbcp(_MB_CP_OEM);
Packit df99a1
#endif
Packit df99a1
  /* Parse options */
Packit df99a1
  for (i=1; i
Packit df99a1
    {
Packit df99a1
      char *s = argv[i];
Packit df99a1
      if (s[0] == '-' && s[1] != 0)
Packit df99a1
        i = parse_option(argc, argv, i);
Packit df99a1
      else if (!inputfilename)
Packit df99a1
        inputfilename = s;
Packit df99a1
      else if (! outputfilename)
Packit df99a1
        outputfilename = s;
Packit df99a1
      else
Packit df99a1
        usage();
Packit df99a1
    }
Packit df99a1
Packit df99a1
  /* Defaults */
Packit df99a1
  if (! inputfilename)
Packit df99a1
    inputfilename = "-";
Packit df99a1
  if (! outputfilename)
Packit df99a1
    outputfilename = "-";
Packit df99a1
  if (! flag_pagespec)
Packit df99a1
    flag_pagespec = (flag_format) ? "1-$" : "1";
Packit df99a1
  if (flag_eachpage)
Packit df99a1
    {
Packit df99a1
      int sz = check_eachpage(outputfilename);
Packit df99a1
      if (! sz)
Packit df99a1
        die(i18n("Flag -eachpage demands a '%%d' specification in the output file name."));
Packit df99a1
      pagefilename = (char*)malloc(sz);
Packit df99a1
      if (! pagefilename)
Packit df99a1
        die(i18n("Out of memory"));
Packit df99a1
    }
Packit df99a1
  
Packit df99a1
  /* Create context and document */
Packit df99a1
  programname = argv[0];
Packit df99a1
  if (! (ctx = ddjvu_context_create(programname)))
Packit df99a1
    die(i18n("Cannot create djvu context."));
Packit df99a1
  if (! (doc = ddjvu_document_create_by_filename(ctx, inputfilename, TRUE)))
Packit df99a1
    die(i18n("Cannot open djvu document '%s'."), inputfilename);
Packit df99a1
  while (! ddjvu_document_decoding_done(doc))
Packit df99a1
    handle(TRUE);
Packit df99a1
  if (ddjvu_document_decoding_error(doc))
Packit df99a1
    die(i18n("Cannot decode document."));
Packit df99a1
  
Packit df99a1
  /* Process all pages */
Packit df99a1
  i = ddjvu_document_get_pagenum(doc);
Packit df99a1
  parse_pagespec(flag_pagespec, i, dopage);
Packit df99a1
Packit df99a1
  /* Close output file */
Packit df99a1
  closefile(0);
Packit df99a1
Packit df99a1
  /* Release */
Packit df99a1
  if (doc)
Packit df99a1
    ddjvu_document_release(doc);
Packit df99a1
  if (ctx)
Packit df99a1
    ddjvu_context_release(ctx);
Packit df99a1
  return 0;
Packit df99a1
}