Blame libdjvu/GBitmap.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 "GBitmap.h"
Packit df99a1
#include "ByteStream.h"
Packit df99a1
#include "GRect.h"
Packit df99a1
#include "GString.h"
Packit df99a1
#include "GThreads.h"
Packit df99a1
#include "GException.h"
Packit df99a1
#include <stddef.h>
Packit df99a1
#include <stdlib.h>
Packit df99a1
#include <string.h>
Packit df99a1
Packit df99a1
// - Author: Leon Bottou, 05/1997
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
// ----- constructor and destructor
Packit df99a1
Packit df99a1
GBitmap::~GBitmap()
Packit df99a1
{
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
GBitmap::destroy(void)
Packit df99a1
{
Packit df99a1
  gbytes_data.resize(0);
Packit df99a1
  bytes = 0;
Packit df99a1
  grle.resize(0);
Packit df99a1
  grlerows.resize(0);
Packit df99a1
  rlelength = 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
GBitmap::GBitmap()
Packit df99a1
  : nrows(0), ncolumns(0), border(0), 
Packit df99a1
    bytes_per_row(0), grays(0), bytes(0), gbytes_data(bytes_data), 
Packit df99a1
    grle(rle), grlerows(rlerows), rlelength(0),
Packit df99a1
    monitorptr(0)
Packit df99a1
{
Packit df99a1
}
Packit df99a1
Packit df99a1
GBitmap::GBitmap(int nrows, int ncolumns, int border)
Packit df99a1
  : nrows(0), ncolumns(0), border(0), 
Packit df99a1
    bytes_per_row(0), grays(0), bytes(0), gbytes_data(bytes_data), 
Packit df99a1
    grle(rle), grlerows(rlerows), rlelength(0),
Packit df99a1
    monitorptr(0)
Packit df99a1
{
Packit df99a1
  G_TRY
Packit df99a1
  { 
Packit df99a1
    init(nrows, ncolumns, border);
Packit df99a1
  }
Packit df99a1
  G_CATCH_ALL
Packit df99a1
  {
Packit df99a1
    destroy();
Packit df99a1
    G_RETHROW;
Packit df99a1
  }
Packit df99a1
  G_ENDCATCH;
Packit df99a1
}
Packit df99a1
Packit df99a1
GBitmap::GBitmap(ByteStream &ref, int border)
Packit df99a1
  : nrows(0), ncolumns(0), border(0), 
Packit df99a1
    bytes_per_row(0), grays(0), bytes(0), gbytes_data(bytes_data),
Packit df99a1
    grle(rle), grlerows(rlerows), rlelength(0),
Packit df99a1
    monitorptr(0)
Packit df99a1
{
Packit df99a1
  G_TRY
Packit df99a1
  { 
Packit df99a1
    init(ref, border);
Packit df99a1
  }
Packit df99a1
  G_CATCH_ALL
Packit df99a1
  {
Packit df99a1
    destroy();
Packit df99a1
    G_RETHROW;
Packit df99a1
  }
Packit df99a1
  G_ENDCATCH;
Packit df99a1
}
Packit df99a1
Packit df99a1
GBitmap::GBitmap(const GBitmap &ref)
Packit df99a1
  : nrows(0), ncolumns(0), border(0), 
Packit df99a1
    bytes_per_row(0), grays(0), bytes(0), gbytes_data(bytes_data), 
Packit df99a1
    grle(rle), grlerows(rlerows), rlelength(0),
Packit df99a1
    monitorptr(0)
Packit df99a1
{
Packit df99a1
  G_TRY
Packit df99a1
  { 
Packit df99a1
    init(ref, ref.border);
Packit df99a1
  }
Packit df99a1
  G_CATCH_ALL
Packit df99a1
  {
Packit df99a1
    destroy();
Packit df99a1
    G_RETHROW;
Packit df99a1
  }
Packit df99a1
  G_ENDCATCH;
Packit df99a1
}
Packit df99a1
Packit df99a1
GBitmap::GBitmap(const GBitmap &ref, int border)
Packit df99a1
  : nrows(0), ncolumns(0), border(0), 
Packit df99a1
    bytes_per_row(0), grays(0), bytes(0), gbytes_data(bytes_data),
Packit df99a1
    grle(rle), grlerows(rlerows), rlelength(0),
Packit df99a1
    monitorptr(0)
Packit df99a1
{
Packit df99a1
  G_TRY
Packit df99a1
  { 
Packit df99a1
    init(ref, border);
Packit df99a1
  }
Packit df99a1
  G_CATCH_ALL
Packit df99a1
  {
Packit df99a1
    destroy();
Packit df99a1
    G_RETHROW;
Packit df99a1
  }
Packit df99a1
  G_ENDCATCH;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
GBitmap::GBitmap(const GBitmap &ref, const GRect &rect, int border)
Packit df99a1
  : nrows(0), ncolumns(0), border(0), 
Packit df99a1
    bytes_per_row(0), grays(0), bytes(0), gbytes_data(bytes_data),
Packit df99a1
    grle(rle), grlerows(rlerows), rlelength(0),
Packit df99a1
    monitorptr(0)
Packit df99a1
{
Packit df99a1
  G_TRY
Packit df99a1
  { 
Packit df99a1
    init(ref, rect, border);
Packit df99a1
  }
Packit df99a1
  G_CATCH_ALL
Packit df99a1
  {
Packit df99a1
    destroy();
Packit df99a1
    G_RETHROW;
Packit df99a1
  }
Packit df99a1
  G_ENDCATCH;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
// ----- initialization
Packit df99a1
Packit df99a1
void 
Packit df99a1
GBitmap::init(int arows, int acolumns, int aborder)
Packit df99a1
{
Packit df99a1
  if (arows != (unsigned short) arows ||
Packit df99a1
      acolumns != (unsigned short) acolumns ||
Packit df99a1
      acolumns + aborder != (unsigned short)(acolumns + aborder))
Packit df99a1
    G_THROW("Illegal arguments");
Packit df99a1
  GMonitorLock lock(monitor());
Packit df99a1
  destroy();
Packit df99a1
  grays = 2;
Packit df99a1
  nrows = arows;
Packit df99a1
  ncolumns = acolumns;
Packit df99a1
  border = aborder;
Packit df99a1
  bytes_per_row = ncolumns + border;
Packit df99a1
  int npixels = nrows * bytes_per_row + border;
Packit df99a1
  gzerobuffer=zeroes(bytes_per_row + border);
Packit df99a1
  if (npixels > 0) 
Packit df99a1
    {
Packit df99a1
      gbytes_data.resize(npixels);
Packit df99a1
      gbytes_data.clear();
Packit df99a1
      bytes = bytes_data;
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
void 
Packit df99a1
GBitmap::init(const GBitmap &ref, int aborder)
Packit df99a1
{
Packit df99a1
  GMonitorLock lock(monitor());
Packit df99a1
  if (this != &ref) 
Packit df99a1
    {
Packit df99a1
      GMonitorLock lock(ref.monitor());
Packit df99a1
      init(ref.nrows, ref.ncolumns, aborder);
Packit df99a1
      grays = ref.grays;
Packit df99a1
      unsigned char *row = bytes_data+border;
Packit df99a1
      for (int n=0; n
Packit df99a1
      memcpy( (void*)row, (void*)ref[n],  ncolumns );
Packit df99a1
    }
Packit df99a1
  else if (aborder > border)
Packit df99a1
    {
Packit df99a1
      minborder(aborder);
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
void 
Packit df99a1
GBitmap::init(const GBitmap &ref, const GRect &rect, int border)
Packit df99a1
{
Packit df99a1
  GMonitorLock lock(monitor());
Packit df99a1
  // test bitmap physical equality
Packit df99a1
  if (this == &ref)
Packit df99a1
    {
Packit df99a1
      GBitmap tmp;
Packit df99a1
      tmp.grays = grays;
Packit df99a1
      tmp.border = border;
Packit df99a1
      tmp.bytes_per_row = bytes_per_row;
Packit df99a1
      tmp.ncolumns = ncolumns;
Packit df99a1
      tmp.nrows = nrows;
Packit df99a1
      tmp.bytes = bytes;
Packit df99a1
      tmp.gbytes_data.swap(gbytes_data);
Packit df99a1
      tmp.grle.swap(grle);
Packit df99a1
      bytes = 0 ;
Packit df99a1
      init(tmp, rect, border);
Packit df99a1
    }
Packit df99a1
  else
Packit df99a1
    {
Packit df99a1
      GMonitorLock lock(ref.monitor());
Packit df99a1
      // create empty bitmap
Packit df99a1
      init(rect.height(), rect.width(), border);
Packit df99a1
      grays = ref.grays;
Packit df99a1
      // compute destination rectangle
Packit df99a1
      GRect rect2(0, 0, ref.columns(), ref.rows() );
Packit df99a1
      rect2.intersect(rect2, rect);
Packit df99a1
      rect2.translate(-rect.xmin, -rect.ymin);
Packit df99a1
      // copy bits
Packit df99a1
      if (! rect2.isempty())
Packit df99a1
        {
Packit df99a1
          for (int y=rect2.ymin; y
Packit df99a1
            {
Packit df99a1
              unsigned char *dst = (*this)[y];
Packit df99a1
              const unsigned char *src = ref[y+rect.ymin] + rect.xmin;
Packit df99a1
              for (int x=rect2.xmin; x
Packit df99a1
                dst[x] = src[x];
Packit df99a1
            }
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
void 
Packit df99a1
GBitmap::init(ByteStream &ref, int aborder)
Packit df99a1
{
Packit df99a1
  GMonitorLock lock(monitor());
Packit df99a1
  // Get magic number
Packit df99a1
  char magic[2];
Packit df99a1
  magic[0] = magic[1] = 0;
Packit df99a1
  ref.readall((void*)magic, sizeof(magic));
Packit df99a1
  char lookahead = '\n';
Packit df99a1
  int acolumns = read_integer(lookahead, ref);
Packit df99a1
  int arows = read_integer(lookahead, ref);
Packit df99a1
  int maxval = 1;
Packit df99a1
  init(arows, acolumns, aborder);
Packit df99a1
  // go reading file
Packit df99a1
  if (magic[0]=='P')
Packit df99a1
    {
Packit df99a1
      switch(magic[1])
Packit df99a1
        {
Packit df99a1
        case '1':
Packit df99a1
          grays = 2;
Packit df99a1
          read_pbm_text(ref); 
Packit df99a1
          return;
Packit df99a1
        case '2':
Packit df99a1
          maxval = read_integer(lookahead, ref);
Packit df99a1
          if (maxval > 65535)
Packit df99a1
            G_THROW("Cannot read PGM with depth greater than 16 bits.");
Packit df99a1
          grays = (maxval>255 ? 256 : maxval+1);
Packit df99a1
          read_pgm_text(ref, maxval); 
Packit df99a1
          return;
Packit df99a1
        case '4':
Packit df99a1
          grays = 2;
Packit df99a1
          read_pbm_raw(ref); 
Packit df99a1
          return;
Packit df99a1
        case '5':
Packit df99a1
          maxval = read_integer(lookahead, ref);
Packit df99a1
          if (maxval > 65535)
Packit df99a1
            G_THROW("Cannot read PGM with depth greater than 16 bits.");
Packit df99a1
          grays = (maxval>255 ? 256 : maxval+1);
Packit df99a1
          read_pgm_raw(ref, maxval); 
Packit df99a1
          return;
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
  else if (magic[0]=='R')
Packit df99a1
    {
Packit df99a1
      switch(magic[1])
Packit df99a1
        {
Packit df99a1
        case '4':
Packit df99a1
          grays = 2;
Packit df99a1
          read_rle_raw(ref); 
Packit df99a1
          return;
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
  G_THROW( ERR_MSG("GBitmap.bad_format") );
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
GBitmap::donate_data(unsigned char *data, int w, int h)
Packit df99a1
{
Packit df99a1
  destroy();
Packit df99a1
  grays = 2;
Packit df99a1
  nrows = h;
Packit df99a1
  ncolumns = w;
Packit df99a1
  border = 0;
Packit df99a1
  bytes_per_row = w;
Packit df99a1
  gbytes_data.replace(data,w*h);
Packit df99a1
  bytes = bytes_data;
Packit df99a1
  rlelength = 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
GBitmap::donate_rle(unsigned char *rledata, unsigned int rledatalen, int w, int h)
Packit df99a1
{
Packit df99a1
  destroy();
Packit df99a1
  grays = 2;
Packit df99a1
  nrows = h;
Packit df99a1
  ncolumns = w;
Packit df99a1
  border = 0;
Packit df99a1
  bytes_per_row = w;
Packit df99a1
//  rle = rledata;
Packit df99a1
  grle.replace(rledata,rledatalen);
Packit df99a1
  rlelength = rledatalen;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
unsigned char *
Packit df99a1
GBitmap::take_data(size_t &offset)
Packit df99a1
{
Packit df99a1
  GMonitorLock lock(monitor());
Packit df99a1
  unsigned char *ret = bytes_data;
Packit df99a1
  if (ret) offset = (size_t)border;
Packit df99a1
  bytes_data=0;
Packit df99a1
  return ret;
Packit df99a1
}
Packit df99a1
Packit df99a1
const unsigned char *
Packit df99a1
GBitmap::get_rle(unsigned int &rle_length)
Packit df99a1
{
Packit df99a1
  if(!rle)
Packit df99a1
    compress();
Packit df99a1
  rle_length=rlelength;
Packit df99a1
  return rle; 
Packit df99a1
}
Packit df99a1
Packit df99a1
// ----- compression
Packit df99a1
Packit df99a1
Packit df99a1
void 
Packit df99a1
GBitmap::compress()
Packit df99a1
{
Packit df99a1
  if (grays > 2)
Packit df99a1
    G_THROW( ERR_MSG("GBitmap.cant_compress") );
Packit df99a1
  GMonitorLock lock(monitor());
Packit df99a1
  if (bytes)
Packit df99a1
    {
Packit df99a1
      grle.resize(0);
Packit df99a1
      grlerows.resize(0);
Packit df99a1
      rlelength = encode(rle,grle);
Packit df99a1
      if (rlelength)
Packit df99a1
        {
Packit df99a1
          gbytes_data.resize(0);
Packit df99a1
          bytes = 0;
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
GBitmap::uncompress()
Packit df99a1
{
Packit df99a1
  GMonitorLock lock(monitor());
Packit df99a1
  if (!bytes && rle)
Packit df99a1
    decode(rle);
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
unsigned int 
Packit df99a1
GBitmap::get_memory_usage() const
Packit df99a1
{
Packit df99a1
  unsigned long usage = sizeof(GBitmap);
Packit df99a1
  if (bytes)
Packit df99a1
    usage += nrows * bytes_per_row + border;
Packit df99a1
  if (rle)
Packit df99a1
    usage += rlelength;
Packit df99a1
  return usage;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
void 
Packit df99a1
GBitmap::minborder(int minimum)
Packit df99a1
{
Packit df99a1
  if (border < minimum)
Packit df99a1
    {
Packit df99a1
      GMonitorLock lock(monitor());
Packit df99a1
      if (border < minimum)
Packit df99a1
        {
Packit df99a1
          if (bytes)
Packit df99a1
            {
Packit df99a1
              GBitmap tmp(*this, minimum);
Packit df99a1
              bytes_per_row = tmp.bytes_per_row;
Packit df99a1
              tmp.gbytes_data.swap(gbytes_data);
Packit df99a1
              bytes = bytes_data;
Packit df99a1
              tmp.bytes = 0;
Packit df99a1
            }
Packit df99a1
          border = minimum;
Packit df99a1
          gzerobuffer=zeroes(border + ncolumns + border);
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
#define NMONITORS 8
Packit df99a1
static GMonitor monitors[NMONITORS];
Packit df99a1
Packit df99a1
void
Packit df99a1
GBitmap::share()
Packit df99a1
{
Packit df99a1
  if (!monitorptr)
Packit df99a1
    {
Packit df99a1
      size_t x = (size_t)this;
Packit df99a1
      monitorptr = &monitors[(x^(x>>5)) % NMONITORS];
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
// ----- gray levels
Packit df99a1
Packit df99a1
void
Packit df99a1
GBitmap::set_grays(int ngrays)
Packit df99a1
{
Packit df99a1
  if (ngrays<2 || ngrays>256)
Packit df99a1
    G_THROW( ERR_MSG("GBitmap.bad_levels") );
Packit df99a1
  // set gray levels
Packit df99a1
  GMonitorLock lock(monitor());
Packit df99a1
  grays = ngrays;
Packit df99a1
  if (ngrays>2 && !bytes)
Packit df99a1
    uncompress();
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
GBitmap::change_grays(int ngrays)
Packit df99a1
{
Packit df99a1
  GMonitorLock lock(monitor());
Packit df99a1
  // set number of grays
Packit df99a1
  int ng = ngrays - 1;
Packit df99a1
  int og = grays - 1;
Packit df99a1
  set_grays(ngrays);
Packit df99a1
  // setup conversion table
Packit df99a1
  unsigned char conv[256];
Packit df99a1
  for (int i=0; i<256; i++)
Packit df99a1
    {
Packit df99a1
      if (i > og)
Packit df99a1
        conv[i] = ng;
Packit df99a1
      else
Packit df99a1
        conv[i] = (i*ng+og/2)/og;
Packit df99a1
    }
Packit df99a1
  // perform conversion
Packit df99a1
  for (int row=0; row
Packit df99a1
    {
Packit df99a1
      unsigned char *p = (*this)[row];
Packit df99a1
      for (int n=0; n
Packit df99a1
        p[n] = conv[ p[n] ];
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
GBitmap::binarize_grays(int threshold)
Packit df99a1
{
Packit df99a1
  GMonitorLock lock(monitor());
Packit df99a1
  if (bytes)
Packit df99a1
    for (int row=0; row
Packit df99a1
      {
Packit df99a1
        unsigned char *p = (*this)[row];
Packit df99a1
        for(unsigned char const * const pend=p+ncolumns;p
Packit df99a1
        {
Packit df99a1
          *p = (*p>threshold) ? 1 : 0;
Packit df99a1
        }
Packit df99a1
      }
Packit df99a1
  grays = 2;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
// ----- additive blitting
Packit df99a1
Packit df99a1
#undef min
Packit df99a1
#undef max
Packit df99a1
Packit df99a1
static inline int
Packit df99a1
min(int x, int y) 
Packit df99a1
{ 
Packit df99a1
  return (x < y ? x : y);
Packit df99a1
}
Packit df99a1
Packit df99a1
static inline int
Packit df99a1
max(int x, int y) 
Packit df99a1
{ 
Packit df99a1
  return (x > y ? x : y);
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
GBitmap::blit(const GBitmap *bm, int x, int y)
Packit df99a1
{
Packit df99a1
  // Check boundaries
Packit df99a1
  if ((x >= ncolumns)              || 
Packit df99a1
      (y >= nrows)                 ||
Packit df99a1
      (x + (int)bm->columns() < 0) || 
Packit df99a1
      (y + (int)bm->rows() < 0)     )
Packit df99a1
    return;
Packit df99a1
Packit df99a1
  // Perform blit
Packit df99a1
  GMonitorLock lock1(monitor());
Packit df99a1
  GMonitorLock lock2(bm->monitor());
Packit df99a1
  if (bm->bytes)
Packit df99a1
    {
Packit df99a1
      if (!bytes_data)
Packit df99a1
        uncompress();
Packit df99a1
      // Blit from bitmap
Packit df99a1
      const unsigned char *srow = bm->bytes + bm->border;
Packit df99a1
      unsigned char *drow = bytes_data + border + y*bytes_per_row + x;
Packit df99a1
      for (int sr = 0; sr < bm->nrows; sr++)
Packit df99a1
        {
Packit df99a1
          if (sr+y>=0 && sr+y
Packit df99a1
            {
Packit df99a1
              int sc = max(0, -x);
Packit df99a1
              int sc1 = min(bm->ncolumns, ncolumns-x);
Packit df99a1
              while (sc < sc1)
Packit df99a1
                {
Packit df99a1
                  drow[sc] += srow[sc];
Packit df99a1
                  sc += 1;
Packit df99a1
                }
Packit df99a1
            }
Packit df99a1
          srow += bm->bytes_per_row;
Packit df99a1
          drow += bytes_per_row;
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
  else if (bm->rle)
Packit df99a1
    {
Packit df99a1
      if (!bytes_data)
Packit df99a1
        uncompress();
Packit df99a1
      // Blit from rle
Packit df99a1
      const unsigned char *runs = bm->rle;
Packit df99a1
      unsigned char *drow = bytes_data + border + y*bytes_per_row + x;
Packit df99a1
      int sr = bm->nrows - 1;
Packit df99a1
      drow += sr * bytes_per_row;
Packit df99a1
      int sc = 0;
Packit df99a1
      char p = 0;
Packit df99a1
      while (sr >= 0)
Packit df99a1
        {
Packit df99a1
          const int z = read_run(runs);
Packit df99a1
          if (sc+z > bm->ncolumns)
Packit df99a1
            G_THROW( ERR_MSG("GBitmap.lost_sync") );
Packit df99a1
          int nc = sc + z;
Packit df99a1
          if (p && sr+y>=0 && sr+y
Packit df99a1
            {
Packit df99a1
              if (sc + x < 0) 
Packit df99a1
                sc = min(-x, nc); 
Packit df99a1
              while (sc < nc && sc + x
Packit df99a1
                drow[sc++] += 1;
Packit df99a1
            }
Packit df99a1
          sc = nc;
Packit df99a1
          p = 1 - p;
Packit df99a1
          if (sc >= bm->ncolumns) 
Packit df99a1
            {
Packit df99a1
              p = 0;
Packit df99a1
              sc = 0;
Packit df99a1
              drow -= bytes_per_row;
Packit df99a1
              sr -= 1; 
Packit df99a1
            }
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
void 
Packit df99a1
GBitmap::blit(const GBitmap *bm, int xh, int yh, int subsample)
Packit df99a1
{
Packit df99a1
  // Use code when no subsampling is necessary
Packit df99a1
  if (subsample == 1)
Packit df99a1
    {
Packit df99a1
      blit(bm, xh, yh);
Packit df99a1
      return;
Packit df99a1
    }
Packit df99a1
Packit df99a1
  // Check boundaries
Packit df99a1
  if ((xh >= ncolumns * subsample) || 
Packit df99a1
      (yh >= nrows * subsample)    ||
Packit df99a1
      (xh + (int)bm->columns() < 0)   || 
Packit df99a1
      (yh + (int)bm->rows() < 0)     )
Packit df99a1
    return;
Packit df99a1
Packit df99a1
  // Perform subsampling blit
Packit df99a1
  GMonitorLock lock1(monitor());
Packit df99a1
  GMonitorLock lock2(bm->monitor());
Packit df99a1
  if (bm->bytes)
Packit df99a1
    {
Packit df99a1
      if (!bytes_data)
Packit df99a1
        uncompress();
Packit df99a1
      // Blit from bitmap
Packit df99a1
      int dr, dr1, zdc, zdc1;
Packit df99a1
      euclidian_ratio(yh, subsample, dr, dr1);
Packit df99a1
      euclidian_ratio(xh, subsample, zdc, zdc1);
Packit df99a1
      const unsigned char *srow = bm->bytes + bm->border;
Packit df99a1
      unsigned char *drow = bytes_data + border + dr*bytes_per_row;
Packit df99a1
      for (int sr = 0; sr < bm->nrows; sr++)
Packit df99a1
        {
Packit df99a1
          if (dr>=0 && dr
Packit df99a1
            {
Packit df99a1
              int dc = zdc;
Packit df99a1
              int dc1 = zdc1;
Packit df99a1
              for (int sc=0; sc < bm->ncolumns; sc++) 
Packit df99a1
                {
Packit df99a1
                  if (dc>=0 && dc
Packit df99a1
                    drow[dc] += srow[sc];
Packit df99a1
                  if (++dc1 >= subsample) 
Packit df99a1
                    {
Packit df99a1
                      dc1 = 0;
Packit df99a1
                      dc += 1;
Packit df99a1
                    }
Packit df99a1
                }
Packit df99a1
            }
Packit df99a1
          // next line in source
Packit df99a1
          srow += bm->bytes_per_row;
Packit df99a1
          // next line fraction in destination
Packit df99a1
          if (++dr1 >= subsample)
Packit df99a1
            {
Packit df99a1
              dr1 = 0;
Packit df99a1
              dr += 1;
Packit df99a1
              drow += bytes_per_row;
Packit df99a1
            }
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
  else if (bm->rle)
Packit df99a1
    {
Packit df99a1
      if (!bytes_data)
Packit df99a1
        uncompress();
Packit df99a1
      // Blit from rle
Packit df99a1
      int dr, dr1, zdc, zdc1;
Packit df99a1
      euclidian_ratio(yh+bm->nrows-1, subsample, dr, dr1);
Packit df99a1
      euclidian_ratio(xh, subsample, zdc, zdc1);
Packit df99a1
      const unsigned char *runs = bm->rle;
Packit df99a1
      unsigned char *drow = bytes_data + border + dr*bytes_per_row;
Packit df99a1
      int sr = bm->nrows -1;
Packit df99a1
      int sc = 0;
Packit df99a1
      char p = 0;
Packit df99a1
      int dc = zdc;
Packit df99a1
      int dc1 = zdc1;
Packit df99a1
      while (sr >= 0)
Packit df99a1
        {
Packit df99a1
          int z = read_run(runs);
Packit df99a1
          if (sc+z > bm->ncolumns)
Packit df99a1
            G_THROW( ERR_MSG("GBitmap.lost_sync") );
Packit df99a1
          int nc = sc + z;
Packit df99a1
Packit df99a1
          if (dr>=0 && dr
Packit df99a1
            while (z>0 && dc
Packit df99a1
              {
Packit df99a1
                int zd = subsample - dc1;
Packit df99a1
                if (zd > z) 
Packit df99a1
                  zd = z;
Packit df99a1
                if (p && dc>=0) 
Packit df99a1
                  drow[dc] += zd;
Packit df99a1
                z -= zd;
Packit df99a1
                dc1 += zd;
Packit df99a1
                if (dc1 >= subsample)
Packit df99a1
                  {
Packit df99a1
                    dc1 = 0;
Packit df99a1
                    dc += 1;
Packit df99a1
                  }
Packit df99a1
              }
Packit df99a1
          // next fractional row
Packit df99a1
          sc = nc;
Packit df99a1
          p = 1 - p;
Packit df99a1
          if (sc >= bm->ncolumns) 
Packit df99a1
            {
Packit df99a1
              sc = 0;
Packit df99a1
              dc = zdc;
Packit df99a1
              dc1 = zdc1;
Packit df99a1
              p = 0;
Packit df99a1
              sr -= 1; 
Packit df99a1
              if (--dr1 < 0)
Packit df99a1
                {
Packit df99a1
                  dr1 = subsample - 1;
Packit df99a1
                  dr -= 1;
Packit df99a1
                  drow -= bytes_per_row;
Packit df99a1
                }
Packit df99a1
            }
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
// ------ load bitmaps
Packit df99a1
Packit df99a1
Packit df99a1
unsigned int 
Packit df99a1
GBitmap::read_integer(char &c, ByteStream &bs)
Packit df99a1
{
Packit df99a1
  unsigned int x = 0;
Packit df99a1
  // eat blank before integer
Packit df99a1
  while (c==' ' || c=='\t' || c=='\r' || c=='\n' || c=='#') 
Packit df99a1
    {
Packit df99a1
      if (c=='#') 
Packit df99a1
        do { } while (bs.read(&c,1) && c!='\n' && c!='\r');
Packit df99a1
      c = 0; 
Packit df99a1
      bs.read(&c, 1);
Packit df99a1
    }
Packit df99a1
  // check integer
Packit df99a1
  if (c<'0' || c>'9')
Packit df99a1
    G_THROW( ERR_MSG("GBitmap.not_int") );
Packit df99a1
  // eat integer
Packit df99a1
  while (c>='0' && c<='9') 
Packit df99a1
    {
Packit df99a1
      x = x*10 + c - '0';
Packit df99a1
      c = 0;
Packit df99a1
      bs.read(&c, 1);
Packit df99a1
    }
Packit df99a1
  return x;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
void 
Packit df99a1
GBitmap::read_pbm_text(ByteStream &bs)
Packit df99a1
{
Packit df99a1
  unsigned char *row = bytes_data + border;
Packit df99a1
  row += (nrows-1) * bytes_per_row;
Packit df99a1
  for (int n = nrows-1; n>=0; n--) 
Packit df99a1
    {
Packit df99a1
      for (int c = 0; c
Packit df99a1
        {
Packit df99a1
          char bit = 0;
Packit df99a1
          bs.read(&bit,1);
Packit df99a1
          while (bit==' ' || bit=='\t' || bit=='\r' || bit=='\n')
Packit df99a1
            { 
Packit df99a1
              bit=0; 
Packit df99a1
              bs.read(&bit,1); 
Packit df99a1
            }
Packit df99a1
          if (bit=='1')
Packit df99a1
            row[c] = 1;
Packit df99a1
          else if (bit=='0')
Packit df99a1
            row[c] = 0;
Packit df99a1
          else
Packit df99a1
            G_THROW( ERR_MSG("GBitmap.bad_PBM") );
Packit df99a1
        }
Packit df99a1
      row -= bytes_per_row;
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
GBitmap::read_pgm_text(ByteStream &bs, int maxval)
Packit df99a1
{
Packit df99a1
  unsigned char *row = bytes_data + border;
Packit df99a1
  row += (nrows-1) * bytes_per_row;
Packit df99a1
  char lookahead = '\n';
Packit df99a1
  GTArray<unsigned char> ramp(0, maxval);
Packit df99a1
  for (int i=0; i<=maxval; i++)
Packit df99a1
    ramp[i] = (i
Packit df99a1
  for (int n = nrows-1; n>=0; n--) 
Packit df99a1
    {
Packit df99a1
      for (int c = 0; c
Packit df99a1
        row[c] = ramp[(int)read_integer(lookahead, bs)];
Packit df99a1
      row -= bytes_per_row;
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
GBitmap::read_pbm_raw(ByteStream &bs)
Packit df99a1
{
Packit df99a1
  unsigned char *row = bytes_data + border;
Packit df99a1
  row += (nrows-1) * bytes_per_row;
Packit df99a1
  for (int n = nrows-1; n>=0; n--) 
Packit df99a1
    {
Packit df99a1
      unsigned char acc = 0;
Packit df99a1
      unsigned char mask = 0;
Packit df99a1
      for (int c = 0; c
Packit df99a1
        {
Packit df99a1
          if (!mask) 
Packit df99a1
            {
Packit df99a1
              bs.read(&acc, 1);
Packit df99a1
              mask = (unsigned char)0x80;
Packit df99a1
            }
Packit df99a1
          if (acc & mask)
Packit df99a1
            row[c] = 1;
Packit df99a1
          else
Packit df99a1
            row[c] = 0;
Packit df99a1
          mask >>= 1;
Packit df99a1
        }
Packit df99a1
      row -= bytes_per_row;
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
GBitmap::read_pgm_raw(ByteStream &bs, int maxval)
Packit df99a1
{
Packit df99a1
  int maxbin = (maxval>255) ? 65536 : 256;
Packit df99a1
  GTArray<unsigned char> ramp(0, maxbin-1);
Packit df99a1
  for (int i=0; i
Packit df99a1
    ramp[i] = (i
Packit df99a1
  unsigned char *bramp = ramp;
Packit df99a1
  unsigned char *row = bytes_data + border;
Packit df99a1
  row += (nrows-1) * bytes_per_row;
Packit df99a1
  for (int n = nrows-1; n>=0; n--) 
Packit df99a1
    {
Packit df99a1
      if (maxbin > 256)
Packit df99a1
        {
Packit df99a1
          for (int c = 0; c
Packit df99a1
            {
Packit df99a1
              unsigned char x[2];
Packit df99a1
              bs.read((void*)&x, 2);
Packit df99a1
              row[c] = bramp[x[0]*256+x[1]];
Packit df99a1
            }
Packit df99a1
        }
Packit df99a1
      else
Packit df99a1
        {
Packit df99a1
          for (int c = 0; c
Packit df99a1
            {
Packit df99a1
              unsigned char x;
Packit df99a1
              bs.read((void*)&x, 1);
Packit df99a1
              row[c] = bramp[x];
Packit df99a1
            }
Packit df99a1
        }
Packit df99a1
      row -= bytes_per_row;
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
GBitmap::read_rle_raw(ByteStream &bs)
Packit df99a1
{
Packit df99a1
  // interpret runs data
Packit df99a1
  unsigned char h;
Packit df99a1
  unsigned char p = 0;
Packit df99a1
  unsigned char *row = bytes_data + border;
Packit df99a1
  int n = nrows - 1;
Packit df99a1
  row += n * bytes_per_row;
Packit df99a1
  int c = 0;
Packit df99a1
  while (n >= 0)
Packit df99a1
    {
Packit df99a1
      bs.read(&h, 1);
Packit df99a1
      int x = h;
Packit df99a1
      if (x >= (int)RUNOVERFLOWVALUE)
Packit df99a1
        {
Packit df99a1
          bs.read(&h, 1);
Packit df99a1
          x = h + ((x - (int)RUNOVERFLOWVALUE) << 8);
Packit df99a1
        }
Packit df99a1
      if (c+x > ncolumns)
Packit df99a1
        G_THROW( ERR_MSG("GBitmap.lost_sync") );
Packit df99a1
      while (x-- > 0)
Packit df99a1
        row[c++] = p;
Packit df99a1
      p = 1 - p;
Packit df99a1
      if (c >= ncolumns) 
Packit df99a1
        {
Packit df99a1
          c = 0;
Packit df99a1
          p = 0;
Packit df99a1
          row -= bytes_per_row;
Packit df99a1
          n -= 1; 
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
// ------ save bitmaps
Packit df99a1
Packit df99a1
void 
Packit df99a1
GBitmap::save_pbm(ByteStream &bs, int raw)
Packit df99a1
{
Packit df99a1
  // check arguments
Packit df99a1
  if (grays > 2)
Packit df99a1
    G_THROW( ERR_MSG("GBitmap.cant_make_PBM") );
Packit df99a1
  GMonitorLock lock(monitor());
Packit df99a1
  // header
Packit df99a1
  {
Packit df99a1
    GUTF8String head;
Packit df99a1
    head.format("P%c\n%d %d\n", (raw ? '4' : '1'), ncolumns, nrows);
Packit df99a1
    bs.writall((void*)(const char *)head, head.length());
Packit df99a1
  }
Packit df99a1
  // body
Packit df99a1
  if(raw)
Packit df99a1
  {
Packit df99a1
    if(!rle)
Packit df99a1
      compress();
Packit df99a1
    const unsigned char *runs=rle;
Packit df99a1
    const unsigned char * const runs_end=rle+rlelength;
Packit df99a1
    const int count=(ncolumns+7)>>3;
Packit df99a1
    unsigned char *buf;
Packit df99a1
    GPBuffer<unsigned char> gbuf(buf,count);
Packit df99a1
    while(runs
Packit df99a1
    {
Packit df99a1
      rle_get_bitmap(ncolumns,runs,buf,false);
Packit df99a1
      bs.writall(buf,count);
Packit df99a1
    }
Packit df99a1
  }else
Packit df99a1
  {
Packit df99a1
    if (!bytes)
Packit df99a1
      uncompress();
Packit df99a1
    const unsigned char *row = bytes + border;
Packit df99a1
    int n = nrows - 1;
Packit df99a1
    row += n * bytes_per_row;
Packit df99a1
    while (n >= 0)
Packit df99a1
    {
Packit df99a1
      unsigned char eol='\n';
Packit df99a1
      for (int c=0; c
Packit df99a1
      {
Packit df99a1
        unsigned char bit= (row[c] ? '1' : '0');
Packit df99a1
        bs.write((void*)&bit, 1);
Packit df99a1
        c += 1;
Packit df99a1
        if (c==ncolumns || (c&(int)RUNMSBMASK)==0) 
Packit df99a1
          bs.write((void*)&eol, 1);          
Packit df99a1
       }
Packit df99a1
      // next row
Packit df99a1
      row -= bytes_per_row;
Packit df99a1
      n -= 1;
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
GBitmap::save_pgm(ByteStream &bs, int raw)
Packit df99a1
{
Packit df99a1
  // checks
Packit df99a1
  GMonitorLock lock(monitor());
Packit df99a1
  if (!bytes)
Packit df99a1
    uncompress();
Packit df99a1
  // header
Packit df99a1
  GUTF8String head;
Packit df99a1
  head.format("P%c\n%d %d\n%d\n", (raw ? '5' : '2'), ncolumns, nrows, grays-1);
Packit df99a1
  bs.writall((void*)(const char *)head, head.length());
Packit df99a1
  // body
Packit df99a1
  const unsigned char *row = bytes + border;
Packit df99a1
  int n = nrows - 1;
Packit df99a1
  row += n * bytes_per_row;
Packit df99a1
  while (n >= 0)
Packit df99a1
    {
Packit df99a1
      if (raw)
Packit df99a1
        {
Packit df99a1
          for (int c=0; c
Packit df99a1
            {
Packit df99a1
              char x = grays - 1 - row[c];
Packit df99a1
              bs.write((void*)&x, 1);
Packit df99a1
            }
Packit df99a1
        }
Packit df99a1
      else 
Packit df99a1
        {
Packit df99a1
          unsigned char eol='\n';
Packit df99a1
          for (int c=0; c
Packit df99a1
            {
Packit df99a1
              head.format("%d ", grays - 1 - row[c]);
Packit df99a1
              bs.writall((void*)(const char *)head, head.length());
Packit df99a1
              c += 1;
Packit df99a1
              if (c==ncolumns || (c&0x1f)==0) 
Packit df99a1
                bs.write((void*)&eol, 1);          
Packit df99a1
            }
Packit df99a1
        }
Packit df99a1
      row -= bytes_per_row;
Packit df99a1
      n -= 1;
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
GBitmap::save_rle(ByteStream &bs)
Packit df99a1
{
Packit df99a1
  // checks
Packit df99a1
  if (ncolumns==0 || nrows==0)
Packit df99a1
    G_THROW( ERR_MSG("GBitmap.not_init") );
Packit df99a1
  GMonitorLock lock(monitor());
Packit df99a1
  if (grays > 2)
Packit df99a1
    G_THROW( ERR_MSG("GBitmap.cant_make_PBM") );
Packit df99a1
  // header
Packit df99a1
  GUTF8String head;
Packit df99a1
  head.format("R4\n%d %d\n", ncolumns, nrows);
Packit df99a1
  bs.writall((void*)(const char *)head, head.length());
Packit df99a1
  // body
Packit df99a1
  if (rle)
Packit df99a1
    {
Packit df99a1
      bs.writall((void*)rle, rlelength);
Packit df99a1
    }
Packit df99a1
  else
Packit df99a1
    {
Packit df99a1
      unsigned char *runs = 0;
Packit df99a1
      GPBuffer<unsigned char> gruns(runs);
Packit df99a1
      int size = encode(runs,gruns);
Packit df99a1
      bs.writall((void*)runs, size);
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
// ------ runs
Packit df99a1
Packit df99a1
Packit df99a1
void
Packit df99a1
GBitmap::makerows(
Packit df99a1
  int nrows, const int ncolumns, unsigned char *runs, unsigned char *rlerows[])
Packit df99a1
{
Packit df99a1
  while (nrows-- > 0)
Packit df99a1
  {
Packit df99a1
    rlerows[nrows] = runs;
Packit df99a1
    int c;
Packit df99a1
    for(c=0;c
Packit df99a1
      EMPTY_LOOP;
Packit df99a1
    if (c > ncolumns)
Packit df99a1
      G_THROW( ERR_MSG("GBitmap.lost_sync2") );
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
void
Packit df99a1
GBitmap::rle_get_bitmap (
Packit df99a1
  const int ncolumns,
Packit df99a1
  const unsigned char *&runs,
Packit df99a1
  unsigned char *bitmap,
Packit df99a1
  const bool invert )
Packit df99a1
{
Packit df99a1
  const int obyte_def=invert?0xff:0;
Packit df99a1
  const int obyte_ndef=invert?0:0xff;
Packit df99a1
  int mask=0x80,obyte=0;
Packit df99a1
  for(int c=ncolumns;c > 0 ;)
Packit df99a1
  {
Packit df99a1
    int x=read_run(runs);
Packit df99a1
    c-=x;
Packit df99a1
    while((x--)>0)
Packit df99a1
    {
Packit df99a1
      if(!(mask>>=1))
Packit df99a1
      {
Packit df99a1
        *(bitmap++) = obyte^obyte_def;
Packit df99a1
        obyte=0;
Packit df99a1
        mask=0x80;
Packit df99a1
        for(;x>=8;x-=8)
Packit df99a1
        {
Packit df99a1
          *(bitmap++)=obyte_def;
Packit df99a1
        }
Packit df99a1
      }
Packit df99a1
    }
Packit df99a1
    if(c>0)
Packit df99a1
    {
Packit df99a1
      int x=read_run(runs);
Packit df99a1
      c-=x;
Packit df99a1
      while((x--)>0)
Packit df99a1
      {
Packit df99a1
        obyte|=mask;
Packit df99a1
        if(!(mask>>=1))
Packit df99a1
        {
Packit df99a1
          *(bitmap++)=obyte^obyte_def;
Packit df99a1
          obyte=0;
Packit df99a1
          mask=0x80;
Packit df99a1
          for(;(x>8);x-=8)
Packit df99a1
            *(bitmap++)=obyte_ndef;
Packit df99a1
        }
Packit df99a1
      }
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
  if(mask != 0x80)
Packit df99a1
  {
Packit df99a1
    *(bitmap++)=obyte^obyte_def;
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
int 
Packit df99a1
GBitmap::rle_get_bits(int rowno, unsigned char *bits) const
Packit df99a1
{
Packit df99a1
  GMonitorLock lock(monitor());
Packit df99a1
  if (!rle)
Packit df99a1
    return 0;
Packit df99a1
  if (rowno<0 || rowno>=nrows)
Packit df99a1
    return 0;
Packit df99a1
  if (!rlerows)
Packit df99a1
  {
Packit df99a1
    const_cast<GPBuffer<unsigned char *> &>(grlerows).resize(nrows);
Packit df99a1
    makerows(nrows,ncolumns,rle,const_cast<unsigned char **>(rlerows));
Packit df99a1
  }
Packit df99a1
  int n = 0;
Packit df99a1
  int p = 0;
Packit df99a1
  int c = 0;
Packit df99a1
  unsigned char *runs = rlerows[rowno];
Packit df99a1
  while (c < ncolumns)
Packit df99a1
    {
Packit df99a1
      const int x=read_run(runs);
Packit df99a1
      if ((c+=x)>ncolumns)
Packit df99a1
        c = ncolumns;
Packit df99a1
      while (n
Packit df99a1
        bits[n++] = p;
Packit df99a1
      p = 1-p;
Packit df99a1
    }
Packit df99a1
  return n;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
int 
Packit df99a1
GBitmap::rle_get_runs(int rowno, int *rlens) const
Packit df99a1
{
Packit df99a1
  GMonitorLock lock(monitor());
Packit df99a1
  if (!rle)
Packit df99a1
    return 0;
Packit df99a1
  if (rowno<0 || rowno>=nrows)
Packit df99a1
    return 0;
Packit df99a1
  if (!rlerows)
Packit df99a1
  {
Packit df99a1
    const_cast<GPBuffer<unsigned char *> &>(grlerows).resize(nrows);
Packit df99a1
    makerows(nrows,ncolumns,rle,const_cast<unsigned char **>(rlerows));
Packit df99a1
  }
Packit df99a1
  int n = 0;
Packit df99a1
  int d = 0;
Packit df99a1
  int c = 0;
Packit df99a1
  unsigned char *runs = rlerows[rowno];
Packit df99a1
  while (c < ncolumns)
Packit df99a1
    {
Packit df99a1
      const int x=read_run(runs);
Packit df99a1
      if (n>0 && !x)
Packit df99a1
        {
Packit df99a1
          n--;
Packit df99a1
          d = d-rlens[n];
Packit df99a1
        }
Packit df99a1
      else 
Packit df99a1
        {
Packit df99a1
          rlens[n++] = (c+=x)-d;
Packit df99a1
          d = c;
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
  return n;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
int 
Packit df99a1
GBitmap::rle_get_rect(GRect &rect) const
Packit df99a1
{
Packit df99a1
  GMonitorLock lock(monitor());
Packit df99a1
  if (!rle) 
Packit df99a1
    return 0;
Packit df99a1
  int area = 0;
Packit df99a1
  unsigned char *runs = rle;
Packit df99a1
  rect.xmin = ncolumns;
Packit df99a1
  rect.ymin = nrows;
Packit df99a1
  rect.xmax = 0;
Packit df99a1
  rect.ymax = 0;
Packit df99a1
  int r = nrows;
Packit df99a1
  while (--r >= 0)
Packit df99a1
    {
Packit df99a1
      int p = 0;
Packit df99a1
      int c = 0;
Packit df99a1
      int n = 0;
Packit df99a1
      while (c < ncolumns)
Packit df99a1
        {
Packit df99a1
          const int x=read_run(runs);
Packit df99a1
          if(x)
Packit df99a1
            {
Packit df99a1
              if (p)
Packit df99a1
                {
Packit df99a1
                  if (c < rect.xmin) 
Packit df99a1
                    rect.xmin = c;
Packit df99a1
                  if ((c += x) > rect.xmax) 
Packit df99a1
                    rect.xmax = c-1;
Packit df99a1
                  n += x;
Packit df99a1
                }
Packit df99a1
              else
Packit df99a1
                {
Packit df99a1
                  c += x;
Packit df99a1
                }
Packit df99a1
            }
Packit df99a1
          p = 1-p;
Packit df99a1
        }
Packit df99a1
      area += n;
Packit df99a1
      if (n)
Packit df99a1
        {
Packit df99a1
          rect.ymin = r;
Packit df99a1
          if (r > rect.ymax) 
Packit df99a1
            rect.ymax = r;
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
  if (area==0)
Packit df99a1
    rect.clear();
Packit df99a1
  return area;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
// ------ helpers
Packit df99a1
Packit df99a1
int
Packit df99a1
GBitmap::encode(unsigned char *&pruns,GPBuffer<unsigned char> &gpruns) const
Packit df99a1
{
Packit df99a1
  // uncompress rle information
Packit df99a1
  if (nrows==0 || ncolumns==0)
Packit df99a1
  {
Packit df99a1
    gpruns.resize(0);
Packit df99a1
    return 0;
Packit df99a1
  }
Packit df99a1
  if (!bytes)
Packit df99a1
    {
Packit df99a1
      unsigned char *runs;
Packit df99a1
      GPBuffer<unsigned char> gruns(runs,rlelength);
Packit df99a1
      memcpy((void*)runs, rle, rlelength);
Packit df99a1
      gruns.swap(gpruns);
Packit df99a1
      return rlelength;
Packit df99a1
    }
Packit df99a1
  gpruns.resize(0);
Packit df99a1
  // create run array
Packit df99a1
  int pos = 0;
Packit df99a1
  int maxpos = 1024 + ncolumns + ncolumns;
Packit df99a1
  unsigned char *runs;
Packit df99a1
  GPBuffer<unsigned char> gruns(runs,maxpos);
Packit df99a1
  // encode bitmap as rle
Packit df99a1
  const unsigned char *row = bytes + border;
Packit df99a1
  int n = nrows - 1;
Packit df99a1
  row += n * bytes_per_row;
Packit df99a1
  while (n >= 0)
Packit df99a1
    {
Packit df99a1
      if (maxpos < pos+ncolumns+ncolumns+2)
Packit df99a1
        {
Packit df99a1
          maxpos += 1024 + ncolumns + ncolumns;
Packit df99a1
          gruns.resize(maxpos);
Packit df99a1
        }
Packit df99a1
Packit df99a1
      unsigned char *runs_pos=runs+pos;
Packit df99a1
      const unsigned char * const runs_pos_start=runs_pos;
Packit df99a1
      append_line(runs_pos,row,ncolumns);
Packit df99a1
      pos+=(size_t)runs_pos-(size_t)runs_pos_start;
Packit df99a1
      row -= bytes_per_row;
Packit df99a1
      n -= 1;
Packit df99a1
    }
Packit df99a1
  // return result
Packit df99a1
  gruns.resize(pos);
Packit df99a1
  gpruns.swap(gruns);
Packit df99a1
  return pos;
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
GBitmap::decode(unsigned char *runs)
Packit df99a1
{
Packit df99a1
  // initialize pixel array
Packit df99a1
  if (nrows==0 || ncolumns==0)
Packit df99a1
    G_THROW( ERR_MSG("GBitmap.not_init") );
Packit df99a1
  bytes_per_row = ncolumns + border;
Packit df99a1
  if (runs==0)
Packit df99a1
    G_THROW( ERR_MSG("GBitmap.null_arg") );
Packit df99a1
  int npixels = nrows * bytes_per_row + border;
Packit df99a1
  if (!bytes_data)
Packit df99a1
  {
Packit df99a1
    gbytes_data.resize(npixels);
Packit df99a1
    bytes = bytes_data;
Packit df99a1
  }
Packit df99a1
  gbytes_data.clear();
Packit df99a1
  gzerobuffer=zeroes(bytes_per_row + border);
Packit df99a1
  // interpret runs data
Packit df99a1
  int c, n;
Packit df99a1
  unsigned char p = 0;
Packit df99a1
  unsigned char *row = bytes_data + border;
Packit df99a1
  n = nrows - 1;
Packit df99a1
  row += n * bytes_per_row;
Packit df99a1
  c = 0;
Packit df99a1
  while (n >= 0)
Packit df99a1
    {
Packit df99a1
      int x = read_run(runs);
Packit df99a1
      if (c+x > ncolumns)
Packit df99a1
        G_THROW( ERR_MSG("GBitmap.lost_sync2") );
Packit df99a1
      while (x-- > 0)
Packit df99a1
        row[c++] = p;
Packit df99a1
      p = 1 - p;
Packit df99a1
      if (c >= ncolumns) 
Packit df99a1
        {
Packit df99a1
          c = 0;
Packit df99a1
          p = 0;
Packit df99a1
          row -= bytes_per_row;
Packit df99a1
          n -= 1; 
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
  // Free rle data possibly attached to this bitmap
Packit df99a1
  grle.resize(0);
Packit df99a1
  grlerows.resize(0);
Packit df99a1
  rlelength = 0;
Packit df99a1
#ifndef NDEBUG
Packit df99a1
  check_border();
Packit df99a1
#endif
Packit df99a1
}
Packit df99a1
Packit df99a1
class GBitmap::ZeroBuffer : public GPEnabled
Packit df99a1
{
Packit df99a1
public:
Packit df99a1
  ZeroBuffer(const unsigned int zerosize);
Packit df99a1
  unsigned char *zerobuffer;
Packit df99a1
  GPBuffer<unsigned char> gzerobuffer;
Packit df99a1
};
Packit df99a1
Packit df99a1
GBitmap::ZeroBuffer::ZeroBuffer(const unsigned int zerosize)
Packit df99a1
: gzerobuffer(zerobuffer,zerosize)
Packit df99a1
{
Packit df99a1
  gzerobuffer.clear();
Packit df99a1
  GBitmap::zerobuffer=zerobuffer;
Packit df99a1
  GBitmap::zerosize=zerosize;
Packit df99a1
}
Packit df99a1
Packit df99a1
static const unsigned char static_zerobuffer[]=
Packit df99a1
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 32
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 64
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 96 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 128 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 160
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 192
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 234
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 256
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 288
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 320
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 352 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 384 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 416
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 448
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 480
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 512
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 544
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 576
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 608 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 640 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 672
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 704
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 736
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 768
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 800
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 832
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 864 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 896 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 928
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 960
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 992
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+32
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+64
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+96 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+128 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+160
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+192
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+234
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+256
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+288
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+320
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+352 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+384 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+416
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+448
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+480
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+512
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+544
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+576
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+608 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+640 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+672
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+704
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+736
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+768
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+800
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+832
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+864 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+896 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+928
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+960
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+992
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+32
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+64
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+96 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+128 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+160
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+192
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+234
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+256
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+288
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+320
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+352 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+384 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+416
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+448
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+480
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+512
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+544
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+576
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+608 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+640 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+672
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+704
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+736
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+768
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+800
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+832
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+864 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+896 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+928
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+960
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+992
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+32
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+64
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+96 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+128 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+160
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+192
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+234
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+256
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+288
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+320
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+352 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+384 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+416
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+448
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+480
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+512
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+544
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+576
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+608 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+640 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+672
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+704
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+736
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+768
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+800
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+832
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+864 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+896 
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+928
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+960
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+992
Packit df99a1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // 4096
Packit df99a1
Packit df99a1
int GBitmap::zerosize = sizeof(static_zerobuffer);
Packit df99a1
unsigned char *GBitmap::zerobuffer=const_cast<unsigned char *>(static_zerobuffer);
Packit df99a1
Packit df99a1
GP<GBitmap::ZeroBuffer>
Packit df99a1
GBitmap::zeroes(int required)
Packit df99a1
{
Packit df99a1
  GMonitorLock lock(&monitors[0]); // any monitor would do
Packit df99a1
  static GP<GBitmap::ZeroBuffer> gzerobuffer;
Packit df99a1
  if (zerosize < required)
Packit df99a1
  {
Packit df99a1
    int z;
Packit df99a1
    for(z=zerosize;z
Packit df99a1
      EMPTY_LOOP;
Packit df99a1
    z=(z+0xfff)&(~0xfff);
Packit df99a1
    gzerobuffer=new GBitmap::ZeroBuffer((unsigned int)z);
Packit df99a1
  }
Packit df99a1
  return gzerobuffer;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
// Fills a bitmap with the given value
Packit df99a1
void 
Packit df99a1
GBitmap::fill(unsigned char value)
Packit df99a1
{
Packit df99a1
  GMonitorLock lock(monitor());
Packit df99a1
  for(unsigned int y=0; y
Packit df99a1
    {
Packit df99a1
      unsigned char* bm_y = (*this)[y];
Packit df99a1
      for(unsigned int x=0; x
Packit df99a1
        bm_y[x] = value;
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
void 
Packit df99a1
GBitmap::append_long_run(unsigned char *&data, int count)
Packit df99a1
{
Packit df99a1
  while (count > MAXRUNSIZE)
Packit df99a1
    {
Packit df99a1
      data[0] = data[1] = 0xff;
Packit df99a1
      data[2] = 0;
Packit df99a1
      data += 3;
Packit df99a1
      count -= MAXRUNSIZE;
Packit df99a1
    }
Packit df99a1
  if (count < RUNOVERFLOWVALUE)
Packit df99a1
    {
Packit df99a1
      data[0] = count;
Packit df99a1
      data += 1;
Packit df99a1
    }
Packit df99a1
  else
Packit df99a1
    {
Packit df99a1
      data[0] = (count>>8) + GBitmap::RUNOVERFLOWVALUE;
Packit df99a1
      data[1] = (count & 0xff);
Packit df99a1
      data += 2;
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
void
Packit df99a1
GBitmap::append_line(unsigned char *&data,const unsigned char *row,
Packit df99a1
                     const int rowlen,bool invert)
Packit df99a1
{
Packit df99a1
  const unsigned char *rowend=row+rowlen;
Packit df99a1
  bool p=!invert;
Packit df99a1
  while(row
Packit df99a1
    {
Packit df99a1
      int count=0;
Packit df99a1
      if ((p=!p)) 
Packit df99a1
        {
Packit df99a1
          if(*row)
Packit df99a1
            for(++count,++row;(row
Packit df99a1
            	EMPTY_LOOP;
Packit df99a1
        } 
Packit df99a1
      else if(!*row)
Packit df99a1
        {
Packit df99a1
          for(++count,++row;(row
Packit df99a1
          	EMPTY_LOOP;
Packit df99a1
        }
Packit df99a1
      append_run(data,count);
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
#if 0
Packit df99a1
static inline int
Packit df99a1
GetRowTDLRNR(
Packit df99a1
  GBitmap &bit,const int row, const unsigned char *&startptr,
Packit df99a1
  const unsigned char *&stopptr)
Packit df99a1
{
Packit df99a1
  stopptr=(startptr=bit[row])+bit.columns();
Packit df99a1
  return 1;
Packit df99a1
}
Packit df99a1
Packit df99a1
static inline int
Packit df99a1
GetRowTDLRNR(
Packit df99a1
  GBitmap &bit,const int row, const unsigned char *&startptr,
Packit df99a1
  const unsigned char *&stopptr)
Packit df99a1
{
Packit df99a1
  stopptr=(startptr=bit[row])+bit.columns();
Packit df99a1
  return 1;
Packit df99a1
}
Packit df99a1
Packit df99a1
static inline int
Packit df99a1
GetRowTDRLNR(
Packit df99a1
  GBitmap &bit,const int row, const unsigned char *&startptr,
Packit df99a1
  const unsigned char *&stopptr)
Packit df99a1
{
Packit df99a1
  startptr=(stopptr=bit[row]-1)+bit.columns();
Packit df99a1
  return -1;
Packit df99a1
}
Packit df99a1
#endif // 0
Packit df99a1
Packit df99a1
GP<GBitmap> 
Packit df99a1
GBitmap::rotate(int count)
Packit df99a1
{
Packit df99a1
  GP<GBitmap> newbitmap=this;
Packit df99a1
  count = count & 3;
Packit df99a1
  if(count)
Packit df99a1
  {
Packit df99a1
    if( count & 0x01 )
Packit df99a1
    {
Packit df99a1
      newbitmap = new GBitmap(ncolumns, nrows);
Packit df99a1
    }else
Packit df99a1
    {
Packit df99a1
      newbitmap = new GBitmap(nrows, ncolumns);
Packit df99a1
    }
Packit df99a1
    GMonitorLock lock(monitor());
Packit df99a1
    if (!bytes_data)
Packit df99a1
      uncompress();
Packit df99a1
    GBitmap &dbitmap = *newbitmap;
Packit df99a1
    dbitmap.set_grays(grays);
Packit df99a1
    switch(count)
Packit df99a1
    {
Packit df99a1
    case 3: // rotate 90 counter clockwise
Packit df99a1
      {
Packit df99a1
        const int lastrow = dbitmap.rows()-1;
Packit df99a1
        for(int y=0; y
Packit df99a1
        {
Packit df99a1
          const unsigned char *r=operator[] (y);
Packit df99a1
          for(int x=0,xnew=lastrow;xnew>=0; x++,xnew--)
Packit df99a1
          {
Packit df99a1
            dbitmap[xnew][y] = r[x];
Packit df99a1
          }
Packit df99a1
        }
Packit df99a1
      }
Packit df99a1
      break;
Packit df99a1
    case 2: // rotate 180 counter clockwise
Packit df99a1
      {
Packit df99a1
        const int lastrow = dbitmap.rows()-1;
Packit df99a1
        const int lastcolumn = dbitmap.columns()-1;
Packit df99a1
        for(int y=0,ynew=lastrow;ynew>=0; y++,ynew--)
Packit df99a1
        {
Packit df99a1
          const unsigned char *r=operator[] (y);
Packit df99a1
          unsigned char *d=dbitmap[ynew];
Packit df99a1
          for(int xnew=lastcolumn;xnew>=0; r++,--xnew)
Packit df99a1
          {
Packit df99a1
            d[xnew] = *r;
Packit df99a1
          }
Packit df99a1
        }
Packit df99a1
      }
Packit df99a1
      break;
Packit df99a1
    case 1: // rotate 270 counter clockwise
Packit df99a1
      {
Packit df99a1
        const int lastcolumn = dbitmap.columns()-1;
Packit df99a1
        for(int y=0,ynew=lastcolumn;ynew>=0;y++,ynew--)
Packit df99a1
        {
Packit df99a1
          const unsigned char *r=operator[] (y);
Packit df99a1
          for(int x=0; x
Packit df99a1
          {
Packit df99a1
            dbitmap[x][ynew] = r[x];
Packit df99a1
          }
Packit df99a1
        }
Packit df99a1
      }
Packit df99a1
      break;
Packit df99a1
    }
Packit df99a1
    if(grays == 2)
Packit df99a1
    {
Packit df99a1
      compress();
Packit df99a1
      dbitmap.compress();
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
  return newbitmap;
Packit df99a1
}
Packit df99a1
Packit df99a1
#ifndef NDEBUG
Packit df99a1
void 
Packit df99a1
GBitmap::check_border() const
Packit df99a1
{int col ;
Packit df99a1
  if (bytes)
Packit df99a1
    {
Packit df99a1
      const unsigned char *p = (*this)[-1];
Packit df99a1
      for (col=-border; col
Packit df99a1
        if (p[col])
Packit df99a1
          G_THROW( ERR_MSG("GBitmap.zero_damaged") );
Packit df99a1
      for (int row=0; row
Packit df99a1
        {
Packit df99a1
          p = (*this)[row];
Packit df99a1
          for (col=-border; col<0; col++)
Packit df99a1
            if (p[col])
Packit df99a1
              G_THROW( ERR_MSG("GBitmap.left_damaged") );
Packit df99a1
          for (col=ncolumns; col
Packit df99a1
            if (p[col])
Packit df99a1
              G_THROW( ERR_MSG("GBitmap.right_damaged") );
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
#endif
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
Packit df99a1