00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 #ifdef HAVE_CONFIG_H
00058 # include "config.h"
00059 #endif
00060 #if NEED_GNUG_PRAGMAS
00061 # pragma implementation
00062 #endif
00063
00064
00065
00066
00067
00068 #ifndef NEED_DECODER_ONLY
00069
00070 #include "JB2Image.h"
00071 #include "GBitmap.h"
00072 #include <string.h>
00073
00074
00075 #ifdef HAVE_NAMESPACES
00076 namespace DJVU {
00077 # ifdef NOT_DEFINED // Just to fool emacs c++ mode
00078 }
00079 #endif
00080 #endif
00081
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 class JB2Dict::JB2Codec::Encode : public JB2Dict::JB2Codec
00095 {
00096 public:
00097 Encode(void);
00098 void init(const GP<ByteStream> &gbs);
00099
00100 void code(const GP<JB2Image> &jim);
00101 void code(JB2Image *jim) { const GP<JB2Image> gjim(jim);code(gjim); }
00102 void code(const GP<JB2Dict> &jim);
00103 void code(JB2Dict *jim) { const GP<JB2Dict> gjim(jim);code(gjim); }
00104
00105 protected:
00106 void CodeNum(const int num, const int lo, const int hi, NumContext &ctx);
00107 void encode_libonly_shape(const GP<JB2Image> &jim, int shapeno);
00108
00109 bool CodeBit(const bool bit, BitContext &ctx);
00110 void code_comment(GUTF8String &comment);
00111 void code_record_type(int &rectype);
00112 int code_match_index(int &index, JB2Dict &jim);
00113 void code_inherited_shape_count(JB2Dict &jim);
00114 void code_image_size(JB2Dict &jim);
00115 void code_image_size(JB2Image &jim);
00116 void code_absolute_location(JB2Blit *jblt, int rows, int columns);
00117 void code_absolute_mark_size(GBitmap &bm, int border=0);
00118 void code_relative_mark_size(GBitmap &bm, int cw, int ch, int border=0);
00119 void code_bitmap_directly(GBitmap &bm,const int dw, int dy,
00120 unsigned char *up2, unsigned char *up1, unsigned char *up0 );
00121 int get_diff(const int x_diff,NumContext &rel_loc);
00122 void code_bitmap_by_cross_coding (GBitmap &bm, GBitmap &cbm,
00123 const int xd2c, const int dw, int dy, int cy,
00124 unsigned char *up1, unsigned char *up0, unsigned char *xup1,
00125 unsigned char *xup0, unsigned char *xdn1 );
00126
00127 private:
00128 GP<ZPCodec> gzp;
00129 };
00130
00131
00135
00136 void
00137 JB2Dict::encode(const GP<ByteStream> &gbs) const
00138 {
00139 JB2Codec::Encode codec;
00140 codec.init(gbs);
00141 codec.code(const_cast<JB2Dict *>(this));
00142 }
00143
00147
00148 void
00149 JB2Image::encode(const GP<ByteStream> &gbs) const
00150 {
00151 JB2Codec::Encode codec;
00152 codec.init(gbs);
00153 codec.code(const_cast<JB2Image *>(this));
00154 }
00155
00159
00160 #define START_OF_DATA (0)
00161 #define NEW_MARK (1)
00162 #define NEW_MARK_LIBRARY_ONLY (2)
00163 #define NEW_MARK_IMAGE_ONLY (3)
00164 #define MATCHED_REFINE (4)
00165 #define MATCHED_REFINE_LIBRARY_ONLY (5)
00166 #define MATCHED_REFINE_IMAGE_ONLY (6)
00167 #define MATCHED_COPY (7)
00168 #define NON_MARK_DATA (8)
00169 #define REQUIRED_DICT_OR_RESET (9)
00170 #define PRESERVED_COMMENT (10)
00171 #define END_OF_DATA (11)
00172
00173
00174
00175 static const int BIGPOSITIVE = 262142;
00176 static const int BIGNEGATIVE = -262143;
00177 static const int CELLCHUNK = 20000;
00178 static const int CELLEXTRA = 500;
00179
00180
00181
00182 JB2Dict::JB2Codec::Encode::Encode(void)
00183 : JB2Dict::JB2Codec(1) {}
00184
00185 void
00186 JB2Dict::JB2Codec::Encode::init(const GP<ByteStream> &gbs)
00187 {
00188 gzp=ZPCodec::create(gbs,true,true);
00189 }
00190
00191 inline bool
00192 JB2Dict::JB2Codec::Encode::CodeBit(const bool bit, BitContext &ctx)
00193 {
00194 gzp->encoder(bit?1:0, ctx);
00195 return bit;
00196 }
00197
00198 void
00199 JB2Dict::JB2Codec::Encode::CodeNum(int num, int low, int high, NumContext &ctx)
00200 {
00201 if (num < low || num > high)
00202 G_THROW( ERR_MSG("JB2Image.bad_number") );
00203 JB2Codec::CodeNum(low,high,&ctx,num);
00204 }
00205
00206
00207
00208 void
00209 JB2Dict::JB2Codec::Encode::code_comment(GUTF8String &comment)
00210 {
00211
00212 int size=comment.length();
00213 CodeNum(size, 0, BIGPOSITIVE, dist_comment_length);
00214 for (int i=0; i<size; i++)
00215 {
00216 CodeNum(comment[i], 0, 255, dist_comment_byte);
00217 }
00218 }
00219
00220
00221
00222 inline void
00223 JB2Dict::JB2Codec::Encode::code_record_type(int &rectype)
00224 {
00225 CodeNum(rectype, START_OF_DATA, END_OF_DATA, dist_record_type);
00226 }
00227
00228 int
00229 JB2Dict::JB2Codec::Encode::code_match_index(int &index, JB2Dict &jim)
00230 {
00231 int match=shape2lib[index];
00232 CodeNum(match, 0, lib2shape.hbound(), dist_match_index);
00233 return match;
00234 }
00235
00236
00237
00238 void
00239 JB2Dict::JB2Codec::Encode::code_inherited_shape_count(JB2Dict &jim)
00240 {
00241 CodeNum(jim.get_inherited_shape_count(),
00242 0, BIGPOSITIVE, inherited_shape_count_dist);
00243 }
00244
00245 void
00246 JB2Dict::JB2Codec::Encode::code_image_size(JB2Dict &jim)
00247 {
00248 CodeNum(0, 0, BIGPOSITIVE, image_size_dist);
00249 CodeNum(0, 0, BIGPOSITIVE, image_size_dist);
00250 JB2Codec::code_image_size(jim);
00251 }
00252
00253 void
00254 JB2Dict::JB2Codec::Encode::code_image_size(JB2Image &jim)
00255 {
00256 image_columns = jim.get_width();
00257 CodeNum(image_columns, 0, BIGPOSITIVE, image_size_dist);
00258 image_rows = jim.get_height();
00259 CodeNum(image_rows, 0, BIGPOSITIVE, image_size_dist);
00260 JB2Codec::code_image_size(jim);
00261 }
00262
00263 inline int
00264 JB2Dict::JB2Codec::Encode::get_diff(int x_diff,NumContext &rel_loc)
00265 {
00266 CodeNum(x_diff, BIGNEGATIVE, BIGPOSITIVE, rel_loc);
00267 return x_diff;
00268 }
00269
00270 void
00271 JB2Dict::JB2Codec::Encode::code_absolute_location(JB2Blit *jblt, int rows, int columns)
00272 {
00273
00274 if (!gotstartrecordp)
00275 G_THROW( ERR_MSG("JB2Image.no_start") );
00276
00277 CodeNum(jblt->left+1, 1, image_columns, abs_loc_x);
00278 CodeNum(jblt->bottom+rows-1+1, 1, image_rows, abs_loc_y);
00279 }
00280
00281 void
00282 JB2Dict::JB2Codec::Encode::code_absolute_mark_size(GBitmap &bm, int border)
00283 {
00284 CodeNum(bm.columns(), 0, BIGPOSITIVE, abs_size_x);
00285 CodeNum(bm.rows(), 0, BIGPOSITIVE, abs_size_y);
00286 }
00287
00288 void
00289 JB2Dict::JB2Codec::Encode::code_relative_mark_size(GBitmap &bm, int cw, int ch, int border)
00290 {
00291 CodeNum(bm.columns()-cw, BIGNEGATIVE, BIGPOSITIVE, rel_size_x);
00292 CodeNum(bm.rows()-ch, BIGNEGATIVE, BIGPOSITIVE, rel_size_y);
00293 }
00294
00295
00296
00297 void
00298 JB2Dict::JB2Codec::Encode::code_bitmap_directly(
00299 GBitmap &bm,const int dw, int dy,
00300 unsigned char *up2, unsigned char *up1, unsigned char *up0 )
00301 {
00302 ZPCodec &zp=*gzp;
00303
00304 while (dy >= 0)
00305 {
00306 int context=get_direct_context(up2, up1, up0, 0);
00307 for (int dx=0;dx < dw;)
00308 {
00309 int n = up0[dx++];
00310 zp.encoder(n, bitdist[context]);
00311 context=shift_direct_context(context, n, up2, up1, up0, dx);
00312 }
00313
00314 dy -= 1;
00315 up2 = up1;
00316 up1 = up0;
00317 up0 = bm[dy];
00318 }
00319 }
00320
00321
00322
00323 void
00324 JB2Dict::JB2Codec::Encode::code_bitmap_by_cross_coding (GBitmap &bm, GBitmap &cbm,
00325 const int xd2c, const int dw, int dy, int cy,
00326 unsigned char *up1, unsigned char *up0, unsigned char *xup1,
00327 unsigned char *xup0, unsigned char *xdn1 )
00328 {
00329 ZPCodec &zp=*gzp;
00330
00331 while (dy >= 0)
00332 {
00333 int context=get_cross_context(up1, up0, xup1, xup0, xdn1, 0);
00334 for(int dx=0;dx < dw;)
00335 {
00336 const int n = up0[dx++];
00337 zp.encoder(n, cbitdist[context]);
00338 context=shift_cross_context(context, n,
00339 up1, up0, xup1, xup0, xdn1, dx);
00340 }
00341
00342 up1 = up0;
00343 up0 = bm[--dy];
00344 xup1 = xup0;
00345 xup0 = xdn1;
00346 xdn1 = cbm[(--cy)-1] + xd2c;
00347 }
00348 }
00349
00350
00351
00352 void
00353 JB2Dict::JB2Codec::Encode::code(const GP<JB2Dict> &gjim)
00354 {
00355 if(!gjim)
00356 {
00357 G_THROW( ERR_MSG("JB2Image.bad_number") );
00358 }
00359 JB2Dict &jim=*gjim;
00360
00361
00362
00363 int firstshape = jim.get_inherited_shape_count();
00364 int nshape = jim.get_shape_count();
00365 init_library(jim);
00366
00367 int rectype = REQUIRED_DICT_OR_RESET;
00368 if (jim.get_inherited_shape_count() > 0)
00369 code_record(rectype, gjim, 0);
00370 rectype = START_OF_DATA;
00371 code_record(rectype, gjim, 0);
00372
00373 rectype = PRESERVED_COMMENT;
00374 if (!! jim.comment)
00375 code_record(rectype, gjim, 0);
00376
00377 int shapeno;
00378 DJVU_PROGRESS_TASK(jb2code,"jb2 encode", nshape-firstshape);
00379 for (shapeno=firstshape; shapeno<nshape; shapeno++)
00380 {
00381 DJVU_PROGRESS_RUN(jb2code, (shapeno-firstshape)|0xff);
00382
00383 JB2Shape &jshp = jim.get_shape(shapeno);
00384 rectype=(jshp.parent >= 0)
00385 ?MATCHED_REFINE_LIBRARY_ONLY:NEW_MARK_LIBRARY_ONLY;
00386 code_record(rectype, gjim, &jshp);
00387 add_library(shapeno, jshp);
00388
00389 if (cur_ncell > CELLCHUNK)
00390 {
00391 rectype = REQUIRED_DICT_OR_RESET;
00392 code_record(rectype, 0, 0);
00393 }
00394 }
00395
00396 rectype = END_OF_DATA;
00397 code_record(rectype, gjim, 0);
00398 gzp=0;
00399 }
00400
00401
00402
00403 void
00404 JB2Dict::JB2Codec::Encode::code(const GP<JB2Image> &gjim)
00405 {
00406 if(!gjim)
00407 {
00408 G_THROW( ERR_MSG("JB2Image.bad_number") );
00409 }
00410 JB2Image &jim=*gjim;
00411
00412
00413
00414 int i;
00415 init_library(jim);
00416 int firstshape = jim.get_inherited_shape_count();
00417 int nshape = jim.get_shape_count();
00418 int nblit = jim.get_blit_count();
00419
00420 shape2lib.resize(0,nshape-1);
00421 for (i=firstshape; i<nshape; i++)
00422 shape2lib[i] = -1;
00423
00424
00425
00426
00427 for (i=0; i<nblit; i++)
00428 {
00429 JB2Blit *jblt = jim.get_blit(i);
00430 int shapeno = jblt->shapeno;
00431 if (shapeno < firstshape)
00432 continue;
00433 if (shape2lib[shapeno] >= -2)
00434 shape2lib[shapeno] -= 1;
00435 shapeno = jim.get_shape(shapeno).parent;
00436 while (shapeno>=firstshape && shape2lib[shapeno]>=-3)
00437 {
00438 shape2lib[shapeno] = -4;
00439 shapeno = jim.get_shape(shapeno).parent;
00440 }
00441 }
00442
00443 int rectype = REQUIRED_DICT_OR_RESET;
00444 if (jim.get_inherited_shape_count() > 0)
00445 code_record(rectype, gjim, 0, 0);
00446 rectype = START_OF_DATA;
00447 code_record(rectype, gjim, 0, 0);
00448
00449 rectype = PRESERVED_COMMENT;
00450 if (!! jim.comment)
00451 code_record(rectype, gjim, 0, 0);
00452
00453 int blitno;
00454 DJVU_PROGRESS_TASK(jb2code,"jb2 encode", nblit);
00455 for (blitno=0; blitno<nblit; blitno++)
00456 {
00457 DJVU_PROGRESS_RUN(jb2code, blitno|0xff);
00458 JB2Blit *jblt = jim.get_blit(blitno);
00459 int shapeno = jblt->shapeno;
00460 JB2Shape &jshp = jim.get_shape(shapeno);
00461
00462 if (shape2lib[shapeno] >= 0)
00463 {
00464 int rectype = MATCHED_COPY;
00465 code_record(rectype, gjim, 0, jblt);
00466 }
00467
00468 else if (jshp.bits)
00469 {
00470
00471 if (jshp.parent>=0 && shape2lib[jshp.parent]<0)
00472 encode_libonly_shape(gjim, jshp.parent);
00473
00474 #define LIBRARY_CONTAINS_ALL
00475 int libraryp = 0;
00476 #ifdef LIBRARY_CONTAINS_MARKS // baseline
00477 if (jshp.parent >= -1)
00478 libraryp = 1;
00479 #endif
00480 #ifdef LIBRARY_CONTAINS_SHARED // worse
00481 if (shape2lib[shapeno] <= -3)
00482 libraryp = 1;
00483 #endif
00484 #ifdef LIBRARY_CONTAINS_ALL // better
00485 libraryp = 1;
00486 #endif
00487
00488 if (jshp.parent<-1 && !libraryp)
00489 {
00490 int rectype = NON_MARK_DATA;
00491 code_record(rectype, gjim, &jshp, jblt);
00492 }
00493 else if (jshp.parent < 0)
00494 {
00495 int rectype = (libraryp ? NEW_MARK : NEW_MARK_IMAGE_ONLY);
00496 code_record(rectype, gjim, &jshp, jblt);
00497 }
00498 else
00499 {
00500 int rectype = (libraryp ? MATCHED_REFINE : MATCHED_REFINE_IMAGE_ONLY);
00501 code_record(rectype, gjim, &jshp, jblt);
00502 }
00503
00504 if (libraryp)
00505 add_library(shapeno, jshp);
00506 }
00507
00508 if (cur_ncell > CELLCHUNK)
00509 {
00510 rectype = REQUIRED_DICT_OR_RESET;
00511 code_record(rectype, 0, 0);
00512 }
00513 }
00514
00515 rectype = END_OF_DATA;
00516 code_record(rectype, gjim, 0, 0);
00517 gzp=0;
00518 }
00519
00523
00524 void
00525 JB2Dict::JB2Codec::Encode::encode_libonly_shape(
00526 const GP<JB2Image> &gjim, int shapeno )
00527 {
00528 if(!gjim)
00529 {
00530 G_THROW( ERR_MSG("JB2Image.bad_number") );
00531 }
00532 JB2Image &jim=*gjim;
00533
00534 JB2Shape &jshp = jim.get_shape(shapeno);
00535 if (jshp.parent>=0 && shape2lib[jshp.parent]<0)
00536 encode_libonly_shape(gjim, jshp.parent);
00537
00538 if (shape2lib[shapeno] < 0)
00539 {
00540
00541 int rectype=(jshp.parent >= 0)
00542 ?NEW_MARK_LIBRARY_ONLY:MATCHED_REFINE_LIBRARY_ONLY;
00543 code_record(rectype, gjim, &jshp, 0);
00544
00545 add_library(shapeno, jshp);
00546
00547 if (cur_ncell > CELLCHUNK)
00548 {
00549 rectype = REQUIRED_DICT_OR_RESET;
00550 code_record(rectype, 0, 0);
00551 }
00552 }
00553 }
00554
00555
00556 #ifdef HAVE_NAMESPACES
00557 }
00558 # ifndef NOT_USING_DJVU_NAMESPACE
00559 using namespace DJVU;
00560 # endif
00561 #endif
00562
00563 #endif
00564