dslinux/user/pixil/packages/dvdview/dvdview/oldlibgfx/libvideogfx/graphics/basic .cvsignore Makefile.am bitmap.cc bitmap.hh image.cc image.hh image_tmpl.cc

amadeus dslinux_amadeus at user.in-berlin.de
Tue Oct 3 13:25:49 CEST 2006


Update of /cvsroot/dslinux/dslinux/user/pixil/packages/dvdview/dvdview/oldlibgfx/libvideogfx/graphics/basic
In directory antilope:/tmp/cvs-serv11916/packages/dvdview/dvdview/oldlibgfx/libvideogfx/graphics/basic

Added Files:
	.cvsignore Makefile.am bitmap.cc bitmap.hh image.cc image.hh 
	image_tmpl.cc 
Log Message:
adding pristine copy of pixil to HEAD so I can branch from it

--- NEW FILE: image_tmpl.cc ---
/*
 *  image_tmpl.cc
 */

#include "image.hh"

template class Image<Pixel>;
template class Image_RGB<Pixel>;
template class Image_YUV<Pixel>;
template class Bitmap<Pixel>;

template class Bitmap<bool>;
template class Bitmap<double>;

#include "image.cc"
#include "bitmap.cc"

--- NEW FILE: .cvsignore ---
Makefile
Makefile.in
*.lo
_libs
.libs
.deps
libvideogfx-graphics-basic.la

--- NEW FILE: image.hh ---
/********************************************************************************
  libvideogfx/graphics/basic/image.hh

  purpose:
    Data types for RGB and YUV images.

  notes:
   - Be careful when accessing the image data using more than one
     pointer at the same time (see bitmap.hh)

   - When extracting a bitmap from the image be sure to save a reference or
     a pointer to the bitmap and not use a bitmap object of its own:
     USE THIS: Bitmap<Pixel>* bm = &img.AskBitmap(...);
     NOT THIS: Bitmap<Pixel>  bm =  img.AskBitmap(...);
     The second version means that you extracted bitmap is independent of the
     image you took it from. So writing into the Bitmap will not have any
     effect on the image.

  to do:
   - Add Chroma411 format.
   - Add Image_YCbCr<T>.

  author(s):
   - Dirk Farin, farin at ti.uni-mannheim.de
     University Mannheim, Dept. Circuitry and Simulation
     B 6,26 EG, room 0.10 / D-68131 Mannheim / Germany

  modifications:
    18/Jul/2000 - Dirk Farin - new convenient bitmap access methods
    05/Nov/1999 - Dirk Farin - adapted comments to DOC++
    24/Aug/1999 - Dirk Farin - moved template instantiation into
      separate file to solve multiple defined functions
    20/Jul/1999 - Dirk Farin - moved 'border'-entry from
      ImageInfo_Alignment to ImageInfo_Base
    15/Jul/1999 - Dirk Farin - GetChromaSizes()
    12/Jul/1999 - Dirk Farin - class Image is now a base class. The
      most common user interface routines did move into the derived
      classes Image_RGB and Image_YUV.
    02/Jun/1999 - Dirk Farin - first implementation
 ********************************************************************************
    Copyright (C) 1999  Dirk Farin

    This program is distributed under GNU Public License (GPL) as
    outlined in the COPYING file that comes with the source distribution.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
********************************************************************************/

#ifndef LIBVIDEOGFX_GRAPHICS_BASIC_IMAGE_HH
#define LIBVIDEOGFX_GRAPHICS_BASIC_IMAGE_HH

#include "libvideogfx/types.hh"

#include "bitmap.hh"


/// Chroma format of image.
enum ChromaFormat {
  /** Subsampling h:2 v:2 */ Chroma420,
  /** Subsampling h:2 v:1 */ Chroma422,
  /** No subsampling      */ Chroma444
};


/** Check if chroma is horizontally subsampled. Usage of the more general #ChromaSubH()# is recommended. */
inline bool IsSubH(ChromaFormat cf) { return cf != Chroma444; }
/** Check if chroma is vertically subsampled. Usage of the more general #ChromaSubV()# is recommended. */
inline bool IsSubV(ChromaFormat cf) { return cf == Chroma420; }
/** Get horizontal subsampling factor. */
inline int  ChromaSubH(ChromaFormat cf) { return (cf != Chroma444) ? 2 : 1; }
/** Get vertical subsampling factor. */
inline int  ChromaSubV(ChromaFormat cf) { return (cf == Chroma420) ? 2 : 1; }



// ------------------------ Image parameters -------------------------------

/** Base class for image parameters.
 */
class ImageInfo_Base
{
public:
  ImageInfo_Base()
    : width(0), height(0), border(0), has_alphamask(false) { }
  
  /// Image logical width.
  int  width;
  /// Image logical height.
  int  height;
  /** Add a border of width 'border' around the image that contains only unused data.
      This may be useful for some algorithms like filters that always consider a region
      around a pixel. */
  int  border;

  // --- Image structure information ---
  /// If image includes an alpha bitmap.
  bool has_alphamask;
};


/** Bitmap data alignment information. */
class ImageInfo_Alignment
{
public:
  /** Default aligmnent constructor. Default values are: not alignment, physical
      image size need not match logical image size. */
  ImageInfo_Alignment()
    : halign(1), valign(1),
      exact_size(false) { }

  /* See documentation "doc/bitmapdimensions.eps" for an explanation on
     what these values are defining, too. */

  /// Round width up to a multiple of this value.
  int  halign;
  /// Round height up to a multiple of this value.
  int  valign;

  /** If set to #true#: don't allow the alignment or the border to be greater than specified.
      {\bf Explanation}: As it is more efficient to keep and older bitmap if the new one
      is smaller than the old one, the old one is sometimes used instead of creating
      a new one. This does not work if you are depending on the exact memory layout of
      the image. So you can disable it by setting exact\_size to true. */
  bool exact_size;
};


/** Extra image parameters for YUV images. */
class ImageInfo_YUVExtraInfo
{
public:
  ImageInfo_YUVExtraInfo()
    : chroma(Chroma444), nocolor(false), reduced_chroma_size(false) { }

  /// Chroma format of the image.
  ChromaFormat chroma;
  /// Image is a greyscale image. Not bitmaps are allocated for the U- and V-channels.
  bool nocolor;
  /** Bitmap size of chroma planes will be reduced according to the
      value of 'chroma'. */
  bool reduced_chroma_size;
};


/* The ***Param*** structs are for asking image attributes;
   the ***Spec*** are for setting the image attributes. */

/// Parameters of existing RGB images (size, existence of alpha bitmap)
class ImageParam     : public ImageInfo_Base  { };
/// Parameters of existing YUV images
class ImageParam_YUV : public ImageParam,     public ImageInfo_YUVExtraInfo
{
public:
  int GetChromaWidth()  const { return (width +ChromaSubH(chroma)-1)/ChromaSubH(chroma); }
  int GetChromaHeight() const { return (height+ChromaSubV(chroma)-1)/ChromaSubV(chroma); }

  /// Get size of chroma bitmaps.
  void GetChromaSizes(int& w,int &h) const
    {
      h = GetChromaHeight();
      w = GetChromaWidth();
    }
};


/// Specification of image parameters for RGB image creation.
class ImageSpec      : public ImageParam,     public ImageInfo_Alignment { };
/// Specification of image parameters for YUV image creation.
class ImageSpec_YUV  : public ImageParam_YUV, public ImageInfo_Alignment { };



/**
   Easy handling of RGB and YUV images. Both types of images can
   additionally contain an alpha mask. YUV type images support
   4:4:4, 4:2:2 and 4:2:0 chroma formats and greyscale only images.
   You can decide if you want the chroma planes to be the same
   size even though you are not using 4:4:4. This can help
   in later chroma format conversion as it can be done in place.
*/
template <class Pel> class Image
{
  friend void EnhanceImageWithBorder(Image<Pixel>&, int, bool);  // GCC 2.96 bug ???

public:
  virtual ~Image() { }

  enum BitmapChannel { Bitmap_Red = 0, Bitmap_Green = 1, Bitmap_Blue = 2,
		       Bitmap_Y   = 0, Bitmap_Cr    = 1, Bitmap_Cb   = 2,
	                               Bitmap_U     = 1, Bitmap_V    = 2,
		       Bitmap_Hue = 0, Bitmap_Saturation = 1, Bitmap_Brightness = 2,
                       Bitmap_Alpha=3
  };

  /// Get colorspace independent image parameters.
  void GetParam(ImageParam& p) const { p=d_param; }

  /** Get write access to a bitmap in the image. Please use the read-only variant of this method if you do
      not need write access. */
  Bitmap<Pel>&       AskBitmap      (BitmapChannel bm_id)       { return d_bm[bm_id]; }
  /// Get read-only access to a bitmap in the image.
  const Bitmap<Pel>& AskBitmap_const(BitmapChannel bm_id) const { return d_bm[bm_id]; }


  /** Replace a complete bitmap. Note that the new bitmap either has to be empty or has to
      be exactly the same size as the old one.
      Furthermore you are responsible that all alignments and the border size is sufficient
      for your application. This is not checked!
      
      If you insert or remove (by replacing a bitmap by an empty one) an alpha bitmap,
      the alphamask-flag in ImageParam will be set accordingly.
  */
  void ReplaceBitmap(BitmapChannel id,Bitmap<Pel>&);
  /// Set new image parameters.
  void SetParam(const ImageParam& param) { d_param=param; }

  /// Get write access to alpha bitmap.
        Pel*const* AskFrameA()             { return d_bm[Bitmap_Alpha].AskFrame(); }
  /// Get read-only access to alpha bitmap.
  const Pel*const* AskFrameA_const() const { return d_bm[Bitmap_Alpha].AskFrame_const(); }

  Bitmap<Pel>& AskBitmapA() { return d_bm[Bitmap_Alpha]; }
  const Bitmap<Pel>& AskBitmapA_const() const { return d_bm[Bitmap_Alpha]; }

  // --- hints ---

  /** Give the hint that the contents of the image is not used any more. This does not effect
      the logical behaviour of the image but can improve performance. */
  void Hint_ContentsIsNotUsedAnymore() { for (int i=0;i<4;i++) d_bm[i].Hint_ContentsIsNotUsedAnymore(); }


  // DEBUG

  int AskRefCntr() const { d_bm[0].AskRefCntr(); }

private:

protected:
  Image() { }
  Image(const Image<Pel>&);
  const Image<Pel>& operator=(const Image<Pel>&);

  void _Create(const ImageSpec&,bool bitmaps12,bool subh,bool subv);
  void _Destroy();

  Bitmap<Pel> d_bm[4];
  ImageParam  d_param;
};


/** RGB image. */
template <class Pel> class Image_RGB : public Image<Pel>
{
public:
  Image_RGB() { }
  Image_RGB(const Image_RGB<Pel>& img) : Image<Pel>(img) { }
  ~Image_RGB() { }

  /// Create new RGB image according to the specifications.
  void Create(const ImageSpec&);
  /// Free the image.
  void Destroy() { _Destroy(); }

  // --- shortcuts ---

  /// Get write access to the red color channel bitmap.
  Pel*const* AskFrameR() { return d_bm[Bitmap_Red  ].AskFrame(); }
  /// Get write access to the green color channel bitmap.
  Pel*const* AskFrameG() { return d_bm[Bitmap_Green].AskFrame(); }
  /// Get write access to the blue color channel bitmap.
  Pel*const* AskFrameB() { return d_bm[Bitmap_Blue ].AskFrame(); }

  /// Get read-only access to the red color channel bitmap.
  const Pel*const* AskFrameR_const() const { return d_bm[Bitmap_Red  ].AskFrame_const(); }
  /// Get read-only access to the green color channel bitmap.
  const Pel*const* AskFrameG_const() const { return d_bm[Bitmap_Green].AskFrame_const(); }
  /// Get read-only access to the blue color channel bitmap.
  const Pel*const* AskFrameB_const() const { return d_bm[Bitmap_Blue ].AskFrame_const(); }

  Bitmap<Pel>& AskBitmapR() { return d_bm[Bitmap_Red  ]; }
  Bitmap<Pel>& AskBitmapG() { return d_bm[Bitmap_Green]; }
  Bitmap<Pel>& AskBitmapB() { return d_bm[Bitmap_Blue ]; }

  const Bitmap<Pel>& AskBitmapR_const() { return d_bm[Bitmap_Red  ]; }
  const Bitmap<Pel>& AskBitmapG_const() { return d_bm[Bitmap_Green]; }
  const Bitmap<Pel>& AskBitmapB_const() { return d_bm[Bitmap_Blue ]; }
};


/** YUV image. */
template <class Pel> class Image_YUV : public Image<Pel>
{
public:
  Image_YUV() { }
  Image_YUV(const Image_YUV<Pel>& img) : Image<Pel>(img) { d_info_yuvextra=img.d_info_yuvextra; }
  ~Image_YUV() { }

  /// Create new RGB image according to the specifications.
  void Create(const ImageSpec_YUV&);
  /// Free the image.
  void Destroy() { _Destroy(); }

  /// Get image parameters including the YUV specific image parameters.
  void GetParam(ImageParam_YUV& p) const { Image<Pel>::GetParam(p); ((ImageInfo_YUVExtraInfo&)p)=d_info_yuvextra; }

  /** This method not only alters the chroma format but also checks that all bitmaps
      are the right size. That means that if you change the size of bitmaps because
      of a chroma convertion, you have to call this functions {\em after} replacing the
      bitmaps. */
  void SetChromaFormat(ChromaFormat cf);
  /// Set image parameters.
  void SetParam(const ImageParam_YUV& param) { d_info_yuvextra=param; d_param=param; }

  // shortcuts

  /// Get write access to the luminance color channel bitmap.
  Pel*const* AskFrameY() { return d_bm[Bitmap_Y].AskFrame(); }
  /// Get write access to the U-chrominance color channel bitmap.
  Pel*const* AskFrameU() { return d_bm[Bitmap_U].AskFrame(); }
  /// Get write access to the V-chrominance color channel bitmap.
  Pel*const* AskFrameV() { return d_bm[Bitmap_V].AskFrame(); }

  /// Get read-only access to the luminance color channel bitmap.
  const Pel*const* AskFrameY_const() const { return d_bm[Bitmap_Y].AskFrame_const(); }
  /// Get read-only access to the U-chrominance color channel bitmap.
  const Pel*const* AskFrameU_const() const { return d_bm[Bitmap_U].AskFrame_const(); }
  /// Get read-only access to the V-chrominance color channel bitmap.
  const Pel*const* AskFrameV_const() const { return d_bm[Bitmap_V].AskFrame_const(); }

  Bitmap<Pel>& AskBitmapY() { return d_bm[Bitmap_Y]; }
  Bitmap<Pel>& AskBitmapU() { return d_bm[Bitmap_U]; }
  Bitmap<Pel>& AskBitmapV() { return d_bm[Bitmap_V]; }

  const Bitmap<Pel>& AskBitmapY_const() { return d_bm[Bitmap_Y]; }
  const Bitmap<Pel>& AskBitmapU_const() { return d_bm[Bitmap_U]; }
  const Bitmap<Pel>& AskBitmapV_const() { return d_bm[Bitmap_V]; }

private:
  ImageInfo_YUVExtraInfo d_info_yuvextra;
};

#endif

--- NEW FILE: Makefile.am ---
## Makefile.am for libvideogfx/libvideogfx/graphics/basic

noinst_LTLIBRARIES = libvideogfx-graphics-basic.la

libvideogfx_graphics_basic_includedir = \
	$(includedir)/libvideogfx/graphics/basic

libvideogfx_graphics_basic_la_SOURCES = \
	bitmap.cc	\
	bitmap.hh	\
	image.cc	\
	image.hh	\
	image_tmpl.cc

libvideogfx_graphics_basic_include_HEADERS = \
	bitmap.hh	\
	image.hh

INCLUDES = \
	-I$(top_srcdir)

.PHONY: files

files:
	@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
	  echo $$p; \
	done

--- NEW FILE: bitmap.hh ---
/********************************************************************************
  libvideogfx/graphics/basic/bitmap.hh

  purpose:
    Abstract data type 'bitmap'.

  notes:

  to do:

  author(s):
   - Dirk Farin, farin at ti.uni-mannheim.de
     University Mannheim, Dept. Circuitry and Simulation
     B 6,26 EG, room 0.10 / D-68131 Mannheim / Germany

  modifications:
    19/May/2000 - Dirk Farin - adapted comments to doxygen
    11/Jan/2000 - Dirk Farin - new method: SetSize()
    05/Nov/1999 - Dirk Farin - adapted comments to DOC++
    08/Jul/1999 - Dirk Farin - introduced ContentsNotImportant-hint
    23/Jun/1999 - Dirk Farin - bitmap border
    22/Jun/1999 - Dirk Farin - bitmap data is now shared
    02/Jun/1999 - Dirk Farin - first implementation based on DVDview code
 ********************************************************************************
    Copyright (C) 1999  Dirk Farin

    This program is distributed under GNU Public License (GPL) as
    outlined in the COPYING file that comes with the source distribution.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/

#ifndef LIBVIDEOGFX_GRAPHICS_BASIC_BITMAP_HH
#define LIBVIDEOGFX_GRAPHICS_BASIC_BITMAP_HH

#include "libvideogfx/types.hh"


/**
   A two dimensional bitmap template class for arbitrary types.
   Bitmap can easily be created given its size, optional alignment and surrounding border.
   Access to the data is the same whether you want frame or field access.
   This data type is implemented as a shared data object. That means
   that assignment of bitmaps is very efficient.

   You get access to the actual bitmap data by using a variant of the AskFrame() / AskField()
   methods. These return a pointer array with pointers to the beginning of the lines of data.
   The border area can be accessed with values that are below 0 or greater/equal bitmap width.
   Use the *\_const version whenever possible as this improves performance when using bitmap sharing.

   \image latex bitmapdimensions.eps width=7cm

   Notes:
   <UL>
   <LI> Whenever you call the non-const versions of AskFrame() or AskField(),
      all pointers you got back from preceding calls to these methods may
      become illegal!
      So if it is possible that you access const-pointers and non-const-pointers
      to the same image at the same time (like in a color conversion routine)
      always get the non-const-pointers first!

   <LI> Resize(int width,int height,int halign=1,int valign=1,int border=0,bool exactalign=false)
      is not really needed. It is better to create a new one and copy the envelope object.
   <LI> Hint-methods do not affect the logical behavior of the object but can be
     used to increase performance.
   </UL>
*/
template <class Pel> class Bitmap
{
public:
  Bitmap();   /// Create Bitmap object with no bitmap data attached.
  Bitmap(const Bitmap&);
  ~Bitmap();

  void Create(int width,int height,int halign=1,int valign=1,int border=0,bool exactsize=false);
  void CreateFromExistingMemory(Pel* data,int width,int height,int border=0,
				int internalw=0,int internalh=0);

  /** Change the alignment of the bitmap. If possible the old internal bitmap sizes are not modified
      to be more time efficient. For example removing a border does nothing if \c exactsize is false. */
  void SetAlignment(int halign,int valign,int border,bool exactsize=false);

  /** Free bitmap. */
  void Destroy();

  /// Get write access to full bitmap data.
  Pel*const* AskFrame();
  /// Get read-only access to full bitmap data.
  const Pel*const* AskFrame_const() const;

  /** Get write access to a field of the bitmap. This means that consecutive elements of the pointer array
      point to lines with a distance of 2. */
  Pel*const* AskField(bool top);
  /// Get read-only access to a field of the bitmap.
  const Pel*const* AskField_const(bool top) const;

  const Pel* operator[](int y) const { return AskFrame_const()[y]; }

  /** Ask logical bitmap width.
      Logical sizes do not include aligment and border sizes. */
  int AskWidth()  const { assert(indirect); return indirect->d_width;  }
  /** Ask logical bitmap height.
      Logical sizes do not include aligment and border sizes. */
  int AskHeight() const { assert(indirect); return indirect->d_height; }

  /** Ask internal bitmap width.
      Internal sizes include alignment and borders.
      Internal sizes can be different from (be greater than) the values you expect them to be,
      except you have created the bitmap without setting 'exactsize' to true. */
  int AskInternalWidth()  const { assert(indirect); return indirect->d_internal_width;  }
  /// Ask internal bitmap height. See AskInternalWidth() for more information.
  int AskInternalHeight() const { assert(indirect); return indirect->d_internal_height; }
  /// Ask border size.
  int AskBorderWidth()    const { assert(indirect); return indirect->d_border; }

  /** Resizes bitmap. Contents will not be destroyed. You cannot resize the bitmap to any size larger
      than the current internal size excluding the borders. The new bitmap has the same alignment
      as the old one. */
  void SetSize(int w,int h);

  /** Check if bitmap contains data. This can be useful when defining images that consist of a not fixed
      set of bitmaps. You could test for example if the alpha-channel bitmap exists. */
  bool IsEmpty() const { return indirect==NULL; }

  /// Assignment operator. Not only the bitmap contents but also the alignment information will be copied.
  const Bitmap<Pel>& operator=(const Bitmap<Pel>&);

  /** Call this hint if you know that you do not need the image contents any more.
      This could be the case when:
      <UL>
      <LI> You are about to destroy it soon (but give it as parameter to another function before).
      <LI> The next time you write to the image, the contents will be completely overwritten.
      </UL>
  */
  void Hint_ContentsIsNotUsedAnymore() { d_hint_contents_not_important=true; }

  // DEBUG. Very ugly method only intended for debugging purpose.
  int AskRefCntr() const { if (!indirect) return 0;
  else return (d_hint_contents_not_important ? 100 : 0) + indirect->d_ref_cntr; }
  void ShowParam() const;


private:
  /* IMPLEMENTATION:
     Bitmap really is only an envelope class for BitmapData objects. As much as possible bitmap sharing
     is used.
  */

  /* Make a private copy of the bitmap if it is shared with other Bitmap envelope objects.
   */
  void Decouple();
  
  struct BitmapData
  {
    int   d_ref_cntr;  // envelope->letter access counter
	 
    int   d_width,d_height;
    int   d_internal_width, d_internal_height;
    int   d_halign,d_valign;
    int   d_border;

    bool  d_directmemory; ///< Bitmap class is a wrapper for a fixed memory area (behave like a singleton).

    Pel*  d_bitmapptr; // pointer to linear bitmap data.
    
    /* These pointers point to arrays of pointers that point to the beginnings of bitmap lines
       (behind the border). d_*[0] points to the topmost line including the border.
       So the top left pixel of the bitmap is accessed as d_frameptr[d_border][0] */
    Pel** d_frameptr;
    Pel** d_top_field;
    Pel** d_bottom_field;

    /* Create new bitmap. You will get exactly the size you specified. */
    void Create(int width,int height,int halign,int valign,int border);

    /* Create a wrapper for a fixed memory area. */
    void CreateDirectBitmap(Pel* start,int width,int height,
			    int internal_width,int internal_height,int border);

  private:
    friend class Bitmap<Pel>;

    static int AlignUp(int val,int alignment);
  }* indirect;

  bool  d_hint_contents_not_important; // TRUE if contents is not relevant using this Bitmap interface
};

/*! \fn void Bitmap<Pel>::Create(int width,int height,int halign=1,int valign=1,int border=0,bool exactsize=false)
  \brief Create new bitmap.
  \param width bitmap width
  \param height bitmap height
  \param halign horizontal alignment. \c width will be extended to be a multiple of this value
   (\f$width\ \textrm{mod}\ halign\f$ will be 0).
  \param valign vertical alignment. \c height will be extended to be a multiple of this value.
   (\f$height\ \textrm{mod}\ valign\f$ will be 0).
  \param border additional space that is added to all four sides after alignment has occurred.
  \param exactsize force the bitmap to have the minimum size that fulfills all given parameters

  Notes:
  <UL>
  <LI> Position [0][0] is the top left of the bitmap, left and top border pixels are
       addressed using negative indices.
  <LI> \c border should be an even number if you intend to use field access.
  <LI> Set \c exactsize to \c false if you do not depend on the actual memory layout
       as this allows for better memory reuseage.
  <LI> You may call Create() without destroying the old contents with Destroy().
  </UL>
*/

#endif

--- NEW FILE: image.cc ---
/********************************************************************************
    Copyright (C) 1999  Dirk Farin

    This program is distributed under GNU Public License (GPL) as
    outlined in the COPYING file that comes with the source distribution.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
********************************************************************************/

#include "image.hh"


template <class Pel> void Image<Pel>::_Create(const ImageSpec& spec,bool bitmaps12,bool subh,bool subv)
{
  // Create first bitmap (red channel or Y-channel)

  d_bm[0].Create(spec.width,spec.height,spec.halign,spec.valign,spec.border,spec.exact_size);


  // Create second and third bitmap (green, blue or U,V-channel)
  
  if (bitmaps12)
    {
      ImageSpec chrspec = spec;

      if (subh)
	{
	  chrspec.width =(chrspec.width +1)/2;
	  //chrspec.halign/=2;
	}
      if (subv)
	{
	  chrspec.height=(chrspec.height+1)/2;
	  //chrspec.valign/=2;
	}

      d_bm[1].Create(chrspec.width,chrspec.height,chrspec.halign,chrspec.valign,
		     chrspec.border,chrspec.exact_size);
      d_bm[2].Create(chrspec.width,chrspec.height,chrspec.halign,chrspec.valign,
		     chrspec.border,chrspec.exact_size);
    }


  // Create fourth bitmap (alpha mask)

  if (spec.has_alphamask) 
    d_bm[Bitmap_Alpha].Create(spec.width,spec.height,spec.halign,spec.valign,spec.border,spec.exact_size);

  d_param = spec;
}


template <class Pel> void Image<Pel>::_Destroy()
{
  for (int i=0;i<4;i++)
    d_bm[i].Destroy();
}


template <class Pel> void Image<Pel>::ReplaceBitmap(BitmapChannel id,Bitmap<Pel>& bm)
{
  d_bm[id] = bm;

  if (id==Bitmap_Alpha)
    {
      if (bm.IsEmpty())
	d_param.has_alphamask = false;
      else
	d_param.has_alphamask = true;
    }
}


template <class Pel> Image<Pel>::Image(const Image<Pel>& img)
{
  for (int i=0;i<4;i++)
    d_bm[i] = img.d_bm[i];
  d_param = img.d_param;
}


template <class Pel> const Image<Pel>& Image<Pel>::operator=(const Image<Pel>& img)
{
  for (int i=0;i<4;i++)
    d_bm[i] = img.d_bm[i];
  d_param = img.d_param;

  return *this;
}



// ----------------------- RGB images -----------------------------------



template <class Pel> void Image_RGB<Pel>::Create(const ImageSpec& spec)
{
  _Create(spec,
	  true,       /* 3 bitmaps */
	  false,false /* no subsampling */);
}


// ------------------------ YUV images ---------------------------------

template <class Pel> void Image_YUV<Pel>::Create(const ImageSpec_YUV& spec)
{
  ImageSpec s;
  ((ImageParam&)s)=spec;
  ((ImageInfo_Alignment&)s)=spec;

  _Create(s,!spec.nocolor,
	  spec.reduced_chroma_size && IsSubH(spec.chroma),
	  spec.reduced_chroma_size && IsSubV(spec.chroma));

  d_info_yuvextra = spec;
}


template <class Pel> void Image_YUV<Pel>::SetChromaFormat(ChromaFormat cf)
{
#ifndef NDEBUG
  assert(!d_bm[Bitmap_Y].IsEmpty());
  assert(d_bm[Bitmap_Y].AskWidth()  == d_param.width);
  assert(d_bm[Bitmap_Y].AskHeight() == d_param.height);

  if (d_info_yuvextra.nocolor)
    {
      assert(d_bm[Bitmap_U].IsEmpty());
      assert(d_bm[Bitmap_V].IsEmpty());
    }
  else
    {
      assert(!d_bm[Bitmap_U].IsEmpty());
      assert(!d_bm[Bitmap_V].IsEmpty());

      int w = d_param.width;
      int h = d_param.height;

      if (IsSubH(cf)) w=(w+1)/2;
      if (IsSubV(cf)) h=(h+1)/2;

      assert(d_bm[Bitmap_U].AskWidth()  == w);
      assert(d_bm[Bitmap_U].AskHeight() == h);
      assert(d_bm[Bitmap_V].AskWidth()  == w);
      assert(d_bm[Bitmap_V].AskHeight() == h);
    }
#endif

  d_info_yuvextra.chroma=cf;
}

--- NEW FILE: bitmap.cc ---
/********************************************************************************
    Copyright (C) 1999  Dirk Farin

    This program is distributed under GNU Public License (GPL) as
    outlined in the COPYING file that comes with the source distribution.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/

#include <iostream.h>
#include <string.h>

#include "bitmap.hh"


/* Return 'val', rounded upward to the next multiple of 'alignment'.
 */
template <class Pel> inline int Bitmap<Pel>::BitmapData::AlignUp(int val,int alignment)
{
  assert(alignment>0);

  int alignedval = val;
  if ((alignedval%alignment)!=0) alignedval += alignment-(val%alignment);

  assert((alignedval%alignment)==0);  // alignment is correct
  assert(alignedval < val+alignment); // aligned value is only as large as needed
  assert(alignedval >= alignment);    // aligned value is not smaller than before

  return alignedval;
}


static bool AlignmentMatches(int align,int val)
{
  return (val%align)==0;
}


template <class Pel> Bitmap<Pel>::Bitmap()
  : indirect(NULL),
    d_hint_contents_not_important(true) // contents cannot be important as it is empty/undefined
{
}


template <class Pel> Bitmap<Pel>::Bitmap(const Bitmap& bm)
  : indirect(bm.indirect),
    d_hint_contents_not_important(bm.d_hint_contents_not_important)
{
  if (indirect)
    indirect->d_ref_cntr++;

  if (!indirect)
    {
      assert(d_hint_contents_not_important);
    }
}


template <class Pel> Bitmap<Pel>::~Bitmap()
{
  Destroy();

  assert(indirect==NULL);
}


/* From the Bitmap class point of view, the bitmap is destroyed. From a global point of view
   this is only strictly correct of it was the last reference to this bitmap.
*/
template <class Pel> void Bitmap<Pel>::Destroy()
{
  if (indirect)
    {
      indirect->d_ref_cntr--;
      if (indirect->d_ref_cntr==0)
	{
	  if (!indirect->d_directmemory) delete[] indirect->d_bitmapptr;
	  delete[] indirect->d_frameptr;
	  delete[] indirect->d_top_field;
	  delete[] indirect->d_bottom_field;
	  delete indirect;
	}

      indirect=NULL;
    }
}


template <class Pel> void Bitmap<Pel>::Decouple()
{
  if (indirect==NULL)
    return;

  if (indirect->d_ref_cntr>1)
    {
      // Cannot decouple direct memory bitmaps.
      assert(!indirect->d_directmemory);

      // create new exclusive BitmapData with the same contents
      BitmapData* bmdata = new BitmapData;
      bmdata->Create(indirect->d_width,indirect->d_height,
		     indirect->d_halign,indirect->d_valign,
		     indirect->d_border);
	  
      if (!d_hint_contents_not_important)
	{
	  cout << "MEMCPY 1 --------------\n";
	  memcpy(bmdata->d_bitmapptr,
		 indirect->d_bitmapptr,
		 indirect->d_internal_width*indirect->d_internal_height*sizeof(Pel));
	}
	  
      bmdata->d_ref_cntr=1;
      indirect->d_ref_cntr--;
      indirect=bmdata;
    }
  else
    {
      // We are the only user of the data.
    }
}


template <class Pel> void Bitmap<Pel>::Create(int width,int height,int halign,int valign,int border,bool exactsize)
{
  /* If this bitmap contains already a bitmap and the sizes are
     the same as those requested. Don't create a new one but reuse the old one instead. */
  if (indirect && // has access to a bitmap
      indirect->d_ref_cntr==1 && /* We are the single user of the old bitmap.
				    This is not really necessary as the bitmap could be shared until
				    we need write-access. But then in Decouple() the bitmap (with random
				    contents) would be copied. To prevent this, we would have to keep track
				    if the contents is random. As most of the time a bitmap is created it
				    will also be written to, we allocate a new one here already.

				    NOTE: Deferred creation could be useful in this case:
				    Bitmap a;
				    [do magic things to 'a']
				    {
				    Bitmap b;
				    b=a;
				    a.Create(...);
				    }
				    [do magic things to 'a']
				 */
      indirect->d_width  ==  width &&    // same width
      indirect->d_height == height &&    // same height
      (( exactsize &&                    // exactly the same alignment of exactsize is wanted
	 indirect->d_halign == halign &&
	 indirect->d_valign == valign &&
	 indirect->d_border == border) ||
       (!exactsize &&
  	 AlignmentMatches(halign,indirect->d_halign) && // old alignment is stronger than new one
	 AlignmentMatches(valign,indirect->d_valign) &&
	 indirect->d_border >= border)))
    {
      // Can reuse old bitmap.

      return;
    }

  // Destroy old bitmap (or at least the reference to the letter-object).
  Destroy();

  // Create new bitmap of correct size.
  indirect = new Bitmap<Pel>::BitmapData;
  indirect->Create(width,height,halign,valign,border);
  indirect->d_ref_cntr=1;
  d_hint_contents_not_important=true;
}


template <class Pel> void Bitmap<Pel>::CreateFromExistingMemory(Pel* data,int width,int height,int border,
								int internalw,int internalh)
{
  Destroy();

  indirect = new Bitmap<Pel>::BitmapData;
  indirect->CreateDirectBitmap(data,width,height,internalw,internalh,border);
  indirect->d_ref_cntr=1;
  d_hint_contents_not_important=true;
}


template <class Pel> void Bitmap<Pel>::ShowParam() const
{
  if (!indirect)
    {
      cout << "No actual data in bitmap.\n";
    }
  else
    {
      cout << " w, h: " << indirect->d_width << " x " << indirect->d_height << endl;
      cout << "iw,ih: " << indirect->d_internal_width << " x " << indirect->d_internal_height << endl;
      cout << "ha,va: " << indirect->d_halign << " x " << indirect->d_valign << endl;
      cout << "border:" << indirect->d_border << endl;
      cout << "direct memory: " << (indirect->d_directmemory ? "yes" : "no") << endl;
    }
}


template <class Pel> void Bitmap<Pel>::SetAlignment(int halign,int valign,int border,bool exactsize)
{
  assert(indirect);

  int newibmw = BitmapData::AlignUp(indirect->d_width ,halign);
  int newibmh = BitmapData::AlignUp(indirect->d_height,valign);
  int newinternw = newibmw + 2*border;
  int newinternh = newibmh + 2*border;

  bool modify=false;
  if (!exactsize)
    {
      // Passt das Alignment nicht mehr oder wird der Border groesser, muss neue BM erstellt werden.

      if (newibmw > indirect->d_internal_width -2*indirect->d_border ||
	  newibmh > indirect->d_internal_height-2*indirect->d_border ||
	  border > indirect->d_border)
	modify = true;
    }
  else
    {
      if (newinternw != indirect->d_internal_width ||
	  newinternh != indirect->d_internal_height ||
	  border != indirect->d_border)
	modify = true;
    }

  if (modify)
    {
      assert(!indirect->d_directmemory);

      Bitmap<Pel> newbm;
      newbm.Create(indirect->d_width,indirect->d_height,halign,valign,border,exactsize);
      const Pel*const* sp = AskFrame_const();
            Pel*const* dp = newbm.AskFrame();

      int b = AskBorderWidth();
      if (border<b) b=border;

      cout << "MEMCPY 2 -------\n";

      for (int y=-b;y<indirect->d_height+b;y++)
	memcpy(&dp[y][-b],&sp[y][-b],(indirect->d_width+2*b)*sizeof(Pel));

      *this = newbm;
    }
}


template <class Pel> void Bitmap<Pel>::BitmapData::Create(int width,int height,
							  int halign,int valign,int border)
{
  assert(halign>0);
  assert(valign>0);
  assert(border>=0);
  assert(width >0);
  assert(height>0);

  d_width  = width;
  d_height = height; 
  d_halign = halign;
  d_valign = valign; 
  d_border = border;

  d_internal_width  = AlignUp(width ,halign) +2*border;
  d_internal_height = AlignUp(height,valign) +2*border;

  d_bitmapptr    = new Pel[d_internal_width * d_internal_height];
  d_frameptr     = new Pel* [d_internal_height];
  d_top_field    = new Pel* [(d_internal_height+1)/2];
  d_bottom_field = new Pel* [(d_internal_height+1)/2];

  d_directmemory = false;

  // Frame-Pointer ausfuellen
  {for (int y=0;y<d_internal_height;y++)
    d_frameptr[y]= &d_bitmapptr[y*d_internal_width+border];}

  // Field-Pointer ausfuellen
  {for (int y=0,y2=0;y2<d_internal_height;y++)
    {
      d_top_field   [y]= &d_bitmapptr[y2*d_internal_width+border]; y2++;
      d_bottom_field[y]= &d_bitmapptr[y2*d_internal_width+border]; y2++;
    }}
}


template <class Pel> void Bitmap<Pel>::BitmapData::CreateDirectBitmap(Pel* mem,int width,int height,
								      int internal_w,int internal_h,
								      int border)
{
  if (internal_w==0) internal_w=width;
  if (internal_h==0) internal_h=height;

  assert(internal_w>=width);
  assert(internal_h>=height);
  assert(width >0);
  assert(height>0);
  assert(border>=0);

  d_width  = width;
  d_height = height; 
  d_halign = 1;
  d_valign = 1; 
  d_border = border;

  d_internal_width  = internal_w;
  d_internal_height = internal_h;

  d_bitmapptr    = mem;
  d_frameptr     = new Pel* [d_internal_height];
  d_top_field    = new Pel* [(d_internal_height+1)/2];
  d_bottom_field = new Pel* [ d_internal_height   /2];

  d_directmemory = true;

  // Frame-Pointer ausfuellen
  {for (int y=0;y<d_internal_height;y++)
    d_frameptr[y]= &d_bitmapptr[y*d_internal_width+border];}

  // Field-Pointer ausfuellen
  {for (int y=0,y2=0;y2<d_internal_height;y++)
    {
      d_top_field   [y]= &d_bitmapptr[y2*d_internal_width+border]; y2++;
      d_bottom_field[y]= &d_bitmapptr[y2*d_internal_width+border]; y2++;
    }}
}


template <class Pel> Pel*const* Bitmap<Pel>::AskFrame()
{
  assert(indirect);
  Decouple();

  d_hint_contents_not_important=false;
  return &indirect->d_frameptr[indirect->d_border];
}


template <class Pel> const Pel*const * Bitmap<Pel>::AskFrame_const() const
{
  assert(indirect);
  return &indirect->d_frameptr[indirect->d_border];
}


template <class Pel> Pel*const* Bitmap<Pel>::AskField(bool top)
{
  assert(indirect);
  Decouple();

  d_hint_contents_not_important=false;
  return top ? &indirect->d_top_field   [indirect->d_border/2]   :
               &indirect->d_bottom_field[indirect->d_border/2];
}

template <class Pel> const Pel*const* Bitmap<Pel>::AskField_const(bool top) const
{
  assert(indirect);
  return top ? &indirect->d_top_field   [indirect->d_border/2] :
               &indirect->d_bottom_field[indirect->d_border/2];
}


template <class Pel> void Bitmap<Pel>::SetSize(int w,int h)
{
  assert(indirect);

  assert(w<=indirect->d_internal_width  -2*indirect->d_border &&
	 h<=indirect->d_internal_height -2*indirect->d_border);

  indirect->d_width  = w;
  indirect->d_height = h;
}


template <class Pel> const Bitmap<Pel>& Bitmap<Pel>::operator=(const Bitmap<Pel>& bm)
{
  if (bm.indirect==NULL)
    {
      // Copying an empty bitmap destroys the current bitmap.

      Destroy();
    }
  else
    {
      bm.indirect->d_ref_cntr++;
      Destroy();
      indirect=bm.indirect;
      d_hint_contents_not_important = bm.d_hint_contents_not_important;
    }

  return *this;
}






More information about the dslinux-commit mailing list