#ifndef _LICE_H #define _LICE_H /* Cockos WDL - LICE - Lightweight Image Compositing Engine Copyright (C) 2007 and later, Cockos Incorporated Portions Copyright (C) 2007 "schwa" This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ #ifdef _WIN32 #include #else #include "../swell/swell-types.h" // use SWELL on other systems #endif // one of these can be defined in your project if you choose: //#define LICE_FAVOR_SPEED // optimizes some stuff that doesnt seem to benefit much (like LICE_DeltaBlit/LICE_RotatedBlit/LICE_TransformBlit) // (nothing) default probably good overall //#define LICE_FAVOR_SIZE // reduces code size of normal/scaled blit functions //#define LICE_FAVOR_SIZE_EXTREME // same as LICE_FAVOR_SIZE w/ smaller gains with bigger perf penalties (solid fills etc) #ifdef LICE_FAVOR_SPEED #ifdef LICE_FAVOR_SIZE_EXTREME #undef LICE_FAVOR_SIZE_EXTREME #endif #ifdef LICE_FAVOR_SIZE #undef LICE_FAVOR_SIZE #endif #endif #if defined(LICE_FAVOR_SIZE_EXTREME) && !defined(LICE_FAVOR_SIZE) #define LICE_FAVOR_SIZE #endif typedef unsigned int LICE_pixel; typedef unsigned char LICE_pixel_chan; #define LICE_RGBA(r,g,b,a) (((b)&0xff)|(((g)&0xff)<<8)|(((r)&0xff)<<16)|(((a)&0xff)<<24)) #define LICE_GETB(v) ((v)&0xff) #define LICE_GETG(v) (((v)>>8)&0xff) #define LICE_GETR(v) (((v)>>16)&0xff) #define LICE_GETA(v) (((v)>>24)&0xff) #if defined(__APPLE__) && defined(__ppc__) #define LICE_PIXEL_A 0 #define LICE_PIXEL_R 1 #define LICE_PIXEL_G 2 #define LICE_PIXEL_B 3 #else #define LICE_PIXEL_B 0 #define LICE_PIXEL_G 1 #define LICE_PIXEL_R 2 #define LICE_PIXEL_A 3 #endif static inline LICE_pixel LICE_RGBA_FROMNATIVE(LICE_pixel col, int alpha=0) { return LICE_RGBA(GetRValue(col),GetGValue(col),GetBValue(col),alpha); } // bitmap interface, and some built-in types (memory bitmap and system bitmap) class LICE_IBitmap { public: virtual ~LICE_IBitmap() { } virtual LICE_pixel *getBits()=0; virtual int getWidth()=0; virtual int getHeight()=0; virtual int getRowSpan()=0; // includes any off-bitmap data virtual bool isFlipped() { return false; } virtual bool resize(int w, int h)=0; virtual HDC getDC() { return 0; } // only sysbitmaps have to implement this virtual INT_PTR Extended(int id, void* data) { return 0; } }; #define LICE_EXT_SET_SCALING 0x2000 // data = int *, scaling is .8 fixed point. returns true if supported. affects LICE_*() draw operations #define LICE_EXT_GET_SCALING 0x2001 // data ignored, returns .8 fixed point, returns 0 if unscaled #define LICE_EXT_SET_ADVISORY_SCALING 0x2002 // data = int *, scaling is .8 fixed point. returns true if supported. does not affect draw operations #define LICE_EXT_GET_ADVISORY_SCALING 0x2003 // data ignored, returns .8 fixed point. returns 0 if unscaled #define LICE_EXT_GET_ANY_SCALING 0x2004 // data ignored, returns .8 fixed point, 0 if unscaled #define LICE_MEMBITMAP_ALIGNAMT 63 class LICE_MemBitmap : public LICE_IBitmap { public: LICE_MemBitmap(int w=0, int h=0, unsigned int linealign=4); virtual ~LICE_MemBitmap(); // LICE_IBitmap interface virtual LICE_pixel *getBits() { const UINT_PTR extra=LICE_MEMBITMAP_ALIGNAMT; return (LICE_pixel *) (((UINT_PTR)m_fb + extra)&~extra); } virtual int getWidth() { return m_width; } virtual int getHeight() { return m_height; } virtual int getRowSpan() { return (m_width+m_linealign)&~m_linealign; } virtual bool resize(int w, int h) { return __resize(w,h); } // returns TRUE if a resize occurred // todo: LICE_EXT_SET_SCALING ? private: bool __resize(int w, int h); LICE_pixel *m_fb; int m_width, m_height; int m_allocsize; unsigned int m_linealign; }; class LICE_SysBitmap : public LICE_IBitmap { public: LICE_SysBitmap(int w=0, int h=0); virtual ~LICE_SysBitmap(); // LICE_IBitmap interface virtual LICE_pixel *getBits() { return m_bits; } virtual int getWidth() { return m_width; } virtual int getHeight() { return m_height; } virtual int getRowSpan() { return m_allocw; }; virtual bool resize(int w, int h) { return __resize(w,h); } // returns TRUE if a resize occurred virtual INT_PTR Extended(int id, void* data) { switch (id) { case LICE_EXT_SET_ADVISORY_SCALING: { int sc = data && *(int*)data != 256 ? *(int *)data : 0; if (sc < 0) sc = 0; m_adv_scaling = sc; } return 1; case LICE_EXT_SET_SCALING: { int sc = data && *(int*)data != 256 ? *(int *)data : 0; if (sc < 0) sc = 0; if (m_draw_scaling != sc) { const int tmp=m_width; m_draw_scaling = sc; m_width=0; resize(tmp,m_height); } } return 1; case LICE_EXT_GET_SCALING: return m_draw_scaling; case LICE_EXT_GET_ADVISORY_SCALING: return m_adv_scaling; case LICE_EXT_GET_ANY_SCALING: if (m_draw_scaling > 0) { if (m_adv_scaling > 0) return (m_adv_scaling * m_draw_scaling) >> 8; return m_draw_scaling; } return m_adv_scaling; } return 0; } // sysbitmap specific calls virtual HDC getDC() { return m_dc; } private: bool __resize(int w, int h); int m_width, m_height; HDC m_dc; LICE_pixel *m_bits; int m_allocw, m_alloch; #ifdef _WIN32 HBITMAP m_bitmap; HGDIOBJ m_oldbitmap; #endif int m_draw_scaling, m_adv_scaling; }; class LICE_WrapperBitmap : public LICE_IBitmap { public: LICE_WrapperBitmap(LICE_pixel *buf, int w, int h, int span, bool flipped) { m_buf=buf; m_w=w; m_h=h; m_span=span; m_flipped=flipped; } virtual ~LICE_WrapperBitmap() {} virtual bool resize(int w, int h) { return false; } virtual LICE_pixel *getBits() { return m_buf; } virtual int getWidth() { return m_w; } virtual int getHeight() { return m_h; } virtual int getRowSpan() { return m_span; } virtual HDC getDC() { return NULL; } virtual bool isFlipped() { return m_flipped; } LICE_pixel *m_buf; int m_w,m_h,m_span; bool m_flipped; }; class LICE_SubBitmap : public LICE_IBitmap // note: you should only keep these around as long as they are needed, and don't resize the parent while this is allocated { public: LICE_SubBitmap(LICE_IBitmap *parent, int x, int y, int w, int h) { m_parent=parent; if(x<0)x=0; if(y<0)y=0; m_x=x;m_y=y; __resize(w,h); } virtual ~LICE_SubBitmap() { } virtual bool resize(int w, int h) { return __resize(w,h); } bool __resize(int w, int h) { m_w=0;m_h=0; if (m_parent && m_x >= 0 && m_y >= 0 && m_x < m_parent->getWidth() && m_y < m_parent->getHeight()) { if (w > m_parent->getWidth()-m_x) w=m_parent->getWidth()-m_x; if (h > m_parent->getHeight()-m_y) h=m_parent->getHeight()-m_y; m_w=w; m_h=h; } return true; } virtual bool isFlipped() { return m_parent && m_parent->isFlipped(); } virtual LICE_pixel *getBits() { if (!m_parent) return 0; int xc = m_x, yc = m_y, h = m_h; const int scale = (int)m_parent->Extended(LICE_EXT_GET_SCALING,NULL); if (scale > 0) { xc = (xc*scale)>>8; yc = (yc*scale)>>8; h = (h*scale)>>8; } LICE_pixel* parentptr=m_parent->getBits(); if (m_parent->isFlipped()) parentptr += (m_parent->getHeight() - (yc+h))*m_parent->getRowSpan()+xc; else parentptr += yc*m_parent->getRowSpan()+xc; return parentptr; } enum { LICE_GET_SUBBITMAP_VERSION = 0x51b7000, LICE_SUBBITMAP_VERSION = 0x1000 // if we change any of this struct, then we *must* increment this version. }; virtual INT_PTR Extended(int id, void* data) { if (id == LICE_GET_SUBBITMAP_VERSION) return LICE_SUBBITMAP_VERSION; if (!m_parent) return 0; return m_parent->Extended(id, data); } virtual int getWidth() { return m_w; } virtual int getHeight() { return m_h; } virtual int getRowSpan() { return m_parent ? m_parent->getRowSpan() : 0; } virtual HDC getDC() { return NULL; } int m_w,m_h,m_x,m_y; LICE_IBitmap *m_parent; }; // flags that most blit functions can take #define LICE_BLIT_MODE_MASK 0xff #define LICE_BLIT_MODE_COPY 0 #define LICE_BLIT_MODE_ADD 1 #define LICE_BLIT_MODE_DODGE 2 #define LICE_BLIT_MODE_MUL 3 #define LICE_BLIT_MODE_OVERLAY 4 #define LICE_BLIT_MODE_HSVADJ 5 #define LICE_BLIT_MODE_CHANCOPY 0xf0 // in this mode, only available for LICE_Blit(), the low nibble is 2 bits of source channel (low 2), 2 bits of dest channel (high 2) #define LICE_BLIT_FILTER_MASK 0xff00 #define LICE_BLIT_FILTER_NONE 0 #define LICE_BLIT_FILTER_BILINEAR 0x100 // currently pretty slow! ack #define LICE_BLIT_IGNORE_SCALING 0x20000 #define LICE_BLIT_USE_ALPHA 0x10000 // use source's alpha channel #ifndef lice_max #define lice_max(x,y) ((x)<(y)?(y):(x)) #define lice_min(x,y) ((x)<(y)?(x):(y)) #endif #ifdef _MSC_VER #include #define lice_isfinite(x) _finite(x) #else #define lice_isfinite(x) isfinite(x) #endif // Reaper exports most LICE functions, so the function declarations below // will collide with reaper_plugin.h #ifndef LICE_PROVIDED_BY_APP // bitmap loaders // dispatch to a linked loader implementation based on file extension LICE_IBitmap* LICE_LoadImage(const char* filename, LICE_IBitmap* bmp=NULL, bool tryIgnoreExtension=false); char *LICE_GetImageExtensionList(bool wantAllSup=true, bool wantAllFiles=true); // returns doublenull terminated GetOpenFileName() style list -- free() when done. bool LICE_ImageIsSupported(const char *filename); // must be a filename that ends in .jpg, etc. if you want to check the extension, pass .ext // pass a bmp if you wish to load it into that bitmap. note that if it fails bmp will not be deleted. LICE_IBitmap *LICE_LoadPNG(const char *filename, LICE_IBitmap *bmp=NULL); // returns a bitmap (bmp if nonzero) on success LICE_IBitmap *LICE_LoadPNGFromMemory(const void *data_in, int buflen, LICE_IBitmap *bmp=NULL); LICE_IBitmap *LICE_LoadPNGFromResource(HINSTANCE hInst, const char *resid, LICE_IBitmap *bmp=NULL); // returns a bitmap (bmp if nonzero) on success #ifndef _WIN32 LICE_IBitmap *LICE_LoadPNGFromNamedResource(const char *name, LICE_IBitmap *bmp=NULL); // returns a bitmap (bmp if nonzero) on success #endif LICE_IBitmap *LICE_LoadBMP(const char *filename, LICE_IBitmap *bmp=NULL); // returns a bitmap (bmp if nonzero) on success LICE_IBitmap *LICE_LoadBMPFromResource(HINSTANCE hInst, const char *resid, LICE_IBitmap *bmp=NULL); // returns a bitmap (bmp if nonzero) on success LICE_IBitmap *LICE_LoadIcon(const char *filename, int reqiconsz=16, LICE_IBitmap *bmp=NULL); // returns a bitmap (bmp if nonzero) on success LICE_IBitmap *LICE_LoadIconFromResource(HINSTANCE hInst, const char *resid, int reqiconsz=16, LICE_IBitmap *bmp=NULL); // returns a bitmap (bmp if nonzero) on success LICE_IBitmap *LICE_LoadJPG(const char *filename, LICE_IBitmap *bmp=NULL); LICE_IBitmap *LICE_LoadJPGFromMemory(const void *data_in, int buflen, LICE_IBitmap *bmp = NULL); LICE_IBitmap* LICE_LoadJPGFromResource(HINSTANCE hInst, const char *resid, LICE_IBitmap* bmp = 0); LICE_IBitmap *LICE_LoadGIF(const char *filename, LICE_IBitmap *bmp=NULL, int *nframes=NULL); // if nframes set, will be set to number of images (stacked vertically), otherwise first frame used LICE_IBitmap *LICE_LoadPCX(const char *filename, LICE_IBitmap *bmp=NULL); // returns a bitmap (bmp if nonzero) on success // bitmap saving bool LICE_WritePNG(const char *filename, LICE_IBitmap *bmp, bool wantalpha=true); bool LICE_WriteJPG(const char *filename, LICE_IBitmap *bmp, int quality=95, bool force_baseline=true); bool LICE_WriteGIF(const char *filename, LICE_IBitmap *bmp, int transparent_alpha=0, bool dither=true); // if alphaExtended(LICE_EXT_GET_SCALING,NULL); \ if (rsc>0) \ StretchBlt(hdc,_x,_y,_w,_h,(src)->getDC(),(_sx*rsc)/256,(_sy*rsc)/256,(_w*rsc)>>8,(_h*rsc)>>8,_mode); \ else BitBlt(hdc,_x,_y,_w,_h,(src)->getDC(),_sx,_sy,_mode); \ } while (0) #else #define LICE_Scale_BitBlt(hdc, x,y,w,h, src, sx,sy, mode) BitBlt(hdc,x,y,w,h,(src)->getDC(),sx,sy,mode) #endif #endif