Skip to content

Instantly share code, notes, and snippets.

@ianmustafa
Last active February 23, 2023 06:20
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save ianmustafa/b8ab7dfd490ff2081ac6d29d828727db to your computer and use it in GitHub Desktop.
Save ianmustafa/b8ab7dfd490ff2081ac6d29d828727db to your computer and use it in GitHub Desktop.
Optimalisasi Gambar dalam PHP menggunakan Imagick.

Ini adalah custom function yang saya pakai untuk mengoptimalisasi gambar. Kompatibel dengan PHP versi 5.5 keatas, serta membutuhkan ekstensi Imagick.

Cukup panjang dan sedikit lambat, tapi mampu menyelesaikan beberapa masalah yang kami temui, diantaranya:

  1. Gambar yang kami pakai di situs berorientasi landscape, tapi tidak semua gambar yang masuk dan layak pakai berorientasi landscape, banyak yang berorientasi portrait, dan tidak sedikit yang tidak mungkin di-crop. Akhirnya, saya akali dengan memperkecil gambar ke dalam ukuran kanvas yang telah diatur, dan menambahkan gambar latar berupa gambar asli yang sudah di-blur.
  2. Dengan menggunakan kompresi JPEG sebesar 60% dan menggunakan method Imagick::stripImage(), saya bisa memastikan gambar yang dihasilkan memiliki ukuran sekecil mungkin. Dimana ini baik untuk ukuran total dan kecepatan akses halaman web secara keseluruhan.
  3. Selain proses pembuatan gambar latar blur yang sudah saya jelaskan diatas, yang membuat script ini agak lambat adalah dalam sekali proses, script ini bisa menghasilkan 4 jenis gambar sekaligus dengan berbagai ukuran, mulai dari kecil (200x150px), sedang (400x300px), besar (800x600px) dan ukuran yang disesuaikan untuk dipakai sebagai Open Graph Meta tag og:image untuk Facebook (1200x630px).

Ini bukan snippet yang sempurna, tapi setidaknya it works. Dan secara flow ini masih jadi teknik image optimization favorit saya.

Bagaimana dengan Anda? Tinggalkan komentar di bawah atau kunjungi profil saya. 😊

<?php
/* Maafkan kalo penamaan variabelnya berantakan 😁
Ini juga agak lambat karena kompleksitasnya, terutama
di baris 61-95 (pembuatan gambar latar yang di-blur
untuk mengisi ruang kosong / menghindari crop)
*/
function imageoptim($imagepath, $savename) {
// Set imagepath default
$imagepath = "upload/source/{$savename}";
// Pindahkan gambar hasil Upload
move_uploaded_file($imagepath, $imagepath);
// Konfigurasi target gambar yang ingin dibuat
// Disini saya pakai 4 target:
// kecil, sedang, besar, dan untuk dipakai di OpenGraph Facebook
$imageconfig = array(
'sm' => array(
'x' => 200,
'y' => 150,
'b' => 4
),
'md' => array(
'x' => 400,
'y' => 300,
'b' => 8
),
'lg' => array(
'x' => 800,
'y' => 600,
'b' => 16
),
'fb' => array(
'x' => 1200,
'y' => 630,
'b' => 18
)
);
// Optimalisasi gambar
foreach ($imageconfig as $suffix => $config) {
// Set nama file baru, pakai jenis gambar target sebagai suffix
$ext_pos = strrpos($savename, '.');
$savename_suffix = substr($savename, 0, $ext_pos) . ".{$suffix}" . substr($savename, $ext_pos);
// Hitung aspek rasio gambar
$or = $config['x'] / $config['y'];
// Kita buat objek gambar dasar untuk diolah,
// serta ambil informasi gambarnya
$baseimage = new Imagick($imagepath);
$mime = $baseimage->getImageMimeType();
$w = $baseimage->getImageWidth();
$h = $baseimage->getImageHeight();
$r = $w / $h;
// Clone objek gambar dasar untuk dijadikan gambar utama,
// lalu ubah ukurannya
$mainimage = $baseimage->clone();
$mainimage->scaleImage($config['x'], $config['y'], true);
// Jika rasio gambar tidak sesuai dengan dimensi target,
// kita bisa membuat gambar latar blur untuk mengisi ruang kosong di sekitar gambar
if ($r != $or) {
// Buat kanvas baru
$compimage = new Imagick();
$compimage->newImage($config['x'], $config['y'], new ImagickPixel('#fff'));
$compimage->setImageFormat($baseimage->getImageFormat());
// Ambil dimensi baru dari gambar utama yang telah diubah ukurannya
$nw = $mainimage->getImageWidth();
$nh = $mainimage->getImageHeight();
// Set ukuran gambar latar
$bgw = $r < $or ? $config['x'] : ceil($config['y'] * $r);
$bgh = $r < $or ? ceil($config['x'] * $h / $w) : $config['y'];
// Set posisi gambar utama di kanvas
$icx = $r < $or ? ceil(($config['x'] - $nw) / 2) : 0;
$icy = $r < $or ? 0 : ceil(($config['y'] - $nh) / 2);
// Set posisi gambar latar di kanvas
$bgcx = $r < $or ? 0 : ceil(($config['x'] - $bgw) / 2);
$bgcy = $r < $or ? ceil(($config['y'] - $bgh) / 2) : 0;
// Lalu clone gambar dasar untuk dijadikan gambar latar,
// ubah ukurannya, lalu blur dan set opacity-nya
$bgimage = $baseimage->clone();
$bgimage->scaleImage($bgw, $bgh, true);
$bgimage->gaussianBlurImage($config['b'], $config['b']);
$bgimage->setImageOpacity(0.5);
// Gabungkan semua gambar menjadi satu
$compimage->compositeImage($bgimage, Imagick::COMPOSITE_DEFAULT, $bgcx, $bgcy);
$compimage->compositeImage($mainimage, Imagick::COMPOSITE_DEFAULT, $icx, $icy);
// Lalu cloen gambar hasil gabungan untuk dijadikan output
$output = $compimage->clone();
$compimage->destroy();
}
// Atau, jika dimensinya sesuai, langsung pakai gambar utama
else {
// Lalu cloen gambar utama untuk dijadikan output
$output = $mainimage->clone();
$mainimage->destroy();
}
// Atur format gambar, kualitas kompresi dan opsi interlace
$output->setImageFormat('jpg');
$output->setImageCompression(Imagick::COMPRESSION_JPEG);
$output->setImageCompressionQuality(60);
$output->setImageUnits(Imagick::RESOLUTION_PIXELSPERINCH);
$output->setImageResolution(72, 72);
$output->setInterlaceScheme(Imagick::INTERLACE_PLANE);
$output->stripImage();
// Simpan gambar, namun jika gagal langsung return false
if (!$output->writeImage(BASEPATH . "upload/optimized/{$savename_suffix}")) return false;
// Destroy :)
$baseimage->destroy();
$output->destroy();
}
// Selesai
return true;
}
@ferdays
Copy link

ferdays commented Apr 11, 2017

mantap om

@rffatih
Copy link

rffatih commented Dec 26, 2019

mantap om v.2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment