source: trunk/libdjvu/JB2EncodeCodec.cpp @ 269

Last change on this file since 269 was 206, checked in by Eugene Romanenko, 14 years ago

DJVU plugin: djvulibre updated to version 3.5.19

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