void 
JB2Dict::JB2Codec::code_bitmap_by_cross_coding (GBitmap &bm, GP<GBitmap> &cbm, const int libno)
{
  // Make sure bitmaps will not be disturbed
  GP<GBitmap> copycbm=GBitmap::create();
  if (cbm->monitor())
    {
      // Perform a copy when the bitmap is explicitely shared
      GMonitorLock lock2(cbm->monitor());
      copycbm->init(*cbm);
      cbm = copycbm;
    }
  GMonitorLock lock1(bm.monitor());
  // Center bitmaps
  const int cw = cbm->columns();
  const int dw = bm.columns();
  const int dh = bm.rows();
  const LibRect &l = libinfo[libno];
  const int xd2c = (dw/2 - dw + 1) - ((l.right - l.left + 1)/2 - l.right);
  const int yd2c = (dh/2 - dh + 1) - ((l.top - l.bottom + 1)/2 - l.top);
  // Ensure borders are adequate
  bm.minborder(2);
  cbm->minborder(2-xd2c);
  cbm->minborder(2+dw+xd2c-cw);
  // Initialize row pointers
  const int dy = dh - 1;
  const int cy = dy + yd2c;
#ifndef NDEBUG
  bm.check_border();
  cbm->check_border();
#endif
  code_bitmap_by_cross_coding (bm,*cbm, xd2c, dw, dy, cy, bm[dy+1], bm[dy],
    (*cbm)[cy+1] + xd2c, (*cbm)[cy  ] + xd2c, (*cbm)[cy-1] + xd2c);
}
void 
JB2Dict::JB2Codec::Decode::code_bitmap_by_cross_coding (GBitmap &bm, GBitmap &cbm,
  const int xd2c, const int dw, int dy, int cy,
  unsigned char *up1, unsigned char *up0, unsigned char *xup1, 
  unsigned char *xup0, unsigned char *xdn1 )
{
      ZPCodec &zp=*gzp;
      // iterate on rows (decoding)      
      while (dy >= 0)
        {
          int context=get_cross_context(
                            up1, up0, xup1, xup0, xdn1, 0);
          for(int dx=0;dx < dw;)
            {
              const int n = zp.decoder(cbitdist[context]);
              up0[dx++] = n;
              context=shift_cross_context(context, n,  
                                  up1, up0, xup1, xup0, xdn1, dx);
            }
          // next row
          up1 = up0;
          up0 = bm[--dy];
          xup1 = xup0;
          xup0 = xdn1;
          xdn1 = cbm[(--cy)-1] + xd2c;
#ifndef NDEBUG
          bm.check_border();
#endif
        }
}
void 
JB2Dict::JB2Codec::Decode::code_bitmap_directly(
  GBitmap &bm,const int dw, int dy,
  unsigned char *up2, unsigned char *up1, unsigned char *up0 )
{
      ZPCodec &zp=*gzp;
      // iterate on rows (decoding)      
      while (dy >= 0)
        {
          int context=get_direct_context(up2, up1, up0, 0);
          for(int dx=0;dx < dw;)
            {
              int n = zp.decoder(bitdist[context]);
              up0[dx++] = n;
              context=shift_direct_context(context, n, up2, up1, up0, dx);
            }
          // next row
          dy -= 1;
          up2 = up1;
          up1 = up0;
          up0 = bm[dy];
        }
#ifndef NDEBUG
      bm.check_border();
#endif
}