당연히 "codeproject" 에서 갖고 왔습니다.
- Download full source files - 2.10 Mb
- Download lite source files - 442 Kb
- Download executable demo - 576 Kb
Preface
CxImage grew together with the CodeProject site, since 2001, and reached this level thanks to the CodeProject community. Thanks a lot for the suggestions, the contributions and for the critiques. However, if I look at the other image processing libraries, it is clear that nowadays, the CxImage project is quite inadequate from many points of view. For this reason, this one will be last release in this form. Of course the development will not stop: it is just going to follow new directions.
Introduction
CxImage
is a C++ class that can load,
save, display, transform images in a very simple and fast way.
Why another image library? Around there are many good libraries (OpenIL, FreeImage, PaintLib ...), these are powerful, complete, and constantly updated. However if you ever try to use them, you may find some difficulties; because these libraries are mainly platform independent, written in C, sometimes with a basic C++ wrapper and with tons of compiler switch declarations. Now with the new GDI+ classes on the scene, maybe CxImage isn't so useful, but at least here you have the source code. It is not a MFC library, altogether it's a windows library, because of some particular constructors and the painting functions, but the backbone is platform independent.
License
The class CxImage
is free; as for
the TIFF, JPEG, PNG and ZLIB libraries : "If you use this source code in a
product, acknowledgment is not required but would be appreciated."
CxImage
is open source and licensed
under the zlib license . In a nutshell, this means that you can
use the code however you wish, as long as you don't claim it as your own.
What's new in version 5.99c
BugfixesCxImageTIF::Encode
: default compression for 4 bpp image wasNONE
, now it'sLZW
.- fixed
SetXDPI
andSetYDPI
to accept only positive dpi values - fixed EXIF decoder against invalid
TAG_EXIF_OFFSET
/TAG_INTEROP_OFFSET
- fixed missing definitions in ximawnd.cpp when
CXIMAGE_SUPPORT_BMP
is 0 - fixed
CxFileJas
constructor to avoid crashes, when Jasper deals with its temporary files, decoding large images - removed default imagetype value from
CxImage::Save
- fixed
Mean()
for images with an active selection - fixed GIF decoder for animated images with corrupted frames.
- fixed GIF decoder for images with screen descriptor larger than the first frame.
- fixed GIF decoder to handle the disposal methods correctly.
CxImageWMF
reads images mapped inMM_TEXT
, whenMM_ANISOTROPIC
fails.- fixed Clear for 1 and 4 bpp images.
- fixed typo in ximajpg.cpp:
ENTRPY_OPT_SUPPORTED
->ENTROPY_OPT_SUPPORTED
- fixed potential memory overflow in RLE decoder reading corrupted bitmaps.
- Better UNICODE support and fixed
TCHAR
mappings for Linux. - fixed bug in
IsTransparent
, for images with a valid alpha layer. - fixed bug in
Create
: a vaild image was created even if width or height were zero. CxMemFile
: fixed problem for compilers wheremalloc(0)
returns 0, improvements inAlloc
.
- new functions:
Rotate2()
,Resample2()
QIShrink()
,RedEyeRemove()
,Edge()
,SelectionSplit()
,IsSamePalette
,BlendPixelColor
,GetVersionNumber
,Encode2RGBA
- new dithering algorithms: Bayer, Burkes, Stucki, Jarvis-Judice-Ninke, Sierra, Stevenson-Arce
- renamed
AlphaGetBits
withAlphaGetPointer
- new compiler switch:
CXIMAGE_SUPPORT_INTERPOLATION
to enable pixel color interpolations,
implemented in the ximaint.cpp module - New bEnableInterpolation parameter for
Skew()
- New blend parameter for
Colorize()
- color conversion routines now are declared as
static
- FFT2 now works also with Borland compilers
- more interpolation kernels
- Smooth stretching parameter for
Draw
- Added
FreeMemory
function, to avoid heap problems using Encode with memory buffers - new
bMixAlpha
parameter and new OpScreen blending mode forMix()
- LZW compression is the default algorithm for GIF compression.
CxImagePNG
now can encode interlaced images- Get/SetCodecOption now has an "ImageType" parameter, so that each format keeps its specific options
- Faster
RotateLeft
andRotateRight
CxImageJPG
now can write back the EXIF information (verbatim copy).
- Demo: new dialogs for Resample, Rotate, Skew with more options, JPEG compression
- New license based on zlib/libpng philosophy, see ximage.h and license.txt
- Demo: new tool: tracker
- Demo: new View/Smooth menu to test smooth drawing in zoom and stretch modes
- Demo: more CodecOptions on the Options dialog, enabled LZW compression for GIF and TIF formats.
- PNG: updated to libpng 1.2.7
- JBIG: updated to version 1.6
- Better documentation : now using Doxygen.
CxImage structure
In the vertical hierarchy of the library, CxImage
stays on the top of the other modules, it's not a clean OOP
approach, but the result was good since the first release and now it's too late
to change again. Anyway you can always use the derived classes to perform the
format specific operations, like for CxImageTIF
to save multipage TIFFs.
The glue to connect all the modules and the C libraries is CxFile
, a virtual class that provides the standard
methods to access the data from a file on the disk or in memory.
A Cximage
object is basically a bitmap,
with the addition of some member variables to store useful information:
class CxImage { ... protected: void* pDib; //contains the header, the palette, the pixels BITMAPINFOHEADER head; //standard header CXIMAGEINFO info; //extended information BYTE* pSelection; //selected region BYTE* pAlpha; //alpha channel CxImage** pLayers; //generic layers }
CxImage::head
is the bitmap header and
CxImage::pDib
is a normal bitmap (as you can
see in the implementation of CxImageBMP::Encode
).
CxImage::info
is a handy container of many
information shared between different formats, and for all the member
functions.
typedef struct tagCxImageInfo { DWORD dwEffWidth; //DWORD aligned scan line width BYTE* pImage; //THE IMAGE BITS void* pGhost; //if this is a ghost, pGhost point to the body DWORD dwType; //original image format char szLastError[256]; //debugging long nProgress; //monitor long nEscape; //escape long nBkgndIndex; //used for GIF, PNG, MNG RGBQUAD nBkgndColor; //used for RGB transparency BYTE nQuality; //used for JPEG long nFrame; //used for TIF, GIF, MNG : actual frame long nNumFrames; //used for TIF, GIF, MNG : total number of
//frames DWORD dwFrameDelay; //used for GIF, MNG long xDPI; //horizontal resolution long yDPI; //vertical resolution RECT rSelectionBox; //bounding rectangle BYTE nAlphaMax; //max opacity (fade) bool bAlphaPaletteEnabled; //true if alpha values in the palette are // enabled. bool bEnabled; //enables the painting functions long xOffset; long yOffset; DWORD dwEncodeOption; //for GIF, TIF : 0=def.1=unc,2=fax3,3=fax4, // 4=pack,5=jpg RGBQUAD last_c; //for GetNearestIndex optimization BYTE last_c_index; bool last_c_isvalid; long nNumLayers; DWORD dwFlags; } CXIMAGEINFO;
A
|
CxImage::pDib
is the background image.
CxImage::pAlpha
is the transparency layer.
CxImage::pSelection
is the selection layer,
used to create regions of interest for image processing. Over these 3 specific
planes, you can add other generic layers, stored in CxImage::pLayers
. The generic layers are full CxImage
objects, so you can build complex structures of nested layers.
CxImage Class Members & Operations
CxImage 5.99c is documented using Doxygen , however for historical reasons, many uncommon features are still undocumented. The class members reference, together with release history, and license, can be found here
Supported formats and options
The whole library is quite big, in the main header file
ximcfg.h you'll find the switches to enable or disable a specific
graphic format or feature. Each JPG, PNG and TIFF library adds about 100KB to
the final application, while the CxImage
impact is about 50KB. So you should support and link only the formats that your
application really needs.
formats | #define | required libraries | size [Kbyte] |
BMP GIF ICO TGA PCX WBMP WMF |
CXIMAGE_SUPPORT_BMP |
built in |
24 |
JPEG | CXIMAGE_SUPPORT_JPG |
jpeg |
88 |
PNG | CXIMAGE_SUPPORT_PNG |
png, zlib |
104 |
MNG | CXIMAGE_SUPPORT_MNG |
mng, zlib, jpeg |
148 |
TIFF | CXIMAGE_SUPPORT_TIF |
tiff, zlib, jpeg |
124 |
JBIG | CXIMAGE_SUPPORT_JBG |
jbig |
28 |
PNM,PPM,PGM RAS |
CXIMAGE_SUPPORT_PNM |
jasper |
176 |
JPEG-2000 |
CXIMAGE_SUPPORT_JP2 |
jasper |
176 |
Option | #define | Size [Kbyte] |
CxImage core | all switches off | 20 |
geometric transformations | CXIMAGE_SUPPORT_TRANSFORMATION |
16 |
image processing | CXIMAGE_SUPPORT_DSP |
24 |
drawing and windows specific functions | CXIMAGE_SUPPORT_WINDOWS |
12 |
transparency | CXIMAGE_SUPPORT_ALPHA |
4 |
selections | CXIMAGE_SUPPORT_SELECTION |
4 |
multiple layers | CXIMAGE_SUPPORT_LAYERS |
< 4 |
graphic formats conversion |
CXIMAGE_SUPPORT_DECODE |
< 4 |
Using CxImage in your projects
The CxImgLib.dsw workspace shows the libraries required to build an
application (demo.exe) including almost all the features and the formats
available in CxImage. You must compile all the libraries before you can link the
final application.
Building the projects will need some minutes to complete (the intermediate files occupy 60MB!). When everything is done, select the demo project and launch the application. |
CxImgLib.dsw |
To use CxImage in your project, you must edit these settings:
Project Settings
|- C/C++
| |- Code Generation
| | |- Use run-time library : Multithreaded DLL (must be the same for
| | | all the linked libraries)
| | |- Struct member alignment : must be the same for all the linked
| | | libraries
| |- Precompiled headers : not using precompiled headers
| |- Preprocessor
| |- Additional Include Directories: ..\cximage
|- Link
|- General
|- Object/library modules: ../png/Debug/png.lib
../jpeg/Debug/jpeg.lib
../zlib/Debug/zlib.lib
../tiff/Debug/tiff.lib
../cximage/Debug/cximage.lib ...
Adding your custom functions in CxImage
Writing a new function for image processing is not so hard with CxImage
. Here I'm going to describe CxImage::Jitter
, it's very simple but it shows many
aspects to take care when you work inside CxImage. The first thing, of course,
is the declaration : bool
Jitter(long radius=2);
in the CXIMAGE_SUPPORT_DSP
section of ximage.h, you can declare
the function everywhere in the public
scope of the class. And now the definition:
bool CxImage::Jitter(long radius) { // check if the image is valid, this should be always the first line in // the function if (!pDib) return false; // local variables long nx,ny; // temporary image to store the partial results of the algorithm CxImage tmp(*this,pSelection!=0,true,true); // limit the effects of the functions only in the smallest rectangle that // holds the selected region (defined with the Selection...() functions ), // this will speed up the loops. long xmin,xmax,ymin,ymax; if (pSelection){ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right; ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top; } else { xmin = ymin = 0; xmax = head.biWidth; ymax=head.biHeight; } // main loop : scan the image in vertical direction for(long y=ymin; y// monitor the progress of the loops info.nProgress = (long)(100*y/head.biHeight); // let the application a way to exit quickly if (info.nEscape) break; // main loop : scan the image in horizontal direction for(long x=xmin; x // if the feature is enabled, process only the pixels inside the // selected region #if CXIMAGE_SUPPORT_SELECTION if (SelectionIsInside(x,y)) #endif //CXIMAGE_SUPPORT_SELECTION { // main algorithm nx=x+(long)((rand()/(float)RAND_MAX - 0.5)*(radius*2)); ny=y+(long)((rand()/(float)RAND_MAX - 0.5)*(radius*2)); if (!IsInside(nx,ny)) { nx=x; ny=y; } // save the result in the temporary image. // if you can, use PixelColor only for 24 bpp images, // and PixelIndex for 8, 4 and 1 bpp images : it's faster if (head.biClrUsed==0){ tmp.SetPixelColor(x,y,GetPixelColor(nx,ny)); } else { tmp.SetPixelIndex(x,y,GetPixelIndex(nx,ny)); } // if the feature is enabled, process also the pixels // in the alpha layer #if CXIMAGE_SUPPORT_ALPHA tmp.AlphaSet(x,y,AlphaGet(nx,ny)); #endif //CXIMAGE_SUPPORT_ALPHA } } } // save the result and exit Transfer(tmp); return true; }
Examples: how to ...
... convert from a format to another
CxImage image; // bmp -> jpg image.Load("image.bmp", CXIMAGE_FORMAT_BMP); if (image.IsValid()){ if(!image.IsGrayScale()) image.IncreaseBpp(24); image.SetJpegQuality(99); image.Save("image.jpg",CXIMAGE_FORMAT_JPG); } // png -> tif image.Load("image.png", CXIMAGE_FORMAT_PNG); if (image.IsValid()){ image.Save("image.tif",CXIMAGE_FORMAT_TIF); }
... load an image resource
//Load the resource IDR_PNG1 from the PNG resource type CxImage* newImage = new CxImage(); newImage->LoadResource(FindResource(NULL,MAKEINTRESOURCE(IDR_PNG1), "PNG"),CXIMAGE_FORMAT_PNG);or
//Load the resource IDR_JPG1 from DLL CxImage* newImage = new CxImage(); HINSTANCE hdll=LoadLibrary("imagelib.dll"); if (hdll){ HRSRC hres=FindResource(hdll,MAKEINTRESOURCE(IDR_JPG1),"JPG"); newImage->LoadResource(hres,CXIMAGE_FORMAT_JPG,hdll); FreeLibrary(hdll); }or
//Load a bitmap resource; HBITMAP bitmap = ::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP1))); CxImage *newImage = new CxImage(); newImage->CreateFromHBITMAP(bitmap);
... decode an image from memory
CxImage image((BYTE*)buffer,size,image_type);or
CxMemFile memfile((BYTE*)buffer,size); CxImage image(&memfile,image_type);or
CxMemFile memfile((BYTE*)buffer,size);
CxImage* image = new CxImage();
image->Decode(&memfile,type);
... encode an image in memory
long size=0; BYTE* buffer=0; image.Encode(buffer,size,image_type); ... free(buffer);or
CxMemFile memfile;
memfile.Open();
image.Encode(&memfile,image_type);
BYTE* buffer = memfile.GetBuffer();
long size = memfile.Size();
...
free(buffer);
... create a multipage TIFF
CxImage *pimage[3]; pimage[0]=&image1; pimage[1]=&image2; pimage[2]=&image3; FILE* hFile; hFile = fopen("multipage.tif","w+b"); CxImageTIF multiimage; multiimage.Encode(hFile,pimage,3); fclose(hFile);or
FILE* hFile; hFile = fopen("c:\\multi.tif","w+b"); CxImageTIF image; image.Load("c:\\1.tif",CXIMAGE_FORMAT_TIF); image.Encode(hFile,true); image.Load("c:\\2.bmp",CXIMAGE_FORMAT_BMP); image.Encode(hFile,true); image.Load("c:\\3.png",CXIMAGE_FORMAT_PNG); image.Encode(hFile); fclose(hFile);
... copy/paste an image
//copy HANDLE hDIB = image->CopyToHandle(); if (::OpenClipboard(AfxGetApp()->m_pMainWnd->GetSafeHwnd())) { if(::EmptyClipboard()) { if (::SetClipboardData(CF_DIB,hDIB) == NULL ) { AfxMessageBox( "Unable to set Clipboard data" ); } } } CloseClipboard(); //paste HANDLE hBitmap=NULL; CxImage *newima = new CxImage(); if (OpenClipboard()) hBitmap=GetClipboardData(CF_DIB); if (hBitmap) newima->CreateFromHANDLE(hBitmap); CloseClipboard();
... display a file in a picture box
HBITMAP m_bitmap = NULL;
CxImage image("myfile.png", CXIMAGE_FORMAT_PNG); ... m_bitmap = image.MakeBitmap(m_picture.GetDC()->m_hDC);
m_picture.SetBitmap(m_bitmap);
...
if (m_bitmap) DeleteObject(m_bitmap);
History and credits.
Starting form my CxDib
class, that
implements memory DIBs only, I tried to add some members to read images from
files. Looking for a solution, I found a nice MFC class named CImage
on the net, release 1.4 (1998). CImage
supports BMP, GIF, PNG and JPG, but suffers many
little bugs and uses a complex class structure, so I decided to strip it to the
base and merge CxDib
with the CImage
philosophy, to obtain the new CxImage
class. Also I updated the libraries for JPG, PNG
and ZLIB.
With CxImage
it is very easy to add new
image types, so I added the TIFF library (rev. 6) and a minimal support for
ICON
s, MNG, TGA and PCX. Finally I added some
specific functions to obtain an image from global HANDLE
s (windows clipboard) and objects (windows
resources). This is the story until the early release, the following is written
in the documentation.
- CImage © 1995-1998, Alejandro Aguilar Sierra.
- IJG JPEG library ©1994-1998, Thomas G. Lane.
- LibPNG version 1.2.7© 1998-2004 Glenn Randers-Pehrson
- LibTIFF version 3.5.7 © 1988-1997 Sam Leffler, © 1991-1997 Silicon Graphics, Inc.
- LibMNG version 1.0.2 © 2000,2001 Gerard Juyn.
- Gif-RLE © Hutchison Avenue Software Corporation, 1998
- LibJ2K© David Janssens, 2001 - 2002
- LibJBG version 1.6 © Markus Kuhn, 2004
- JasPer version 1.700.2 © Image Power, UBC, Michael David Adams, 2001 - 2003
- zlib version 1.2.1 © 1995-2003 Jean-loup Gailly and Mark Adler
- Thanks to Troels Knakkergaard for his precious work in the earlier versions
of CxImage, Rajiv Ramachandran for
CTwain
code; to Abe for multi page tiffs code; to Chris Shearer Cooper for memory file suggestions and code; to Brent Corkum forBCMenu
code.
More specific credits and disclaimers are in every header file of each library.
About Davide Pizzolato
- - - - - - - DISCONTINUED - - - - - - - The author will not maintain this page any more, neither replies to questions posted on the message board Click here to view Davide Pizzolato's online profile. |
Other popular articles:
|