#ifndef AVIFILE_IMAGE_H #define AVIFILE_IMAGE_H #include "infotypes.h" #include "formats.h" AVM_BEGIN_NAMESPACE; /** * Class that hides some details of proper BITMAPINFOHEADER * initialization methods. */ class BitmapInfo : public BITMAPINFOHEADER { public: uint32_t m_iColors[3]; BitmapInfo(); BitmapInfo(int width, int height, int bpp); BitmapInfo(const BITMAPINFOHEADER & hdr); BitmapInfo(const BitmapInfo & bi); BitmapInfo(const BitmapInfo * bi); static int BitCount(int csp); void SetBitFields15(); // by default SetBits will use BI_RGB & 16bit void SetBitFields16(); void SetRGB(); // set top-down RGB image void SetBits(int bits); // set top-down YUV image void SetSpace(int csp); void SetDirection(int dir) { if (biHeight < 0) biHeight = -biHeight; //labs biHeight = (dir) ? biHeight : -biHeight; } int Bpp() const; bool operator== (const BitmapInfo & bi) const { return (biWidth == bi.biWidth && biHeight == bi.biHeight && Bpp() == bi.Bpp() && (biCompression == bi.biCompression || (IsRGB() && bi.IsRGB()) ) ); } bool IsRGB() const { return biCompression == BI_RGB || biCompression == BI_BITFIELDS; } void Print() const; }; /** * This class describes an uncompressed image in one of several supported * formats. These formats currently include RGB ( 15, 16, 24 and 32 bits ) * and packed YUV ( non-subsampled 24-bit YUV and 16-bit YUY2 formats ). * It is capable of converting between all supported formats. Some of * conversions are optimized, but it is generally not recommended to use * these conversions in time-critical code. */ /** * mplayer compatible surface declaration * used to allow development of common conversion routines */ // for internal usage BGR/RGB,Y | U | V | Alpha static const uint_t CIMAGE_MAX_PLANES = 4; struct ci_surface_t { unsigned int m_iFormat; // fourcc int m_iWidth, m_iHeight; // surface's real width & height struct window_s { int x; int y; int w; int h; } m_Window; // visible area uint8_t* m_pPlane[CIMAGE_MAX_PLANES]; int m_iStride[CIMAGE_MAX_PLANES]; int m_iBpp; // bytes per plane int m_iFlip; // 1 - upside-down -1 downside-up (usually RGB) // mostly private extension - // do not even think about using them now int* m_iQScale; int m_iQStride; int m_iAge; // mainly for ffmpeg int m_iType; // i/p/b frame float m_fAspectRatio; // select area of visible image // the rest of the image will not be converted, transfered,.... void SetWindow(int x = 0, int y = 0, int w = 0, int h = 0); // pointer to start of visible data uint8_t* GetWindow(uint_t idx = 0); const uint8_t* GetWindow(uint_t idx = 0) const; }; class IImageAllocator; class CImage : public ci_surface_t { public: // non-conversion constructors /** * Creates new image in format 'header' from specified memory area. * Either allocates its own memory area & copies src data into it, or reuses * parent data. - Note: data can't be specified as void* here to distinguish * different constructors */ CImage(const BitmapInfo* header, const uint8_t* data = 0, bool copy = true); CImage(const BitmapInfo* header, const uint8_t* planes[CIMAGE_MAX_PLANES], const int strides[CIMAGE_MAX_PLANES], bool copy = true); /* Creates 24-bit RGB image from 24-bit RGB 'data' */ CImage(const uint8_t* data, int width, int height); /* Creates a copy of image 'im' */ CImage(const CImage* im); // Conversion constructors /** * Creates RGB image in depth 'depth' from image 'im' * or image with given color space */ CImage(const CImage* im, uint_t csp_bits); /** Creates new image in format 'header' from image 'im' */ CImage(const CImage* im, const BitmapInfo* header); ~CImage(); void AddRef() const { m_iRefcount++; } void Release() const; uint8_t* Data(uint_t idx = 0) { return m_pPlane[idx]; } const uint8_t* Data(uint_t idx = 0) const { return m_pPlane[idx]; } uint_t Stride(uint_t idx = 0) const { return m_iStride[idx]; } // for RGB images only! uint8_t *At(int i) { return Data() + i * m_iBpl; } const uint8_t *At(int i) const { return Data() + i * m_iBpl; } uint8_t *At(int i, int j) { return Offset(i) + j * m_iBpl; } uint8_t *Offset(int i) { return Data() + i * m_iBpp; } const uint8_t *Offset(int i) const { return Data() + i * m_iBpp; } // returns bytes per the first plane int Bpp() const { return m_iBpp; } // returns bytes per line (width * bpp) int Bpl() const { return m_iBpl; } int Depth() const { return m_iDepth; } fourcc_t Format() const { return m_iFormat; } uint_t Bytes(uint_t idx = 0) const { return m_iBytes[idx]; } int Pixels() const { return m_iPixels; } int Width() const { return m_iWidth; } int Height() const { return m_iHeight; } float Aspect() const { return m_fAspectRatio; } int AspectWidth() const { return (int)(m_fAspectRatio * m_iWidth + 0.5); } // returns true for upside-down image bool Direction() const { return !(m_pInfo.biHeight < 0); } /** * Is it in format 'hdr'? */ bool IsFmt(const BitmapInfo* hdr) const { return (m_pInfo == *hdr); } BitmapInfo* GetFmt() { return &m_pInfo; } const BitmapInfo* GetFmt() const { return &m_pInfo; } /** * Translations 24-bit RGB <-> Non-subsampled packed 24-bit YUV * ( for image processing purposes ) */ void ToYUV(); void ToRGB(); /** * Fast MMX blur filter ( blur over the square with 2^range*2^range dimensions ) * Blur(x); Blur(y, x) has the same effect as Blur(y) */ void Blur(int range, int from = 0); /** * Writes 24-bit uncompressed bitmap with name 'filename'. */ void Dump(const char *filename); /** * RGB<->BGR translation for 24-bit images */ void ByteSwap(); float GetQuality() const { return m_fQuality; } void SetQuality(float q) { m_fQuality = q; } void* GetUserData() const { return m_pUserData; } void SetUserData(void* userData) { m_pUserData = userData; } IImageAllocator* GetAllocator() const { return m_pAllocator; } void SetAllocator(IImageAllocator* pAllocator) { m_pAllocator = pAllocator; } // set image to black color void Clear(); static bool Supported(const BITMAPINFOHEADER& bi); static bool Supported(int csp, int bitcount = 0); // convert some common fourcc to those internaly used // i.e. Y422 -> YUY2, IYUV -> I420 static fourcc_t StandardFOURCC(fourcc_t csp); /** * General way of converting is as follows. * a) There's one function for converting anything to 24-bit RGB and back. * b) There is a number of 'shortcuts' between formats, * e.g. YUY2<->16-bit RGB. * c) If there's no shortcut between particular two formats, the conversion * is done in two steps through temporary image. */ void Convert(const CImage* from_img); void Convert(const uint8_t* from_data, const BitmapInfo* from_fmt); // do not use - it's for internal usage and will be removed! void Slice(const ci_surface_t* ci, int alpha = 0); protected: void fillMembers(); void setPlanes(); mutable int m_iRefcount; BitmapInfo m_pInfo; uint_t m_iBytes[CIMAGE_MAX_PLANES]; int m_iDepth; int m_iBpl; int m_iPixels; float m_fQuality; void* m_pUserData; IImageAllocator* m_pAllocator; bool m_bDataOwner[CIMAGE_MAX_PLANES]; public: uint_t m_uiPosition; // decoded position int64_t m_lTimestamp; // 64bit timestamp (us) private: /* copying disabled */ CImage& operator= (CImage&) { return *this; } CImage(const CImage&) {} }; /** * Interface for Image allocators * * Usually implemented by VideoRenderer and used for DirectRendering support */ class IImageAllocator { public: // number of allocated buffers virtual uint_t GetImages() const =0; virtual CImage* ImageAlloc(const BITMAPINFOHEADER& bh, uint_t idx, uint_t align) =0; virtual void ReleaseImages() =0; //virtual int ImageResize(int w, int h, uint_t idx) =0; }; struct yuv; struct lookuptable { int m_plY[256]; int m_plRV[256]; int m_plGV[256]; int m_plGU[256]; int m_plBU[256]; lookuptable(); }; /** * Structure that represents 24-bit RGB pixel. */ struct __attribute__((__packed__)) col { static lookuptable t; uint8_t b,g,r; col() {} col(uint8_t B, uint8_t G, uint8_t R) :b(B),g(G),r(R) {} inline col(yuv YUV); int CREF() const { return (int(b) << 16) + (int(g) << 8) + int(r); } uint_t Y() const { int _Y= 6392l * b + 33055l * g + 16853l * r + 0x8000; return (_Y>>16)+16; } uint16_t bgr15() const { return (uint16_t) (((((((r<<5)&0xff00)|g)<<5)&0xfff00)|b)>>3); } uint16_t bgr16() const { return (uint16_t) (((((((r<<5)&0xff00)|g)<<6)&0xfff00)|b)>>3); } uint32_t bgr32() const { return (uint32_t) ((r<<24) | (g<<16) | b); } }; /** * Structure that represents 24-bit ( 888 ) YUV pixel. */ struct __attribute__((__packed__)) yuv { uint8_t Y; uint8_t Cb;/* aka U */ uint8_t Cr;/* aka V */ yuv() {} yuv(uint8_t _Y, uint8_t _Cb, uint8_t _Cr) :Y(_Y), Cb(_Cb), Cr(_Cr) {} yuv(col Col) { int _Y = ((25*Col.b + 129*Col.g + 66*Col.r) >> 8) + 0x10; if (_Y < 0x10) _Y = 0x10; else if (_Y > 0xef) _Y = 0xef; Y = _Y; int _Cb = ((112*Col.b -74*Col.g -38*Col.r) >> 8) + 0x80; if (_Cb < 0x10) _Cb = 0x10; else if (_Cb > 0xef) _Cb = 0xef; Cb = _Cb; int _Cr = ((-18*Col.b -94*Col.g + 112*Col.r) >> 8) + 0x80; if (_Cr < 0x10) _Cr = 0x10; else if (_Cr > 0xef) _Cr = 0xef; Cr = _Cr; } }; inline col::col(yuv YUV) { int y = t.m_plY[YUV.Y]; int B = (y + t.m_plBU[YUV.Cb]) >> 8; if (B < 0) B = 0; else if (B > 0xff) B = 0xff; b = B; int G = (y + t.m_plGU[YUV.Cb] + t.m_plGV[YUV.Cr]) >> 8; if (G < 0) G = 0; else if (G > 0xff) G = 0xff; g = G; int R = (y + t.m_plRV[YUV.Cr]) >> 8; if (R < 0) R = 0; else if (R > 0xff) R = 0xff; r = R; } AVM_END_NAMESPACE; #ifdef AVM_COMPATIBLE typedef avm::CImage CImage; typedef avm::BitmapInfo BitmapInfo; typedef avm::yuv yuv; typedef avm::col col; #endif #endif // AVIFILE_IMAGE_H