MagickWand API 是 C 語言和 ImageMagick 影像處理函式庫之間建議使用的介面。與 MagickCore C API 不同,MagickWand 只使用少數的不透明類型。可以使用存取器來設定或取得重要的魔杖屬性。可以在這裡找到 MagickWand 公開方法的說明:
- Magick Wand 方法
- 設定或取得 Magick Wand 屬性
- Magick Wand 影像方法
- 像素迭代器方法
- 像素 Wand 方法
- 影像向量繪圖
- 命令列介面
- Wand 視圖方法
- 已棄用方法
- 錯誤和警告代碼
撰寫完 MagickWand 程式後,請像這樣編譯它:
cc `MagickWand-config --cflags --cppflags` -O2 -o wand wand.c `MagickWand-config --ldflags --libs`
如果 ImageMagick 不在您的預設系統路徑中,請設定 PKG_CONFIG_PATH 環境變數
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
以下是一個範例程式,它使用 MagickWand API 來幫助您入門,wand.c。它會讀取影像、建立縮圖,並將結果寫入磁碟。
#include <stdio.h> #include <stdlib.h> #include <MagickWand/MagickWand.h> int main(int argc,char **argv) { #define ThrowWandException(wand) \ { \ char \ *description; \ \ ExceptionType \ severity; \ \ description=MagickGetException(wand,&severity); \ (void) fprintf(stderr,"%s %s %lu %s\n",GetMagickModule(),description); \ description=(char *) MagickRelinquishMemory(description); \ exit(-1); \ } MagickBooleanType status; MagickWand *magick_wand; if (argc != 3) { (void) fprintf(stdout,"Usage: %s image thumbnail\n",argv[0]); exit(0); } /* Read an image. */ MagickWandGenesis(); magick_wand=NewMagickWand(); status=MagickReadImage(magick_wand,argv[1]); if (status == MagickFalse) ThrowWandException(magick_wand); /* Turn the images into a thumbnail sequence. */ MagickResetIterator(magick_wand); while (MagickNextImage(magick_wand) != MagickFalse) MagickResizeImage(magick_wand,106,80,LanczosFilter,1.0); /* Write the image then destroy it. */ status=MagickWriteImages(magick_wand,argv[2],MagickTrue); if (status == MagickFalse) ThrowWandException(magick_wand); magick_wand=DestroyMagickWand(magick_wand); MagickWandTerminus(); return(0); }
以下是另一個程式,它展示了使用 MagickWand API 取得和設定影像像素的一種方法,contrast.c。它會讀取影像、套用 sigmoid 非線性對比度控制,並將結果寫入磁碟。
#include <stdio.h> #include <stdlib.h> #include <math.h> #include <MagickWand/MagickWand.h> int main(int argc,char **argv) { #define SigmoidalContrast(x) \ (QuantumRange*(1.0/(1+exp(10.0*(0.5-QuantumScale*x)))-0.0066928509)*1.0092503) #define ThrowWandException(wand) \ { \ char \ *description; \ \ ExceptionType \ severity; \ \ description=MagickGetException(wand,&severity); \ (void) fprintf(stderr,"%s %s %lu %s\n",GetMagickModule(),description); \ description=(char *) MagickRelinquishMemory(description); \ exit(-1); \ } long y; MagickBooleanType status; MagickWand *contrast_wand, *image_wand; PixelInfo pixel; PixelIterator *contrast_iterator, *iterator; PixelWand **contrast_pixels, **pixels; register long x; unsigned long width; if (argc != 3) { (void) fprintf(stdout,"Usage: %s image sigmoidal-image\n",argv[0]); exit(0); } /* Read an image. */ MagickWandGenesis(); image_wand=NewMagickWand(); status=MagickReadImage(image_wand,argv[1]); if (status == MagickFalse) ThrowWandException(image_wand); contrast_wand=CloneMagickWand(image_wand); /* Sigmoidal non-linearity contrast control. */ iterator=NewPixelIterator(image_wand); contrast_iterator=NewPixelIterator(contrast_wand); if ((iterator == (PixelIterator *) NULL) || (contrast_iterator == (PixelIterator *) NULL)) ThrowWandException(image_wand); for (y=0; y < (long) MagickGetImageHeight(image_wand); y++) { pixels=PixelGetNextIteratorRow(iterator,&width); contrast_pixels=PixelGetNextIteratorRow(contrast_iterator,&width); if ((pixels == (PixelWand **) NULL) || (contrast_pixels == (PixelWand **) NULL)) break; for (x=0; x < (long) width; x++) { PixelGetMagickColor(pixels[x],&pixel); pixel.red=SigmoidalContrast(pixel.red); pixel.green=SigmoidalContrast(pixel.green); pixel.blue=SigmoidalContrast(pixel.blue); pixel.index=SigmoidalContrast(pixel.index); PixelSetPixelColor(contrast_pixels[x],&pixel); } (void) PixelSyncIterator(contrast_iterator); } if (y < (long) MagickGetImageHeight(image_wand)) ThrowWandException(image_wand); contrast_iterator=DestroyPixelIterator(contrast_iterator); iterator=DestroyPixelIterator(iterator); image_wand=DestroyMagickWand(image_wand); /* Write the image then destroy it. */ status=MagickWriteImages(contrast_wand,argv[2],MagickTrue); if (status == MagickFalse) ThrowWandException(image_wand); contrast_wand=DestroyMagickWand(contrast_wand); MagickWandTerminus(); return(0); }
現在,讓我們利用雙核心或四核心處理系統,透過 wand 視圖並行執行演算法,來執行相同的對比度增強。 sigmoidal-contrast.c 模組會讀取影像、套用 sigmoid 非線性對比度控制,並將結果寫入磁碟,就像先前的對比度增強程式一樣,但現在它會並行執行(假設 ImageMagick 是使用 OpenMP 支援建置的)。
#include <stdio.h> #include <stdio.h> #include <stdlib.h> #include <math.h> #include <MagickWand/MagickWand.h> static MagickBooleanType SigmoidalContrast(WandView *contrast_view, const ssize_t y,const int thread_id,void *context) { #define SigmoidalContrast(x) \ (QuantumRange*(1.0/(1+exp(10.0*(0.5-QuantumScale*x)))-0.0066928509)*1.0092503) PixelInfo pixel; PixelWand **pixels; RectangleInfo extent; register ssize_t x; extent=GetWandViewExtent(contrast_view); pixels=GetWandViewPixels(contrast_view); for (x=0; x < (ssize_t) extent.width; x++) { PixelGetMagickColor(pixels[x],&pixel); pixel.red=SigmoidalContrast(pixel.red); pixel.green=SigmoidalContrast(pixel.green); pixel.blue=SigmoidalContrast(pixel.blue); pixel.index=SigmoidalContrast(pixel.index); PixelSetPixelColor(pixels[x],&pixel); } return(MagickTrue); } int main(int argc,char **argv) { #define ThrowWandException(wand) \ { \ char \ *description; \ \ ExceptionType \ severity; \ \ description=MagickGetException(wand,&severity); \ (void) fprintf(stderr,"%s %s %lu %s\n",GetMagickModule(),description); \ description=(char *) MagickRelinquishMemory(description); \ exit(-1); \ } MagickBooleanType status; MagickWand *contrast_wand; PixelInfo pixel; WandView *contrast_view; if (argc != 3) { (void) fprintf(stdout,"Usage: %s image sigmoidal-image\n",argv[0]); exit(0); } /* Read an image. */ MagickWandGenesis(); contrast_wand=NewMagickWand(); status=MagickReadImage(contrast_wand,argv[1]); if (status == MagickFalse) ThrowWandException(contrast_wand); /* Sigmoidal non-linearity contrast control. */ contrast_view=NewWandView(contrast_wand); if (contrast_view == (WandView *) NULL) ThrowWandException(contrast_wand); status=UpdateWandViewIterator(contrast_view,SigmoidalContrast,(void *) NULL); if (status == MagickFalse) ThrowWandException(contrast_wand); contrast_view=DestroyWandView(contrast_view); /* Write the image then destroy it. */ status=MagickWriteImages(contrast_wand,argv[2],MagickTrue); if (status == MagickFalse) ThrowWandException(contrast_wand); contrast_wand=DestroyMagickWand(contrast_wand); MagickWandTerminus(); return(0); }
MagickWandTerminus() 是 ImageMagick 函式庫中的一個函數,用於在關閉使用 ImageMagick 的應用程式時清理和釋放資源。這個函數應該在應用程式程序關閉過程中,在主執行緒中呼叫。重要的是,這個函數必須在任何使用 ImageMagick 函數的執行緒都已終止後才能呼叫。
ImageMagick 可能透過 OpenMP(一種並行程式設計方法)在內部使用執行緒。因此,在呼叫 MagickWandTerminus() 之前,確保任何對 ImageMagick 的函數呼叫都已完成非常重要。這可以防止 OpenMP 工作執行緒存取被這個終止函數銷毀的資源的問題。
如果正在使用 OpenMP(從 5.0 版開始),OpenMP 實現本身會使用自己的方法來處理啟動和停止工作執行緒,以及分配和釋放資源。這表示在呼叫 MagickWandTerminus() 之後,某些 OpenMP 資源和工作執行緒可能仍然處於分配狀態。為了解決這個問題,可以呼叫 omp_pause_resource_all(omp_pause_hard) 函數。這個函數是在 OpenMP 5.0 版中引入的,可以確保釋放 OpenMP 分配的任何資源(例如執行緒和執行緒專用記憶體)。建議在 MagickWandTerminus() 完成執行後呼叫這個函數。
C 語言的 MagickWand 範例 說明了如何使用 ImageMagick MagickWand API。每個範例都以 C 函數的形式呈現,並包含標頭檔,因此可以將其複製到檔案中,然後包含在您自己的 C 專案中。