Blame libdjvu/GPixmap.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
// -- Implements class PIXMAP
Packit df99a1
// Author: Leon Bottou 07/1997
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
#include "GPixmap.h"
Packit df99a1
Packit df99a1
#include "GString.h"
Packit df99a1
#include "GException.h"
Packit df99a1
#include "ByteStream.h"
Packit df99a1
#include "GRect.h"
Packit df99a1
#include "GBitmap.h"
Packit df99a1
#include "GThreads.h"
Packit df99a1
#include "Arrays.h"
Packit df99a1
#include "JPEGDecoder.h"
Packit df99a1
Packit df99a1
#include <stddef.h>
Packit df99a1
#include <stdlib.h>
Packit df99a1
#include <math.h>
Packit df99a1
#include <assert.h>
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
Packit df99a1
Packit df99a1
//////////////////////////////////////////////////
Packit df99a1
// ------- predefined colors
Packit df99a1
//////////////////////////////////////////////////
Packit df99a1
Packit df99a1
Packit df99a1
const GPixel GPixel::WHITE = { 255, 255, 255 };
Packit df99a1
const GPixel GPixel::BLACK = {   0,   0,   0 };
Packit df99a1
const GPixel GPixel::BLUE  = { 255,   0,   0 };
Packit df99a1
const GPixel GPixel::GREEN = {   0, 255,   0 };
Packit df99a1
const GPixel GPixel::RED   = {   0,   0, 255 };
Packit df99a1
Packit df99a1
Packit df99a1
//////////////////////////////////////////////////
Packit df99a1
// ----- utilities
Packit df99a1
//////////////////////////////////////////////////
Packit df99a1
Packit df99a1
Packit df99a1
static const GPixel *
Packit df99a1
new_gray_ramp(int grays,GPixel *ramp)
Packit df99a1
{
Packit df99a1
  int color = 0xff0000;
Packit df99a1
  int decrement = color / (grays-1);
Packit df99a1
  for (int i=0; i
Packit df99a1
    {
Packit df99a1
      int level = color >> 16;
Packit df99a1
      ramp[i].b = level;
Packit df99a1
      ramp[i].g = level;
Packit df99a1
      ramp[i].r = level;
Packit df99a1
      color -= decrement;
Packit df99a1
    }
Packit df99a1
  return ramp;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
static inline int
Packit df99a1
mini(int x, int y) 
Packit df99a1
{ 
Packit df99a1
  return (x < y ? x : y);
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
static inline int
Packit df99a1
maxi(int x, int y) 
Packit df99a1
{ 
Packit df99a1
  return (x > y ? x : y);
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
static inline void 
Packit df99a1
euclidian_ratio(int a, int b, int &q, int &r)
Packit df99a1
{
Packit df99a1
  q = a / b;
Packit df99a1
  r = a - b*q;
Packit df99a1
  if (r < 0)
Packit df99a1
  {
Packit df99a1
    q -= 1;
Packit df99a1
    r += b;
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
//////////////////////////////////////////////////
Packit df99a1
// global lock used by some rare operations
Packit df99a1
//////////////////////////////////////////////////
Packit df99a1
Packit df99a1
static GMonitor &pixmap_monitor() {
Packit df99a1
  static GMonitor xpixmap_monitor;
Packit df99a1
  return xpixmap_monitor;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
//////////////////////////////////////////////////
Packit df99a1
// constructors and destructors
Packit df99a1
//////////////////////////////////////////////////
Packit df99a1
Packit df99a1
Packit df99a1
GPixmap::~GPixmap()
Packit df99a1
{
Packit df99a1
  delete [] pixels_data;
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
GPixmap::destroy(void)
Packit df99a1
{
Packit df99a1
  delete [] pixels_data;
Packit df99a1
  pixels = pixels_data = 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
GPixmap::GPixmap()
Packit df99a1
: nrows(0), ncolumns(0), pixels(0), pixels_data(0)
Packit df99a1
{
Packit df99a1
}
Packit df99a1
Packit df99a1
GPixmap::GPixmap(int nrows, int ncolumns, const GPixel *filler)
Packit df99a1
: nrows(0), ncolumns(0), pixels(0), pixels_data(0)
Packit df99a1
{
Packit df99a1
  G_TRY
Packit df99a1
  {
Packit df99a1
    init(nrows, ncolumns, filler);
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
GPixmap::GPixmap(ByteStream &bs)
Packit df99a1
: nrows(0), ncolumns(0), pixels(0), pixels_data(0)
Packit df99a1
{
Packit df99a1
  G_TRY
Packit df99a1
  {
Packit df99a1
	init(bs);
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
GPixmap::GPixmap(const GBitmap &ref)
Packit df99a1
: nrows(0), ncolumns(0), pixels(0), pixels_data(0)
Packit df99a1
{
Packit df99a1
  G_TRY
Packit df99a1
  {
Packit df99a1
	init(ref, 0);
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
GPixmap::GPixmap(const GBitmap &ref, const GRect &rect)
Packit df99a1
: nrows(0), ncolumns(0), pixels(0), pixels_data(0)
Packit df99a1
{
Packit df99a1
  G_TRY
Packit df99a1
  {
Packit df99a1
    init(ref, rect, 0);
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
GPixmap::GPixmap(const GPixmap &ref)
Packit df99a1
: nrows(0), ncolumns(0), pixels(0), pixels_data(0)
Packit df99a1
{
Packit df99a1
  G_TRY
Packit df99a1
  {
Packit df99a1
    init(ref);
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
GPixmap::GPixmap(const GPixmap &ref, const GRect &rect)
Packit df99a1
: nrows(0), ncolumns(0), pixels(0), pixels_data(0)
Packit df99a1
{
Packit df99a1
  G_TRY
Packit df99a1
  {
Packit df99a1
	init(ref, rect);
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
// Initialization
Packit df99a1
//////////////////////////////////////////////////
Packit df99a1
Packit df99a1
Packit df99a1
void 
Packit df99a1
GPixmap::init(int arows, int acolumns, const GPixel *filler)
Packit df99a1
{
Packit df99a1
  if (arows != (unsigned short) arows ||
Packit df99a1
      acolumns != (unsigned short) acolumns )
Packit df99a1
    G_THROW("Illegal arguments");
Packit df99a1
  destroy();
Packit df99a1
  nrows = arows;
Packit df99a1
  ncolumns = acolumns;
Packit df99a1
  nrowsize = acolumns;
Packit df99a1
  int npix = nrows * nrowsize;
Packit df99a1
  if (npix > 0)
Packit df99a1
  {
Packit df99a1
    pixels = pixels_data = new GPixel[npix];
Packit df99a1
    if (filler)
Packit df99a1
    { 
Packit df99a1
      while (--npix>=0) 
Packit df99a1
        pixels_data[npix] = *filler;
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
void 
Packit df99a1
GPixmap::init(const GBitmap &ref, const GPixel *userramp)
Packit df99a1
{
Packit df99a1
  init(ref.rows(), ref.columns(), 0);
Packit df99a1
  GPixel *xramp;
Packit df99a1
  GPBuffer<GPixel> gxramp(xramp);
Packit df99a1
  if (nrows>0 && ncolumns>0)
Packit df99a1
  {
Packit df99a1
    // Create pixel ramp
Packit df99a1
    const GPixel *ramp = userramp;
Packit df99a1
    if (!userramp)
Packit df99a1
	{
Packit df99a1
          gxramp.resize(256);
Packit df99a1
          gxramp.clear();
Packit df99a1
	  ramp = new_gray_ramp(ref.get_grays(),xramp);
Packit df99a1
	}
Packit df99a1
    // Copy pixels
Packit df99a1
    for (int y=0; y
Packit df99a1
    {
Packit df99a1
      GPixel *dst = (*this)[y];
Packit df99a1
      const unsigned char *src = ref[y];
Packit df99a1
      for (int x=0; x
Packit df99a1
        dst[x] = ramp[ src[x] ];
Packit df99a1
    }
Packit df99a1
    // Free ramp
Packit df99a1
//    if (!userramp)
Packit df99a1
//      delete [] (GPixel*)ramp;
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
void 
Packit df99a1
GPixmap::init(const GBitmap &ref, const GRect &rect, const GPixel *userramp)
Packit df99a1
{
Packit df99a1
  init(rect.height(), rect.width(), 0);
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
    GPixel *xramp;
Packit df99a1
    GPBuffer<GPixel> gxramp(xramp);
Packit df99a1
    // allocate ramp
Packit df99a1
    const GPixel *ramp = userramp;
Packit df99a1
    if (!userramp)
Packit df99a1
	{
Packit df99a1
	  gxramp.resize(256);
Packit df99a1
          gxramp.clear();
Packit df99a1
          ramp = new_gray_ramp(ref.get_grays(),xramp);
Packit df99a1
	}
Packit df99a1
    // copy pixels
Packit df99a1
    for (int y=rect2.ymin; y
Packit df99a1
    {
Packit df99a1
      GPixel *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] = ramp[ src[x] ];
Packit df99a1
    }
Packit df99a1
    // free ramp
Packit df99a1
//    if (!userramp)
Packit df99a1
//      delete [] (GPixel*) ramp;
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
void 
Packit df99a1
GPixmap::init(const GPixmap &ref)
Packit df99a1
{
Packit df99a1
  init(ref.rows(), ref.columns(), 0);
Packit df99a1
  if (nrows>0 && ncolumns>0)
Packit df99a1
  {
Packit df99a1
    for (int y=0; y
Packit df99a1
    {
Packit df99a1
      GPixel *dst = (*this)[y];
Packit df99a1
      const GPixel *src = ref[y];
Packit df99a1
      for (int x=0; x
Packit df99a1
        dst[x] = src[x];
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
void 
Packit df99a1
GPixmap::init(const GPixmap &ref, const GRect &rect)
Packit df99a1
{
Packit df99a1
  init(rect.height(), rect.width(), 0);
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
      GPixel *dst = (*this)[y];
Packit df99a1
      const GPixel *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
void 
Packit df99a1
GPixmap::donate_data(GPixel *data, int w, int h)
Packit df99a1
{
Packit df99a1
  destroy();
Packit df99a1
  nrows = h;
Packit df99a1
  ncolumns = w;
Packit df99a1
  nrowsize = w;
Packit df99a1
  pixels_data=pixels=data;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
GPixel *
Packit df99a1
GPixmap::take_data(size_t &offset)
Packit df99a1
{
Packit df99a1
  GPixel *ret = pixels_data;
Packit df99a1
  pixels_data = 0;
Packit df99a1
  offset = 0;
Packit df99a1
  return ret;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
//////////////////////////////////////////////////
Packit df99a1
// Save and load ppm files
Packit df99a1
//////////////////////////////////////////////////
Packit df99a1
Packit df99a1
Packit df99a1
static unsigned int 
Packit df99a1
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("GPixmap.no_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
GPixmap::init(ByteStream &bs)
Packit df99a1
{
Packit df99a1
  // Read header
Packit df99a1
  bool raw = false;
Packit df99a1
  bool grey = false;
Packit df99a1
  int magic = bs.read16();
Packit df99a1
  GP<GBitmap> bm;
Packit df99a1
  switch (magic)
Packit df99a1
    {
Packit df99a1
    case ('P'<<8)+'2':
Packit df99a1
      grey = true;
Packit df99a1
      break;
Packit df99a1
    case ('P'<<8)+'3':
Packit df99a1
      break;
Packit df99a1
    case ('P'<<8)+'5':
Packit df99a1
      raw = grey = true;
Packit df99a1
    case ('P'<<8)+'6':
Packit df99a1
      raw = true;
Packit df99a1
      break;
Packit df99a1
    case ('P'<<8)+'1':
Packit df99a1
    case ('P'<<8)+'4': 
Packit df99a1
      bs.seek(0L);
Packit df99a1
      bm = GBitmap::create(bs); 
Packit df99a1
      init(*bm);
Packit df99a1
      return;
Packit df99a1
    default:
Packit df99a1
#ifdef NEED_JPEG_DECODER
Packit df99a1
      bs.seek(0L);
Packit df99a1
      JPEGDecoder::decode(bs,*this);
Packit df99a1
      return;
Packit df99a1
#else
Packit df99a1
      
Packit df99a1
      G_THROW( ERR_MSG("GPixmap.unk_PPM") );
Packit df99a1
#endif
Packit df99a1
    }
Packit df99a1
  // Read image size
Packit df99a1
  char lookahead = '\n';
Packit df99a1
  int bytesperrow = 0;
Packit df99a1
  int bytespercomp = 1;
Packit df99a1
  int acolumns = read_integer(lookahead, bs);
Packit df99a1
  int arows = read_integer(lookahead, bs);
Packit df99a1
  int maxval = read_integer(lookahead, bs);
Packit df99a1
  if (maxval > 65535)
Packit df99a1
    G_THROW("Cannot read PPM with depth greater than 48 bits.");
Packit df99a1
  if (maxval > 255)
Packit df99a1
    bytespercomp = 2;
Packit df99a1
  init(arows, acolumns, 0);
Packit df99a1
  // Prepare ramp
Packit df99a1
  GTArray<unsigned char> ramp;
Packit df99a1
  int maxbin = 1 << (8 * bytespercomp);
Packit df99a1
  ramp.resize(0, maxbin-1);
Packit df99a1
  for (int i=0; i
Packit df99a1
    ramp[i] = (i
Packit df99a1
  unsigned char *bramp = ramp;
Packit df99a1
  // Read image data
Packit df99a1
  if (raw && grey)
Packit df99a1
    {
Packit df99a1
      bytesperrow = ncolumns * bytespercomp;
Packit df99a1
      GTArray<unsigned char> line(bytesperrow);
Packit df99a1
      for (int y=nrows-1; y>=0; y--) 
Packit df99a1
        {
Packit df99a1
          GPixel *p = (*this)[y];
Packit df99a1
          unsigned char *g = &line[0];
Packit df99a1
          if ( bs.readall((void*)g, bytesperrow) < (size_t)bytesperrow)
Packit df99a1
            G_THROW( ByteStream::EndOfFile );
Packit df99a1
          if (bytespercomp <= 1)
Packit df99a1
            {
Packit df99a1
              for (int x=0; x
Packit df99a1
                p[x].r = p[x].g = p[x].b = bramp[g[0]];
Packit df99a1
            }
Packit df99a1
          else
Packit df99a1
            {
Packit df99a1
              for (int x=0; x
Packit df99a1
                p[x].r = p[x].g = p[x].b = bramp[g[0]*256+g[1]];
Packit df99a1
            }
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
  else if (raw)
Packit df99a1
    {
Packit df99a1
      bytesperrow = ncolumns * bytespercomp * 3;
Packit df99a1
      GTArray<unsigned char> line(bytesperrow);
Packit df99a1
      for (int y=nrows-1; y>=0; y--) 
Packit df99a1
        {
Packit df99a1
          GPixel *p = (*this)[y];
Packit df99a1
          unsigned char *rgb = &line[0];
Packit df99a1
          if ( bs.readall((void*)rgb, bytesperrow) < (size_t)bytesperrow)
Packit df99a1
            G_THROW( ByteStream::EndOfFile );
Packit df99a1
          if (bytespercomp <= 1)
Packit df99a1
            {
Packit df99a1
              for (int x=0; x
Packit df99a1
                {
Packit df99a1
                  p[x].r = bramp[rgb[0]];
Packit df99a1
                  p[x].g = bramp[rgb[1]];
Packit df99a1
                  p[x].b = bramp[rgb[2]];
Packit df99a1
                }
Packit df99a1
            }
Packit df99a1
          else
Packit df99a1
            for (int x=0; x
Packit df99a1
              {
Packit df99a1
                p[x].r = bramp[rgb[0]*256+rgb[1]];
Packit df99a1
                p[x].g = bramp[rgb[2]*256+rgb[3]];
Packit df99a1
                p[x].b = bramp[rgb[4]*256+rgb[5]];
Packit df99a1
              }
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
  else
Packit df99a1
    {
Packit df99a1
      for (int y=nrows-1; y>=0; y--) 
Packit df99a1
        {
Packit df99a1
          GPixel *p = (*this)[y];
Packit df99a1
          for (int x=0; x
Packit df99a1
            if (grey)
Packit df99a1
              {
Packit df99a1
                p[x].g = p[x].b = p[x].r = ramp[(int)read_integer(lookahead, bs)];
Packit df99a1
              }
Packit df99a1
            else
Packit df99a1
              {
Packit df99a1
                p[x].r = ramp[(int)read_integer(lookahead, bs)];
Packit df99a1
                p[x].g = ramp[(int)read_integer(lookahead, bs)];
Packit df99a1
                p[x].b = ramp[(int)read_integer(lookahead, bs)];
Packit df99a1
              }
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
void 
Packit df99a1
GPixmap::save_ppm(ByteStream &bs, int raw) const
Packit df99a1
{
Packit df99a1
  GUTF8String head;
Packit df99a1
  head.format("P%c\n%d %d\n255\n", (raw ? '6' : '3'), ncolumns, nrows);
Packit df99a1
  bs.writall((void*)(const char *)head, head.length());
Packit df99a1
  if (raw)
Packit df99a1
    {
Packit df99a1
      int rowsize = ncolumns+ncolumns+ncolumns;
Packit df99a1
      GTArray<unsigned char> xrgb(rowsize);
Packit df99a1
      for (int y=nrows-1; y>=0; y--) 
Packit df99a1
        {
Packit df99a1
          const GPixel *p = (*this)[y];
Packit df99a1
          unsigned char *d = xrgb;
Packit df99a1
          for (int x=0; x
Packit df99a1
            {
Packit df99a1
              *d++ = p[x].r;
Packit df99a1
              *d++ = p[x].g;
Packit df99a1
              *d++ = p[x].b;
Packit df99a1
            }
Packit df99a1
          bs.writall((void*)(unsigned char*)xrgb, ncolumns * 3);
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
  else
Packit df99a1
    {
Packit df99a1
      for (int y=nrows-1; y>=0; y--) 
Packit df99a1
        {
Packit df99a1
          const GPixel *p = (*this)[y];
Packit df99a1
          unsigned char eol='\n';
Packit df99a1
          for (int x=0; x
Packit df99a1
            {
Packit df99a1
              head.format("%d %d %d  ", p[x].r, p[x].g, p[x].b);
Packit df99a1
              bs.writall((void*)(const char *)head, head.length());
Packit df99a1
              x += 1;
Packit df99a1
              if (x==ncolumns || (x&0x7)==0) 
Packit df99a1
                bs.write((void*)&eol, 1);          
Packit df99a1
            }
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
//////////////////////////////////////////////////
Packit df99a1
// Color correction
Packit df99a1
//////////////////////////////////////////////////
Packit df99a1
Packit df99a1
Packit df99a1
static void
Packit df99a1
color_correction_table(double gamma, GPixel white,
Packit df99a1
                       unsigned char gtable[256][3] )
Packit df99a1
{
Packit df99a1
  // Check argument
Packit df99a1
  if (gamma<0.1 || gamma>10.0)
Packit df99a1
    G_THROW( ERR_MSG("GPixmap.bad_param") );
Packit df99a1
  if (gamma<1.001 && gamma>0.999 && white==GPixel::WHITE)
Packit df99a1
    {
Packit df99a1
      // Trivial correction
Packit df99a1
      for (int i=0; i<256; i++)
Packit df99a1
        gtable[i][0] = gtable[i][1] = gtable[i][2] = i;
Packit df99a1
    }
Packit df99a1
  else
Packit df99a1
    {
Packit df99a1
      // Must compute the correction
Packit df99a1
      for (int i=0; i<256; i++)
Packit df99a1
        {
Packit df99a1
          double x = (double)(i)/255.0;
Packit df99a1
#ifdef BEZIERGAMMA
Packit df99a1
          double t = ( sqrt(1.0+(gamma*gamma-1.0)*x) - 1.0 ) / (gamma - 1.0);
Packit df99a1
          x = ( (1.0 - gamma)*t + 2.0 * gamma ) * t / (gamma + 1.0);
Packit df99a1
#else
Packit df99a1
          x = pow(x, 1.0/gamma);        
Packit df99a1
#endif
Packit df99a1
          gtable[i][0] = (int) floor(white.b * x + 0.5);
Packit df99a1
          gtable[i][1] = (int) floor(white.g * x + 0.5);
Packit df99a1
          gtable[i][2] = (int) floor(white.r * x + 0.5);
Packit df99a1
        }
Packit df99a1
      // Make sure that min and max values are exactly black or white
Packit df99a1
      gtable[0][0] = 0;
Packit df99a1
      gtable[0][1] = 0;
Packit df99a1
      gtable[0][2] = 0;
Packit df99a1
      gtable[255][0] = white.b;
Packit df99a1
      gtable[255][1] = white.g;
Packit df99a1
      gtable[255][2] = white.r;
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
static void
Packit df99a1
color_correction_table_cache(double gamma, GPixel white,
Packit df99a1
                             unsigned char gtable[256][3] )
Packit df99a1
{
Packit df99a1
  // Compute color correction table
Packit df99a1
  if (gamma<1.001 && gamma>0.999 && white==GPixel::WHITE)
Packit df99a1
    {
Packit df99a1
      color_correction_table(gamma, white, gtable);
Packit df99a1
    }
Packit df99a1
  else
Packit df99a1
    {
Packit df99a1
      static double lgamma = -1.0;
Packit df99a1
      static GPixel lwhite = GPixel::BLACK;
Packit df99a1
      static unsigned char ctable[256][3];
Packit df99a1
      GMonitorLock lock(&pixmap_monitor());
Packit df99a1
      if (gamma != lgamma || white != lwhite)
Packit df99a1
        {
Packit df99a1
          color_correction_table(gamma, white, ctable);
Packit df99a1
          lgamma = gamma;
Packit df99a1
          lwhite = white;
Packit df99a1
        }
Packit df99a1
      memcpy(gtable, ctable, 256*3*sizeof(unsigned char));
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
GPixmap::color_correct(double gamma_correction, GPixel white)
Packit df99a1
{
Packit df99a1
  // Trivial corrections
Packit df99a1
  if (gamma_correction>0.999 && gamma_correction<1.001 && white==GPixel::WHITE)
Packit df99a1
    return;
Packit df99a1
  // Compute correction table
Packit df99a1
  unsigned char gtable[256][3];
Packit df99a1
  color_correction_table_cache(gamma_correction, white, gtable);
Packit df99a1
  // Perform correction
Packit df99a1
  for (int y=0; y
Packit df99a1
  {
Packit df99a1
    GPixel *pix = (*this)[y];
Packit df99a1
    for (int x=0; x
Packit df99a1
    {
Packit df99a1
      pix->b = gtable[ pix->b ][0];
Packit df99a1
      pix->g = gtable[ pix->g ][1];
Packit df99a1
      pix->r = gtable[ pix->r ][2];
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
GPixmap::color_correct(double gamma_correction)
Packit df99a1
{
Packit df99a1
  // Trivial corrections
Packit df99a1
  if (gamma_correction<=0.999 || gamma_correction>=1.001)
Packit df99a1
    color_correct(gamma_correction, GPixel::WHITE);
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
void 
Packit df99a1
GPixmap::color_correct(double gamma_correction, GPixel white,
Packit df99a1
                       GPixel *pix, int npixels)
Packit df99a1
{
Packit df99a1
  // Trivial corrections
Packit df99a1
  if (gamma_correction>0.999 && gamma_correction<1.001 && white==GPixel::WHITE)
Packit df99a1
    return;
Packit df99a1
  // Compute correction table
Packit df99a1
  unsigned char gtable[256][3];
Packit df99a1
  color_correction_table_cache(gamma_correction, white, gtable);
Packit df99a1
  // Perform correction
Packit df99a1
  while (--npixels>=0)
Packit df99a1
    {
Packit df99a1
      pix->b = gtable[pix->b][0];
Packit df99a1
      pix->g = gtable[pix->g][1];
Packit df99a1
      pix->r = gtable[pix->r][2];
Packit df99a1
      pix++;
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
void 
Packit df99a1
GPixmap::color_correct(double gamma_correction, GPixel *pix, int npixels)
Packit df99a1
{
Packit df99a1
  // Trivial corrections
Packit df99a1
  if (gamma_correction<=0.999 || gamma_correction>=1.001)
Packit df99a1
    color_correct(gamma_correction,GPixel::WHITE,pix,npixels);
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
//////////////////////////////////////////////////
Packit df99a1
// Dithering
Packit df99a1
//////////////////////////////////////////////////
Packit df99a1
Packit df99a1
Packit df99a1
void
Packit df99a1
GPixmap::ordered_666_dither(int xmin, int ymin)
Packit df99a1
{
Packit df99a1
  static unsigned char quantize[256+0x33+0x33];
Packit df99a1
  static unsigned char *quant = quantize + 0x33;
Packit df99a1
  static char  dither_ok = 0;
Packit df99a1
  static short dither[16][16] = 
Packit df99a1
  {
Packit df99a1
    {   0,192, 48,240, 12,204, 60,252,  3,195, 51,243, 15,207, 63,255 },
Packit df99a1
    { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 },
Packit df99a1
    {  32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 },
Packit df99a1
    { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 },
Packit df99a1
    {   8,200, 56,248,  4,196, 52,244, 11,203, 59,251,  7,199, 55,247 },
Packit df99a1
    { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 },
Packit df99a1
    {  40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 },
Packit df99a1
    { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 },
Packit df99a1
    {   2,194, 50,242, 14,206, 62,254,  1,193, 49,241, 13,205, 61,253 },
Packit df99a1
    { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 },
Packit df99a1
    {  34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 },
Packit df99a1
    { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 },
Packit df99a1
    {  10,202, 58,250,  6,198, 54,246,  9,201, 57,249,  5,197, 53,245 },
Packit df99a1
    { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 },
Packit df99a1
    {  42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 },
Packit df99a1
    { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 }
Packit df99a1
  };
Packit df99a1
  // Prepare tables
Packit df99a1
  if (!dither_ok)
Packit df99a1
  {
Packit df99a1
    int i, j;
Packit df99a1
    for (i=0; i<16; i++)
Packit df99a1
      for (j=0; j<16; j++)
Packit df99a1
        dither[i][j] = ((255 - 2*dither[i][j]) * 0x33) / 512;    
Packit df99a1
    j = -0x33;
Packit df99a1
    for (i=0x19; i<256; i+=0x33)
Packit df99a1
      while (j <= i)
Packit df99a1
        quant[j++] = i-0x19;
Packit df99a1
    assert(i-0x19 == 0xff);
Packit df99a1
    while (j< 256+0x33)
Packit df99a1
      quant[j++] = i-0x19;
Packit df99a1
    dither_ok = 1;
Packit df99a1
  }
Packit df99a1
  // Go dithering
Packit df99a1
  for (int y=0; y
Packit df99a1
  {
Packit df99a1
    GPixel *pix = (*this)[y];
Packit df99a1
    for (int x=0; x
Packit df99a1
    {
Packit df99a1
      pix->r = quant[ pix->r + dither[(x+xmin+0)&0xf][(y+ymin+0)&0xf] ];
Packit df99a1
      pix->g = quant[ pix->g + dither[(x+xmin+5)&0xf][(y+ymin+11)&0xf] ];
Packit df99a1
      pix->b = quant[ pix->b + dither[(x+xmin+11)&0xf][(y+ymin+5)&0xf] ];
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
GPixmap::ordered_32k_dither(int xmin, int ymin)
Packit df99a1
{
Packit df99a1
  static unsigned char quantize[256+8+8];
Packit df99a1
  static unsigned char *quant = quantize + 8;
Packit df99a1
  static char  dither_ok = 0;
Packit df99a1
  static short dither[16][16] = 
Packit df99a1
  {
Packit df99a1
    {   0,192, 48,240, 12,204, 60,252,  3,195, 51,243, 15,207, 63,255 },
Packit df99a1
    { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 },
Packit df99a1
    {  32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 },
Packit df99a1
    { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 },
Packit df99a1
    {   8,200, 56,248,  4,196, 52,244, 11,203, 59,251,  7,199, 55,247 },
Packit df99a1
    { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 },
Packit df99a1
    {  40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 },
Packit df99a1
    { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 },
Packit df99a1
    {   2,194, 50,242, 14,206, 62,254,  1,193, 49,241, 13,205, 61,253 },
Packit df99a1
    { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 },
Packit df99a1
    {  34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 },
Packit df99a1
    { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 },
Packit df99a1
    {  10,202, 58,250,  6,198, 54,246,  9,201, 57,249,  5,197, 53,245 },
Packit df99a1
    { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 },
Packit df99a1
    {  42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 },
Packit df99a1
    { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 }
Packit df99a1
  };
Packit df99a1
  // Prepare tables
Packit df99a1
  if (!dither_ok)
Packit df99a1
  {
Packit df99a1
    int i, j;
Packit df99a1
    for (i=0; i<16; i++)
Packit df99a1
      for (j=0; j<16; j++)
Packit df99a1
        dither[i][j] = ((255 - 2*dither[i][j]) * 8) / 512;    
Packit df99a1
    j = -8;
Packit df99a1
    for (i=3; i<256; i+=8)
Packit df99a1
      while (j <= i)
Packit df99a1
        quant[j++] = i;
Packit df99a1
    while (j<256+8)
Packit df99a1
      quant[j++] = 0xff;
Packit df99a1
    dither_ok = 1;
Packit df99a1
  }
Packit df99a1
  // Go dithering
Packit df99a1
  for (int y=0; y
Packit df99a1
  {
Packit df99a1
    GPixel *pix = (*this)[y];
Packit df99a1
    for (int x=0; x
Packit df99a1
    {
Packit df99a1
      pix->r = quant[ pix->r + dither[(x+xmin+0)&0xf][(y+ymin+0)&0xf] ];
Packit df99a1
      pix->g = quant[ pix->g + dither[(x+xmin+5)&0xf][(y+ymin+11)&0xf] ];
Packit df99a1
      pix->b = quant[ pix->b + dither[(x+xmin+11)&0xf][(y+ymin+5)&0xf] ];
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
//////////////////////////////////////////////////
Packit df99a1
// Upsample Downsample
Packit df99a1
//////////////////////////////////////////////////
Packit df99a1
Packit df99a1
Packit df99a1
void  
Packit df99a1
GPixmap::downsample(const GPixmap *src, int factor, const GRect *pdr)
Packit df99a1
{
Packit df99a1
  // check arguments
Packit df99a1
  GRect rect(0, 0, (src->columns()+factor-1)/factor, (src->rows()+factor-1)/factor);
Packit df99a1
  if (pdr != 0)
Packit df99a1
  {
Packit df99a1
    if (pdr->xmin < rect.xmin || 
Packit df99a1
        pdr->ymin < rect.ymin || 
Packit df99a1
        pdr->xmax > rect.xmax || 
Packit df99a1
        pdr->ymax > rect.ymax  )
Packit df99a1
      G_THROW( ERR_MSG("GPixmap.overflow1") );
Packit df99a1
    rect = *pdr;
Packit df99a1
  }
Packit df99a1
Packit df99a1
  // precompute inverse map
Packit df99a1
  static int invmap[256];
Packit df99a1
  static int invmapok = 0;
Packit df99a1
  if (! invmapok)
Packit df99a1
  {
Packit df99a1
    invmapok = 1;
Packit df99a1
    for (int i=1; i<(int)(sizeof(invmap)/sizeof(int)); i++)
Packit df99a1
      invmap[i] = 0x10000 / i;
Packit df99a1
  }
Packit df99a1
  
Packit df99a1
  // initialise pixmap
Packit df99a1
  init(rect.height(), rect.width(), 0);
Packit df99a1
Packit df99a1
  // determine starting and ending points in source rectangle
Packit df99a1
  int sy = rect.ymin * factor;
Packit df99a1
  int sxz = rect.xmin * factor;
Packit df99a1
Packit df99a1
Packit df99a1
  // loop over source rows
Packit df99a1
  const GPixel *sptr = (*src)[sy];
Packit df99a1
  GPixel *dptr = (*this)[0];
Packit df99a1
  for (int y=0; y
Packit df99a1
  {
Packit df99a1
    int sx = sxz;
Packit df99a1
    // loop over source columns
Packit df99a1
    for (int x=0; x
Packit df99a1
    {
Packit df99a1
      int r=0, g=0, b=0, s=0;
Packit df99a1
      // compute average bounds
Packit df99a1
      const GPixel *ksptr = sptr;
Packit df99a1
      int lsy = sy + factor;
Packit df99a1
      if (lsy > (int)src->rows())
Packit df99a1
        lsy = (int)src->rows();
Packit df99a1
      int lsx = sx + factor;
Packit df99a1
      if (lsx > (int)src->columns())
Packit df99a1
        lsx = (int)src->columns();
Packit df99a1
      // compute average
Packit df99a1
      for (int rsy=sy; rsy
Packit df99a1
      {
Packit df99a1
        for (int rsx = sx; rsx
Packit df99a1
        {
Packit df99a1
          r += ksptr[rsx].r;
Packit df99a1
          g += ksptr[rsx].g;
Packit df99a1
          b += ksptr[rsx].b;
Packit df99a1
          s += 1;
Packit df99a1
        }
Packit df99a1
        ksptr += src->rowsize();
Packit df99a1
      }
Packit df99a1
      // set pixel color
Packit df99a1
      if (s >= (int)(sizeof(invmap)/sizeof(int)))
Packit df99a1
      {
Packit df99a1
        dptr[x].r = r / s;
Packit df99a1
        dptr[x].g = g / s;
Packit df99a1
        dptr[x].b = b / s;
Packit df99a1
      }
Packit df99a1
      else
Packit df99a1
      {
Packit df99a1
        dptr[x].r = (r*invmap[s] + 0x8000) >> 16;
Packit df99a1
        dptr[x].g = (g*invmap[s] + 0x8000) >> 16;
Packit df99a1
        dptr[x].b = (b*invmap[s] + 0x8000) >> 16;
Packit df99a1
      }
Packit df99a1
      // next column
Packit df99a1
      sx = sx + factor;
Packit df99a1
    }
Packit df99a1
    // next row
Packit df99a1
    sy = sy + factor;
Packit df99a1
    sptr = sptr + factor * src->rowsize();
Packit df99a1
    dptr = dptr + rowsize();
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
void  
Packit df99a1
GPixmap::upsample(const GPixmap *src, int factor, const GRect *pdr)
Packit df99a1
{
Packit df99a1
  // check arguments
Packit df99a1
  GRect rect(0, 0, src->columns()*factor, src->rows()*factor);
Packit df99a1
  if (pdr != 0)
Packit df99a1
  {
Packit df99a1
    if (pdr->xmin < rect.xmin || 
Packit df99a1
        pdr->ymin < rect.ymin || 
Packit df99a1
        pdr->xmax > rect.xmax || 
Packit df99a1
        pdr->ymax > rect.ymax  )
Packit df99a1
      G_THROW( ERR_MSG("GPixmap.overflow2") );
Packit df99a1
    rect = *pdr;
Packit df99a1
  }
Packit df99a1
  // initialise pixmap
Packit df99a1
  init(rect.height(), rect.width(), 0);
Packit df99a1
  // compute starting point in source rectangle
Packit df99a1
  int sy, sy1, sxz, sx1z;
Packit df99a1
  euclidian_ratio(rect.ymin, factor, sy, sy1);
Packit df99a1
  euclidian_ratio(rect.xmin, factor, sxz, sx1z);
Packit df99a1
  // loop over rows
Packit df99a1
  const GPixel *sptr = (*src)[sy];
Packit df99a1
  GPixel *dptr = (*this)[0];
Packit df99a1
  for (int y=0; y
Packit df99a1
  {
Packit df99a1
    // loop over columns
Packit df99a1
    int sx = sxz;
Packit df99a1
    int sx1 = sx1z;
Packit df99a1
    for (int x=0; x
Packit df99a1
    {
Packit df99a1
      dptr[x] = sptr[sx];
Packit df99a1
      // next column
Packit df99a1
      if (++sx1 >= factor)
Packit df99a1
      {
Packit df99a1
        sx1 = 0;
Packit df99a1
        sx += 1;
Packit df99a1
      }
Packit df99a1
    }
Packit df99a1
    // next row
Packit df99a1
    dptr += rowsize();
Packit df99a1
    if (++sy1 >= factor)
Packit df99a1
    {
Packit df99a1
      sy1 = 0;
Packit df99a1
      sptr += src->rowsize();
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
static inline void
Packit df99a1
downsample_4x4_to_3x3 (const GPixel *s, int sadd, GPixel *d, int dadd)
Packit df99a1
{
Packit df99a1
  const GPixel *x = s;
Packit df99a1
  const GPixel *y = x + sadd;
Packit df99a1
  d[0].b = ( 11*x[0].b + 2*(x[1].b + y[0].b ) + y[1].b  + 8) >> 4;
Packit df99a1
  d[0].g = ( 11*x[0].g + 2*(x[1].g + y[0].g ) + y[1].g  + 8) >> 4;
Packit df99a1
  d[0].r = ( 11*x[0].r + 2*(x[1].r + y[0].r ) + y[1].r  + 8) >> 4;
Packit df99a1
  d[1].b = ( 7*(x[1].b + x[2].b) + y[1].b + y[2].b + 8 )     >> 4;
Packit df99a1
  d[1].g = ( 7*(x[1].g + x[2].g) + y[1].g + y[2].g + 8 )     >> 4;
Packit df99a1
  d[1].r = ( 7*(x[1].r + x[2].r) + y[1].r + y[2].r + 8 )     >> 4;
Packit df99a1
  d[2].b = ( 11*x[3].b + 2*(x[2].b + y[3].b ) + y[2].b  + 8) >> 4;
Packit df99a1
  d[2].g = ( 11*x[3].g + 2*(x[2].g + y[3].g ) + y[2].g  + 8) >> 4;
Packit df99a1
  d[2].r = ( 11*x[3].r + 2*(x[2].r + y[3].r ) + y[2].r  + 8) >> 4;
Packit df99a1
  d = d + dadd;
Packit df99a1
  x = x + sadd + sadd;
Packit df99a1
  d[0].b = ( 7*(x[0].b + y[0].b) + x[1].b + y[1].b + 8 )     >> 4;
Packit df99a1
  d[0].g = ( 7*(x[0].g + y[0].g) + x[1].g + y[1].g + 8 )     >> 4;
Packit df99a1
  d[0].r = ( 7*(x[0].r + y[0].r) + x[1].r + y[1].r + 8 )     >> 4;
Packit df99a1
  d[1].b = ( x[2].b + y[2].b + x[1].b + y[1].b + 2 )         >> 2;
Packit df99a1
  d[1].g = ( x[2].g + y[2].g + x[1].g + y[1].g + 2 )         >> 2;
Packit df99a1
  d[1].r = ( x[2].r + y[2].r + x[1].r + y[1].r + 2 )         >> 2;
Packit df99a1
  d[2].b = ( 7*(x[3].b + y[3].b) + x[2].b + y[2].b + 8 )     >> 4;
Packit df99a1
  d[2].g = ( 7*(x[3].g + y[3].g) + x[2].g + y[2].g + 8 )     >> 4;
Packit df99a1
  d[2].r = ( 7*(x[3].r + y[3].r) + x[2].r + y[2].r + 8 )     >> 4;
Packit df99a1
  d = d + dadd;
Packit df99a1
  y = y + sadd + sadd;
Packit df99a1
  d[0].b = ( 11*y[0].b + 2*(y[1].b + x[0].b ) + x[1].b  + 8) >> 4;
Packit df99a1
  d[0].g = ( 11*y[0].g + 2*(y[1].g + x[0].g ) + x[1].g  + 8) >> 4;
Packit df99a1
  d[0].r = ( 11*y[0].r + 2*(y[1].r + x[0].r ) + x[1].r  + 8) >> 4;
Packit df99a1
  d[1].b = ( 7*(y[1].b + y[2].b) + x[1].b + x[2].b + 8 )     >> 4;
Packit df99a1
  d[1].g = ( 7*(y[1].g + y[2].g) + x[1].g + x[2].g + 8 )     >> 4;
Packit df99a1
  d[1].r = ( 7*(y[1].r + y[2].r) + x[1].r + x[2].r + 8 )     >> 4;
Packit df99a1
  d[2].b = ( 11*y[3].b + 2*(y[2].b + x[3].b ) + x[2].b  + 8) >> 4;
Packit df99a1
  d[2].g = ( 11*y[3].g + 2*(y[2].g + x[3].g ) + x[2].g  + 8) >> 4;
Packit df99a1
  d[2].r = ( 11*y[3].r + 2*(y[2].r + x[3].r ) + x[2].r  + 8) >> 4;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
static inline void
Packit df99a1
upsample_2x2_to_3x3 (const GPixel *s, int sadd, GPixel *d, int dadd)
Packit df99a1
{
Packit df99a1
  const GPixel *x = s;
Packit df99a1
  const GPixel *y = x + sadd;
Packit df99a1
  d[0] = x[0];
Packit df99a1
  d[1].b = (x[0].b + x[1].b + 1) >> 1;
Packit df99a1
  d[1].g = (x[0].g + x[1].g + 1) >> 1;
Packit df99a1
  d[1].r = (x[0].r + x[1].r + 1) >> 1;
Packit df99a1
  d[2] = x[1];
Packit df99a1
  d = d + dadd;
Packit df99a1
  d[0].b = (x[0].b + y[0].b + 1) >> 1;
Packit df99a1
  d[0].g = (x[0].g + y[0].g + 1) >> 1;
Packit df99a1
  d[0].r = (x[0].r + y[0].r + 1) >> 1;
Packit df99a1
  d[1].b = (x[0].b + y[0].b + x[1].b + y[1].b + 2) >> 2;
Packit df99a1
  d[1].g = (x[0].g + y[0].g + x[1].g + y[1].g + 2) >> 2;
Packit df99a1
  d[1].r = (x[0].r + y[0].r + x[1].r + y[1].r + 2) >> 2;
Packit df99a1
  d[2].b = (x[1].b + y[1].b + 1) >> 1;
Packit df99a1
  d[2].g = (x[1].g + y[1].g + 1) >> 1;
Packit df99a1
  d[2].r = (x[1].r + y[1].r + 1) >> 1;
Packit df99a1
  d = d + dadd;
Packit df99a1
  d[0] = y[0];
Packit df99a1
  d[1].b = (y[0].b + y[1].b + 1) >> 1;
Packit df99a1
  d[1].g = (y[0].g + y[1].g + 1) >> 1;
Packit df99a1
  d[1].r = (y[0].r + y[1].r + 1) >> 1;
Packit df99a1
  d[2] = y[1];
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
static inline void
Packit df99a1
copy_to_partial(int w, int h,
Packit df99a1
                const GPixel *s, int sadd,
Packit df99a1
                GPixel *d, int dadd, int xmin, int xmax, int ymin, int ymax)
Packit df99a1
{
Packit df99a1
  int y = 0;
Packit df99a1
  while (y
Packit df99a1
    {
Packit df99a1
      y += 1;
Packit df99a1
      s += sadd;
Packit df99a1
      d += dadd;
Packit df99a1
    }
Packit df99a1
  while (y
Packit df99a1
    {
Packit df99a1
      int x = (xmin>0 ? xmin : 0);
Packit df99a1
      while (x
Packit df99a1
        {
Packit df99a1
          d[x] = s[x];
Packit df99a1
          x++;
Packit df99a1
        }
Packit df99a1
      y += 1;
Packit df99a1
      s += sadd;
Packit df99a1
      d += dadd;
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
static inline void
Packit df99a1
copy_line(const GPixel *s, int smin, int smax,
Packit df99a1
          GPixel *d, int dmin, int dmax)
Packit df99a1
{
Packit df99a1
  int x = dmin;
Packit df99a1
  while (x < smin) 
Packit df99a1
  { 
Packit df99a1
    d[x] = s[smin]; 
Packit df99a1
    x++; 
Packit df99a1
  }
Packit df99a1
  while (x < dmax && x < smax)  
Packit df99a1
  { 
Packit df99a1
    d[x] = s[x]; 
Packit df99a1
    x++; 
Packit df99a1
  }
Packit df99a1
  while (x < dmax)              
Packit df99a1
  {
Packit df99a1
    d[x] = s[smax-1]; 
Packit df99a1
    x++; 
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
static inline void
Packit df99a1
copy_from_partial(int w, int h,
Packit df99a1
                  const GPixel *s, int sadd, int xmin, int xmax, int ymin, int ymax,
Packit df99a1
                  GPixel *d, int dadd)
Packit df99a1
{
Packit df99a1
  int y = 0;
Packit df99a1
  s += (ymin>0 ? sadd * ymin : 0);
Packit df99a1
  while (y
Packit df99a1
    {
Packit df99a1
      copy_line(s, xmin, xmax, d, 0, w);
Packit df99a1
      y += 1;
Packit df99a1
      d += dadd;
Packit df99a1
    }
Packit df99a1
  while (y
Packit df99a1
    {
Packit df99a1
      copy_line(s, xmin, xmax, d, 0, w);
Packit df99a1
      y += 1;
Packit df99a1
      s += sadd;
Packit df99a1
      d += dadd;
Packit df99a1
    }
Packit df99a1
  s -= sadd;
Packit df99a1
  while (y < h)
Packit df99a1
    {
Packit df99a1
      copy_line(s, xmin, xmax, d, 0, w);
Packit df99a1
      y += 1;
Packit df99a1
      d += dadd;
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
void  
Packit df99a1
GPixmap::downsample43(const GPixmap *src, const GRect *pdr)
Packit df99a1
{
Packit df99a1
  // check arguments
Packit df99a1
  int srcwidth = src->columns();
Packit df99a1
  int srcheight = src->rows();
Packit df99a1
  int destwidth = (srcwidth * 3 + 3 ) / 4;
Packit df99a1
  int destheight = (srcheight * 3 + 3) / 4;
Packit df99a1
  GRect rect(0, 0, destwidth, destheight);
Packit df99a1
  if (pdr != 0)
Packit df99a1
  {
Packit df99a1
    if (pdr->xmin < rect.xmin || 
Packit df99a1
        pdr->ymin < rect.ymin || 
Packit df99a1
        pdr->xmax > rect.xmax || 
Packit df99a1
        pdr->ymax > rect.ymax  )
Packit df99a1
      G_THROW( ERR_MSG("GPixmap.overflow3") );
Packit df99a1
    rect = *pdr;
Packit df99a1
    destwidth = rect.width();
Packit df99a1
    destheight = rect.height();
Packit df99a1
  }
Packit df99a1
  // initialize pixmap
Packit df99a1
  init(destheight, destwidth, 0);
Packit df99a1
Packit df99a1
  // compute bounds
Packit df99a1
  int dxz, dy;   // location of bottomleft block in destination image
Packit df99a1
  int sxz, sy;   // location of bottomleft block in source image
Packit df99a1
  euclidian_ratio(rect.ymin, 3, sy, dy);
Packit df99a1
  euclidian_ratio(rect.xmin, 3, sxz, dxz);
Packit df99a1
  sxz = 4 * sxz;   
Packit df99a1
  sy  = 4 * sy;
Packit df99a1
  dxz = - dxz;
Packit df99a1
  dy  = - dy;
Packit df99a1
Packit df99a1
  // prepare variables
Packit df99a1
  int sadd = src->rowsize();
Packit df99a1
  int dadd = this->rowsize();
Packit df99a1
  const GPixel *sptr = (*src)[0]  + sy * sadd;
Packit df99a1
  GPixel *dptr = (*this)[0] + dy * dadd;
Packit df99a1
  int s4add = 4 * sadd;
Packit df99a1
  int d3add = 3 * dadd;
Packit df99a1
Packit df99a1
  // iterate over row blocks
Packit df99a1
  while (dy < destheight)
Packit df99a1
  {
Packit df99a1
    int sx = sxz;
Packit df99a1
    int dx = dxz;
Packit df99a1
    // iterate over column blocks
Packit df99a1
    while (dx < destwidth)
Packit df99a1
    {
Packit df99a1
      GPixel xin[16], xout[9];
Packit df99a1
Packit df99a1
      if (dx>=0 && dy>=0 && dx+3<=destwidth && dy+3<=destheight)
Packit df99a1
        {
Packit df99a1
          if (sx+4<=srcwidth && sy+4<=srcheight)
Packit df99a1
            {
Packit df99a1
              downsample_4x4_to_3x3(sptr+sx, sadd, dptr+dx, dadd);
Packit df99a1
            }
Packit df99a1
          else
Packit df99a1
            {
Packit df99a1
              copy_from_partial(4,4, sptr+sx,sadd,-sx,srcwidth-sx,-sy,srcheight-sy, xin,4);
Packit df99a1
              downsample_4x4_to_3x3(xin, 4, dptr+dx, dadd);
Packit df99a1
            }
Packit df99a1
        }
Packit df99a1
      else
Packit df99a1
        {
Packit df99a1
          if (sx+4<=srcwidth && sy+4<=srcheight)
Packit df99a1
            {
Packit df99a1
              downsample_4x4_to_3x3(sptr+sx, sadd, xout, 3);  
Packit df99a1
              copy_to_partial(3,3, xout, 3, dptr+dx, dadd,-dx,destwidth-dx,-dy,destheight-dy);
Packit df99a1
            }
Packit df99a1
          else
Packit df99a1
            {
Packit df99a1
              copy_from_partial(4,4, sptr+sx,sadd,-sx,srcwidth-sx,-sy,srcheight-sy, xin,4);
Packit df99a1
              downsample_4x4_to_3x3(xin, 4, xout, 3);  
Packit df99a1
              copy_to_partial(3,3, xout,3, dptr+dx,dadd,-dx,destwidth-dx,-dy,destheight-dy);
Packit df99a1
            }
Packit df99a1
        }
Packit df99a1
      // next column
Packit df99a1
      dx += 3;
Packit df99a1
      sx += 4;
Packit df99a1
    }
Packit df99a1
    // next row
Packit df99a1
    dy += 3;
Packit df99a1
    dptr += d3add;
Packit df99a1
    sy += 4;
Packit df99a1
    sptr += s4add;
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
void  
Packit df99a1
GPixmap::upsample23(const GPixmap *src, const GRect *pdr)
Packit df99a1
{
Packit df99a1
  // check arguments
Packit df99a1
  int srcwidth = src->columns();
Packit df99a1
  int srcheight = src->rows();
Packit df99a1
  int destwidth = (srcwidth * 3 + 1 ) / 2;
Packit df99a1
  int destheight = (srcheight * 3 + 1) / 2;
Packit df99a1
  GRect rect(0, 0, destwidth, destheight);
Packit df99a1
  if (pdr != 0)
Packit df99a1
  {
Packit df99a1
    if (pdr->xmin < rect.xmin || 
Packit df99a1
        pdr->ymin < rect.ymin || 
Packit df99a1
        pdr->xmax > rect.xmax || 
Packit df99a1
        pdr->ymax > rect.ymax  )
Packit df99a1
      G_THROW( ERR_MSG("GPixmap.overflow4") );
Packit df99a1
    rect = *pdr;
Packit df99a1
    destwidth = rect.width();
Packit df99a1
    destheight = rect.height();
Packit df99a1
  }
Packit df99a1
  // initialize pixmap
Packit df99a1
  init(destheight, destwidth, 0);
Packit df99a1
Packit df99a1
  // compute bounds
Packit df99a1
  int dxz, dy;   // location of bottomleft block in destination image
Packit df99a1
  int sxz, sy;   // location of bottomleft block in source image
Packit df99a1
  euclidian_ratio(rect.ymin, 3, sy, dy);
Packit df99a1
  euclidian_ratio(rect.xmin, 3, sxz, dxz);
Packit df99a1
  sxz = 2 * sxz;   
Packit df99a1
  sy  = 2 * sy;
Packit df99a1
  dxz = - dxz;
Packit df99a1
  dy  = - dy;
Packit df99a1
Packit df99a1
  // prepare variables
Packit df99a1
  int sadd = src->rowsize();
Packit df99a1
  int dadd = this->rowsize();
Packit df99a1
  const GPixel *sptr = (*src)[0]  + sy * sadd;
Packit df99a1
  GPixel *dptr = (*this)[0] + dy * dadd;
Packit df99a1
  int s2add = 2 * sadd;
Packit df99a1
  int d3add = 3 * dadd;
Packit df99a1
Packit df99a1
  // iterate over row blocks
Packit df99a1
  while (dy < destheight)
Packit df99a1
  {
Packit df99a1
    int sx = sxz;
Packit df99a1
    int dx = dxz;
Packit df99a1
    // iterate over column blocks
Packit df99a1
    while (dx < destwidth)
Packit df99a1
    {
Packit df99a1
      GPixel xin[4], xout[9];
Packit df99a1
Packit df99a1
      if (dx>=0 && dy>=0 && dx+3<=destwidth && dy+3<=destheight)
Packit df99a1
      {
Packit df99a1
        if (sx+2<=srcwidth && sy+2<=srcheight)
Packit df99a1
        {
Packit df99a1
          upsample_2x2_to_3x3( sptr+sx, sadd, dptr+dx, dadd);
Packit df99a1
        }
Packit df99a1
        else
Packit df99a1
        {
Packit df99a1
          copy_from_partial(2, 2, sptr+sx, sadd, -sx, srcwidth-sx, -sy, srcheight-sy, xin, 2);
Packit df99a1
          upsample_2x2_to_3x3(xin, 2, dptr+dx, dadd);
Packit df99a1
        }
Packit df99a1
      }
Packit df99a1
      else
Packit df99a1
      {
Packit df99a1
        if (sx+2<=srcwidth && sy+2<=srcheight)
Packit df99a1
        {
Packit df99a1
          upsample_2x2_to_3x3( sptr+sx, sadd, xout, 3);  
Packit df99a1
          copy_to_partial(3,3, xout, 3, dptr+dx, dadd, -dx, destwidth-dx, -dy, destheight-dy);
Packit df99a1
        }
Packit df99a1
        else
Packit df99a1
        {
Packit df99a1
          copy_from_partial(2, 2, sptr+sx, sadd, -sx, srcwidth-sx, -sy, srcheight-sy, xin, 2);
Packit df99a1
          upsample_2x2_to_3x3(xin, 2, xout, 3);  
Packit df99a1
          copy_to_partial(3,3, xout, 3, dptr+dx, dadd, -dx, destwidth-dx, -dy, destheight-dy);
Packit df99a1
        }
Packit df99a1
      }
Packit df99a1
      // next column
Packit df99a1
      dx += 3;
Packit df99a1
      sx += 2;
Packit df99a1
    }
Packit df99a1
    // next row
Packit df99a1
    dy += 3;
Packit df99a1
    dptr += d3add;
Packit df99a1
    sy += 2;
Packit df99a1
    sptr += s2add;
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
//////////////////////////////////////////////////
Packit df99a1
// Blitting and attenuating
Packit df99a1
//////////////////////////////////////////////////
Packit df99a1
Packit df99a1
Packit df99a1
static unsigned char clip[512];
Packit df99a1
static bool clipok = false;
Packit df99a1
Packit df99a1
static void
Packit df99a1
compute_clip()
Packit df99a1
{
Packit df99a1
  clipok = true;
Packit df99a1
  for (unsigned int i=0; i
Packit df99a1
    clip[i] = (i<256 ? i : 255);
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
void 
Packit df99a1
GPixmap::attenuate(const GBitmap *bm, int xpos, int ypos)
Packit df99a1
{
Packit df99a1
  // Check
Packit df99a1
  if (!bm) G_THROW( ERR_MSG("GPixmap.null_alpha") );
Packit df99a1
  // Compute number of rows and columns
Packit df99a1
  int xrows = mini(ypos + (int)bm->rows(), nrows) - maxi(0, ypos),
Packit df99a1
    xcolumns = mini(xpos + (int) bm->columns(), ncolumns) - maxi(0, xpos);
Packit df99a1
  if(xrows <= 0 || xcolumns <= 0)
Packit df99a1
    return;
Packit df99a1
  // Precompute multiplier map
Packit df99a1
  unsigned int multiplier[256];
Packit df99a1
  unsigned int maxgray = bm->get_grays() - 1;
Packit df99a1
  for (unsigned int i=0; i
Packit df99a1
    multiplier[i] = 0x10000 * i / maxgray;
Packit df99a1
  // Compute starting point
Packit df99a1
  const unsigned char *src = (*bm)[0] - mini(0,ypos)*bm->rowsize()-mini(0,xpos);
Packit df99a1
  GPixel *dst = (*this)[0] + maxi(0, ypos)*rowsize()+maxi(0, xpos);
Packit df99a1
  // Loop over rows
Packit df99a1
  for (int y=0; y
Packit df99a1
    {
Packit df99a1
      // Loop over columns
Packit df99a1
      for (int x=0; x
Packit df99a1
        {
Packit df99a1
          unsigned char srcpix = src[x];
Packit df99a1
          // Perform pixel operation
Packit df99a1
          if (srcpix > 0)
Packit df99a1
            {
Packit df99a1
              if (srcpix >= maxgray)
Packit df99a1
                {
Packit df99a1
                  dst[x].b = 0;
Packit df99a1
                  dst[x].g = 0;
Packit df99a1
                  dst[x].r = 0;
Packit df99a1
                }
Packit df99a1
              else
Packit df99a1
                {
Packit df99a1
                  unsigned int level = multiplier[srcpix];
Packit df99a1
                  dst[x].b -=  (dst[x].b * level) >> 16;
Packit df99a1
                  dst[x].g -=  (dst[x].g * level) >> 16;
Packit df99a1
                  dst[x].r -=  (dst[x].r * level) >> 16;
Packit df99a1
                }
Packit df99a1
            }
Packit df99a1
        }
Packit df99a1
      // Next line
Packit df99a1
      dst += rowsize();
Packit df99a1
      src += bm->rowsize();
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
void 
Packit df99a1
GPixmap::blit(const GBitmap *bm, int xpos, int ypos, const GPixel *color)
Packit df99a1
{
Packit df99a1
  // Check
Packit df99a1
  if (!bm) G_THROW( ERR_MSG("GPixmap.null_alpha") );
Packit df99a1
  if (!clipok) compute_clip();
Packit df99a1
  if (!color) return;
Packit df99a1
  // Compute number of rows and columns
Packit df99a1
  int xrows = mini(ypos + (int)bm->rows(), nrows) - maxi(0, ypos),
Packit df99a1
    xcolumns = mini(xpos + (int) bm->columns(), ncolumns) - maxi(0, xpos);
Packit df99a1
  if(xrows <= 0 || xcolumns <= 0)
Packit df99a1
    return;
Packit df99a1
  // Precompute multiplier map
Packit df99a1
  unsigned int multiplier[256];
Packit df99a1
  unsigned int maxgray = bm->get_grays() - 1;
Packit df99a1
  for (unsigned int i=1; i
Packit df99a1
    multiplier[i] = 0x10000 * i / maxgray;
Packit df99a1
  // Cache target color
Packit df99a1
  unsigned char gr = color->r;
Packit df99a1
  unsigned char gg = color->g;
Packit df99a1
  unsigned char gb = color->b;
Packit df99a1
  // Compute starting point
Packit df99a1
  const unsigned char *src = (*bm)[0] - mini(0,ypos)*bm->rowsize()-mini(0,xpos);
Packit df99a1
  GPixel *dst = (*this)[0] + maxi(0, ypos)*rowsize()+maxi(0, xpos);
Packit df99a1
  // Loop over rows
Packit df99a1
  for (int y=0; y
Packit df99a1
    {
Packit df99a1
      // Loop over columns
Packit df99a1
      for (int x=0; x
Packit df99a1
        {
Packit df99a1
          unsigned char srcpix = src[x];
Packit df99a1
          // Perform pixel operation
Packit df99a1
          if (srcpix > 0)
Packit df99a1
            {
Packit df99a1
              if (srcpix >= maxgray)
Packit df99a1
                {
Packit df99a1
                  dst[x].b = clip[dst[x].b + gb];
Packit df99a1
                  dst[x].g = clip[dst[x].g + gg];
Packit df99a1
                  dst[x].r = clip[dst[x].r + gr];
Packit df99a1
                }
Packit df99a1
              else
Packit df99a1
                {
Packit df99a1
                  unsigned int level = multiplier[srcpix];
Packit df99a1
                  dst[x].b = clip[dst[x].b + ((gb * level) >> 16)];
Packit df99a1
                  dst[x].g = clip[dst[x].g + ((gg * level) >> 16)];
Packit df99a1
                  dst[x].r = clip[dst[x].r + ((gr * level) >> 16)];
Packit df99a1
                }
Packit df99a1
            }
Packit df99a1
        }
Packit df99a1
      // Next line
Packit df99a1
      dst += rowsize();
Packit df99a1
      src += bm->rowsize();
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
void 
Packit df99a1
GPixmap::blit(const GBitmap *bm, int xpos, int ypos, const GPixmap *color)
Packit df99a1
{
Packit df99a1
  // Check
Packit df99a1
  if (!bm) G_THROW( ERR_MSG("GPixmap.null_alpha") );
Packit df99a1
  if (!color) G_THROW( ERR_MSG("GPixmap.null_color") );
Packit df99a1
  if (!clipok) compute_clip();
Packit df99a1
  if (bm->rows()!=color->rows() || bm->columns()!=color->columns())
Packit df99a1
    G_THROW( ERR_MSG("GPixmap.diff_size") );
Packit df99a1
  // Compute number of rows and columns
Packit df99a1
  int xrows = mini(ypos + (int)bm->rows(), nrows) - maxi(0, ypos),
Packit df99a1
      xcolumns = mini(xpos + (int) bm->columns(), ncolumns) - maxi(0, xpos);
Packit df99a1
  if(xrows <= 0 || xcolumns <= 0)
Packit df99a1
    return;
Packit df99a1
  // Precompute multiplier map
Packit df99a1
  unsigned int multiplier[256];
Packit df99a1
  unsigned int maxgray = bm->get_grays() - 1;
Packit df99a1
  for (unsigned int i=1; i
Packit df99a1
    multiplier[i] = 0x10000 * i / maxgray;
Packit df99a1
  // Cache target color
Packit df99a1
  // Compute starting point
Packit df99a1
  const unsigned char *src = (*bm)[0] - mini(0,ypos)*bm->rowsize()-mini(0,xpos);
Packit df99a1
  const GPixel *src2 = (*color)[0] + maxi(0, ypos)*color->rowsize()+maxi(0, xpos);
Packit df99a1
  GPixel *dst = (*this)[0] + maxi(0, ypos)*rowsize()+maxi(0, xpos);
Packit df99a1
  // Loop over rows
Packit df99a1
  for (int y=0; y
Packit df99a1
    {
Packit df99a1
      // Loop over columns
Packit df99a1
      for (int x=0; x
Packit df99a1
        {
Packit df99a1
          unsigned char srcpix = src[x];
Packit df99a1
          // Perform pixel operation
Packit df99a1
          if (srcpix > 0)
Packit df99a1
            {
Packit df99a1
              if (srcpix >= maxgray)
Packit df99a1
                {
Packit df99a1
                  dst[x].b = clip[dst[x].b + src2[x].b];
Packit df99a1
                  dst[x].g = clip[dst[x].g + src2[x].g];
Packit df99a1
                  dst[x].r = clip[dst[x].r + src2[x].r];
Packit df99a1
                }
Packit df99a1
              else
Packit df99a1
                {
Packit df99a1
                  unsigned int level = multiplier[srcpix];
Packit df99a1
                  dst[x].b = clip[dst[x].b + ((src2[x].b * level) >> 16)];
Packit df99a1
                  dst[x].g = clip[dst[x].g + ((src2[x].g * level) >> 16)];
Packit df99a1
                  dst[x].r = clip[dst[x].r + ((src2[x].r * level) >> 16)];
Packit df99a1
                }
Packit df99a1
            }
Packit df99a1
        }
Packit df99a1
      // Next line
Packit df99a1
      dst += rowsize();
Packit df99a1
      src += bm->rowsize();
Packit df99a1
      src2 += color->rowsize();
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
void 
Packit df99a1
GPixmap::blend(const GBitmap *bm, int xpos, int ypos, const GPixmap *color)
Packit df99a1
{
Packit df99a1
  // Check
Packit df99a1
  if (!bm) G_THROW( ERR_MSG("GPixmap.null_alpha") );
Packit df99a1
  if (!color) G_THROW( ERR_MSG("GPixmap.null_color") );
Packit df99a1
  if (!clipok) compute_clip();
Packit df99a1
  if (bm->rows()!=color->rows() || bm->columns()!=color->columns())
Packit df99a1
    G_THROW( ERR_MSG("GPixmap.diff_size") );
Packit df99a1
  // Compute number of rows and columns
Packit df99a1
  int xrows = mini(ypos + (int)bm->rows(), nrows) - maxi(0, ypos),
Packit df99a1
      xcolumns = mini(xpos + (int) bm->columns(), ncolumns) - maxi(0, xpos);
Packit df99a1
  if(xrows <= 0 || xcolumns <= 0)
Packit df99a1
    return;
Packit df99a1
  // Precompute multiplier map
Packit df99a1
  unsigned int multiplier[256];
Packit df99a1
  unsigned int maxgray = bm->get_grays() - 1;
Packit df99a1
  for (unsigned int i=1; i
Packit df99a1
    multiplier[i] = 0x10000 * i / maxgray;
Packit df99a1
  // Cache target color
Packit df99a1
  // Compute starting point
Packit df99a1
  const unsigned char *src = (*bm)[0] - mini(0,ypos)*bm->rowsize()-mini(0,xpos);
Packit df99a1
  const GPixel *src2 = (*color)[0] + maxi(0, ypos)*color->rowsize()+maxi(0, xpos);
Packit df99a1
  GPixel *dst = (*this)[0] + maxi(0, ypos)*rowsize()+maxi(0, xpos);
Packit df99a1
  // Loop over rows
Packit df99a1
  for (int y=0; y
Packit df99a1
    {
Packit df99a1
      // Loop over columns
Packit df99a1
      for (int x=0; x
Packit df99a1
        {
Packit df99a1
          unsigned char srcpix = src[x];
Packit df99a1
          // Perform pixel operation
Packit df99a1
          if (srcpix > 0)
Packit df99a1
            {
Packit df99a1
              if (srcpix >= maxgray)
Packit df99a1
                {
Packit df99a1
                  dst[x].b = src2[x].b;
Packit df99a1
                  dst[x].g = src2[x].g;
Packit df99a1
                  dst[x].r = src2[x].r;
Packit df99a1
                }
Packit df99a1
              else
Packit df99a1
                {
Packit df99a1
                  unsigned int level = multiplier[srcpix];
Packit df99a1
                  dst[x].b -= (((int)dst[x].b - (int)src2[x].b) * level) >> 16;
Packit df99a1
                  dst[x].g -= (((int)dst[x].g - (int)src2[x].g) * level) >> 16;
Packit df99a1
                  dst[x].r -= (((int)dst[x].r - (int)src2[x].r) * level) >> 16;
Packit df99a1
                }
Packit df99a1
            }
Packit df99a1
        }
Packit df99a1
      // Next line
Packit df99a1
      dst += rowsize();
Packit df99a1
      src += bm->rowsize();
Packit df99a1
      src2 += color->rowsize();
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
void 
Packit df99a1
GPixmap::stencil(const GBitmap *bm, 
Packit df99a1
                const GPixmap *pm, int pms, const GRect *pmr, 
Packit df99a1
                 double corr, GPixel white)
Packit df99a1
{
Packit df99a1
  // Check arguments
Packit df99a1
  GRect rect(0, 0, pm->columns()*pms, pm->rows()*pms);
Packit df99a1
  if (pmr != 0)
Packit df99a1
    {
Packit df99a1
      if (pmr->xmin < rect.xmin || 
Packit df99a1
          pmr->ymin < rect.ymin || 
Packit df99a1
          pmr->xmax > rect.xmax || 
Packit df99a1
          pmr->ymax > rect.ymax  )
Packit df99a1
        G_THROW( ERR_MSG("GPixmap.overflow5") );
Packit df99a1
      rect = *pmr;
Packit df99a1
    }
Packit df99a1
  // Compute number of rows
Packit df99a1
  int xrows = nrows;
Packit df99a1
  if ((int)bm->rows() < xrows)
Packit df99a1
    xrows = bm->rows();
Packit df99a1
  if (rect.height() < xrows)
Packit df99a1
    xrows = rect.height();
Packit df99a1
  // Compute number of columns
Packit df99a1
  int xcolumns = ncolumns;
Packit df99a1
  if ((int)bm->columns() < xcolumns)
Packit df99a1
    xcolumns = bm->columns();
Packit df99a1
  if (rect.width() < xcolumns)
Packit df99a1
    xcolumns = rect.width();
Packit df99a1
  // Precompute multiplier map
Packit df99a1
  unsigned int multiplier[256];
Packit df99a1
  unsigned int maxgray = bm->get_grays() - 1;
Packit df99a1
  for (unsigned int i=1; i
Packit df99a1
    multiplier[i] = 0x10000 * i / maxgray;
Packit df99a1
  // Prepare color correction table
Packit df99a1
  unsigned char gtable[256][3];
Packit df99a1
  color_correction_table_cache(corr, white, gtable);
Packit df99a1
  // Compute starting point in blown up foreground pixmap
Packit df99a1
  int fgy, fgy1, fgxz, fgx1z;
Packit df99a1
  euclidian_ratio(rect.ymin, pms, fgy, fgy1);
Packit df99a1
  euclidian_ratio(rect.xmin, pms, fgxz, fgx1z);
Packit df99a1
  const GPixel *fg = (*pm)[fgy];
Packit df99a1
  const unsigned char *src = (*bm)[0];
Packit df99a1
  GPixel *dst = (*this)[0];
Packit df99a1
  // Loop over rows
Packit df99a1
  for (int y=0; y
Packit df99a1
  {
Packit df99a1
    // Loop over columns
Packit df99a1
    int fgx = fgxz;
Packit df99a1
    int fgx1 = fgx1z;
Packit df99a1
    for (int x=0; x
Packit df99a1
    {
Packit df99a1
      unsigned char srcpix = src[x];
Packit df99a1
      // Perform pixel operation
Packit df99a1
      if (srcpix > 0)
Packit df99a1
      {
Packit df99a1
        if (srcpix >= maxgray)
Packit df99a1
        {
Packit df99a1
          dst[x].b = gtable[fg[fgx].b][0];
Packit df99a1
          dst[x].g = gtable[fg[fgx].g][1];
Packit df99a1
          dst[x].r = gtable[fg[fgx].r][2];
Packit df99a1
        }
Packit df99a1
        else
Packit df99a1
        {
Packit df99a1
          unsigned int level = multiplier[srcpix];
Packit df99a1
          dst[x].b -= (((int)dst[x].b-(int)gtable[fg[fgx].b][0])*level) >> 16;
Packit df99a1
          dst[x].g -= (((int)dst[x].g-(int)gtable[fg[fgx].g][1])*level) >> 16;
Packit df99a1
          dst[x].r -= (((int)dst[x].r-(int)gtable[fg[fgx].r][2])*level) >> 16;
Packit df99a1
        }
Packit df99a1
      }
Packit df99a1
      // Next column
Packit df99a1
      if (++fgx1 >= pms)
Packit df99a1
      {
Packit df99a1
        fgx1 = 0;
Packit df99a1
        fgx += 1;
Packit df99a1
      }
Packit df99a1
    }
Packit df99a1
    // Next line
Packit df99a1
    dst += rowsize();
Packit df99a1
    src += bm->rowsize();
Packit df99a1
    if (++fgy1 >= pms)
Packit df99a1
    {
Packit df99a1
      fgy1 = 0;
Packit df99a1
      fg += pm->rowsize();
Packit df99a1
    } 
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
GPixmap::stencil(const GBitmap *bm, 
Packit df99a1
                const GPixmap *pm, int pms, const GRect *pmr, 
Packit df99a1
                double corr)
Packit df99a1
{
Packit df99a1
  stencil(bm, pm, pms, pmr, corr, GPixel::WHITE);
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
GP<GPixmap> GPixmap::rotate(int count)
Packit df99a1
{
Packit df99a1
  GP<GPixmap> newpixmap(this);
Packit df99a1
  count = count & 3;
Packit df99a1
  if(count)
Packit df99a1
  {
Packit df99a1
    if( count&0x01)
Packit df99a1
      newpixmap = new GPixmap(ncolumns, nrows);
Packit df99a1
    else
Packit df99a1
      newpixmap = new GPixmap(nrows, ncolumns);
Packit df99a1
Packit df99a1
    GPixmap &dpixmap = *newpixmap;
Packit df99a1
Packit df99a1
    GMonitorLock lock(&pixmap_monitor());
Packit df99a1
    switch(count)
Packit df99a1
    {
Packit df99a1
    case 3: //// rotate 90 counter clockwise
Packit df99a1
        {
Packit df99a1
            int lastrow = dpixmap.rows()-1;
Packit df99a1
Packit df99a1
            for(int y=0; y
Packit df99a1
            {
Packit df99a1
                const GPixel *r=operator [] (y);
Packit df99a1
                for(int x=0,xnew=lastrow; xnew>=0; x++,xnew--)
Packit df99a1
                {
Packit df99a1
                    dpixmap[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
            int lastrow = dpixmap.rows()-1;
Packit df99a1
            int lastcolumn = dpixmap.columns()-1;
Packit df99a1
Packit df99a1
            for(int y=0,ynew=lastrow; ynew>=0; y++,ynew--)
Packit df99a1
            {
Packit df99a1
                const GPixel *r=operator [] (y);
Packit df99a1
                GPixel *d=dpixmap[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
            int lastcolumn = dpixmap.columns()-1;
Packit df99a1
Packit df99a1
            for(int y=0,ynew=lastcolumn; ynew>=0; y++,ynew--)
Packit df99a1
            {
Packit df99a1
                const GPixel *r=operator [] (y);
Packit df99a1
                for(int x=0; x
Packit df99a1
                {
Packit df99a1
                    dpixmap[x][ynew] = r[x];
Packit df99a1
                }
Packit df99a1
            }
Packit df99a1
        }
Packit df99a1
        break;
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
  return newpixmap;
Packit df99a1
}
Packit df99a1
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