source: trunk/libdjvu/JB2EncodeCodec.cpp @ 76

Last change on this file since 76 was 17, checked in by Eugene Romanenko, 16 years ago

update makefiles, remove absolute paths, update djvulibre to version 3.5.17

File size: 17.6 KB
Line 
1//C-  -*- C++ -*-
2//C- -------------------------------------------------------------------
3//C- DjVuLibre-3.5
4//C- Copyright (c) 2002  Leon Bottou and Yann Le Cun.
5//C- Copyright (c) 2001  AT&T
6//C-
7//C- This software is subject to, and may be distributed under, the
8//C- GNU General Public License, Version 2. The license should have
9//C- accompanied the software or you may obtain a copy of the license
10//C- from the Free Software Foundation at http://www.fsf.org .
11//C-
12//C- This program is distributed in the hope that it will be useful,
13//C- but WITHOUT ANY WARRANTY; without even the implied warranty of
14//C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15//C- GNU General Public License for more details.
16//C-
17//C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library
18//C- distributed by Lizardtech Software.  On July 19th 2002, Lizardtech
19//C- Software authorized us to replace the original DjVu(r) Reference
20//C- Library notice by the following text (see doc/lizard2002.djvu):
21//C-
22//C-  ------------------------------------------------------------------
23//C- | DjVu (r) Reference Library (v. 3.5)
24//C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
25//C- | The DjVu Reference Library is protected by U.S. Pat. No.
26//C- | 6,058,214 and patents pending.
27//C- |
28//C- | This software is subject to, and may be distributed under, the
29//C- | GNU General Public License, Version 2. The license should have
30//C- | accompanied the software or you may obtain a copy of the license
31//C- | from the Free Software Foundation at http://www.fsf.org .
32//C- |
33//C- | The computer code originally released by LizardTech under this
34//C- | license and unmodified by other parties is deemed "the LIZARDTECH
35//C- | ORIGINAL CODE."  Subject to any third party intellectual property
36//C- | claims, LizardTech grants recipient a worldwide, royalty-free,
37//C- | non-exclusive license to make, use, sell, or otherwise dispose of
38//C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the
39//C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU
40//C- | General Public License.   This grant only confers the right to
41//C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to
42//C- | the extent such infringement is reasonably necessary to enable
43//C- | recipient to make, have made, practice, sell, or otherwise dispose
44//C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to
45//C- | any greater extent that may be necessary to utilize further
46//C- | modifications or combinations.
47//C- |
48//C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
49//C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
50//C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
51//C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
52//C- +------------------------------------------------------------------
53//
54// $Id: JB2EncodeCodec.cpp,v 1.9 2003/11/07 22:08:22 leonb Exp $
55// $Name:  $
56
57#ifdef HAVE_CONFIG_H
58# include "config.h"
59#endif
60#if NEED_GNUG_PRAGMAS
61# pragma implementation
62#endif
63
64// From: Leon Bottou, 1/31/2002
65// Lizardtech has split the corresponding cpp file into a decoder and an encoder.
66// Only superficial changes.  The meat is mine.
67
68#ifndef NEED_DECODER_ONLY
69
70#include "JB2Image.h"
71#include "GBitmap.h"
72#include <string.h>
73
74
75#ifdef HAVE_NAMESPACES
76namespace DJVU {
77# ifdef NOT_DEFINED // Just to fool emacs c++ mode
78}
79#endif
80#endif
81
82////////////////////////////////////////
83//// CLASS JB2Codec::Encode:  DECLARATION
84////////////////////////////////////////
85
86// This class is accessed via the encode
87// functions of class JB2Image
88
89
90//**** Class JB2Codec
91// This class implements the JB2 coder.
92// Contains all contextual information for encoding a JB2Image.
93
94class JB2Dict::JB2Codec::Encode : public JB2Dict::JB2Codec
95{
96public:
97  Encode(void);
98  void init(const GP<ByteStream> &gbs);
99//virtual
100  void code(const GP<JB2Image> &jim);
101  void code(JB2Image *jim) { const GP<JB2Image> gjim(jim);code(gjim); }
102  void code(const GP<JB2Dict> &jim);
103  void code(JB2Dict *jim) { const GP<JB2Dict> gjim(jim);code(gjim); }
104
105protected:
106  void CodeNum(const int num, const int lo, const int hi, NumContext &ctx);
107  void encode_libonly_shape(const GP<JB2Image> &jim, int shapeno);
108// virtual
109  bool CodeBit(const bool bit, BitContext &ctx);
110  void code_comment(GUTF8String &comment);
111  void code_record_type(int &rectype);
112  int code_match_index(int &index, JB2Dict &jim);
113  void code_inherited_shape_count(JB2Dict &jim);
114  void code_image_size(JB2Dict &jim);
115  void code_image_size(JB2Image &jim);
116  void code_absolute_location(JB2Blit *jblt,  int rows, int columns);
117  void code_absolute_mark_size(GBitmap &bm, int border=0);
118  void code_relative_mark_size(GBitmap &bm, int cw, int ch, int border=0);
119  void code_bitmap_directly(GBitmap &bm,const int dw, int dy,
120    unsigned char *up2, unsigned char *up1, unsigned char *up0 );
121  int get_diff(const int x_diff,NumContext &rel_loc);
122  void code_bitmap_by_cross_coding (GBitmap &bm, GBitmap &cbm,
123    const int xd2c, const int dw, int dy, int cy,
124    unsigned char *up1, unsigned char *up0, unsigned char *xup1, 
125    unsigned char *xup0, unsigned char *xdn1 );
126
127private:
128  GP<ZPCodec> gzp;
129};
130
131
132////////////////////////////////////////
133//// CLASS JB2DICT: IMPLEMENTATION
134////////////////////////////////////////
135
136void 
137JB2Dict::encode(const GP<ByteStream> &gbs) const
138{
139  JB2Codec::Encode codec;
140  codec.init(gbs);
141  codec.code(const_cast<JB2Dict *>(this));
142}
143
144////////////////////////////////////////
145//// CLASS JB2IMAGE: IMPLEMENTATION
146////////////////////////////////////////
147
148void 
149JB2Image::encode(const GP<ByteStream> &gbs) const
150{
151  JB2Codec::Encode codec;
152  codec.init(gbs);
153  codec.code(const_cast<JB2Image *>(this));
154}
155
156////////////////////////////////////////
157//// CLASS JB2CODEC : IMPLEMENTATION
158////////////////////////////////////////
159
160#define START_OF_DATA                   (0)
161#define NEW_MARK                        (1)
162#define NEW_MARK_LIBRARY_ONLY           (2)
163#define NEW_MARK_IMAGE_ONLY             (3)
164#define MATCHED_REFINE                  (4)
165#define MATCHED_REFINE_LIBRARY_ONLY     (5)
166#define MATCHED_REFINE_IMAGE_ONLY       (6)
167#define MATCHED_COPY                    (7)
168#define NON_MARK_DATA                   (8)
169#define REQUIRED_DICT_OR_RESET          (9)
170#define PRESERVED_COMMENT               (10)
171#define END_OF_DATA                     (11)
172
173// STATIC DATA MEMBERS
174
175static const int BIGPOSITIVE = 262142;
176static const int BIGNEGATIVE = -262143;
177static const int CELLCHUNK = 20000;
178static const int CELLEXTRA =   500;
179
180// CONSTRUCTOR
181
182JB2Dict::JB2Codec::Encode::Encode(void)
183: JB2Dict::JB2Codec(1) {}
184
185void
186JB2Dict::JB2Codec::Encode::init(const GP<ByteStream> &gbs)
187{
188  gzp=ZPCodec::create(gbs,true,true);
189}
190
191inline bool
192JB2Dict::JB2Codec::Encode::CodeBit(const bool bit, BitContext &ctx)
193{
194    gzp->encoder(bit?1:0, ctx);
195    return bit;
196}
197
198void
199JB2Dict::JB2Codec::Encode::CodeNum(int num, int low, int high, NumContext &ctx)
200{
201  if (num < low || num > high)
202    G_THROW( ERR_MSG("JB2Image.bad_number") );
203  JB2Codec::CodeNum(low,high,&ctx,num);
204}
205
206// CODE COMMENTS
207
208void 
209JB2Dict::JB2Codec::Encode::code_comment(GUTF8String &comment)
210{
211  // Encode size
212      int size=comment.length();
213      CodeNum(size, 0, BIGPOSITIVE, dist_comment_length);
214      for (int i=0; i<size; i++) 
215        {
216          CodeNum(comment[i], 0, 255, dist_comment_byte);
217        }
218}
219
220// CODE SIMPLE VALUES
221
222inline void 
223JB2Dict::JB2Codec::Encode::code_record_type(int &rectype)
224{
225  CodeNum(rectype, START_OF_DATA, END_OF_DATA, dist_record_type);
226}
227
228int 
229JB2Dict::JB2Codec::Encode::code_match_index(int &index, JB2Dict &jim)
230{
231    int match=shape2lib[index];
232    CodeNum(match, 0, lib2shape.hbound(), dist_match_index);
233    return match;
234}
235
236// CODE PAIRS
237
238void
239JB2Dict::JB2Codec::Encode::code_inherited_shape_count(JB2Dict &jim)
240{
241  CodeNum(jim.get_inherited_shape_count(),
242    0, BIGPOSITIVE, inherited_shape_count_dist);
243}
244
245void 
246JB2Dict::JB2Codec::Encode::code_image_size(JB2Dict &jim)
247{
248  CodeNum(0, 0, BIGPOSITIVE, image_size_dist);
249  CodeNum(0, 0, BIGPOSITIVE, image_size_dist);
250  JB2Codec::code_image_size(jim);
251}
252
253void 
254JB2Dict::JB2Codec::Encode::code_image_size(JB2Image &jim)
255{
256  image_columns = jim.get_width();
257  CodeNum(image_columns, 0, BIGPOSITIVE, image_size_dist);
258  image_rows = jim.get_height();
259  CodeNum(image_rows, 0, BIGPOSITIVE, image_size_dist);
260  JB2Codec::code_image_size(jim);
261}
262
263inline int
264JB2Dict::JB2Codec::Encode::get_diff(int x_diff,NumContext &rel_loc)
265{
266   CodeNum(x_diff, BIGNEGATIVE, BIGPOSITIVE, rel_loc);
267   return x_diff;
268}
269
270void 
271JB2Dict::JB2Codec::Encode::code_absolute_location(JB2Blit *jblt, int rows, int columns)
272{
273  // Check start record
274  if (!gotstartrecordp)
275    G_THROW( ERR_MSG("JB2Image.no_start") );
276  // Code TOP and LEFT
277  CodeNum(jblt->left+1, 1, image_columns, abs_loc_x);
278  CodeNum(jblt->bottom+rows-1+1, 1, image_rows, abs_loc_y);
279}
280
281void 
282JB2Dict::JB2Codec::Encode::code_absolute_mark_size(GBitmap &bm, int border)
283{
284  CodeNum(bm.columns(), 0, BIGPOSITIVE, abs_size_x);
285  CodeNum(bm.rows(), 0, BIGPOSITIVE, abs_size_y);
286}
287
288void 
289JB2Dict::JB2Codec::Encode::code_relative_mark_size(GBitmap &bm, int cw, int ch, int border)
290{
291  CodeNum(bm.columns()-cw, BIGNEGATIVE, BIGPOSITIVE, rel_size_x);
292  CodeNum(bm.rows()-ch, BIGNEGATIVE, BIGPOSITIVE, rel_size_y);
293}
294
295// CODE BITMAP DIRECTLY
296
297void 
298JB2Dict::JB2Codec::Encode::code_bitmap_directly(
299  GBitmap &bm,const int dw, int dy,
300  unsigned char *up2, unsigned char *up1, unsigned char *up0 )
301{
302      ZPCodec &zp=*gzp;
303      // iterate on rows (encoding)
304      while (dy >= 0)
305        {
306          int context=get_direct_context(up2, up1, up0, 0);
307          for (int dx=0;dx < dw;)
308            {
309              int n = up0[dx++];
310              zp.encoder(n, bitdist[context]);
311              context=shift_direct_context(context, n, up2, up1, up0, dx);
312            }
313          // next row
314          dy -= 1;
315          up2 = up1;
316          up1 = up0;
317          up0 = bm[dy];
318        }
319}
320
321// CODE BITMAP BY CROSS CODING
322
323void 
324JB2Dict::JB2Codec::Encode::code_bitmap_by_cross_coding (GBitmap &bm, GBitmap &cbm,
325  const int xd2c, const int dw, int dy, int cy,
326  unsigned char *up1, unsigned char *up0, unsigned char *xup1, 
327  unsigned char *xup0, unsigned char *xdn1 )
328{
329      ZPCodec &zp=*gzp;
330      // iterate on rows (encoding)
331      while (dy >= 0)
332        {
333          int context=get_cross_context(up1, up0, xup1, xup0, xdn1, 0);
334          for(int dx=0;dx < dw;)
335            {
336              const int n = up0[dx++];
337              zp.encoder(n, cbitdist[context]);
338              context=shift_cross_context(context, n, 
339                                  up1, up0, xup1, xup0, xdn1, dx);
340            }
341          // next row
342          up1 = up0;
343          up0 = bm[--dy];
344          xup1 = xup0;
345          xup0 = xdn1;
346          xdn1 = cbm[(--cy)-1] + xd2c;
347        }
348}
349
350// CODE JB2DICT
351
352void 
353JB2Dict::JB2Codec::Encode::code(const GP<JB2Dict> &gjim)
354{
355  if(!gjim)
356  {
357    G_THROW( ERR_MSG("JB2Image.bad_number") );
358  }
359  JB2Dict &jim=*gjim;
360      // -------------------------
361      // THIS IS THE ENCODING PART
362      // -------------------------
363      int firstshape = jim.get_inherited_shape_count();
364      int nshape = jim.get_shape_count();
365      init_library(jim);
366      // Code headers.
367      int rectype = REQUIRED_DICT_OR_RESET;
368      if (jim.get_inherited_shape_count() > 0)
369        code_record(rectype, gjim, 0);
370      rectype = START_OF_DATA;
371      code_record(rectype, gjim, 0);
372      // Code Comment.
373      rectype = PRESERVED_COMMENT;
374      if (!! jim.comment)
375        code_record(rectype, gjim, 0);
376      // Encode every shape
377      int shapeno;
378      DJVU_PROGRESS_TASK(jb2code,"jb2 encode", nshape-firstshape);
379      for (shapeno=firstshape; shapeno<nshape; shapeno++)
380        {
381          DJVU_PROGRESS_RUN(jb2code, (shapeno-firstshape)|0xff);
382          // Code shape
383          JB2Shape &jshp = jim.get_shape(shapeno);
384          rectype=(jshp.parent >= 0)
385            ?MATCHED_REFINE_LIBRARY_ONLY:NEW_MARK_LIBRARY_ONLY;
386          code_record(rectype, gjim, &jshp);
387          add_library(shapeno, jshp);
388          // Check numcoder status
389          if (cur_ncell > CELLCHUNK) 
390            {
391              rectype = REQUIRED_DICT_OR_RESET;
392              code_record(rectype, 0, 0);             
393            }
394        }
395      // Code end of data record
396      rectype = END_OF_DATA;
397      code_record(rectype, gjim, 0); 
398      gzp=0;
399}
400
401// CODE JB2IMAGE
402
403void 
404JB2Dict::JB2Codec::Encode::code(const GP<JB2Image> &gjim)
405{
406  if(!gjim)
407  {
408    G_THROW( ERR_MSG("JB2Image.bad_number") );
409  }
410  JB2Image &jim=*gjim;
411      // -------------------------
412      // THIS IS THE ENCODING PART
413      // -------------------------
414      int i;
415      init_library(jim);
416      int firstshape = jim.get_inherited_shape_count();
417      int nshape = jim.get_shape_count();
418      int nblit = jim.get_blit_count();
419      // Initialize shape2lib
420      shape2lib.resize(0,nshape-1);
421      for (i=firstshape; i<nshape; i++)
422        shape2lib[i] = -1;
423      // Determine shapes that go into library (shapeno>=firstshape)
424      //  shape2lib is -2 if used by one blit
425      //  shape2lib is -3 if used by more than one blit
426      //  shape2lib is -4 if used as a parent
427      for (i=0; i<nblit; i++)
428        {
429          JB2Blit *jblt = jim.get_blit(i);
430          int shapeno = jblt->shapeno;
431          if (shapeno < firstshape)
432            continue;
433          if (shape2lib[shapeno] >= -2) 
434            shape2lib[shapeno] -= 1;
435          shapeno = jim.get_shape(shapeno).parent;
436          while (shapeno>=firstshape && shape2lib[shapeno]>=-3)
437            {
438              shape2lib[shapeno] = -4;
439              shapeno = jim.get_shape(shapeno).parent;
440            }
441        }
442      // Code headers.
443      int rectype = REQUIRED_DICT_OR_RESET;
444      if (jim.get_inherited_shape_count() > 0)
445        code_record(rectype, gjim, 0, 0);
446      rectype = START_OF_DATA;
447      code_record(rectype, gjim, 0, 0);
448      // Code Comment.
449      rectype = PRESERVED_COMMENT;
450      if (!! jim.comment)
451        code_record(rectype, gjim, 0, 0);
452      // Encode every blit
453      int blitno;
454      DJVU_PROGRESS_TASK(jb2code,"jb2 encode", nblit);
455      for (blitno=0; blitno<nblit; blitno++)
456        {
457          DJVU_PROGRESS_RUN(jb2code, blitno|0xff);
458          JB2Blit *jblt = jim.get_blit(blitno);
459          int shapeno = jblt->shapeno;
460          JB2Shape &jshp = jim.get_shape(shapeno);
461          // Tests if shape exists in library
462          if (shape2lib[shapeno] >= 0)
463            {
464              int rectype = MATCHED_COPY;
465              code_record(rectype, gjim, 0, jblt);
466            }
467          // Avoid coding null shapes/blits
468          else if (jshp.bits) 
469            {
470              // Make sure all parents have been coded
471              if (jshp.parent>=0 && shape2lib[jshp.parent]<0)
472                encode_libonly_shape(gjim, jshp.parent);
473              // Allocate library entry when needed
474#define LIBRARY_CONTAINS_ALL
475              int libraryp = 0;
476#ifdef LIBRARY_CONTAINS_MARKS // baseline
477              if (jshp.parent >= -1)
478                libraryp = 1;
479#endif
480#ifdef LIBRARY_CONTAINS_SHARED // worse             
481              if (shape2lib[shapeno] <= -3)
482                libraryp = 1;
483#endif
484#ifdef LIBRARY_CONTAINS_ALL // better
485              libraryp = 1;
486#endif
487              // Test all blit cases
488              if (jshp.parent<-1 && !libraryp)
489                {
490                  int rectype = NON_MARK_DATA;
491                  code_record(rectype, gjim, &jshp, jblt);
492                }
493              else if (jshp.parent < 0)
494                {
495                  int rectype = (libraryp ? NEW_MARK : NEW_MARK_IMAGE_ONLY);
496                  code_record(rectype, gjim, &jshp, jblt);
497                }
498              else 
499                {
500                  int rectype = (libraryp ? MATCHED_REFINE : MATCHED_REFINE_IMAGE_ONLY);
501                  code_record(rectype, gjim, &jshp, jblt);
502                }
503              // Add shape to library
504              if (libraryp) 
505                add_library(shapeno, jshp);
506            }
507          // Check numcoder status
508          if (cur_ncell > CELLCHUNK) 
509            {
510              rectype = REQUIRED_DICT_OR_RESET;
511              code_record(rectype, 0, 0);
512            }
513        }
514      // Code end of data record
515      rectype = END_OF_DATA;
516      code_record(rectype, gjim, 0, 0); 
517      gzp=0;
518}
519
520////////////////////////////////////////
521//// HELPERS
522////////////////////////////////////////
523
524void 
525JB2Dict::JB2Codec::Encode::encode_libonly_shape(
526  const GP<JB2Image> &gjim, int shapeno )
527{
528  if(!gjim)
529  {
530    G_THROW( ERR_MSG("JB2Image.bad_number") );
531  }
532  JB2Image &jim=*gjim;
533  // Recursively encode parent shape
534  JB2Shape &jshp = jim.get_shape(shapeno);
535  if (jshp.parent>=0 && shape2lib[jshp.parent]<0)
536    encode_libonly_shape(gjim, jshp.parent);
537  // Test that library shape must be encoded
538  if (shape2lib[shapeno] < 0)
539    {
540      // Code library entry
541      int rectype=(jshp.parent >= 0)
542            ?NEW_MARK_LIBRARY_ONLY:MATCHED_REFINE_LIBRARY_ONLY;
543      code_record(rectype, gjim, &jshp, 0);     
544      // Add shape to library
545      add_library(shapeno, jshp);
546      // Check numcoder status
547      if (cur_ncell > CELLCHUNK) 
548        {
549          rectype = REQUIRED_DICT_OR_RESET;
550          code_record(rectype, 0, 0);
551        }
552    }
553}
554
555
556#ifdef HAVE_NAMESPACES
557}
558# ifndef NOT_USING_DJVU_NAMESPACE
559using namespace DJVU;
560# endif
561#endif
562
563#endif /* NEED_DECODER_ONLY */
564
Note: See TracBrowser for help on using the repository browser.