Własne filtry obrazu (sepia, greyscale) w WP_Image_Editor

Standardowo implementacja klasy WP_Image_Editor nie udostępnia nam żadnych filtrów dla obrazów takich jak sepia czy skala odcieni szarości (greyscale). Na szczęście klasa ta została zaimplementowana w bardzo elastyczny sposób, przez co umożliwia dodanie własnych metod. Pokażę więc w jaki sposób można stworzyć własne filtry obrazu.

Idea stojąca za WP_Image_Editor

Klasa WP_Image_Editor jest klasą abstrakcyjną – czyli najprościej mówiąc służy za wzór dla innych, bardziej szczegółowych implementacji operacji na obrazie z wykorzystaniem różnych bibliotek graficznych. Stąd też w WordPressie znajdziemy takie klasy jak WP_Image_Editor_Imagick czy WP_Image_Editor_GD. Obie wspomniane klasy odpowiadają za implementację operacji na obrazie z użyciem dwóch popularnych bibliotek graficznych: ImageMagick i GD. Trzeba o tym pamiętać gdyż fakt ten ma bardzo ważną implikację – implementując jakiś efekt powinniśmy zadbać o jego wsparcie w obu wypadkach (no chyba, że robimy projekt na własne potrzeby i pod konkretną konfigurację serwera).

Implementacja nowych metod operujących na obrazie

Jak można dodać własne metody operujące na obrazie? Trzeba stworzyć klasy potomne dla klas WP_Image_Editor_Imagick i WP_Image_Editor_GD. Poniżej znajduje się moja implementacja metod dziudek_greyscale i dziudek_sepia:

class Dziudek_Imagick_Filters_Editor extends WP_Image_Editor_Imagick {
  public function dziudek_sepia($arg = 100) {
    $this->image->sepiaToneImage($arg);
    return true;
  }
  public function dziudek_greyscale() {
    $this->image->modulateImage(100,0,100);
    return true;
  }
}
class Dziudek_GD_Filters_Editor extends WP_Image_Editor_GD {
  public function dziudek_sepia() {
    imagefilter($this->image, IMG_FILTER_GRAYSCALE);
    imagefilter($this->image, IMG_FILTER_COLORIZE, 90, 60, 40);
    return true;
  }

  public function dziudek_greyscale() {
    imagefilter($this->image, IMG_FILTER_GRAYSCALE);
    return true;
  }
}

Jak widać stworzyliśmy dwie klasy potomne. Teoretycznie mógłbym metody nazwać sepia i greyscale ale niedługo wyjaśni się czemu lepiej zastosować prefiks.

Najprawdopodobniej będziemy musieli też dołączyć wszystkie potrzebne klasy do naszego pliku z nowymi klasami potomnymi:

require_once(ABSPATH . WPINC . '/class-wp-image-editor.php');
require_once(ABSPATH . WPINC . '/class-wp-image-editor-imagick.php');
require_once(ABSPATH . WPINC . '/class-wp-image-editor-gd.php');

Mamy już prawie wszystko czego nam potrzeba – pora sprawić, żeby nasz kod był dostępny w WordPressie w metodzie wp_get_image_editor – w tym celu wykorzystamy filtr wp_image_editors:

function dziudek_add_image_filters_editors( $editors ) {
  array_unshift( $editors, 'Dziudek_Imagick_Filters_Editor' );
  array_unshift( $editors, 'Dziudek_GD_Filters_Editor' );

  return $editors;
}

add_filter( 'wp_image_editors', 'dziudek_add_image_filters_editors' );

Powyższa funkcja spowoduje dodanie naszych klas potomnych do listy dostępnych edytorów obrazu.

Pora użyć naszego kodu

Wyprodukowaliśmy już sporo kodu, zatem pora z niego zrobić użytek 🙂

Aby wykorzystać nasze własne klasy, musimy skorzystać z drugiego parametru metody wp_get_image_editor:

$img_editor = wp_get_image_editor( 
    $path_to_file, 
    array( 'methods' => array( 'dziudek_sepia', 'dziudek_greyscale' ) ) 
);

Pierwszy argument to oczywiscie ścieżka do pliku na którym będziemy działać, natomiast ten drugi argument pozwala nam określić jakich dodatkowych metod oczekujemy po edytorze obrazu. Słowo klucz to „oczekujemy” – może się okazać, że żaden z dostępnych edytorów obrazu nie oferuje pożądanej przez nas funkcjonalności – wtedy zmienna $img_editor będzie zawierać obiekt klasy WP_Error z informacją „No image editor”. W naszym wypadku jednak wszystko powinno zadziałać i WordPress powinien zwrócić instancję klasy Dziudek_GK_Filters_Editor lub Dziudek_Imagick_Filters_Editor zależnie od tego, która z tych bibliotek zainstalowana jest u nas na serwerze.

Dzięki temu będziemy mogli wykonać następujący kod:

$img_editor->dziudek_greyscale();

lub:

$img_editor->dziudek_sepia();

Wracając do prefiksów w nazwach tych metod. Teoretycznie dla skrócenia kodu można by je pominąć, ale pamiętajmy – autor jakiejś wtyczki może dodać własne funkcjonalności różniące się efektami od naszych i wtedy pojawi się problem, gdyż taka implementacja może zostać wczytana zamiast naszej jako edytor obrazu ze względu na spełnienie naszych potrzeb odnośnie funkcjonalności (polecam w tym miejscu analizę metody _wp_image_editor_choose). Zatem osobiście polecam jednak używać prefiksów w nazwach metod lub używanie bardziej wyszukanych nazw metod 🙂

Podsumowanie

Jak widać implementacja klasy WP_Image_Editor jest bardzo elastyczna i pozwala na łatwe dodawanie funkcjonalności. Z mojego punktu widzenia najwygodniejsze jest to, że nie muszę się martwić o wykrywanie poszczególnych bibliotek graficznych – kod WordPressa robi to za mnie. Polecam własne eksperymenty z filtrami obrazu 🙂