|
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 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
df99a1 |
# include "config.h"
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
#if NEED_GNUG_PRAGMAS
|
|
Packit |
df99a1 |
# pragma implementation
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/** @name c44
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
{\bf Synopsis}\\
|
|
Packit |
df99a1 |
\begin{verbatim}
|
|
Packit |
df99a1 |
c44 [options] pnmfile [djvufile]
|
|
Packit |
df99a1 |
c44 [options] jpegfile [djvufile]
|
|
Packit |
df99a1 |
\end{verbatim}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
{\bf Description} ---
|
|
Packit |
df99a1 |
File #"c44.cpp"# illustrates the use of classes \Ref{IWBitmap} and
|
|
Packit |
df99a1 |
\Ref{IWPixmap} for compressing and encoding a color image or a gray level
|
|
Packit |
df99a1 |
image using the DjVu IW44 wavelets. This is the preferred mode for
|
|
Packit |
df99a1 |
creating a DjVu image which does not require separate layers for encoding
|
|
Packit |
df99a1 |
the text and the background images. The files created by #c44# are
|
|
Packit |
df99a1 |
legal Photo DjVu files recognized by the DjVu decoder (see program \Ref{ddjvu}).
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
{\bf Arguments} ---
|
|
Packit |
df99a1 |
Argument #pnmfile# or #jpegfile# is the name of the input file. PGM files
|
|
Packit |
df99a1 |
are recognized for gray level images; PPM files are recognized for color
|
|
Packit |
df99a1 |
images. Popular file formats can be converted to PGM or PPM using the
|
|
Packit |
df99a1 |
NetPBM package (\URL{http://www.arc.umn.edu/GVL/Software/netpbm.html})
|
|
Packit |
df99a1 |
or the ImageMagick package (\URL{http://www.wizards.dupont.com/cristy/}).
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
Optional argument #djvufile# is the name of the output file. It is
|
|
Packit |
df99a1 |
customary to use either suffix #".djvu"#, #".djv"#, #".iw44"# or #".iw4"#.
|
|
Packit |
df99a1 |
Suffix #".djvu"# emphasizes the fact that IW44 files is seamlessly
|
|
Packit |
df99a1 |
recognized by the current DjVu decoder. Suffix #".iw4"# however was
|
|
Packit |
df99a1 |
required by older versions of the DjVu plugin. If this argument is
|
|
Packit |
df99a1 |
omitted, a filename is generated by replacing the suffix of #pnmfile#
|
|
Packit |
df99a1 |
or #jpegfile# with suffix #".djvu"#.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
{\bf Quality Specification}---
|
|
Packit |
df99a1 |
Files produced by the DjVu IW44 Wavelet Encoder are IFF files composed of
|
|
Packit |
df99a1 |
an arbitrary number of chunks (see \Ref{showiff} and \Ref{IWImage.h})
|
|
Packit |
df99a1 |
containing successive refinements of the encoded image. Each chunk is
|
|
Packit |
df99a1 |
composed of several slices. A typical file contains a total of 100 slices
|
|
Packit |
df99a1 |
split between three or four chunks. Various options provide quality
|
|
Packit |
df99a1 |
targets (#-decibel#), slicing targets (#-slice#) or file size targets
|
|
Packit |
df99a1 |
(#-bpp# or #-size#) for each of these refinements. Chunks are generated
|
|
Packit |
df99a1 |
until meeting either the decibel target, the file size target, or the
|
|
Packit |
df99a1 |
slicing target for each chunk.
|
|
Packit |
df99a1 |
\begin{description}
|
|
Packit |
df99a1 |
\item[-bpp n,..,n]
|
|
Packit |
df99a1 |
Selects a increasing sequence of bitrates for building
|
|
Packit |
df99a1 |
progressive IW44 file (in bits per pixel).
|
|
Packit |
df99a1 |
\item[-size n,..,n]
|
|
Packit |
df99a1 |
Selects a increasing sequence of minimal sizes for building
|
|
Packit |
df99a1 |
progressive IW44 file (in bytes).
|
|
Packit |
df99a1 |
\item[-decibel n,..,n]
|
|
Packit |
df99a1 |
Selects an increasing sequence of luminance error expressed as decibels
|
|
Packit |
df99a1 |
ranging from 16 (very low quality) to 48 (very high quality). This
|
|
Packit |
df99a1 |
criterion should not be used when recoding an image which was already
|
|
Packit |
df99a1 |
compressed with a lossy compression scheme (such as Wavelets or JPEG)
|
|
Packit |
df99a1 |
because successive losses of quality accumulate.
|
|
Packit |
df99a1 |
\item[-slice n+...+n]
|
|
Packit |
df99a1 |
Selects an increasing sequence of data slices expressed as integers
|
|
Packit |
df99a1 |
ranging from 1 to 140.
|
|
Packit |
df99a1 |
\end{description}
|
|
Packit |
df99a1 |
These options take a target specification list expressed either as a comma
|
|
Packit |
df99a1 |
separated list of increasing numbers or as a list of numbers separated by
|
|
Packit |
df99a1 |
character #'+'#. Both commands below for instance are equivalent:
|
|
Packit |
df99a1 |
\begin{verbatim}
|
|
Packit |
df99a1 |
c44 -bpp 0.1,0.2,0.5 inputfile.ppm outputfile.djvu
|
|
Packit |
df99a1 |
c44 -bpp 0.1+0.1+0.3 inputfile.ppm outputfile.djvu
|
|
Packit |
df99a1 |
\end{verbatim}
|
|
Packit |
df99a1 |
Both these commands generate a file whose first chunk encodes the image
|
|
Packit |
df99a1 |
with 0.1 bits per pixel, whose second chunk refines the image to 0.2 bits
|
|
Packit |
df99a1 |
per pixel and whose third chunk refines the image to 0.5 bits per pixel.
|
|
Packit |
df99a1 |
In other words, the second chunk provides an extra 0.1 bits per pixel and
|
|
Packit |
df99a1 |
the third chunk provides an extra 0.3 bits per pixels.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
When no quality specification is provided, program #c44# usually generates
|
|
Packit |
df99a1 |
a file composed of three progressive refinement chunks whose quality
|
|
Packit |
df99a1 |
should be acceptable. The best results however are achieved by precisely
|
|
Packit |
df99a1 |
tuning the image quality. As a rule of thumb, #c44# generates an
|
|
Packit |
df99a1 |
acceptable quality when you specify a size equal to 50% to 75% of the size
|
|
Packit |
df99a1 |
of a comparable JPEG image.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
{\bf Color Processing Specification} ---
|
|
Packit |
df99a1 |
Five options control the encoding of the chrominance information of color
|
|
Packit |
df99a1 |
images. These options are of course meaningless for processing a gray
|
|
Packit |
df99a1 |
level image.
|
|
Packit |
df99a1 |
\begin{description}
|
|
Packit |
df99a1 |
\item[-crcbnormal]
|
|
Packit |
df99a1 |
Selects normal chrominance encoding (default). Chrominance information is
|
|
Packit |
df99a1 |
encoded at the same resolution as the luminance.
|
|
Packit |
df99a1 |
\item[-crcbhalf]
|
|
Packit |
df99a1 |
Selects half resolution chrominance encoding. Chrominance information is
|
|
Packit |
df99a1 |
encoded at half the luminance resolution.
|
|
Packit |
df99a1 |
\item[-crcbdelay n]
|
|
Packit |
df99a1 |
This option can be used with #-crcbnormal# and #-crcbhalf# for specifying
|
|
Packit |
df99a1 |
an encoding delay which reduces the bitrate associated with the chrominance. The
|
|
Packit |
df99a1 |
default chrominance encoding delay is 10 slices.
|
|
Packit |
df99a1 |
\item[-crcbfull]
|
|
Packit |
df99a1 |
Selects the highest possible quality for encoding the chrominance information. This
|
|
Packit |
df99a1 |
is equivalent to specifying #-crcbnormal# and #-crcbdelay 0#.
|
|
Packit |
df99a1 |
\item[-crcbnone]
|
|
Packit |
df99a1 |
Disables encoding of the chrominance. Only the luminance information will
|
|
Packit |
df99a1 |
be encoded. The resulting image will show in shades of gray.
|
|
Packit |
df99a1 |
\end{description}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
{\bf Advanced Options} ---
|
|
Packit |
df99a1 |
Program #c44# also recognizes the following options:
|
|
Packit |
df99a1 |
\begin{description}
|
|
Packit |
df99a1 |
\item[-dbfrac f]
|
|
Packit |
df99a1 |
This option alters the meaning of the -decibel option. The decibel target then
|
|
Packit |
df99a1 |
addresses only the average error of the specified fraction of the most
|
|
Packit |
df99a1 |
misrepresented 32x32 pixel blocks.
|
|
Packit |
df99a1 |
\item[-mask pbmfile]
|
|
Packit |
df99a1 |
This option can be used when we know that certain pixels of a background
|
|
Packit |
df99a1 |
image are going to be covered by foreground objects like text or drawings.
|
|
Packit |
df99a1 |
File #pbmfile# must be a PBM file whose size matches the size of the input
|
|
Packit |
df99a1 |
file. Each black pixel in #pbmfile# means that the value of the corresponding
|
|
Packit |
df99a1 |
pixel in the input file is irrelevant. The DjVu IW44 Encoder will replace
|
|
Packit |
df99a1 |
the masked pixels by a color value whose coding cost is minimal (see
|
|
Packit |
df99a1 |
\URL{http://www.research.att.com/~leonb/DJVU/mask}).
|
|
Packit |
df99a1 |
\end{description}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
{\bf Photo DjVu options} ---
|
|
Packit |
df99a1 |
Photo DjVu images have the additional capability to store the resolution
|
|
Packit |
df99a1 |
and gamma correction information.
|
|
Packit |
df99a1 |
\begin{description}
|
|
Packit |
df99a1 |
\item[-dpi n] Sets the resolution information for a Photo DjVu image.
|
|
Packit |
df99a1 |
\item[-gamma n] Sets the gamma correction information for a Photo DjVu image.
|
|
Packit |
df99a1 |
\end{description}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
{\bf Performance} ---
|
|
Packit |
df99a1 |
The main design objective for the DjVu wavelets consisted of allowing
|
|
Packit |
df99a1 |
progressive rendering and smooth scrolling of large images with limited
|
|
Packit |
df99a1 |
memory requirements. Decoding functions process the compressed data and
|
|
Packit |
df99a1 |
update a memory efficient representation of the wavelet coefficients.
|
|
Packit |
df99a1 |
Imaging function then can quickly render an arbitrary segment of the image
|
|
Packit |
df99a1 |
using the available data. Both process can be carried out in two threads
|
|
Packit |
df99a1 |
of execution. This design plays an important role in the DjVu system.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
We have investigated various state-of-the-art wavelet compression schemes:
|
|
Packit |
df99a1 |
although these schemes may achieve slightly smaller file sizes, the
|
|
Packit |
df99a1 |
decoding functions did not even approach our requirements. The IW44
|
|
Packit |
df99a1 |
wavelets reach these requirements today and may in the future implement
|
|
Packit |
df99a1 |
more modern refinements (such as trellis quantization, bitrate
|
|
Packit |
df99a1 |
allocation, etc.) if (and only if) these refinements can be implemented
|
|
Packit |
df99a1 |
within our constraints.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
@memo
|
|
Packit |
df99a1 |
DjVu IW44 wavelet encoder.
|
|
Packit |
df99a1 |
@author
|
|
Packit |
df99a1 |
L\'eon Bottou <leonb@research.att.com>
|
|
Packit |
df99a1 |
*/
|
|
Packit |
df99a1 |
//@{
|
|
Packit |
df99a1 |
//@}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#include "GString.h"
|
|
Packit |
df99a1 |
#include "GException.h"
|
|
Packit |
df99a1 |
#include "IW44Image.h"
|
|
Packit |
df99a1 |
#include "DjVuInfo.h"
|
|
Packit |
df99a1 |
#include "IFFByteStream.h"
|
|
Packit |
df99a1 |
#include "GOS.h"
|
|
Packit |
df99a1 |
#include "GBitmap.h"
|
|
Packit |
df99a1 |
#include "GPixmap.h"
|
|
Packit |
df99a1 |
#include "GURL.h"
|
|
Packit |
df99a1 |
#include "DjVuMessage.h"
|
|
Packit |
df99a1 |
#include "JPEGDecoder.h"
|
|
Packit |
df99a1 |
#include "common.h"
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
// command line data
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
int flag_mask = 0;
|
|
Packit |
df99a1 |
int flag_bpp = 0;
|
|
Packit |
df99a1 |
int flag_size = 0;
|
|
Packit |
df99a1 |
int flag_percent = 0;
|
|
Packit |
df99a1 |
int flag_slice = 0;
|
|
Packit |
df99a1 |
int flag_decibel = 0;
|
|
Packit |
df99a1 |
int flag_crcbdelay = -1;
|
|
Packit |
df99a1 |
int flag_crcbmode = -1;
|
|
Packit |
df99a1 |
double flag_dbfrac = -1;
|
|
Packit |
df99a1 |
int flag_dpi = -1;
|
|
Packit |
df99a1 |
double flag_gamma = -1;
|
|
Packit |
df99a1 |
int argc_bpp = 0;
|
|
Packit |
df99a1 |
int argc_size = 0;
|
|
Packit |
df99a1 |
int argc_slice = 0;
|
|
Packit |
df99a1 |
int argc_decibel = 0;
|
|
Packit |
df99a1 |
IW44Image::CRCBMode arg_crcbmode = IW44Image::CRCBnormal;
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#define MAXCHUNKS 64
|
|
Packit |
df99a1 |
float argv_bpp[MAXCHUNKS];
|
|
Packit |
df99a1 |
int argv_size[MAXCHUNKS];
|
|
Packit |
df99a1 |
int argv_slice[MAXCHUNKS];
|
|
Packit |
df99a1 |
float argv_decibel[MAXCHUNKS];
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
struct C44Global
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
// Globals that need static initialization
|
|
Packit |
df99a1 |
// are grouped here to work around broken compilers.
|
|
Packit |
df99a1 |
GURL pnmurl;
|
|
Packit |
df99a1 |
GURL iw4url;
|
|
Packit |
df99a1 |
GURL mskurl;
|
|
Packit |
df99a1 |
IWEncoderParms parms[MAXCHUNKS];
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static C44Global& g(void)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
static C44Global g;
|
|
Packit |
df99a1 |
return g;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
// parse arguments
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
usage()
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
DjVuPrintErrorUTF8(
|
|
Packit |
df99a1 |
#ifdef DJVULIBRE_VERSION
|
|
Packit |
df99a1 |
"C44 --- DjVuLibre-" DJVULIBRE_VERSION "\n"
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
"Image compression utility using IW44 wavelets\n\n"
|
|
Packit |
df99a1 |
"Usage: c44 [options] pnm-or-jpeg-file [djvufile]\n"
|
|
Packit |
df99a1 |
"Options:\n"
|
|
Packit |
df99a1 |
" -slice n+...+n -- select an increasing sequence of data slices\n"
|
|
Packit |
df99a1 |
" expressed as integers ranging from 1 to 140.\n"
|
|
Packit |
df99a1 |
" -bpp n,..,n -- select a increasing sequence of bitrates\n"
|
|
Packit |
df99a1 |
" for building progressive file (in bits per pixel).\n"
|
|
Packit |
df99a1 |
" -size n,..,n -- select an increasing sequence of minimal sizes\n"
|
|
Packit |
df99a1 |
" for building progressive files (expressed in bytes).\n"
|
|
Packit |
df99a1 |
" -percent n,..,n -- selects the percentage of original file size\n"
|
|
Packit |
df99a1 |
" for building progressive file.\n"
|
|
Packit |
df99a1 |
" -decibel n,..,n -- select an increasing sequence of luminance error\n"
|
|
Packit |
df99a1 |
" expressed as decibels (ranging from 16 to 50).\n"
|
|
Packit |
df99a1 |
" -dbfrac frac -- restrict decibel estimation to a fraction of\n"
|
|
Packit |
df99a1 |
" the most misrepresented 32x32 blocks\n"
|
|
Packit |
df99a1 |
" -mask pbmfile -- select bitmask specifying image zone to encode\n"
|
|
Packit |
df99a1 |
" with minimal bitrate. (default none)\n"
|
|
Packit |
df99a1 |
" -dpi n -- sets the image resolution\n"
|
|
Packit |
df99a1 |
" -gamma n -- sets the image gamma correction\n"
|
|
Packit |
df99a1 |
" -crcbfull -- encode chrominance with highest quality\n"
|
|
Packit |
df99a1 |
" -crcbnormal -- encode chrominance with normal resolution (default)\n"
|
|
Packit |
df99a1 |
" -crcbhalf -- encode chrominance with half resolution\n"
|
|
Packit |
df99a1 |
" -crcbnone -- do not encode chrominance at all\n"
|
|
Packit |
df99a1 |
" -crcbdelay n -- select chrominance coding delay (default 10)\n"
|
|
Packit |
df99a1 |
" for -crcbnormal and -crcbhalf modes\n"
|
|
Packit |
df99a1 |
"\n");
|
|
Packit |
df99a1 |
exit(1);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
parse_bpp(const char *q)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
flag_bpp = 1;
|
|
Packit |
df99a1 |
argc_bpp = 0;
|
|
Packit |
df99a1 |
double lastx = 0;
|
|
Packit |
df99a1 |
while (*q)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
char *ptr;
|
|
Packit |
df99a1 |
double x = strtod(q, &ptr);
|
|
Packit |
df99a1 |
if (ptr == q)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.bitrate_not_number") );
|
|
Packit |
df99a1 |
if (lastx>0 && q[-1]=='+')
|
|
Packit |
df99a1 |
x += lastx;
|
|
Packit |
df99a1 |
if (x<=0 || x>24 || x
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.bitrate_out_of_range") );
|
|
Packit |
df99a1 |
lastx = x;
|
|
Packit |
df99a1 |
if (*ptr && *ptr!='+' && *ptr!=',')
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.bitrate_comma_expected") );
|
|
Packit |
df99a1 |
q = (*ptr ? ptr+1 : ptr);
|
|
Packit |
df99a1 |
argv_bpp[argc_bpp++] = (float)x;
|
|
Packit |
df99a1 |
if (argc_bpp>MAXCHUNKS)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.bitrate_too_many") );
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
if (argc_bpp < 1)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.bitrate_no_chunks") );
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
parse_size(const char *q)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
flag_size = 1;
|
|
Packit |
df99a1 |
argc_size = 0;
|
|
Packit |
df99a1 |
int lastx = 0;
|
|
Packit |
df99a1 |
while (*q)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
char *ptr;
|
|
Packit |
df99a1 |
int x = strtol(q, &ptr, 10);
|
|
Packit |
df99a1 |
if (ptr == q)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.size_not_number") );
|
|
Packit |
df99a1 |
if (lastx>0 && q[-1]=='+')
|
|
Packit |
df99a1 |
x += lastx;
|
|
Packit |
df99a1 |
if (x
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.size_out_of_range") );
|
|
Packit |
df99a1 |
lastx = x;
|
|
Packit |
df99a1 |
if (*ptr && *ptr!='+' && *ptr!=',')
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.size_comma_expected") );
|
|
Packit |
df99a1 |
q = (*ptr ? ptr+1 : ptr);
|
|
Packit |
df99a1 |
argv_size[argc_size++] = x;
|
|
Packit |
df99a1 |
if (argc_size>=MAXCHUNKS)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.size_too_many") );
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
if (argc_size < 1)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.size_no_chunks") );
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
parse_slice(const char *q)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
flag_slice = 1;
|
|
Packit |
df99a1 |
argc_slice = 0;
|
|
Packit |
df99a1 |
int lastx = 0;
|
|
Packit |
df99a1 |
while (*q)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
char *ptr;
|
|
Packit |
df99a1 |
int x = strtol(q, &ptr, 10);
|
|
Packit |
df99a1 |
if (ptr == q)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.slice_not_number") );
|
|
Packit |
df99a1 |
if (lastx>0 && q[-1]=='+')
|
|
Packit |
df99a1 |
x += lastx;
|
|
Packit |
df99a1 |
if (x<1 || x>1000 || x
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.slice_out_of_range") );
|
|
Packit |
df99a1 |
lastx = x;
|
|
Packit |
df99a1 |
if (*ptr && *ptr!='+' && *ptr!=',')
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.slice_comma_expected") );
|
|
Packit |
df99a1 |
q = (*ptr ? ptr+1 : ptr);
|
|
Packit |
df99a1 |
argv_slice[argc_slice++] = x;
|
|
Packit |
df99a1 |
if (argc_slice>=MAXCHUNKS)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.slice_too_many") );
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
if (argc_slice < 1)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.slice_no_chunks") );
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
parse_decibel(const char *q)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
flag_decibel = 1;
|
|
Packit |
df99a1 |
argc_decibel = 0;
|
|
Packit |
df99a1 |
double lastx = 0;
|
|
Packit |
df99a1 |
while (*q)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
char *ptr;
|
|
Packit |
df99a1 |
double x = strtod(q, &ptr);
|
|
Packit |
df99a1 |
if (ptr == q)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.decibel_not_number") );
|
|
Packit |
df99a1 |
if (lastx>0 && q[-1]=='+')
|
|
Packit |
df99a1 |
x += lastx;
|
|
Packit |
df99a1 |
if (x<16 || x>50 || x
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.decibel_out_of_range") );
|
|
Packit |
df99a1 |
lastx = x;
|
|
Packit |
df99a1 |
if (*ptr && *ptr!='+' && *ptr!=',')
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.decibel_comma_expected") );
|
|
Packit |
df99a1 |
q = (*ptr ? ptr+1 : ptr);
|
|
Packit |
df99a1 |
argv_decibel[argc_decibel++] = (float)x;
|
|
Packit |
df99a1 |
if (argc_decibel>=MAXCHUNKS)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.decibel_too_many") );
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
if (argc_decibel < 1)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.decibel_no_chunks") );
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
int
|
|
Packit |
df99a1 |
resolve_quality(int npix)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
// Convert ratio specification into size specification
|
|
Packit |
df99a1 |
if (flag_bpp)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (flag_size)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.exclusive") );
|
|
Packit |
df99a1 |
flag_size = flag_bpp;
|
|
Packit |
df99a1 |
argc_size = argc_bpp;
|
|
Packit |
df99a1 |
for (int i=0; i
|
|
Packit |
df99a1 |
argv_size[i] = (int)(npix*argv_bpp[i]/8.0+0.5);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
// Compute number of chunks
|
|
Packit |
df99a1 |
int nchunk = 0;
|
|
Packit |
df99a1 |
if (flag_slice && nchunk
|
|
Packit |
df99a1 |
nchunk = argc_slice;
|
|
Packit |
df99a1 |
if (flag_size && nchunk
|
|
Packit |
df99a1 |
nchunk = argc_size;
|
|
Packit |
df99a1 |
if (flag_decibel && nchunk
|
|
Packit |
df99a1 |
nchunk = argc_decibel;
|
|
Packit |
df99a1 |
// Force default values
|
|
Packit |
df99a1 |
if (nchunk == 0)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
#ifdef DECIBELS_25_30_34
|
|
Packit |
df99a1 |
nchunk = 3;
|
|
Packit |
df99a1 |
flag_decibel = 1;
|
|
Packit |
df99a1 |
argc_decibel = 3;
|
|
Packit |
df99a1 |
argv_decibel[0]=25;
|
|
Packit |
df99a1 |
argv_decibel[1]=30;
|
|
Packit |
df99a1 |
argv_decibel[2]=34;
|
|
Packit |
df99a1 |
#else
|
|
Packit |
df99a1 |
nchunk = 3;
|
|
Packit |
df99a1 |
flag_slice = 1;
|
|
Packit |
df99a1 |
argc_slice = 3;
|
|
Packit |
df99a1 |
argv_slice[0]=74;
|
|
Packit |
df99a1 |
argv_slice[1]=89;
|
|
Packit |
df99a1 |
argv_slice[2]=99;
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
// Complete short specifications
|
|
Packit |
df99a1 |
while (argc_size < nchunk)
|
|
Packit |
df99a1 |
argv_size[argc_size++] = 0;
|
|
Packit |
df99a1 |
while (argc_slice < nchunk)
|
|
Packit |
df99a1 |
argv_slice[argc_slice++] = 0;
|
|
Packit |
df99a1 |
while (argc_decibel < nchunk)
|
|
Packit |
df99a1 |
argv_decibel[argc_decibel++] = 0.0;
|
|
Packit |
df99a1 |
// Fill parm structure
|
|
Packit |
df99a1 |
for(int i=0; i
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
g().parms[i].bytes = argv_size[i];
|
|
Packit |
df99a1 |
g().parms[i].slices = argv_slice[i];
|
|
Packit |
df99a1 |
g().parms[i].decibels = argv_decibel[i];
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
// Return number of chunks
|
|
Packit |
df99a1 |
return nchunk;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
parse(GArray<GUTF8String> &argv)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
const int argc=argv.hbound()+1;
|
|
Packit |
df99a1 |
for (int i=1; i
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (argv[i][0] == '-')
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (argv[i] == "-percent")
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (++i >= argc)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.no_bpp_arg") );
|
|
Packit |
df99a1 |
if (flag_bpp || flag_size)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.multiple_bitrate") );
|
|
Packit |
df99a1 |
parse_size(argv[i]);
|
|
Packit |
df99a1 |
flag_percent = 1;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else if (argv[i] == "-bpp")
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (++i >= argc)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.no_bpp_arg") );
|
|
Packit |
df99a1 |
if (flag_bpp || flag_size)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.multiple_bitrate") );
|
|
Packit |
df99a1 |
parse_bpp(argv[i]);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else if (argv[i] == "-size")
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (++i >= argc)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.no_size_arg") );
|
|
Packit |
df99a1 |
if (flag_bpp || flag_size)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.multiple_size") );
|
|
Packit |
df99a1 |
parse_size(argv[i]);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else if (argv[i] == "-decibel")
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (++i >= argc)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.no_decibel_arg") );
|
|
Packit |
df99a1 |
if (flag_decibel)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.multiple_decibel") );
|
|
Packit |
df99a1 |
parse_decibel(argv[i]);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else if (argv[i] == "-slice")
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (++i >= argc)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.no_slice_arg") );
|
|
Packit |
df99a1 |
if (flag_slice)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.multiple_slice") );
|
|
Packit |
df99a1 |
parse_slice(argv[i]);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else if (argv[i] == "-mask")
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (++i >= argc)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.no_mask_arg") );
|
|
Packit |
df99a1 |
if (! g().mskurl.is_empty())
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.multiple_mask") );
|
|
Packit |
df99a1 |
g().mskurl = GURL::Filename::UTF8(argv[i]);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else if (argv[i] == "-dbfrac")
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (++i >= argc)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.no_dbfrac_arg") );
|
|
Packit |
df99a1 |
if (flag_dbfrac>0)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.multiple_dbfrac") );
|
|
Packit |
df99a1 |
char *ptr;
|
|
Packit |
df99a1 |
flag_dbfrac = strtod(argv[i], &ptr);
|
|
Packit |
df99a1 |
if (flag_dbfrac<=0 || flag_dbfrac>1 || *ptr)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.illegal_dbfrac") );
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else if (argv[i] == "-crcbnone")
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (flag_crcbmode>=0 || flag_crcbdelay>=0)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.incompatable_chrominance") );
|
|
Packit |
df99a1 |
flag_crcbdelay = flag_crcbmode = 0;
|
|
Packit |
df99a1 |
arg_crcbmode = IW44Image::CRCBnone;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else if (argv[i] == "-crcbhalf")
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (flag_crcbmode>=0)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.incompatable_chrominance") );
|
|
Packit |
df99a1 |
flag_crcbmode = 0;
|
|
Packit |
df99a1 |
arg_crcbmode = IW44Image::CRCBhalf;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else if (argv[i] == "-crcbnormal")
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (flag_crcbmode>=0)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.incompatable_chrominance") );
|
|
Packit |
df99a1 |
flag_crcbmode = 0;
|
|
Packit |
df99a1 |
arg_crcbmode = IW44Image::CRCBnormal;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else if (argv[i] == "-crcbfull")
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (flag_crcbmode>=0 || flag_crcbdelay>=0)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.incompatable_chrominance") );
|
|
Packit |
df99a1 |
flag_crcbdelay = flag_crcbmode = 0;
|
|
Packit |
df99a1 |
arg_crcbmode = IW44Image::CRCBfull;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else if (argv[i] == "-crcbdelay")
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (++i >= argc)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.no_crcbdelay_arg") );
|
|
Packit |
df99a1 |
if (flag_crcbdelay>=0)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.incompatable_chrominance") );
|
|
Packit |
df99a1 |
char *ptr;
|
|
Packit |
df99a1 |
flag_crcbdelay = strtol(argv[i], &ptr, 10);
|
|
Packit |
df99a1 |
if (*ptr || flag_crcbdelay<0 || flag_crcbdelay>=100)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.illegal_crcbdelay") );
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else if (argv[i] == "-dpi")
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (++i >= argc)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.no_dpi_arg") );
|
|
Packit |
df99a1 |
if (flag_dpi>0)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.duplicate_dpi") );
|
|
Packit |
df99a1 |
char *ptr;
|
|
Packit |
df99a1 |
flag_dpi = strtol(argv[i], &ptr, 10);
|
|
Packit |
df99a1 |
if (*ptr || flag_dpi<25 || flag_dpi>4800)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.illegal_dpi") );
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else if (argv[i] == "-gamma")
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (++i >= argc)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.no_gamma_arg") );
|
|
Packit |
df99a1 |
if (flag_gamma > 0)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.duplicate_gamma") );
|
|
Packit |
df99a1 |
char *ptr;
|
|
Packit |
df99a1 |
flag_gamma = strtod(argv[i], &ptr);
|
|
Packit |
df99a1 |
if (*ptr || flag_gamma<=0.25 || flag_gamma>=5)
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.illegal_gamma") );
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else
|
|
Packit |
df99a1 |
usage();
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else if (g().pnmurl.is_empty())
|
|
Packit |
df99a1 |
g().pnmurl = GURL::Filename::UTF8(argv[i]);
|
|
Packit |
df99a1 |
else if (g().iw4url.is_empty())
|
|
Packit |
df99a1 |
g().iw4url = GURL::Filename::UTF8(argv[i]);
|
|
Packit |
df99a1 |
else
|
|
Packit |
df99a1 |
usage();
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
if (g().pnmurl.is_empty())
|
|
Packit |
df99a1 |
usage();
|
|
Packit |
df99a1 |
if (g().iw4url.is_empty())
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GURL codebase=g().pnmurl.base();
|
|
Packit |
df99a1 |
GUTF8String base = g().pnmurl.fname();
|
|
Packit |
df99a1 |
int dot = base.rsearch('.');
|
|
Packit |
df99a1 |
if (dot >= 1)
|
|
Packit |
df99a1 |
base = base.substr(0,dot);
|
|
Packit |
df99a1 |
const char *ext=".djvu";
|
|
Packit |
df99a1 |
g().iw4url = GURL::UTF8(base+ext,codebase);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
GP<GBitmap>
|
|
Packit |
df99a1 |
getmask(int w, int h)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GP<GBitmap> msk8;
|
|
Packit |
df99a1 |
if (! g().mskurl.is_empty())
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GP<ByteStream> mbs=ByteStream::create(g().mskurl,"rb");
|
|
Packit |
df99a1 |
msk8 = GBitmap::create(*mbs);
|
|
Packit |
df99a1 |
if (msk8->columns() != (unsigned int)w ||
|
|
Packit |
df99a1 |
msk8->rows() != (unsigned int)h )
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.different_size") );
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
return msk8;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static void
|
|
Packit |
df99a1 |
create_photo_djvu_file(IW44Image &iw, int w, int h,
|
|
Packit |
df99a1 |
IFFByteStream &iff, int nchunks, IWEncoderParms xparms[])
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
// Prepare info chunk
|
|
Packit |
df99a1 |
GP<DjVuInfo> ginfo=DjVuInfo::create();
|
|
Packit |
df99a1 |
DjVuInfo &info=*ginfo;
|
|
Packit |
df99a1 |
info.width = w;
|
|
Packit |
df99a1 |
info.height = h;
|
|
Packit |
df99a1 |
info.dpi = (flag_dpi>0 ? flag_dpi : 100);
|
|
Packit |
df99a1 |
info.gamma = (flag_gamma>0 ? flag_gamma : 2.2);
|
|
Packit |
df99a1 |
// Write djvu header and info chunk
|
|
Packit |
df99a1 |
iff.put_chunk("FORM:DJVU", 1);
|
|
Packit |
df99a1 |
iff.put_chunk("INFO");
|
|
Packit |
df99a1 |
info.encode(*iff.get_bytestream());
|
|
Packit |
df99a1 |
iff.close_chunk();
|
|
Packit |
df99a1 |
// Write all chunks
|
|
Packit |
df99a1 |
int flag = 1;
|
|
Packit |
df99a1 |
for (int i=0; flag && i
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
iff.put_chunk("BG44");
|
|
Packit |
df99a1 |
flag = iw.encode_chunk(iff.get_bytestream(), xparms[i]);
|
|
Packit |
df99a1 |
iff.close_chunk();
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
// Close djvu chunk
|
|
Packit |
df99a1 |
iff.close_chunk();
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
int
|
|
Packit |
df99a1 |
main(int argc, char **argv)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
DJVU_LOCALE;
|
|
Packit |
df99a1 |
GArray<GUTF8String> dargv(0,argc-1);
|
|
Packit |
df99a1 |
for(int i=0;i
|
|
Packit |
df99a1 |
dargv[i]=GNativeString(argv[i]);
|
|
Packit |
df99a1 |
G_TRY
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
// Parse arguments
|
|
Packit |
df99a1 |
parse(dargv);
|
|
Packit |
df99a1 |
// Check input file
|
|
Packit |
df99a1 |
GP<ByteStream> gibs=ByteStream::create(g().pnmurl,"rb");
|
|
Packit |
df99a1 |
ByteStream &ibs=*gibs;
|
|
Packit |
df99a1 |
char prefix[16];
|
|
Packit |
df99a1 |
memset(prefix, 0, sizeof(prefix));
|
|
Packit |
df99a1 |
if (ibs.readall((void*)prefix, sizeof(prefix)) < sizeof(prefix))
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.failed_pnm_header") );
|
|
Packit |
df99a1 |
#ifdef DEFAULT_JPEG_TO_HALF_SIZE
|
|
Packit |
df99a1 |
// Default specification for jpeg files
|
|
Packit |
df99a1 |
// This is disabled because
|
|
Packit |
df99a1 |
// -1- jpeg detection is unreliable.
|
|
Packit |
df99a1 |
// -2- quality is very difficult to predict.
|
|
Packit |
df99a1 |
if(prefix[0]!='P' &&prefix[0]!='A' && prefix[0]!='F' &&
|
|
Packit |
df99a1 |
!flag_mask && !flag_bpp && !flag_size &&
|
|
Packit |
df99a1 |
!flag_slice && !flag_decibel)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
parse_size("10,20,30,50");
|
|
Packit |
df99a1 |
flag_size = flag_percent = 1;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
// Change percent specification into size specification
|
|
Packit |
df99a1 |
if (flag_size && flag_percent)
|
|
Packit |
df99a1 |
for (int i=0; i
|
|
Packit |
df99a1 |
argv_size[i] = (argv_size[i]*gibs->size())/ 100;
|
|
Packit |
df99a1 |
flag_percent = 0;
|
|
Packit |
df99a1 |
// Load images
|
|
Packit |
df99a1 |
int w = 0;
|
|
Packit |
df99a1 |
int h = 0;
|
|
Packit |
df99a1 |
ibs.seek(0);
|
|
Packit |
df99a1 |
GP<IW44Image> iw;
|
|
Packit |
df99a1 |
// Check color vs gray
|
|
Packit |
df99a1 |
if (prefix[0]=='P' && (prefix[1]=='2' || prefix[1]=='5'))
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
// gray file
|
|
Packit |
df99a1 |
GP<GBitmap> gibm=GBitmap::create(ibs);
|
|
Packit |
df99a1 |
GBitmap &ibm=*gibm;
|
|
Packit |
df99a1 |
w = ibm.columns();
|
|
Packit |
df99a1 |
h = ibm.rows();
|
|
Packit |
df99a1 |
iw = IW44Image::create_encode(ibm, getmask(w,h));
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else if (!GStringRep::cmp(prefix,"AT&TFORM",8) ||
|
|
Packit |
df99a1 |
!GStringRep::cmp(prefix,"FORM",4))
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
char *s = (prefix[0]=='F' ? prefix+8 : prefix+12);
|
|
Packit |
df99a1 |
GP<IFFByteStream> giff=IFFByteStream::create(gibs);
|
|
Packit |
df99a1 |
IFFByteStream &iff=*giff;
|
|
Packit |
df99a1 |
const bool color=!GStringRep::cmp(s,"PM44",4);
|
|
Packit |
df99a1 |
if (color || !GStringRep::cmp(s,"BM44",4))
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
iw = IW44Image::create_encode(IW44Image::COLOR);
|
|
Packit |
df99a1 |
iw->decode_iff(iff);
|
|
Packit |
df99a1 |
w = iw->get_width();
|
|
Packit |
df99a1 |
h = iw->get_height();
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.unrecognized") );
|
|
Packit |
df99a1 |
// Check that no mask has been specified.
|
|
Packit |
df99a1 |
if (! g().mskurl.is_empty())
|
|
Packit |
df99a1 |
G_THROW( ERR_MSG("c44.failed_mask") );
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else // just for kicks, try jpeg.
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
// color file
|
|
Packit |
df99a1 |
const GP<GPixmap> gipm(GPixmap::create(ibs));
|
|
Packit |
df99a1 |
GPixmap &ipm=*gipm;
|
|
Packit |
df99a1 |
w = ipm.columns();
|
|
Packit |
df99a1 |
h = ipm.rows();
|
|
Packit |
df99a1 |
iw = IW44Image::create_encode(ipm, getmask(w,h), arg_crcbmode);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
// Call destructor on input file
|
|
Packit |
df99a1 |
gibs=0;
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
// Perform compression PM44 or BM44 as required
|
|
Packit |
df99a1 |
if (iw)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
g().iw4url.deletefile();
|
|
Packit |
df99a1 |
GP<IFFByteStream> iff =
|
|
Packit |
df99a1 |
IFFByteStream::create(ByteStream::create(g().iw4url,"wb"));
|
|
Packit |
df99a1 |
if (flag_crcbdelay >= 0)
|
|
Packit |
df99a1 |
iw->parm_crcbdelay(flag_crcbdelay);
|
|
Packit |
df99a1 |
if (flag_dbfrac > 0)
|
|
Packit |
df99a1 |
iw->parm_dbfrac((float)flag_dbfrac);
|
|
Packit |
df99a1 |
int nchunk = resolve_quality(w*h);
|
|
Packit |
df99a1 |
// Create djvu file
|
|
Packit |
df99a1 |
create_photo_djvu_file(*iw, w, h, *iff, nchunk, g().parms);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
G_CATCH(ex)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
ex.perror();
|
|
Packit |
df99a1 |
exit(1);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
G_ENDCATCH;
|
|
Packit |
df99a1 |
return 0;
|
|
Packit |
df99a1 |
}
|