Blame libdjvu/MMRDecoder.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
#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
#include "MMRDecoder.h"
Packit df99a1
#include "JB2Image.h"
Packit df99a1
#include "ByteStream.h"
Packit df99a1
#include "GBitmap.h"
Packit df99a1
Packit df99a1
Packit df99a1
#ifdef HAVE_NAMESPACES
Packit df99a1
namespace DJVU {
Packit df99a1
# ifdef NOT_DEFINED // Just to fool emacs c++ mode
Packit df99a1
}
Packit df99a1
#endif
Packit df99a1
#endif
Packit df99a1
Packit df99a1
Packit df99a1
// ----------------------------------------
Packit df99a1
// MMR CODEBOOKS
Packit df99a1
Packit df99a1
static const char invalid_mmr_data[]= ERR_MSG("MMRDecoder.bad_data");
Packit df99a1
Packit df99a1
struct VLCode 
Packit df99a1
{
Packit df99a1
  unsigned short code;
Packit df99a1
  short codelen;
Packit df99a1
  short value;
Packit df99a1
};
Packit df99a1
Packit df99a1
enum MMRMode
Packit df99a1
{ 
Packit df99a1
  P=0, H=1, V0=2, VR1=3, VR2=4, VR3=5, VL1=6, VL2=7, VL3=8 
Packit df99a1
};
Packit df99a1
Packit df99a1
static const VLCode mrcodes[] =
Packit df99a1
{   // Codes on 7 bits
Packit df99a1
  // 7 bit codes
Packit df99a1
  { 0x08,   4,    P }, // 0001
Packit df99a1
  { 0x10,   3,    H }, // 001
Packit df99a1
  { 0x40,   1,   V0 }, // 1
Packit df99a1
  { 0x30,   3,  VR1 }, // 011
Packit df99a1
  { 0x06,   6,  VR2 }, // 000011
Packit df99a1
  { 0x03,   7,  VR3 }, // 0000011
Packit df99a1
  { 0x20,   3,  VL1 }, // 010
Packit df99a1
  { 0x04,   6,  VL2 }, // 000010
Packit df99a1
  { 0x02,   7,  VL3 }, // 0000010
Packit df99a1
  { 0x00,   0,   -1 }  // Illegal entry
Packit df99a1
};
Packit df99a1
Packit df99a1
Packit df99a1
static const VLCode wcodes[] = {    
Packit df99a1
  // 13 bit codes
Packit df99a1
  { 0x06a0,  8,    0 }, // 00110101
Packit df99a1
  { 0x0380,  6,    1 }, // 000111
Packit df99a1
  { 0x0e00,  4,    2 }, // 0111
Packit df99a1
  { 0x1000,  4,    3 }, // 1000
Packit df99a1
  { 0x1600,  4,    4 }, // 1011
Packit df99a1
  { 0x1800,  4,    5 }, // 1100
Packit df99a1
  { 0x1c00,  4,    6 }, // 1110
Packit df99a1
  { 0x1e00,  4,    7 }, // 1111
Packit df99a1
  { 0x1300,  5,    8 }, // 10011
Packit df99a1
  { 0x1400,  5,    9 }, // 10100
Packit df99a1
  { 0x0700,  5,   10 }, // 00111
Packit df99a1
  { 0x0800,  5,   11 }, // 01000
Packit df99a1
  { 0x0400,  6,   12 }, // 001000
Packit df99a1
  { 0x0180,  6,   13 }, // 000011
Packit df99a1
  { 0x1a00,  6,   14 }, // 110100
Packit df99a1
  { 0x1a80,  6,   15 }, // 110101
Packit df99a1
  { 0x1500,  6,   16 }, // 101010
Packit df99a1
  { 0x1580,  6,   17 }, // 101011
Packit df99a1
  { 0x09c0,  7,   18 }, // 0100111
Packit df99a1
  { 0x0300,  7,   19 }, // 0001100
Packit df99a1
  { 0x0200,  7,   20 }, // 0001000
Packit df99a1
  { 0x05c0,  7,   21 }, // 0010111
Packit df99a1
  { 0x00c0,  7,   22 }, // 0000011
Packit df99a1
  { 0x0100,  7,   23 }, // 0000100
Packit df99a1
  { 0x0a00,  7,   24 }, // 0101000
Packit df99a1
  { 0x0ac0,  7,   25 }, // 0101011
Packit df99a1
  { 0x04c0,  7,   26 }, // 0010011
Packit df99a1
  { 0x0900,  7,   27 }, // 0100100
Packit df99a1
  { 0x0600,  7,   28 }, // 0011000
Packit df99a1
  { 0x0040,  8,   29 }, // 00000010
Packit df99a1
  { 0x0060,  8,   30 }, // 00000011
Packit df99a1
  { 0x0340,  8,   31 }, // 00011010
Packit df99a1
  { 0x0360,  8,   32 }, // 00011011
Packit df99a1
  { 0x0240,  8,   33 }, // 00010010
Packit df99a1
  { 0x0260,  8,   34 }, // 00010011
Packit df99a1
  { 0x0280,  8,   35 }, // 00010100
Packit df99a1
  { 0x02a0,  8,   36 }, // 00010101
Packit df99a1
  { 0x02c0,  8,   37 }, // 00010110
Packit df99a1
  { 0x02e0,  8,   38 }, // 00010111
Packit df99a1
  { 0x0500,  8,   39 }, // 00101000
Packit df99a1
  { 0x0520,  8,   40 }, // 00101001
Packit df99a1
  { 0x0540,  8,   41 }, // 00101010
Packit df99a1
  { 0x0560,  8,   42 }, // 00101011
Packit df99a1
  { 0x0580,  8,   43 }, // 00101100
Packit df99a1
  { 0x05a0,  8,   44 }, // 00101101
Packit df99a1
  { 0x0080,  8,   45 }, // 00000100
Packit df99a1
  { 0x00a0,  8,   46 }, // 00000101
Packit df99a1
  { 0x0140,  8,   47 }, // 00001010
Packit df99a1
  { 0x0160,  8,   48 }, // 00001011
Packit df99a1
  { 0x0a40,  8,   49 }, // 01010010
Packit df99a1
  { 0x0a60,  8,   50 }, // 01010011
Packit df99a1
  { 0x0a80,  8,   51 }, // 01010100
Packit df99a1
  { 0x0aa0,  8,   52 }, // 01010101
Packit df99a1
  { 0x0480,  8,   53 }, // 00100100
Packit df99a1
  { 0x04a0,  8,   54 }, // 00100101
Packit df99a1
  { 0x0b00,  8,   55 }, // 01011000
Packit df99a1
  { 0x0b20,  8,   56 }, // 01011001
Packit df99a1
  { 0x0b40,  8,   57 }, // 01011010
Packit df99a1
  { 0x0b60,  8,   58 }, // 01011011
Packit df99a1
  { 0x0940,  8,   59 }, // 01001010
Packit df99a1
  { 0x0960,  8,   60 }, // 01001011
Packit df99a1
  { 0x0640,  8,   61 }, // 00110010
Packit df99a1
  { 0x0660,  8,   62 }, // 00110011
Packit df99a1
  { 0x0680,  8,   63 }, // 00110100
Packit df99a1
  { 0x1b00,  5,   64 }, // 11011
Packit df99a1
  { 0x1200,  5,  128 }, // 10010
Packit df99a1
  { 0x0b80,  6,  192 }, // 010111
Packit df99a1
  { 0x0dc0,  7,  256 }, // 0110111
Packit df99a1
  { 0x06c0,  8,  320 }, // 00110110
Packit df99a1
  { 0x06e0,  8,  384 }, // 00110111
Packit df99a1
  { 0x0c80,  8,  448 }, // 01100100
Packit df99a1
  { 0x0ca0,  8,  512 }, // 01100101
Packit df99a1
  { 0x0d00,  8,  576 }, // 01101000
Packit df99a1
  { 0x0ce0,  8,  640 }, // 01100111
Packit df99a1
  { 0x0cc0,  9,  704 }, // 011001100
Packit df99a1
  { 0x0cd0,  9,  768 }, // 011001101
Packit df99a1
  { 0x0d20,  9,  832 }, // 011010010
Packit df99a1
  { 0x0d30,  9,  896 }, // 011010011
Packit df99a1
  { 0x0d40,  9,  960 }, // 011010100
Packit df99a1
  { 0x0d50,  9, 1024 }, // 011010101
Packit df99a1
  { 0x0d60,  9, 1088 }, // 011010110
Packit df99a1
  { 0x0d70,  9, 1152 }, // 011010111
Packit df99a1
  { 0x0d80,  9, 1216 }, // 011011000
Packit df99a1
  { 0x0d90,  9, 1280 }, // 011011001
Packit df99a1
  { 0x0da0,  9, 1344 }, // 011011010
Packit df99a1
  { 0x0db0,  9, 1408 }, // 011011011
Packit df99a1
  { 0x0980,  9, 1472 }, // 010011000
Packit df99a1
  { 0x0990,  9, 1536 }, // 010011001
Packit df99a1
  { 0x09a0,  9, 1600 }, // 010011010
Packit df99a1
  { 0x0c00,  6, 1664 }, // 011000  (what did they think?)
Packit df99a1
  { 0x09b0,  9, 1728 }, // 010011011
Packit df99a1
  { 0x0020, 11, 1792 }, // 00000001000
Packit df99a1
  { 0x0030, 11, 1856 }, // 00000001100
Packit df99a1
  { 0x0034, 11, 1920 }, // 00000001101
Packit df99a1
  { 0x0024, 12, 1984 }, // 000000010010
Packit df99a1
  { 0x0026, 12, 2048 }, // 000000010011
Packit df99a1
  { 0x0028, 12, 2112 }, // 000000010100
Packit df99a1
  { 0x002a, 12, 2176 }, // 000000010101
Packit df99a1
  { 0x002c, 12, 2240 }, // 000000010110
Packit df99a1
  { 0x002e, 12, 2304 }, // 000000010111
Packit df99a1
  { 0x0038, 12, 2368 }, // 000000011100
Packit df99a1
  { 0x003a, 12, 2432 }, // 000000011101
Packit df99a1
  { 0x003c, 12, 2496 }, // 000000011110
Packit df99a1
  { 0x003e, 12, 2560 }, // 000000011111
Packit df99a1
  { 0x0000,  0,   -1 }  // Illegal entry
Packit df99a1
};
Packit df99a1
Packit df99a1
Packit df99a1
static const VLCode bcodes[] = {
Packit df99a1
  // 13 bit codes
Packit df99a1
  { 0x01b8, 10,    0 }, // 0000110111
Packit df99a1
  { 0x0800,  3,    1 }, // 010
Packit df99a1
  { 0x1800,  2,    2 }, // 11
Packit df99a1
  { 0x1000,  2,    3 }, // 10
Packit df99a1
  { 0x0c00,  3,    4 }, // 011
Packit df99a1
  { 0x0600,  4,    5 }, // 0011
Packit df99a1
  { 0x0400,  4,    6 }, // 0010
Packit df99a1
  { 0x0300,  5,    7 }, // 00011
Packit df99a1
  { 0x0280,  6,    8 }, // 000101
Packit df99a1
  { 0x0200,  6,    9 }, // 000100
Packit df99a1
  { 0x0100,  7,   10 }, // 0000100
Packit df99a1
  { 0x0140,  7,   11 }, // 0000101
Packit df99a1
  { 0x01c0,  7,   12 }, // 0000111
Packit df99a1
  { 0x0080,  8,   13 }, // 00000100
Packit df99a1
  { 0x00e0,  8,   14 }, // 00000111
Packit df99a1
  { 0x0180,  9,   15 }, // 000011000
Packit df99a1
  { 0x00b8, 10,   16 }, // 0000010111
Packit df99a1
  { 0x00c0, 10,   17 }, // 0000011000
Packit df99a1
  { 0x0040, 10,   18 }, // 0000001000
Packit df99a1
  { 0x019c, 11,   19 }, // 00001100111
Packit df99a1
  { 0x01a0, 11,   20 }, // 00001101000
Packit df99a1
  { 0x01b0, 11,   21 }, // 00001101100
Packit df99a1
  { 0x00dc, 11,   22 }, // 00000110111
Packit df99a1
  { 0x00a0, 11,   23 }, // 00000101000
Packit df99a1
  { 0x005c, 11,   24 }, // 00000010111
Packit df99a1
  { 0x0060, 11,   25 }, // 00000011000
Packit df99a1
  { 0x0194, 12,   26 }, // 000011001010
Packit df99a1
  { 0x0196, 12,   27 }, // 000011001011
Packit df99a1
  { 0x0198, 12,   28 }, // 000011001100
Packit df99a1
  { 0x019a, 12,   29 }, // 000011001101
Packit df99a1
  { 0x00d0, 12,   30 }, // 000001101000
Packit df99a1
  { 0x00d2, 12,   31 }, // 000001101001
Packit df99a1
  { 0x00d4, 12,   32 }, // 000001101010
Packit df99a1
  { 0x00d6, 12,   33 }, // 000001101011
Packit df99a1
  { 0x01a4, 12,   34 }, // 000011010010
Packit df99a1
  { 0x01a6, 12,   35 }, // 000011010011
Packit df99a1
  { 0x01a8, 12,   36 }, // 000011010100
Packit df99a1
  { 0x01aa, 12,   37 }, // 000011010101
Packit df99a1
  { 0x01ac, 12,   38 }, // 000011010110
Packit df99a1
  { 0x01ae, 12,   39 }, // 000011010111
Packit df99a1
  { 0x00d8, 12,   40 }, // 000001101100
Packit df99a1
  { 0x00da, 12,   41 }, // 000001101101
Packit df99a1
  { 0x01b4, 12,   42 }, // 000011011010
Packit df99a1
  { 0x01b6, 12,   43 }, // 000011011011
Packit df99a1
  { 0x00a8, 12,   44 }, // 000001010100
Packit df99a1
  { 0x00aa, 12,   45 }, // 000001010101
Packit df99a1
  { 0x00ac, 12,   46 }, // 000001010110
Packit df99a1
  { 0x00ae, 12,   47 }, // 000001010111
Packit df99a1
  { 0x00c8, 12,   48 }, // 000001100100
Packit df99a1
  { 0x00ca, 12,   49 }, // 000001100101
Packit df99a1
  { 0x00a4, 12,   50 }, // 000001010010
Packit df99a1
  { 0x00a6, 12,   51 }, // 000001010011
Packit df99a1
  { 0x0048, 12,   52 }, // 000000100100
Packit df99a1
  { 0x006e, 12,   53 }, // 000000110111
Packit df99a1
  { 0x0070, 12,   54 }, // 000000111000
Packit df99a1
  { 0x004e, 12,   55 }, // 000000100111
Packit df99a1
  { 0x0050, 12,   56 }, // 000000101000
Packit df99a1
  { 0x00b0, 12,   57 }, // 000001011000
Packit df99a1
  { 0x00b2, 12,   58 }, // 000001011001
Packit df99a1
  { 0x0056, 12,   59 }, // 000000101011
Packit df99a1
  { 0x0058, 12,   60 }, // 000000101100
Packit df99a1
  { 0x00b4, 12,   61 }, // 000001011010
Packit df99a1
  { 0x00cc, 12,   62 }, // 000001100110
Packit df99a1
  { 0x00ce, 12,   63 }, // 000001100111
Packit df99a1
  { 0x0078, 10,   64 }, // 0000001111
Packit df99a1
  { 0x0190, 12,  128 }, // 000011001000
Packit df99a1
  { 0x0192, 12,  192 }, // 000011001001
Packit df99a1
  { 0x00b6, 12,  256 }, // 000001011011
Packit df99a1
  { 0x0066, 12,  320 }, // 000000110011
Packit df99a1
  { 0x0068, 12,  384 }, // 000000110100
Packit df99a1
  { 0x006a, 12,  448 }, // 000000110101
Packit df99a1
  { 0x006c, 13,  512 }, // 0000001101100
Packit df99a1
  { 0x006d, 13,  576 }, // 0000001101101
Packit df99a1
  { 0x004a, 13,  640 }, // 0000001001010
Packit df99a1
  { 0x004b, 13,  704 }, // 0000001001011
Packit df99a1
  { 0x004c, 13,  768 }, // 0000001001100
Packit df99a1
  { 0x004d, 13,  832 }, // 0000001001101
Packit df99a1
  { 0x0072, 13,  896 }, // 0000001110010
Packit df99a1
  { 0x0073, 13,  960 }, // 0000001110011
Packit df99a1
  { 0x0074, 13, 1024 }, // 0000001110100
Packit df99a1
  { 0x0075, 13, 1088 }, // 0000001110101
Packit df99a1
  { 0x0076, 13, 1152 }, // 0000001110110
Packit df99a1
  { 0x0077, 13, 1216 }, // 0000001110111
Packit df99a1
  { 0x0052, 13, 1280 }, // 0000001010010
Packit df99a1
  { 0x0053, 13, 1344 }, // 0000001010011
Packit df99a1
  { 0x0054, 13, 1408 }, // 0000001010100
Packit df99a1
  { 0x0055, 13, 1472 }, // 0000001010101
Packit df99a1
  { 0x005a, 13, 1536 }, // 0000001011010
Packit df99a1
  { 0x005b, 13, 1600 }, // 0000001011011
Packit df99a1
  { 0x0064, 13, 1664 }, // 0000001100100
Packit df99a1
  { 0x0065, 13, 1728 }, // 0000001100101
Packit df99a1
  { 0x0020, 11, 1792 }, // 00000001000
Packit df99a1
  { 0x0030, 11, 1856 }, // 00000001100
Packit df99a1
  { 0x0034, 11, 1920 }, // 00000001101
Packit df99a1
  { 0x0024, 12, 1984 }, // 000000010010
Packit df99a1
  { 0x0026, 12, 2048 }, // 000000010011
Packit df99a1
  { 0x0028, 12, 2112 }, // 000000010100
Packit df99a1
  { 0x002a, 12, 2176 }, // 000000010101
Packit df99a1
  { 0x002c, 12, 2240 }, // 000000010110
Packit df99a1
  { 0x002e, 12, 2304 }, // 000000010111
Packit df99a1
  { 0x0038, 12, 2368 }, // 000000011100
Packit df99a1
  { 0x003a, 12, 2432 }, // 000000011101
Packit df99a1
  { 0x003c, 12, 2496 }, // 000000011110
Packit df99a1
  { 0x003e, 12, 2560 }, // 000000011111
Packit df99a1
  { 0x0000,  0,   -1 }  // Illegal entry
Packit df99a1
};
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
// ----------------------------------------
Packit df99a1
// SOURCE OF BITS
Packit df99a1
Packit df99a1
#define VLSBUFSIZE    64
Packit df99a1
Packit df99a1
class MMRDecoder::VLSource : public GPEnabled
Packit df99a1
{
Packit df99a1
protected:
Packit df99a1
  VLSource(GP<ByteStream> &inp;;
Packit df99a1
  void init(const bool striped);
Packit df99a1
public:
Packit df99a1
  // Initializes a bit source on a bytestream
Packit df99a1
  static GP<VLSource> create(GP<ByteStream> &inp, const bool striped);
Packit df99a1
Packit df99a1
  // Synchronize on the next stripe
Packit df99a1
  void nextstripe(void);
Packit df99a1
  // Returns a 32 bits integer with at least the 
Packit df99a1
  // next sixteen code bits in the high order bits.
Packit df99a1
  inline unsigned int peek(void);
Packit df99a1
  // Ensures that next #peek()# contains at least
Packit df99a1
  // the next 24 code bits.
Packit df99a1
  void preload(void);
Packit df99a1
  // Consumes #n# bits.
Packit df99a1
  void shift(const int n);
Packit df99a1
private:
Packit df99a1
  GP<ByteStream> ginp;
Packit df99a1
  ByteStream &inp;
Packit df99a1
  unsigned char buffer[ VLSBUFSIZE ];
Packit df99a1
  unsigned int codeword;
Packit df99a1
  int lowbits;
Packit df99a1
  int bufpos;
Packit df99a1
  int bufmax;
Packit df99a1
  int readmax;
Packit df99a1
};
Packit df99a1
Packit df99a1
MMRDecoder::VLSource::VLSource(GP<ByteStream> &xinp)
Packit df99a1
: ginp(xinp), inp(*ginp), codeword(0), 
Packit df99a1
  lowbits(0), bufpos(0), bufmax(0),
Packit df99a1
  readmax(-1)
Packit df99a1
{}
Packit df99a1
Packit df99a1
void
Packit df99a1
MMRDecoder::VLSource::init(const bool striped)
Packit df99a1
{
Packit df99a1
  if (striped)
Packit df99a1
    readmax = inp.read32();
Packit df99a1
  lowbits = 32;
Packit df99a1
  preload();
Packit df99a1
}
Packit df99a1
Packit df99a1
GP<MMRDecoder::VLSource>
Packit df99a1
MMRDecoder::VLSource::create(GP<ByteStream> &inp, const bool striped)
Packit df99a1
{
Packit df99a1
  VLSource *src=new VLSource(inp);
Packit df99a1
  GP<VLSource> retval=src;
Packit df99a1
  src->init(striped);
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
MMRDecoder::VLSource::shift(const int n)
Packit df99a1
{ 
Packit df99a1
  codeword<<=n;
Packit df99a1
  lowbits+=n;
Packit df99a1
  if (lowbits>=16)
Packit df99a1
    preload();
Packit df99a1
}
Packit df99a1
Packit df99a1
inline unsigned int
Packit df99a1
MMRDecoder::VLSource::peek(void)
Packit df99a1
{
Packit df99a1
  return codeword;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
void
Packit df99a1
MMRDecoder::VLSource::nextstripe(void)
Packit df99a1
{
Packit df99a1
  while (readmax>0)
Packit df99a1
    {
Packit df99a1
      int size = sizeof(buffer);
Packit df99a1
      if (readmax < size) 
Packit df99a1
        size = readmax;
Packit df99a1
      inp.readall(buffer, size);
Packit df99a1
      readmax -= size;
Packit df99a1
    }
Packit df99a1
  bufpos = bufmax = 0;
Packit df99a1
  memset(buffer,0,sizeof(buffer));
Packit df99a1
  readmax = inp.read32();
Packit df99a1
  codeword = 0; 
Packit df99a1
  lowbits = 32;
Packit df99a1
  preload();
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
MMRDecoder::VLSource::preload(void)
Packit df99a1
{
Packit df99a1
  while (lowbits>=8) 
Packit df99a1
    {
Packit df99a1
      if (bufpos >= bufmax) 
Packit df99a1
	{
Packit df99a1
          // Refill buffer
Packit df99a1
	  bufpos = bufmax = 0;
Packit df99a1
          int size = sizeof(buffer);
Packit df99a1
          if (readmax>=0 && readmax
Packit df99a1
            size = readmax;
Packit df99a1
          if (size>0)
Packit df99a1
            bufmax = inp.read((void*)buffer, size);
Packit df99a1
          readmax -= bufmax;
Packit df99a1
	  if (bufmax <= 0)
Packit df99a1
            return;
Packit df99a1
	}
Packit df99a1
      lowbits -= 8;
Packit df99a1
      codeword |= buffer[bufpos++] << lowbits;
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
// ----------------------------------------
Packit df99a1
// VARIABLE LENGTH CODES
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
class MMRDecoder::VLTable : public GPEnabled
Packit df99a1
{
Packit df99a1
protected:
Packit df99a1
  VLTable(const VLCode *codes);
Packit df99a1
  void init(const int nbits);
Packit df99a1
public:
Packit df99a1
  // Construct a VLTable given a codebook with #nbits# long codes.
Packit df99a1
  static GP<VLTable> create(VLCode const * const codes, const int nbits);
Packit df99a1
Packit df99a1
  // Reads one symbol from a VLSource
Packit df99a1
  int decode(MMRDecoder::VLSource *src);
Packit df99a1
Packit df99a1
  const VLCode *code;
Packit df99a1
  int codewordshift;
Packit df99a1
  unsigned char *index;
Packit df99a1
  GPBuffer<unsigned char> gindex;
Packit df99a1
};
Packit df99a1
Packit df99a1
GP<MMRDecoder::VLTable>
Packit df99a1
MMRDecoder::VLTable::create(VLCode const * const codes, const int nbits)
Packit df99a1
{
Packit df99a1
  VLTable *table=new VLTable(codes);
Packit df99a1
  GP<VLTable> retval=table;
Packit df99a1
  table->init(nbits);
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
inline int
Packit df99a1
MMRDecoder::VLTable::decode(MMRDecoder::VLSource *src)    
Packit df99a1
{ 
Packit df99a1
  const VLCode &c = code[ index[ src->peek() >> codewordshift ] ];
Packit df99a1
  src->shift(c.codelen); 
Packit df99a1
  return c.value; 
Packit df99a1
}
Packit df99a1
Packit df99a1
MMRDecoder::VLTable::VLTable(const VLCode *codes)
Packit df99a1
: code(codes), codewordshift(0), gindex(index,0)
Packit df99a1
{}
Packit df99a1
Packit df99a1
void
Packit df99a1
MMRDecoder::VLTable::init(const int nbits)
Packit df99a1
{
Packit df99a1
  // count entries
Packit df99a1
  int ncodes = 0;
Packit df99a1
  while (code[ncodes].codelen)
Packit df99a1
    ncodes++;
Packit df99a1
  // check arguments
Packit df99a1
  if (nbits<=1 || nbits>16)
Packit df99a1
    G_THROW(invalid_mmr_data);
Packit df99a1
  if (ncodes>=256)
Packit df99a1
    G_THROW(invalid_mmr_data);
Packit df99a1
  codewordshift = 32 - nbits;
Packit df99a1
  // allocate table
Packit df99a1
  int size = (1<
Packit df99a1
  gindex.resize(size);
Packit df99a1
  gindex.set(ncodes);
Packit df99a1
  // process codes
Packit df99a1
  for (int i=0; i
Packit df99a1
    const int c = code[i].code;
Packit df99a1
    const int b = code[i].codelen;
Packit df99a1
    if(b<=0 || b>nbits)
Packit df99a1
    {
Packit df99a1
      G_THROW(invalid_mmr_data);
Packit df99a1
    }
Packit df99a1
    // fill table entries whose index high bits are code.
Packit df99a1
    int n = c + (1<<(nbits-b));
Packit df99a1
    while ( --n >= c ) {
Packit df99a1
      if(index[n] != ncodes)
Packit df99a1
       G_THROW( ERR_MSG("MMRDecoder.bad_codebook") );
Packit df99a1
      index[n] = i;
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
// ----------------------------------------
Packit df99a1
// MMR DECODER
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
MMRDecoder::~MMRDecoder() {}
Packit df99a1
Packit df99a1
MMRDecoder::MMRDecoder( const int xwidth, const int xheight )
Packit df99a1
: width(xwidth), height(xheight), lineno(0), 
Packit df99a1
  striplineno(0), rowsperstrip(0), gline(line,width+8),
Packit df99a1
  glineruns(lineruns,width+4), gprevruns(prevruns,width+4)
Packit df99a1
{
Packit df99a1
  gline.clear();
Packit df99a1
  glineruns.clear();
Packit df99a1
  gprevruns.clear();
Packit df99a1
  lineruns[0] = width;
Packit df99a1
  prevruns[0] = width;
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
MMRDecoder::init(GP<ByteStream> gbs, const bool striped)
Packit df99a1
{
Packit df99a1
  rowsperstrip = (striped ? gbs->read16() : height);
Packit df99a1
  src = VLSource::create(gbs, striped);
Packit df99a1
  mrtable = VLTable::create(mrcodes, 7);
Packit df99a1
  btable = VLTable::create(bcodes, 13);
Packit df99a1
  wtable = VLTable::create(wcodes, 13);
Packit df99a1
}
Packit df99a1
Packit df99a1
GP<MMRDecoder> 
Packit df99a1
MMRDecoder::create( GP<ByteStream> gbs, const int width,
Packit df99a1
  const int height, const bool striped )
Packit df99a1
{
Packit df99a1
  MMRDecoder *mmr=new MMRDecoder(width,height);
Packit df99a1
  GP<MMRDecoder> retval=mmr;
Packit df99a1
  mmr->init(gbs,striped);
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
const unsigned short *
Packit df99a1
MMRDecoder::scanruns(const unsigned short **endptr)
Packit df99a1
{
Packit df99a1
  // Check if all lines have been returned
Packit df99a1
  if (lineno >= height)
Packit df99a1
    return 0;
Packit df99a1
  // Check end of stripe
Packit df99a1
  if ( striplineno == rowsperstrip )
Packit df99a1
    {
Packit df99a1
      striplineno=0;
Packit df99a1
      lineruns[0] = prevruns[0] = width;
Packit df99a1
      src->nextstripe();
Packit df99a1
    }
Packit df99a1
  // Swap run buffers
Packit df99a1
  unsigned short *pr = lineruns;
Packit df99a1
  unsigned short *xr = prevruns;
Packit df99a1
  prevruns = pr;
Packit df99a1
  lineruns = xr;
Packit df99a1
  // Loop until scanline is complete
Packit df99a1
  bool a0color = false;
Packit df99a1
  int a0,rle,b1;
Packit df99a1
  for(a0=0,rle=0,b1=*pr++;a0 < width;)
Packit df99a1
    {
Packit df99a1
      // Process MMR codes
Packit df99a1
      const int c=mrtable->decode(src);
Packit df99a1
      switch ( c )
Packit df99a1
      {
Packit df99a1
          /* Pass Mode */
Packit df99a1
        case P: 
Packit df99a1
          { 
Packit df99a1
            b1 += *pr++;
Packit df99a1
            rle += b1 - a0;
Packit df99a1
            a0 = b1;
Packit df99a1
            b1 += *pr++;
Packit df99a1
            break;
Packit df99a1
          }
Packit df99a1
          /* Horizontal Mode */
Packit df99a1
        case H: 
Packit df99a1
          { 
Packit df99a1
            // First run
Packit df99a1
            VLTable &table1 = *(a0color ? btable : wtable);
Packit df99a1
            int inc;
Packit df99a1
            do { inc=table1.decode(src); a0+=inc; rle+=inc; } while (inc>=64);
Packit df99a1
            *xr = rle; xr++; rle = 0;
Packit df99a1
            // Second run
Packit df99a1
            VLTable &table2 = *(!a0color ? btable : wtable);
Packit df99a1
            do { inc=table2.decode(src); a0+=inc; rle+=inc; } while (inc>=64);
Packit df99a1
            *xr = rle; xr++; rle = 0;
Packit df99a1
            break;
Packit df99a1
          }
Packit df99a1
          /* Vertical Modes */
Packit df99a1
        case V0:
Packit df99a1
        case VR3:
Packit df99a1
        case VR2:
Packit df99a1
        case VR1:
Packit df99a1
        case VL3:
Packit df99a1
        case VL2:
Packit df99a1
        case VL1:
Packit df99a1
        {
Packit df99a1
          int inc=b1;
Packit df99a1
          switch ( c )
Packit df99a1
          {
Packit df99a1
          case V0:
Packit df99a1
            inc = b1;
Packit df99a1
            b1 += *pr++;
Packit df99a1
            break;
Packit df99a1
          case VR3:
Packit df99a1
            inc = b1+3;
Packit df99a1
            b1 += *pr++;
Packit df99a1
            break;
Packit df99a1
          case VR2:
Packit df99a1
            inc = b1+2;
Packit df99a1
            b1 += *pr++;
Packit df99a1
            break;
Packit df99a1
          case VR1:
Packit df99a1
            inc = b1+1;
Packit df99a1
            b1 += *pr++;
Packit df99a1
            break;
Packit df99a1
          case VL3:
Packit df99a1
            inc = b1-3;
Packit df99a1
            b1 -= *--pr;
Packit df99a1
            break;
Packit df99a1
          case VL2:
Packit df99a1
            inc = b1-2;
Packit df99a1
            b1 -= *--pr;
Packit df99a1
            break;
Packit df99a1
          case VL1:
Packit df99a1
            inc = b1-1;
Packit df99a1
            b1 -= *--pr;
Packit df99a1
            break;
Packit df99a1
          }
Packit df99a1
          *xr = inc+rle-a0;
Packit df99a1
          xr++;
Packit df99a1
          a0 = inc;
Packit df99a1
          rle = 0;
Packit df99a1
          a0color = !a0color;
Packit df99a1
          break;
Packit df99a1
        }
Packit df99a1
          /* Uncommon modes */
Packit df99a1
        default: 
Packit df99a1
          {
Packit df99a1
            src->preload();
Packit df99a1
            unsigned int m = src->peek();
Packit df99a1
            // -- Could be EOFB ``000000000001000000000001''
Packit df99a1
            //    TIFF6 says that all remaining lines are white
Packit df99a1
            if ((m & 0xffffff00) == 0x00100100)
Packit df99a1
              {
Packit df99a1
                lineno = height;
Packit df99a1
                return 0;
Packit df99a1
              }
Packit df99a1
            // -- Could be UNCOMPRESSED ``0000001111''
Packit df99a1
            //    TIFF6 says people should not do this.
Packit df99a1
            //    RFC1314 says people should do this.
Packit df99a1
            else if ((m & 0xffc00000) == 0x03c00000)
Packit df99a1
              {
Packit df99a1
#ifdef MMRDECODER_REFUSES_UNCOMPRESSED
Packit df99a1
                G_THROW( ERR_MSG("MMRDecoder.cant_process") );
Packit df99a1
#else
Packit df99a1
                // ---THE-FOLLOWING-CODE-IS-POORLY-TESTED---
Packit df99a1
                src->shift(10);
Packit df99a1
                while ((m = (src->peek() & 0xfc000000)))
Packit df99a1
                  {
Packit df99a1
                    if (m == 0x04000000)       // 000001
Packit df99a1
                      {
Packit df99a1
                        src->shift(6);
Packit df99a1
                        if (a0color)
Packit df99a1
                        {
Packit df99a1
                          *xr = rle;
Packit df99a1
                          xr++;
Packit df99a1
                          rle = 0;
Packit df99a1
                          a0color = !a0color;
Packit df99a1
                        }
Packit df99a1
                        rle += 5;
Packit df99a1
                        a0 += 5;
Packit df99a1
                      }
Packit df99a1
                    else                       // 000010 to 111111 
Packit df99a1
                      { 
Packit df99a1
                        src->shift(1);
Packit df99a1
                        if (a0color == !(m & 0x80000000))
Packit df99a1
                        {
Packit df99a1
                          *xr = rle;
Packit df99a1
                          xr++;
Packit df99a1
                          rle = 0;
Packit df99a1
                          a0color = !a0color;
Packit df99a1
                        }
Packit df99a1
                        rle++;
Packit df99a1
                        a0++;
Packit df99a1
                      }
Packit df99a1
                    if (a0 > width)
Packit df99a1
                      G_THROW(invalid_mmr_data);
Packit df99a1
                  }
Packit df99a1
                // Analyze uncompressed termination code.
Packit df99a1
                m = src->peek() & 0xff000000;  
Packit df99a1
                src->shift(8);
Packit df99a1
                if ( (m & 0xfe000000) != 0x02000000 )
Packit df99a1
                  G_THROW(invalid_mmr_data);
Packit df99a1
                if (rle)
Packit df99a1
                {
Packit df99a1
                  *xr = rle;
Packit df99a1
                  xr++;
Packit df99a1
                  rle = 0;
Packit df99a1
                  a0color = !a0color;
Packit df99a1
                }                  
Packit df99a1
                if (a0color == !(m & 0x01000000))
Packit df99a1
                {
Packit df99a1
                  *xr = rle;
Packit df99a1
                  xr++;
Packit df99a1
                  rle = 0;
Packit df99a1
                  a0color = !a0color;
Packit df99a1
                }
Packit df99a1
                // Cross fingers and proceed ...
Packit df99a1
                break;
Packit df99a1
#endif
Packit df99a1
              }
Packit df99a1
            // -- Unknown MMR code.
Packit df99a1
            G_THROW(invalid_mmr_data);
Packit df99a1
          }
Packit df99a1
      }
Packit df99a1
      // Next reference run
Packit df99a1
      for(;b1<=a0 && b1
Packit df99a1
      {
Packit df99a1
        b1 += pr[0]+pr[1];
Packit df99a1
      }
Packit df99a1
    }
Packit df99a1
  // Final P must be followed by V0 (they say!)
Packit df99a1
  if (rle > 0)
Packit df99a1
  {
Packit df99a1
    if (mrtable->decode(src) != V0)
Packit df99a1
    {
Packit df99a1
      G_THROW(invalid_mmr_data);
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
  if (rle > 0)
Packit df99a1
  {
Packit df99a1
    *xr = rle;
Packit df99a1
    xr++;
Packit df99a1
  }
Packit df99a1
  // At this point we should have A0 equal to WIDTH
Packit df99a1
  // But there are buggy files around (Kofax!)
Packit df99a1
  // and we are not the CCITT police.
Packit df99a1
  if (a0 > width) 
Packit df99a1
    {
Packit df99a1
      while (a0 > width && xr > lineruns)
Packit df99a1
        a0 -= *--xr;
Packit df99a1
      if (a0 < width)
Packit df99a1
      {
Packit df99a1
        *xr = width-a0;
Packit df99a1
        xr++;
Packit df99a1
      }
Packit df99a1
    }
Packit df99a1
  /* Increment and return */
Packit df99a1
  if (endptr) 
Packit df99a1
    *endptr = xr;
Packit df99a1
  xr[0] = 0;
Packit df99a1
  xr[1] = 0;
Packit df99a1
  lineno ++;
Packit df99a1
  striplineno ++;
Packit df99a1
  return lineruns;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
const unsigned char *
Packit df99a1
MMRDecoder::scanrle(const bool invert, const unsigned char **endptr)
Packit df99a1
{
Packit df99a1
  // Obtain run lengths
Packit df99a1
  const unsigned short *xr = scanruns();
Packit df99a1
  if (!xr) return 0;
Packit df99a1
  unsigned char *p=line;
Packit df99a1
  // Process inversion
Packit df99a1
  if (invert)
Packit df99a1
    {
Packit df99a1
      if (! *xr) 
Packit df99a1
      {
Packit df99a1
        xr++;
Packit df99a1
      }else
Packit df99a1
      {
Packit df99a1
        *p = 0; p++;
Packit df99a1
      }
Packit df99a1
    }
Packit df99a1
  // Encode lenghts using the RLE format
Packit df99a1
  for(int a0=0;a0 < width;)
Packit df99a1
  {
Packit df99a1
    int count = *xr++;
Packit df99a1
    a0 += count;
Packit df99a1
    GBitmap::append_run(p, count);
Packit df99a1
  }
Packit df99a1
  if (endptr)
Packit df99a1
    *endptr = p;
Packit df99a1
  p[0] = 0;
Packit df99a1
  p[1] = 0;
Packit df99a1
  return line;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
#if 0
Packit df99a1
const unsigned char *
Packit df99a1
MMRDecoder::scanline(void)
Packit df99a1
{
Packit df99a1
  // Obtain run lengths
Packit df99a1
  const unsigned short *xr = scanruns();
Packit df99a1
  if (!xr) return 0;
Packit df99a1
  // Allocate data buffer if needed
Packit df99a1
  unsigned char *p = line;
Packit df99a1
  // Decode run lengths
Packit df99a1
  int a0 = 0;
Packit df99a1
  int a0color = 0;
Packit df99a1
  while (a0 < width)
Packit df99a1
    {
Packit df99a1
      int a1 = a0 + *xr++;
Packit df99a1
      while (a0
Packit df99a1
        line[a0++] = a0color;
Packit df99a1
      a0color = !a0color;
Packit df99a1
    }
Packit df99a1
  return line;
Packit df99a1
}
Packit df99a1
#endif
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
// ----------------------------------------
Packit df99a1
// MAIN DECODING ROUTINE
Packit df99a1
Packit df99a1
bool
Packit df99a1
MMRDecoder::decode_header(
Packit df99a1
  ByteStream &inp, int &width, int &height, int &invert)
Packit df99a1
{
Packit df99a1
  unsigned long int magic = inp.read32();
Packit df99a1
  if((magic&0xfffffffc) != 0x4d4d5200)
Packit df99a1
    G_THROW( ERR_MSG("MMRDecoder.unrecog_header") ); 
Packit df99a1
  invert = ((magic & 0x1) ? 1 : 0);
Packit df99a1
  const bool strip =  ((magic & 0x2) ? 1 : 0);
Packit df99a1
  width = inp.read16();
Packit df99a1
  height = inp.read16();
Packit df99a1
  if (width<=0 || height<=0)
Packit df99a1
    G_THROW( ERR_MSG("MMRDecoder.bad_header") );
Packit df99a1
  return strip;
Packit df99a1
}
Packit df99a1
Packit df99a1
static inline int MAX(int a, int b) { return a>b ? a : b; }
Packit df99a1
static inline int MIN(int a, int b) { return a
Packit df99a1
Packit df99a1
GP<JB2Image>
Packit df99a1
MMRDecoder::decode(GP<ByteStream> gbs)
Packit df99a1
{
Packit df99a1
  ByteStream &inp=*gbs;
Packit df99a1
  // Read header
Packit df99a1
  int width, height, invert;
Packit df99a1
  const bool striped=decode_header(inp, width, height, invert);
Packit df99a1
  // Prepare image
Packit df99a1
  GP<JB2Image> jimg = JB2Image::create();
Packit df99a1
  jimg->set_dimension(width, height);
Packit df99a1
  // Choose pertinent blocksize
Packit df99a1
  int blocksize = MIN(500,MAX(64,MAX(width/17,height/22)));
Packit df99a1
  int blocksperline = (width+blocksize-1)/blocksize;
Packit df99a1
  // Prepare decoder
Packit df99a1
  GP<MMRDecoder> gdcd=MMRDecoder::create(gbs, width, height, striped);
Packit df99a1
  MMRDecoder &dcd=*gdcd;
Packit df99a1
  // Loop on JB2 bands
Packit df99a1
  int line = height-1;
Packit df99a1
  while (line >= 0)
Packit df99a1
    {
Packit df99a1
      int bandline = MIN(blocksize-1,line);
Packit df99a1
      GPArray<GBitmap> blocks(0,blocksperline-1);
Packit df99a1
      // Loop on scanlines
Packit df99a1
      for(; bandline >= 0; bandline--,line--)
Packit df99a1
      {
Packit df99a1
        // Decode one scanline
Packit df99a1
        const unsigned short *s = dcd.scanruns();
Packit df99a1
        if (s)
Packit df99a1
        {
Packit df99a1
	  // Loop on blocks
Packit df99a1
          int x = 0;
Packit df99a1
          int b = 0;
Packit df99a1
          int firstx = 0;
Packit df99a1
          bool c = !!invert;
Packit df99a1
          while (x < width)
Packit df99a1
            {
Packit df99a1
              int xend = x + *s++;
Packit df99a1
              while (b
Packit df99a1
                {
Packit df99a1
                  int lastx = MIN(firstx+blocksize,width);
Packit df99a1
                  if (c)
Packit df99a1
                    {
Packit df99a1
                      if (!blocks[b])
Packit df99a1
                        blocks[b] = GBitmap::create(bandline+1, lastx-firstx);
Packit df99a1
                      unsigned char *bptr = (*blocks[b])[bandline] - firstx;
Packit df99a1
                      int x1 = MAX(x,firstx);
Packit df99a1
                      int x2 = MIN(xend,lastx);
Packit df99a1
                      while (x1 < x2)
Packit df99a1
                        bptr[x1++] = 1;
Packit df99a1
                    }
Packit df99a1
                  if (xend < lastx)
Packit df99a1
                    break;
Packit df99a1
                  firstx = lastx;
Packit df99a1
                  b ++;
Packit df99a1
                }
Packit df99a1
              x = xend;
Packit df99a1
              c = !c; 
Packit df99a1
            }
Packit df99a1
	}
Packit df99a1
      }
Packit df99a1
      // Insert blocks into JB2Image
Packit df99a1
      for (int b=0; b
Packit df99a1
	{
Packit df99a1
	  JB2Shape shape;
Packit df99a1
	  shape.bits = blocks[b];
Packit df99a1
	  if (shape.bits) 
Packit df99a1
	    {
Packit df99a1
	      shape.parent = -1;
Packit df99a1
	      shape.bits->compress();
Packit df99a1
	      JB2Blit blit;
Packit df99a1
	      blit.left = b*blocksize;
Packit df99a1
	      blit.bottom = line+1;
Packit df99a1
	      blit.shapeno = jimg->add_shape(shape);
Packit df99a1
	      jimg->add_blit(blit);
Packit df99a1
	    }
Packit df99a1
	}
Packit df99a1
    }
Packit df99a1
  // Return
Packit df99a1
  return jimg;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
#ifdef HAVE_NAMESPACES
Packit df99a1
}
Packit df99a1
# ifndef NOT_USING_DJVU_NAMESPACE
Packit df99a1
using namespace DJVU;
Packit df99a1
# endif
Packit df99a1
#endif