Color Modes

MagickCore,低階 C 語言 API

MagickCore API 是 C 程式語言與 ImageMagick 影像處理函式庫之間的低階介面,僅建議進階程式設計師使用。與僅使用少數不透明類型和存取器的 MagickWand C 語言 API 不同,使用 MagickCore 時,您幾乎都是直接存取結構成員。MagickCore 公開方法的說明可在此處找到

撰寫 MagickCore 程式後,請像這樣編譯

cc `MagickCore-config --cflags --cppflags` -O2 -o core core.c `MagickCore-config --ldflags --libs`

如果 ImageMagick 不在您的預設系統路徑中,請設定 PKG_CONFIG_PATH 環境變數

export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig 

以下是一個範例程式,它使用 MagickCore API 來幫助您入門,core.c。它會讀取 GIF 影像,建立縮圖,並以 PNG 影像格式將其寫入磁碟。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <MagickCore/MagickCore.h>

int main(int argc,char **argv)
{
  ExceptionInfo
    *exception;

  Image
    *image,
    *images,
    *resize_image,
    *thumbnails;

  ImageInfo
    *image_info;

  if (argc != 3)
    {
      (void) fprintf(stdout,"Usage: %s image thumbnail\n",argv[0]);
      exit(0);
    }
  /*
    Initialize the image info structure and read an image.
  */
  MagickCoreGenesis(*argv,MagickTrue);
  exception=AcquireExceptionInfo();
  image_info=CloneImageInfo((ImageInfo *) NULL);
  (void) strcpy(image_info->filename,argv[1]);
  images=ReadImage(image_info,exception);
  if (exception->severity != UndefinedException)
    CatchException(exception);
  if (images == (Image *) NULL)
    exit(1);
  /*
    Convert the image to a thumbnail.
  */
  thumbnails=NewImageList();
  while ((image=RemoveFirstImageFromList(&images)) != (Image *) NULL)
  {
    resize_image=ResizeImage(image,106,80,LanczosFilter,exception);
    if (resize_image == (Image *) NULL)
      MagickError(exception->severity,exception->reason,exception->description);
    (void) AppendImageToList(&thumbnails,resize_image);
    DestroyImage(image);
  }
  /*
    Write the image thumbnail.
  */
  (void) strcpy(thumbnails->filename,argv[2]);
  WriteImage(image_info,thumbnails,exception);
  /*
    Destroy the image thumbnail and exit.
  */
  thumbnails=DestroyImageList(thumbnails);
  image_info=DestroyImageInfo(image_info);
  exception=DestroyExceptionInfo(exception);
  MagickCoreTerminus();
  return(0);
}

現在,讓我們利用雙核心或四核心處理系統的優勢,透過在 wand 檢視中平行執行演算法來執行相同的對比度增強。 sigmoidal-contrast.c 模組會讀取影像,套用 S 型非線性對比度控制,並將結果寫入磁碟,就像先前的對比度增強程式一樣,但現在它會平行執行(假設 ImageMagick 是使用 OpenMP 支援建置的)。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <MagickCore/MagickCore.h>

static MagickBooleanType SigmoidalContrast(ImageView *contrast_view,
  const ssize_t y,const int id,void *context)
{
#define QuantumScale  ((MagickRealType) 1.0/(MagickRealType) QuantumRange)
#define SigmoidalContrast(x) \
  (QuantumRange*(1.0/(1+exp(10.0*(0.5-QuantumScale*x)))-0.0066928509)*1.0092503)

  RectangleInfo
    extent;

  register IndexPacket
    *indexes;

  register PixelPacket
    *pixels;

  register ssize_t
    x;

  extent=GetImageViewExtent(contrast_view);
  pixels=GetImageViewAuthenticPixels(contrast_view);
  for (x=0; x < (ssize_t) (extent.width-extent.x); x++)
  {
    SetPixelRed(pixels,RoundToQuantum(SigmoidalContrast(GetPixelRed(pixels)));
    SetPixelGreen(pixels,RoundToQuantum(SigmoidalContrast(GetPixelGreen(pixels)));
    SetPixelBlue(pixels,RoundToQuantum(SigmoidalContrast(GetPixelBlue(pixels)));
    SetPixelOpacity(pixels,RoundToQuantum(SigmoidalContrast(GetPixelOpacity(pixels)));
    pixels++;
  }
  indexes=GetImageViewAuthenticIndexes(contrast_view);
  if (indexes != (IndexPacket *) NULL)
    for (x=0; x < (ssize_t) (extent.width-extent.x); x++)
      SetPixelIndex(indexes+x,RoundToQuantum(SigmoidalContrast(GetPixelIndex(indexes+x))));
  return(MagickTrue);
}

int main(int argc,char **argv)
{
#define ThrowImageException(image) \
{ \
 \
  CatchException(exception); \
  if (contrast_image != (Image *) NULL) \
    contrast_image=DestroyImage(contrast_image); \
  exit(-1); \
}
#define ThrowViewException(view) \
{ \
  char \
    *description; \
 \
  ExceptionType \
    severity; \
 \
  description=GetImageViewException(view,&severity); \
  (void) fprintf(stderr,"%s %s %lu %s\n",GetMagickModule(),description); \
  description=DestroyString(description); \
  exit(-1); \
}

  ExceptionInfo
    *exception;

  Image
    *contrast_image;

  ImageInfo
    *image_info;

  ImageView
    *contrast_view;

  MagickBooleanType
    status;

  if (argc != 3)
    {
      (void) fprintf(stdout,"Usage: %s image sigmoidal-image\n",argv[0]);
      exit(0);
    }
  /*
    Read an image.
  */
  MagickCoreGenesis(*argv,MagickTrue);
  image_info=AcquireImageInfo();
  (void) CopyMagickString(image_info->filename,argv[1],MaxTextExtent);
  exception=AcquireExceptionInfo();
  contrast_image=ReadImage(image_info,exception);
  if (contrast_image == (Image *) NULL)
    ThrowImageException(contrast_image);
  /*
    Sigmoidal non-linearity contrast control.
  */
  contrast_view=NewImageView(contrast_image);
  if (contrast_view == (ImageView *) NULL)
    ThrowImageException(contrast_image);
  status=UpdateImageViewIterator(contrast_view,SigmoidalContrast,(void *) NULL);
  if (status == MagickFalse)
    ThrowImageException(contrast_image);
  contrast_view=DestroyImageView(contrast_view);
  /*
    Write the image then destroy it.
  */
  status=WriteImages(image_info,contrast_image,argv[2],exception);
  if (status == MagickFalse)
    ThrowImageException(contrast_image);
  contrast_image=DestroyImage(contrast_image);
  exception=DestroyExceptionInfo(exception);
  image_info=DestroyImageInfo(image_info);
  MagickCoreTerminus();
  return(0);
}

MagickCoreTerminus() 是 ImageMagick 函式庫中的一個函數,用於在關閉使用 ImageMagick 的應用程式時清理和釋放資源。這個函數應該在應用程式進程的主要執行緒中,於關閉過程中被呼叫。重要的是,這個函數必須在所有使用 ImageMagick 函數的執行緒都終止後才能被呼叫。

ImageMagick 可能透過 OpenMP(一種平行程式設計方法)在內部使用執行緒。因此,在呼叫 MagickCoreTerminus() 之前,確保所有對 ImageMagick 的函數呼叫都已完成非常重要。這可以防止 OpenMP 工作執行緒存取被這個終止函數銷毀的資源所產生的問題。

如果使用 OpenMP(從 5.0 版開始),OpenMP 實作本身會使用自己的方法處理啟動和停止工作執行緒,以及配置和釋放資源。這表示在呼叫 MagickCoreTerminus() 之後,某些 OpenMP 資源和工作執行緒可能仍會維持配置狀態。為了處理這個問題,可以呼叫 omp_pause_resource_all(omp_pause_hard) 函數。此函數在 OpenMP 5.0 版中引入,可確保釋放 OpenMP 配置的任何資源(例如執行緒和執行緒專用記憶體)。建議在 MagickCoreTerminus() 完成執行後呼叫此函數。