ImageStone图像处理C++类库

文章地址:http://www.codeproject.com/Articles/13559/ImageStone


ImageStone - 一个功能强大的C + +类库的图像处理


如何使用

ImageStone STL和Boost库是一个只有头的C + +库,它是由完全的头文件,所以你就可以开始使用它只需添加#include “ImageStone.h”在你的源代码的开始,但为了充分利用操作系统的功能,在各种平台之间存在一定的差异。

在Windows

只需要添加include “ImageStone.h”,在您的项目中,通常要附加在StdAfx.h中文件的末尾

ImageStone使用原始的Win32 GDI + API来实现图像的加载 / 保存功能,因此它具有高效率和小的最终文件大小。

在非Windows(UNIX,LINUX,Mac等等)

ImageStone使用FreeImage的解放来实现图像的加载/保存功能。

  1. FreeImage的http://sourceforge.net/projects/freeimage/,然后编译它。
  2. 包括FreeImage的头包括ImageStone
    #include "FreeImage.h"
    #include "ImageStone.h"
  3. 现在你可以使用ImageStone
先进的图像效果

为了减少编译时间,是不能被默认包含了很多很少使用的图像效果(浮雕,扭曲,波纹...),你可以通过以下方式使用:

#define IMAGESTONE_USE_EXT_EFFECT
#include "ImageStone.h"

... Load Image from File, Memory or Resource, Save Image to File

FCObjImage   img ;

// from file
img.Load (L"test.jpg") ;

// from memory
img.Load (pMemory, nSize, IMG_JPG) ;

// from resource under windows
img.LoadBitmap (ID_BITMAP) ;
img.LoadResource (ID_JPG_FILE, _T("JPG"), IMG_JPG) ;

// save as jpg with quality 90 ( max is 100 )
img.Save (L"test.jpg", 90) ;

In order to better support for multiple languages, ImageStone only supports wide char filename, so you need to call a conversion function for ANSI filename.

std::wstring A_to_W (const char* p)
{
    std::wstring   ws ;
    if (p)
    {
        setlocale (LC_CTYPE, "") ;

        std::vector<wchar_t>  buf (strlen(p)+1, 0) ;
        mbstowcs (&buf[0], p, buf.size()-1) ;
        ws = &buf[0] ;
    }
    return ws ;
}

FCObjImage   img ;
img.Load (A_to_W("test.jpg").c_str()) ;

// under windows, you can use _bstr_t to implement conversion
img.Load (_bstr_t("test.jpg")) ;

... Load multi-page GIF

std::vector<FCObjImage*>   frame_list ;
FCImageProperty   prop ;
FCObjImage::Load (L"test.gif", frame_list, &prop) ;

// now frame_list store all frames of Gif image
// member m_frame_delay of prop store delay time between two frame
prop.m_frame_delay ;

// caller must delete all frames when them no longer be used
for (size_t i=0 ; i < frame_list.size() ; i++)
{
    delete frame_list[i] ;
}

... Apply Image Effect

FCObjImage   img ;
img.Load (L"test.jpg") ;

img.Stretch (200, 200) ;
img.Stretch_Smooth (500, 500) ;

FCEffectBlur_Gauss   c1 (16, true) ;
img.ApplyEffect (c1) ;

FCEffectSplash   c2 (20) ;
img.ApplyEffect (c2) ;

FCEffectMosaic   c3 (20) ;
img.ApplyEffect (c3) ;

FCEffectBrightnessContrast   c4 (30, 0) ;
img.ApplyEffect (c4) ;

You can monitor the progress of image processing by setting an observer:

// this monitor will stop image processing when user press ESC key
class CMyProgressMonitor : public FCProgressObserver
{
public:
    virtual bool OnProgressUpdate (int nFinishPercentage)
    {
        MSG   msg ;
        if (PeekMessage (&msg, NULL, WM_KEYDOWN, WM_KEYDOWN, PM_REMOVE) &&
			(msg.wParam == VK_ESCAPE))
        {
            return false ;
        }
        return true ;
    }
};

// apply effect with progress monitor
FCObjImage   img ;
img.Load (L"test.jpg") ;

CMyProgressMonitor   aProgress ;

FCEffectMosaic   c1 (20) ;
img.ApplyEffect (c1, &aProgress) ;

... Custom Image Effect

// create our effect : split RGB channel of image
class CEffectSplitChannel : public FCImageEffect
{
public:
    FCObjImage   m_red, m_green, m_blue ;

private:
    virtual bool IsSupport (const FCObjImage& img)
    {
        return img.IsValidImage() && (img.ColorBits() >= 24) ;
    }

    virtual void OnBeforeProcess (FCObjImage& img)
    {
        int   w = img.Width() ;
        int   h = img.Height() ;
        m_red.Create (w, h, 24) ;
        m_green.Create (w, h, 24) ;
        m_blue.Create (w, h, 24) ;
    }

    virtual void ProcessPixel (FCObjImage& img, int x, int y, BYTE* pPixel)
    {
        PCL_R(m_red.GetBits(x,y)) = PCL_R(pPixel) ;
        PCL_G(m_green.GetBits(x,y)) = PCL_G(pPixel) ;
        PCL_B(m_blue.GetBits(x,y)) = PCL_B(pPixel) ;
    }
};

// test, save RGB channel to image
void Test()
{
    FCObjImage   img ;
    img.Load (L"test.jpg") ;

    CEffectSplitChannel   cmd ;
    img.ApplyEffect (cmd) ;

    cmd.m_red.Save (L"red.jpg") ;
    cmd.m_green.Save (L"green.jpg") ;
    cmd.m_blue.Save (L"blue.jpg") ;
}

... Read and Modify EXIF (Win Only)

FCObjImage   img ;
FCImageProperty   prop ;

img.Load (L"d:\\test.jpg", &prop) ;

// modify manufacturer of the equipment
prop.m_EquipMake = "PhoXo" ;

// modify the date of photograph
prop.m_ExifDTOrig = "2011:11:26 09:26:00" ;

std::vector<std::string>   & ls = prop.m_other_gdiplus_prop ;
for (size_t i=0 ; i < ls.size() ; i++)
{
    Gdiplus::PropertyItem   it = FCImageCodec_Gdiplus::ReferencePropertyBuffer (ls[i]) ;

    // modify ISO speed to 400
    if (it.id == PropertyTagExifISOSpeed)
    {
        short   nISO = 400 ;
        ls[i] = FCImageCodec_Gdiplus::CreatePropertyBuffer(it.id, it.type, 2, &nISO) ;
    }
}

// save image file with modified EXIF
img.Save (L"d:\\test.jpg", prop) ;

... Draw Image (Win Only)

FCObjImage   img ;
img.Load (L"c:\\test.png") ;

// for 32bpp image, method Draw use Win32 API AlphaBlend to draw,
// so we need pre-multiply alpha before draw
// for <= 24bpp image, method Draw use Win32 API BitBlt to draw
if (img.ColorBits() == 32)
{
    img.ApplyEffect (FCEffectPremultipleAlpha()) ;
}

// Draw whole image (no stretch) on point(0,0) of hdc
img.Draw (hdc, 0, 0) ;

// Draw whole image on specified region of hdc.
RECT   rcOnDC = {100, 100, 200, 200} ;
img.Draw (hdc, rcOnDC) ;

// Draw region of image on specified region of hdc.
RECT   rcOnImage = {20, 20, 50, 50} ;
img.Draw (hdc, rcOnDC, &rcOnImage) ;

// Draw whole image in window.
SIZE   img_size = {img.Width(), img.Height()} ;
RECT   rcWindow = {0, 0, 500, 500} ;
RECT   rc = FCObjImage::CalcFitWindowSize(img_size, rcWindow) ;
img.Draw (hdc, rc) ;

Although BitBlt is faster than AlphaBlend, it will destroy the alpha channel of destination. Some features such as: layered window, DWM need alpha channel, so these cases we have to convert image to 32bpp, using AlphaBlend to draw.

... Convert between HBITMAP and Gdiplus::Bitmap (Win Only)

FCObjImage   img ;

// FCObjImage can be converted to HBITMAP automatically, and can be selected into HDC
SelectObject (hdc, img) ;

// create image based on HBITMAP
img.FromHBITMAP (hBitmap) ;

// create Gdiplus::Bitmap, caller must delete returned bitmap
Gdiplus::Bitmap   * pBmp = img.CreateBitmap() ;
if (pBmp)
    delete pBmp ;

// create image based on Gdiplus::Bitmap
Gdiplus::Bitmap   gpBmp (L"c:\\test.jpg") ;
img.FromBitmap (gpBmp) ;

... Add Text on Image (Win Only)

void DrawText (HDC dc)
{
    // GDI draw text
    SetTextColor (dc, RGB(0,0,255)) ;
    TextOut (dc, 0, 0, _T("PhoXo"), 5) ;

    // GDI+ draw text
    Gdiplus::Graphics   g(dc) ;
    g.SetSmoothingMode (Gdiplus::SmoothingModeAntiAlias) ;
    g.SetInterpolationMode (Gdiplus::InterpolationModeHighQualityBicubic) ;

    Gdiplus::FontFamily   ffami (L"Arial") ;
    Gdiplus::StringFormat fmt ;

    Gdiplus::GraphicsPath   str_path ;
    str_path.AddString (L"PhoXo", -1, &ffami,
	Gdiplus::FontStyleBold, 48, Gdiplus::Point(20,20), &fmt) ;

    Gdiplus::Pen   gp (Gdiplus::Color(0,0,160), 8) ;
    gp.SetLineJoin (Gdiplus::LineJoinRound) ;

    Gdiplus::Rect    rc (20, 20, 30, 60) ;
    Gdiplus::Color   cStart (255,255,255) ;
    Gdiplus::Color   cEnd (0,128,255) ;
    Gdiplus::LinearGradientBrush  gb (rc, cStart, cEnd,
	Gdiplus::LinearGradientModeVertical) ;

    g.DrawPath (&gp, &str_path) ;
    g.FillPath (&gb, &str_path) ;
}

void Test()
{
    FCObjImage   img ;
    img.Create (300, 200, 24) ;

    // fill back grid
    img.ApplyEffect (FCEffectFillGrid(FCColor(192,192,192), FCColor(255,255,255), 16)) ;

    DrawText (FCImageDrawDC(img)) ;

    img.Save (L"d:\\test.png") ;
}

... Using in DLL (Win Only)

In most cases, there is no difference on using between in DLL and in client:

extern "C" __declspec(dllexport) HBITMAP LoadFileToDDB (LPCWSTR sFilename)
{
    FCObjImage   img ;
    img.Load (sFilename) ;

    HDC      screen_dc = GetDC(NULL) ;
    HBITMAP  hBmp = CreateCompatibleBitmap(screen_dc, img.Width(), img.Height()) ;
    ReleaseDC (NULL, screen_dc) ;

    img.Draw (FCImageDrawDC(hBmp), 0, 0) ;
    return hBmp ;
}

But, if you want to call Load or Save method of FCObjImage in DllMain or constructor of global object in DLL, you need use FCAutoInitGDIPlus to init GDI+ module in your clients before load DLL, and disable auto GDI+ init ofImageStone in DLL.

// call Load in global object.
class CGlobalObj
{
public:
    CGlobalObj()
    {
        FCImageCodec_Gdiplus::AUTO_INIT_GDIPLUS() = FALSE ;

        FCObjImage   img ;
        img.Load (L"c:\\test.jpg") ;
    }
};

CGlobalObj   g_obj ;

// call Load in DllMain.
BOOL APIENTRY DllMain (HMODULE hModule, DWORD, LPVOID)
{
    FCImageCodec_Gdiplus::AUTO_INIT_GDIPLUS() = FALSE ;

    FCObjImage   img ;
    img.Load (L"c:\\test.jpg") ;

    return TRUE ;
}

... Miscellaneous Function (Win Only)

FCObjImage   img ;

// capture current screen
HDC   screen_dc = GetDC(NULL) ;
RECT  rc = {0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)} ;
img.CaptureDC (screen_dc, rc) ;
ReleaseDC (NULL, screen_dc) ;

// copy this image to clipboard
img.CopyToClipboard() ;

// get image in clipboard
img.GetClipboard() ;

// convert image to HRGN
img.ApplyEffect (FCEffectThreshold(128)) ;
::SetWindowRgn (hWnd, img.CreateHRGN(), TRUE) ;

History

  • 2011 - 11 - 27, V7.0
    + Code Refactoring, more features, more efficient, more easier to use
  • 2007 - 03 - 11, V4.0
    + Add FCPixelFillGradientFrame
    + Add FCPixelLensFlare FCPixelTileReflection FCPixelSoftGlow effect
    * Modify example
    * Improve FCObjImage::AlphaBlend
    * Modify FCPixelBlinds
    * Modify brightness/contrast/hue/saturation/emboss
    * Rewrite gauss blur processor
    - Remove FCPixelDeinterlace
    - Remove FCPixelAddRandomNoise
    - Remove FCPixelFill3DSolidFrame
    - Remove FCImageHandleFactory_IJL15 and FCImageHandle_IPicture
  • 2006 - 10 - 25, V3.0
    * Improve FCImageHandle_Gdiplus class to load multi-frame gif/tiff image and load jpeg's EXIF information
    * Improve FCImageHandle_FreeImage class to save gif with transparency color
    * Change FCPixelHueSaturation's hue arithmetic
    * Change FCPixelColorTone's arithmetic, more look like old photo
    * Change inner FCImageHandleBase interface, it's never mind for user
    * Substitute std::fstream by ANSI C file function, because of a bug in VC2005
    + Add FCImageProperty to store image's property, function FCObjImage::Load and FCObjImage::Savesupport it
    + Add example 010: Load jpeg's EXIF information via GDI+
    - Remove FCObjImage::GetNextFrameDelay and FCObjImage::SetNextFrameDelay, you can get them from FCImageProperty
  • 2006 - 09 - 07, V2.0
    + More mature
  • 2006 - 03 - 11, V1.0
    + Initial version

License

This article, along with any associated source code and files, is licensed under The zlib/libpng License

About the Author

crazybit
Team Leader  PhoXo
China China
Member
graduate from University of Science and Technology of China at 2002.


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值