Blame libdjvu/DjVuPalette.h

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
#ifndef _DJVUPALETTE_H_
Packit df99a1
#define _DJVUPALETTE_H_
Packit df99a1
#ifdef HAVE_CONFIG_H
Packit df99a1
#include "config.h"
Packit df99a1
#endif
Packit df99a1
#if NEED_GNUG_PRAGMAS
Packit df99a1
# pragma interface
Packit df99a1
#endif
Packit df99a1
Packit df99a1
Packit df99a1
#include "GContainer.h"
Packit df99a1
#include "GPixmap.h"
Packit df99a1
#include <string.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
/** @name DjVuPalette.h
Packit df99a1
    Files #"DjVuPalette.h"# and #"DjVuPalette.cpp"# implement a single class
Packit df99a1
    \Ref{DjVuPalette} which provides facilities for computing optimal color
Packit df99a1
    palettes, coding color palettes, and coding sequences of color indices.
Packit df99a1
    @memo 
Packit df99a1
    DjVuPalette header file
Packit df99a1
    @author: 
Packit df99a1
    L\'eon Bottou <leonb@research.att.com> */
Packit df99a1
//@{
Packit df99a1
Packit df99a1
Packit df99a1
/** Computing and coding color palettes and index arrays.
Packit df99a1
    This class provides facilities for computing optimal color palettes,
Packit df99a1
    coding color palettes, and coding sequences of color indices.
Packit df99a1
    
Packit df99a1
    {\bf Creating a color palette} -- The recipe for creating a color palette
Packit df99a1
    consists in (a) creating a DjVuPalette object, (b) constructing a color
Packit df99a1
    histogram using \Ref{histogram_add}, and (c) calling function
Packit df99a1
    \Ref{compute_palette}.
Packit df99a1
Packit df99a1
    {\bf Accessing the color palette} -- Conversion between colors and color
Packit df99a1
    palette indices is easily achieved with \Ref{color_to_index} and
Packit df99a1
    \Ref{index_to_color}.  There are also functions for computing a palette
Packit df99a1
    and quantizing a complete pixmap.
Packit df99a1
Packit df99a1
    {\bf Sequences of color indices} -- The DjVuPalette object also contains
Packit df99a1
    an array \Ref{colordata} optionally containing a sequence of color
Packit df99a1
    indices.  This array will be encoded and decoded by functions \Ref{encode}
Packit df99a1
    and \Ref{decode}.  This feature simplifies the implementation of the ``one
Packit df99a1
    color per symbol'' model in DjVu.
Packit df99a1
Packit df99a1
    {\bf Coding color palettes and color indices} -- Two functions
Packit df99a1
    \Ref{encode} and \Ref{decode} are provided for coding the color palette
Packit df99a1
    and the array of color indices when appropriate.  */
Packit df99a1
#ifdef _WIN32_WCE_EMULATION         // Work around odd behavior under WCE Emulation
Packit df99a1
#define CALLINGCONVENTION __cdecl
Packit df99a1
#else
Packit df99a1
#define CALLINGCONVENTION  /* */
Packit df99a1
#endif
Packit df99a1
Packit df99a1
class DJVUAPI DjVuPalette : public GPEnabled
Packit df99a1
{
Packit df99a1
protected:
Packit df99a1
  DjVuPalette(void);
Packit df99a1
public:
Packit df99a1
  /// Generic creator
Packit df99a1
  static GP<DjVuPalette> create(void) {return new DjVuPalette();}
Packit df99a1
Packit df99a1
  /// Non-virtual destructor
Packit df99a1
  ~DjVuPalette();
Packit df99a1
  // COPY
Packit df99a1
  DjVuPalette(const DjVuPalette &ref;;
Packit df99a1
  DjVuPalette& operator=(const DjVuPalette &ref;;
Packit df99a1
  // PALETTE COMPUTATION
Packit df99a1
  /** Resets the color histogram to zero. */
Packit df99a1
  void histogram_clear();
Packit df99a1
  /** Adds the color specified by #p# to the histogram.
Packit df99a1
      Argument #weight# represent the number of pixels with this color. */
Packit df99a1
  void histogram_add(const GPixel &p, int weight);
Packit df99a1
  /** Adds the color specified by the triple #bgr# to the histogram.
Packit df99a1
      Argument #weight# represent the number of pixels with this color. */
Packit df99a1
  void histogram_add(const unsigned char *bgr, int weight);
Packit df99a1
  /** Adds the color specified by the weighted triple #bgr# to the histogram.
Packit df99a1
      Argument #weight# represent the number of pixels with this color.  This
Packit df99a1
      function will compute the actual color by dividing the elements of the
Packit df99a1
      #bgr# array by #weight# and then use the unnormalized values to compute
Packit df99a1
      the average color per bucket.  This is all a way to avoid excessive loss
Packit df99a1
      of accuracy. */
Packit df99a1
  void histogram_norm_and_add(const int *bgr, int weight);
Packit df99a1
  /** Computes an optimal palette for representing an image where colors
Packit df99a1
      appear according to the histogram.  Argument #maxcolors# is the maximum
Packit df99a1
      number of colors allowed in the palette (up to 1024).  Argument
Packit df99a1
      #minboxsize# controls the minimal size of the color cube area affected
Packit df99a1
      to a color palette entry.  Returns the index of the dominant color. */
Packit df99a1
  int compute_palette(int maxcolors, int minboxsize=0);
Packit df99a1
  /** Computes the optimal palette for pixmap #pm#.  This function builds the
Packit df99a1
      histogram for pixmap #pm# and computes the optimal palette using
Packit df99a1
      \Ref{compute_palette}. */
Packit df99a1
  int compute_pixmap_palette(const GPixmap &pm, int ncolors, int minboxsize=0);
Packit df99a1
  // CONVERSION
Packit df99a1
  /** Returns the number of colors in the palette. */
Packit df99a1
  int size() const;
Packit df99a1
  /** Returns the best palette index for representing color #p#. */
Packit df99a1
  int color_to_index(const GPixel &p);
Packit df99a1
  /** Returns the best palette index for representing color #bgr#. */
Packit df99a1
  int color_to_index(const unsigned char *bgr);
Packit df99a1
  /** Overwrites #p# with the color located at position #index# in the palette. */
Packit df99a1
  void index_to_color(int index, GPixel &p) const;
Packit df99a1
  /** Overwrites #rgb[0..3]# with the color located at 
Packit df99a1
      position #index# in the palette. */
Packit df99a1
  void index_to_color(int index, unsigned char *bgr) const;
Packit df99a1
  /** Quantizes pixmap #pm#. All pixels are replaced by their closest
Packit df99a1
      approximation available in the palette. */
Packit df99a1
  void quantize(GPixmap &pm);
Packit df99a1
  /** Calls \Ref{compute_pixmap_palette} and \Ref{quantize}. */
Packit df99a1
  int compute_palette_and_quantize(GPixmap &pm, int maxcolors, int minboxsize=0);
Packit df99a1
  // COLOR CORRECTION
Packit df99a1
  /** Applies a luminance gamma correction factor of #corr# to the palette
Packit df99a1
      entries.  Values greater than #1.0# make the image brighter.  Values
Packit df99a1
      smaller than #1.0# make the image darker.  The documentation of program
Packit df99a1
      \Ref{ppmcoco} explains how to properly use this function. */
Packit df99a1
  void color_correct(double corr);
Packit df99a1
  // COLOR INDEX DATA
Packit df99a1
  /** Contains an optional sequence of color indices. 
Packit df99a1
      Function \Ref{encode} and \Ref{decode} also encode and decode this
Packit df99a1
      sequence when such a sequence is provided. */
Packit df99a1
  GTArray<short> colordata;
Packit df99a1
  /** Returns colors from the color index sequence.  Pixel #out# is
Packit df99a1
      overwritten with the color corresponding to the #nth# element of the
Packit df99a1
      color sequence \Ref{colordata}. */
Packit df99a1
  void get_color(int nth, GPixel &out) const;
Packit df99a1
  // CODING
Packit df99a1
  /** Writes the palette colors.  This function writes each palette color as a
Packit df99a1
      RGB triple into bytestream #bs#. */
Packit df99a1
  void encode_rgb_entries(ByteStream &bs) const;
Packit df99a1
  /** Reads palette colors.  This function initializes the palette colors by
Packit df99a1
      reading #palettesize# RGB triples from bytestream #bs#. */
Packit df99a1
  void decode_rgb_entries(ByteStream &bs, const int palettesize);
Packit df99a1
  /** Encodes the palette and the color index sequence. This function encodes
Packit df99a1
      the a version byte, the palette size, the palette colors and the color
Packit df99a1
      index sequence into bytestream #bs#.  Note that the color histogram is
Packit df99a1
      never saved. */
Packit df99a1
  void encode(GP<ByteStream> bs) const;
Packit df99a1
  /** Initializes the object by reading data from bytestream #bs#.  This
Packit df99a1
      function reads a version byte, the palette size, the palette and the
Packit df99a1
      color index sequence from bytestream #bs#.  Note that the color
Packit df99a1
      histogram is never saved. */
Packit df99a1
  void decode(GP<ByteStream> bs);
Packit df99a1
Packit df99a1
private:
Packit df99a1
  // Histogram
Packit df99a1
  int mask;
Packit df99a1
  GMap<int,int> *hist;
Packit df99a1
  // Quantization data
Packit df99a1
  struct PColor { unsigned char p[4]; };
Packit df99a1
  GTArray<PColor> palette;
Packit df99a1
  GMap<int,int> *pmap;
Packit df99a1
  // Helpers
Packit df99a1
  void allocate_hist();
Packit df99a1
  void allocate_pmap();
Packit df99a1
  static int CALLINGCONVENTION bcomp (const void*, const void*);
Packit df99a1
  static int CALLINGCONVENTION gcomp (const void*, const void*);
Packit df99a1
  static int CALLINGCONVENTION rcomp (const void*, const void*);
Packit df99a1
  static int CALLINGCONVENTION lcomp (const void*, const void*);
Packit df99a1
  int color_to_index_slow(const unsigned char *bgr);
Packit df99a1
private: // dummy functions
Packit df99a1
  static void encode(ByteStream *);
Packit df99a1
  static void decode(ByteStream *);
Packit df99a1
};
Packit df99a1
Packit df99a1
Packit df99a1
//@}
Packit df99a1
Packit df99a1
// ------------ INLINES
Packit df99a1
Packit df99a1
Packit df99a1
inline void 
Packit df99a1
DjVuPalette::histogram_clear()
Packit df99a1
{
Packit df99a1
  delete hist;
Packit df99a1
  hist = 0;
Packit df99a1
  mask = 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
inline void 
Packit df99a1
DjVuPalette::histogram_add(const unsigned char *bgr, int weight)
Packit df99a1
{
Packit df99a1
  if (weight > 0)
Packit df99a1
    {
Packit df99a1
      if (!hist || hist->size()>=0x4000) 
Packit df99a1
        allocate_hist();
Packit df99a1
      int key = (bgr[0]<<16)|(bgr[1]<<8)|(bgr[2])|(mask);
Packit df99a1
      (*hist)[key] += weight;
Packit df99a1
    }
Packit df99a1
}  
Packit df99a1
Packit df99a1
inline void 
Packit df99a1
DjVuPalette::histogram_add(const GPixel &p, int weight)
Packit df99a1
{
Packit df99a1
  histogram_add(&p.b, weight);
Packit df99a1
}
Packit df99a1
Packit df99a1
inline void 
Packit df99a1
DjVuPalette::histogram_norm_and_add(const int *bgr, int weight)
Packit df99a1
{
Packit df99a1
  if (weight > 0)
Packit df99a1
    {
Packit df99a1
      int p0 = bgr[0]/weight; if (p0>255) p0=255;
Packit df99a1
      int p1 = bgr[1]/weight; if (p1>255) p1=255;
Packit df99a1
      int p2 = bgr[2]/weight; if (p2>255) p2=255;
Packit df99a1
      if (!hist || hist->size()>=0x4000) 
Packit df99a1
        allocate_hist();
Packit df99a1
      int key = (p0<<16)|(p1<<8)|(p2)|(mask);
Packit df99a1
      (*hist)[key] += weight;
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
inline int
Packit df99a1
DjVuPalette::size() const
Packit df99a1
{
Packit df99a1
  return palette.size();
Packit df99a1
}
Packit df99a1
Packit df99a1
inline int 
Packit df99a1
DjVuPalette::color_to_index(const unsigned char *bgr)
Packit df99a1
{
Packit df99a1
  if (! pmap)
Packit df99a1
    allocate_pmap();
Packit df99a1
  int key = (bgr[0]<<16)|(bgr[1]<<8)|(bgr[2]);
Packit df99a1
  GPosition p = pmap->contains(key);
Packit df99a1
  if ( p)
Packit df99a1
    return (*pmap)[p];
Packit df99a1
  return color_to_index_slow(bgr);
Packit df99a1
}
Packit df99a1
Packit df99a1
inline int 
Packit df99a1
DjVuPalette::color_to_index(const GPixel &p)
Packit df99a1
{
Packit df99a1
  return color_to_index(&p.b);
Packit df99a1
}
Packit df99a1
Packit df99a1
inline void 
Packit df99a1
DjVuPalette::index_to_color(int index, unsigned char *bgr) const
Packit df99a1
{
Packit df99a1
  const PColor &color = palette[index];
Packit df99a1
  bgr[0] = color.p[0];
Packit df99a1
  bgr[1] = color.p[1];
Packit df99a1
  bgr[2] = color.p[2];
Packit df99a1
}
Packit df99a1
Packit df99a1
inline void 
Packit df99a1
DjVuPalette::index_to_color(int index, GPixel &p) const
Packit df99a1
{
Packit df99a1
  index_to_color(index, &p.b);
Packit df99a1
}
Packit df99a1
Packit df99a1
inline void
Packit df99a1
DjVuPalette::get_color(int nth, GPixel &p) const
Packit df99a1
{
Packit df99a1
  index_to_color(colordata[nth], p);
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
// ------------ THE END
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
#endif
Packit df99a1
      
Packit df99a1
      
Packit df99a1
             
Packit df99a1
Packit df99a1