现在的位置: 首页 > 综合 > 正文

cximage介绍

2013年12月02日 ⁄ 综合 ⁄ 共 16326字 ⁄ 字号 评论关闭

cximage介绍

 

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

Bugfixes

  • CxImageTIF::Encode: default compression for 4 bpp image was NONE, now it's LZW.
  • fixed SetXDPI and SetYDPI 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 in MM_TEXT, when MM_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 where malloc(0) returns 0, improvements in Alloc.

Changes and major additions

  • new functions: Rotate2() <BD>, Resample2() QIShrink(), RedEyeRemove(), Edge(), SelectionSplit() , IsSamePalette, BlendPixelColor, GetVersionNumber, Encode2RGBA
  • new dithering algorithms: Bayer, Burkes, Stucki, Jarvis-Judice-Ninke, Sierra, Stevenson-Arce
  • renamed AlphaGetBits with AlphaGetPointer
  • 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 for Mix()
  • 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 and RotateRight
  • CxImageJPG now can write back the EXIF information (verbatim copy).

Project - Libraries - Demo application

  • 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 object is also a set of layers. The buffers in each layer are allocated only when necessary.

  

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
CXIMAGE_SUPPORT_GIF
CXIMAGE_SUPPORT_ICO
CXIMAGE_SUPPORT_TGA
CXIMAGE_SUPPORT_PCX
CXIMAGE_SUPPORT_WBMP
CXIMAGE_SUPPORT_WMF

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
CXIMAGE_SUPPORT_RAS
jasper 176
JPEG-2000 CXIMAGE_SUPPORT_JP2
CXIMAGE_SUPPORT_JPC
CXIMAGE_SUPPORT_PGX
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
CXIMAGE_SUPPORT_ENCODE
< 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.
In the same workspace you'll find the projects to build different libraries and applications:

  • CxImage : cximage.lib - static library
  • CxImageCrtDll : cximagecrt.dll - DLL not using mfc
  • CxImageMfcDll : cximage.dll - DLL using mfc
  • Demo : demo.exe - program linked with cximage.lib and the C libraries
  • DemoDll : demodll.exe - program linked with cximagecrt.dll
  • j2k,jasper,jbig,jpeg,png,tiff,zlib : static C libraries

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 <ymax; 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<xmax; 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 ICONs, MNG, TGA and PCX. Finally I added some specific functions to obtain an image from global HANDLEs (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 for BCMenu code.

More specific credits and disclaimers are in every header file of each library

抱歉!评论已关闭.