⚠️ Ini adalah situs terjemahan tidak resmi dan tidak berafiliasi dengan ImageMagick Studio LLC. Untuk informasi resmi, lihat halaman asli (https://imagemagick.org/magick-core/).

MagickCore API adalah antarmuka tingkat rendah antara bahasa pemrograman C dan pustaka pemrosesan gambar ImageMagick, serta hanya direkomendasikan untuk programmer tingkat pakar (wizard-level). Berbeda dengan API C MagickWand yang hanya menggunakan sedikit tipe opak dan accessor, dengan MagickCore Anda hampir selalu mengakses anggota struktur secara langsung. Deskripsi metode publik MagickCore dapat ditemukan di GitHub:

Setelah Anda menulis program MagickCore, kompilasi seperti berikut ini:

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

Atur variabel lingkungan PKG_CONFIG_PATH jika ImageMagick tidak berada di path default sistem Anda:

export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig

Berikut adalah contoh program yang menggunakan MagickCore API untuk membantu Anda memulai, core.c. Program ini membaca gambar GIF, membuat thumbnail, dan menulisnya ke disk dalam format gambar 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);
}

Sekarang mari kita melakukan peningkatan kontras yang sama sambil memanfaatkan sistem pemrosesan dual-core atau quad-core kita, dengan menjalankan algoritmenya secara paralel menggunakan wand view. Modul sigmoidal-contrast.c membaca gambar, menerapkan kontrol kontras non-linearitas sigmoidal, dan menulis hasilnya ke disk seperti program peningkatan kontras sebelumnya, tetapi kali ini prosesnya dilakukan secara paralel (dengan asumsi ImageMagick dibangun dengan dukungan 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() adalah fungsi dalam pustaka ImageMagick yang digunakan untuk membersihkan dan melepaskan sumber daya saat aplikasi yang menggunakan ImageMagick dimatikan (shutdown). Fungsi ini harus dipanggil pada thread utama proses aplikasi selama proses shutdown berlangsung. Sangat penting agar fungsi ini hanya dipanggil setelah semua thread yang menggunakan fungsi-fungsi ImageMagick selesai berjalan.

ImageMagick mungkin menggunakan thread secara internal melalui OpenMP (metode pemrograman paralel). Karena itu, penting untuk memastikan bahwa semua pemanggilan fungsi ke ImageMagick telah selesai sebelum memanggil MagickCoreTerminus(). Hal ini mencegah masalah pada worker thread OpenMP yang mengakses sumber daya yang telah dihancurkan oleh fungsi terminasi ini.

Jika OpenMP digunakan (mulai dari versi 5.0), implementasi OpenMP itu sendiri yang menangani proses memulai dan menghentikan worker thread serta mengalokasikan dan membebaskan sumber daya menggunakan metodenya sendiri. Ini berarti bahwa setelah memanggil MagickCoreTerminus(), sebagian sumber daya dan worker thread OpenMP mungkin masih tetap teralokasi. Untuk mengatasi hal ini, fungsi omp_pause_resource_all(omp_pause_hard) dapat dipanggil. Fungsi ini, yang diperkenalkan pada OpenMP versi 5.0, memastikan bahwa semua sumber daya yang dialokasikan oleh OpenMP (seperti thread dan memori khusus thread) dibebaskan. Disarankan untuk memanggil fungsi ini setelah MagickCoreTerminus() selesai dijalankan.