#pragma once #ifndef T_RASTER_INCLUDED #define T_RASTER_INCLUDED #include "tutil.h" #include "tgeometry.h" #include "tpixel.h" #include "tpixelgr.h" #include "tsmartpointer.h" #include "tbigmemorymanager.h" #undef DVAPI #undef DVVAR #ifdef TRASTER_EXPORTS #define DVAPI DV_EXPORT_API #define DVVAR DV_EXPORT_VAR #else #define DVAPI DV_IMPORT_API #define DVVAR DV_IMPORT_VAR #endif //========================================================= class DVAPI TRasterType { int m_id; /* public: enum Type { None, BW, WB, RGBM32, // LPIXEL, matte channel considered RGBM64, // SPIXEL, matte channel considered CM8, // color-mapped, 8 bits GR8, // grey tones, 8 bits CM16, // color-mapped, 16 bits GR16, // grey tones, 16 bits RGB555, RGB565, CM24, // cmapped, 8+8+8 bits (ink, paint, ramp), +8 bits spare (MSB) CM16S12, CM16S8 // cmapped, 16 bits, standard SGI 256-color colormap // .... }; */ public: TRasterType(int id) : m_id(id){}; int getId() const { return m_id; }; bool operator==(TRasterType a) { return m_id == a.m_id; }; bool operator!=(TRasterType a) { return m_id != a.m_id; }; }; //========================================================= // forward declaration template class TRasterPT; class TRaster; typedef TSmartPointerT TRasterP; //------------------------------------------------------------ // // Smart Pointer a TRaster // #ifdef _WIN32 template class DVAPI TSmartPointerT; #endif //========================================================= /*!This class stores bitmap images. */ class DVAPI TRaster : public TSmartObject { DECLARE_CLASS_CODE protected: int m_pixelSize; int m_lx, m_ly; int m_wrap; int m_lockCount; TRaster *m_parent; // nel caso di sotto-raster UCHAR *m_buffer; bool m_bufferOwner; // i costruttori sono qui per centralizzare la gestione della memoria // e' comunque impossibile fare new TRaster perche' e' una classe astratta // (clone, extract) // crea il buffer associato (NON fa addRef()) TRaster(int lx, int ly, int pixelSize); // si attacca ad un buffer pre-esistente (NON fa addRef() - neanche a parent) TRaster(int lx, int ly, int pixelSize, int wrap, UCHAR *buffer, TRaster *parent, bool bufferOwner = false); private: static TAtomicVar m_totalMemory; TThread::Mutex m_mutex; // not implemented TRaster(const TRaster &); TRaster &operator=(const TRaster &); public: #ifdef _DEBUG bool m_cashed; static unsigned long getTotalMemoryInKB(); #endif virtual ~TRaster(); // accessors // TRasterType getType() const {return m_type;}; int getLx() const { return m_lx; }; int getLy() const { return m_ly; }; TDimension getSize() const { return TDimension(m_lx, m_ly); }; //! Returns the length of a row in pixel. int getWrap() const { return m_wrap; }; TPointD getCenterD() const { return TPointD(0.5 * m_lx, 0.5 * m_ly); }; TPoint getCenter() const { return TPoint(m_lx / 2, m_ly / 2); }; TRect getBounds() const { return TRect(0, 0, m_lx - 1, m_ly - 1); }; int getPixelSize() const { return m_pixelSize; }; int getRowSize() const { return m_pixelSize * m_lx; }; // in bytes // when the bigMemoryManager is active, remapping can change buffers...need to // to lock/unlock them o use them. void lock() { if (!TBigMemoryManager::instance()->isActive()) return; TThread::MutexLocker sl(&m_mutex); if (m_parent) m_parent->lock(); else ++m_lockCount; } void unlock() { if (!TBigMemoryManager::instance()->isActive()) return; TThread::MutexLocker sl(&m_mutex); if (m_parent) m_parent->unlock(); else { assert(m_lockCount > 0); --m_lockCount; } } void beginRemapping(); void endRemapping(); //! Returns a pointer to the image buffer. // WARNING!!!!! before getting the buffer with getRawData(), // you have to lock the raster with'lock method, and unlock // it when you've done with the buffer const UCHAR *getRawData() const { return m_buffer; }; UCHAR *getRawData() { return m_buffer; }; //! Returns a pointer to the image buffer positioned in the (x,y) coords. const UCHAR *getRawData(int x, int y) const { assert(0 <= x && x < m_lx && 0 <= y && y < m_ly); return m_buffer + (y * m_wrap + x) * m_pixelSize; }; UCHAR *getRawData(int x, int y) { assert(0 <= x && x < m_lx && 0 <= y && y < m_ly); return m_buffer + (y * m_wrap + x) * m_pixelSize; }; bool isEmpty() const { return getSize() == TDimension(); }; TRasterP getParent() { return m_parent; } // creazione di TRaster derivati // devono essere virtuali puri perche' il nuovo raster creato deve essere del // tipo giusto virtual TRasterP clone() const = 0; virtual TRasterP extract(TRect &rect) = 0; virtual TRasterP create() const = 0; virtual TRasterP create(int lx, int ly) const = 0; // definita in termini di extract(rect); non lo posso fare subito perche' // manca il // costruttore di copia di TRasterP inline virtual TRasterP extract(int x0, int y0, int x1, int y1); // operazioni sui pixel // Copia il contenuto di src (spostato di offset) nel raster corrente. // Il tipo deve essere lo stesso // In caso di dimensione diversa l'area copiata e' l'intersezione dei due // getBounds() // e i due raster sono allineati in basso a sinistra (src[0,0] -> dst[offset]) /*!Copies the content of the source raster in the current raster. */ void copy(const TRasterP &src, const TPoint &offset = TPoint()); void xMirror(); void yMirror(); void rotate180(); void rotate90(); void clear(); void clearOutside(const TRect &rect); friend class TBigMemoryManager; protected: void fillRawData(const UCHAR *pixel); void fillRawDataOutside(const TRect &rect, const UCHAR *pixel); private: void remap(UCHAR *newLocation); }; //------------------------------------------------------------ inline void detach(TRasterP &r) { if (!r || r->getRefCount() == 1) return; TRasterP tmp(r->clone()); r = tmp; } //========================================================= // forward declaration template class TRasterT; // // TRasterPT: // // Smart Pointer to TRasterT // //!\include raster_ex1.cpp //! \include rasterpt_ex1.cpp // class TRasterPT template class TRasterPT final : public TSmartPointerT> { public: typedef T Pixel; typedef TRasterT Raster; TRasterPT(){}; TRasterPT(int lx, int ly) { create(lx, ly); }; TRasterPT(const TDimension &d) { create(d.lx, d.ly); }; inline TRasterPT(const TRasterP &src); inline TRasterPT(int lx, int ly, int wrap, T *buffer, bool bufferOwner = false); ~TRasterPT(){}; void create(int lx, int ly); void create(const TDimension &d) { create(d.lx, d.ly); }; inline void detach(); operator TRasterP() const; }; //========================================================= // // TRasterT // // e' la classe concreta che discende da TRaster template class TRasterT : public TRaster { protected: // Constructors are protected to prevent direct allocation of TRasterT // instances. // Users must adopt the TRasterPT smart pointer syntax instead. // Buffer Allocation TRasterT(int lx, int ly) : TRaster(lx, ly, sizeof(T)) {} // Buffer Attachment TRasterT(int lx, int ly, int wrap, T *buffer, TRasterT *parent, bool bufferOwner = false) : TRaster(lx, ly, sizeof(T), wrap, reinterpret_cast(buffer), parent, bufferOwner) {} public: typedef T Pixel; ~TRasterT(){}; // accessors // WARNING!!!!! before getting the buffer with pixels(int y), // you have to lock the raster with'lock method, and unlock // it when you've done with the buffer const T *pixels(int y = 0) const { assert(0 <= y && y < getLy()); return reinterpret_cast(m_buffer) + getWrap() * y; }; T *pixels(int y = 0) { assert(0 <= y && y < getLy()); return reinterpret_cast(m_buffer) + getWrap() * y; }; // Derived rasters creation TRasterP clone() const override { TRasterP dst = TRasterPT(m_lx, m_ly); TRasterP src(const_cast((const TRaster *)this)); dst->copy(src); return dst; } TRasterP create() const override { return TRasterPT(m_lx, m_ly); } TRasterP create(int lx, int ly) const override { return TRasterPT(lx, ly); } //!\include raster_ex2.cpp TRasterP extract(int x0, int y0, int x1, int y1) override { TRect rect(x0, y0, x1, y1); return extract(rect); }; TRasterP extract(TRect &rect) override { if (isEmpty() || getBounds().overlaps(rect) == false) return TRasterP(); rect = getBounds() * rect; // addRef(); return TRasterP(new TRasterT(rect.getLx(), rect.getLy(), m_wrap, pixels(rect.y0) + rect.x0, this)); }; TRasterPT extractT(TRect &rect); TRasterPT extractT(int x0, int y0, int x1, int y1) { TRect rect(x0, y0, x1, y1); return extractT(rect); }; friend class TRasterPT; // Pixel Operations void fill(const T &a) { fillRawData(reinterpret_cast(&a)); } void fillOutside(const TRect &rect, const T &a) { fillRawDataOutside(rect, reinterpret_cast(&a)); } }; //--------------------------------------------------------- inline TRasterP TRaster::extract(int x0, int y0, int x1, int y1) { TRect rect(x0, y0, x1, y1); return extract(rect); } //--------------------------------------------------------- template TRasterPT TRasterT::extractT(TRect &rect) { if (isEmpty() || getBounds().overlaps(rect) == false) { return TRasterPT(); } rect = getBounds() * rect; // addRef(); return TRasterPT(new TRasterT(rect.getLx(), rect.getLy(), m_wrap, pixels(rect.y0) + rect.x0, this)); } //========================================================= // // metodi inline di TRasterPT // (n.b. se non si fanno esplicitament "inline" NT si confonde con dll // exort/import) // template inline TRasterPT::TRasterPT(const TRasterP &src) { TSmartPointerT>::m_pointer = dynamic_cast *>(src.getPointer()); if (TSmartPointerT>::m_pointer) TSmartPointerT>::m_pointer->addRef(); } template inline void TRasterPT::create(int lx, int ly) { TRasterT *raster = new TRasterT(lx, ly); *this = TRasterPT(raster); } template inline void TRasterPT::detach() { if (!TSmartPointerT>::m_pointer || TSmartPointerT>::m_pointer->getRefCount() == 1) return; *this = TRasterPT(TSmartPointerT>::m_pointer->clone()); // uso l'operator di assign per aggiornare correttamente // i reference counts del vecchio e del nuovo raster } template inline TRasterPT::operator TRasterP() const { return TRasterP(TSmartPointerT>::m_pointer); } //--------------------------------------------------------- template inline TRasterPT::TRasterPT(int lx, int ly, int wrap, T *buffer, bool bufferOwner) { TSmartPointerT>::m_pointer = new TRasterT(lx, ly, wrap, buffer, 0, bufferOwner); TSmartPointerT>::m_pointer->addRef(); } //--------------------------------------------------------- #ifdef _WIN32 // su NT e' necessario per evitare un warning nelle classi // esportate che si riferiscono a TRaster32P/TRaster64P // su IRIX non compila perche' non riesce ad instanziare le // funzioni online (!!!) template class DVAPI TSmartPointerT>; template class DVAPI TRasterPT; template class DVAPI TSmartPointerT>; template class DVAPI TRasterPT; template class DVAPI TSmartPointerT>; template class DVAPI TRasterPT; template class DVAPI TSmartPointerT>; template class DVAPI TRasterPT; template class DVAPI TSmartPointerT>; template class DVAPI TRasterPT; template class DVAPI TSmartPointerT>; template class DVAPI TRasterPT; #endif typedef TRasterPT TRaster32P; typedef TRasterPT TRaster64P; typedef TRasterPT TRasterGR8P; typedef TRasterPT TRasterGR16P; typedef TRasterPT TRasterGRDP; typedef TRasterPT TRasterYUV422P; //========================================================= // functions // trastercentroid.cpp TPoint computeCentroid(const TRaster32P &r); //========================================================= //========================================================= #endif //__T_RASTER_INCLUDED