Gereksinimler ve Ön Hazırlık
Projeye başlamadan önce sisteminizde Node.js'in güncel bir LTS (Long Term Support) sürümünün yüklü olduğundan emin olmalısınız. Sharp kütüphanesi, C++ tabanlı libvips kütüphanesini kullandığı için kurulum sırasında sisteminizde gerekli derleme araçlarının bulunması önemlidir.
Proje dizininizi oluşturun ve gerekli paketleri yüklemek için aşağıdaki komutları terminalinizde çalıştırın:
mkdir watermark-app
cd watermark-app
npm init -y
npm install sharp
Bu adımlar, projenizi başlatacak ve görsel işleme motoru olan Sharp'ı bağımlılıklarınıza ekleyecektir. Sharp, diğer görsel işleme kütüphanelerine (Jimp veya GraphicsMagick gibi) kıyasla çok daha hızlıdır çünkü libvips kütüphanesini kullanarak görselleri parçalı (stream) olarak işler.
Adım 1: Temel Görsel İşleme Yapısını Kurma
İlk aşamada, bir ana görseli (background) ve filigran görselini (overlay) yükleyip bunları birleştiren temel fonksiyonu yazacağız. Sharp kütüphanesinde composite metodu, ana görselin üzerine başka bir görsel katmanı eklemek için kullanılır.
const sharp = require('sharp');
async function addWatermark(inputPath, outputPath, watermarkPath) {
try {
await sharp(inputPath)
.composite([{ input: watermarkPath, gravity: 'southeast' }])
.toFile(outputPath);
console.log('Filigran başarıyla eklendi!');
} catch (error) {
console.error('Hata oluştu:', error);
}
}
Burada gravity: 'southeast' parametresi, filigranın görselin sağ alt köşesine yerleştirilmesini sağlar. Sharp, otomatik olarak görsel boyutlarını hesaplar ve yerleşimi optimize eder.
Adım 2: Filigranı Özelleştirme ve Konumlandırma
Sadece sağ alt köşe her zaman yeterli olmayabilir. Bazen filigranın opaklığını (şeffaflık) ayarlamak veya belirli bir koordinata yerleştirmek isteyebilirsiniz. Sharp, composite dizisi içinde her katman için ayrı ayarlar sunar.
const addCustomWatermark = async (input, output, watermark) => {
await sharp(input)
.composite([{
input: watermark,
gravity: 'center',
blend: 'over'
}])
.toFile(output);
};
blend: 'over' parametresi, filigranın ana görselin üzerinde görünmesini sağlar. Eğer filigranınızın şeffaflığını değiştirmek isterseniz, filigran görselini önceden sharp(watermark).ensureAlpha(0.5) gibi bir işlemden geçirerek şeffaflaştırabilirsiniz.
Adım 3: Görsel Boyutlandırma ve Otomatik Ölçeklendirme
Gerçek dünya senaryolarında, filigran görseli ana görselden büyük olabilir. Bu durumda filigranı ana görselin boyutuna göre dinamik olarak ölçeklendirmek gerekir. Aşağıdaki örnekte, filigranı ana görselin %20'si kadar olacak şekilde ayarlıyoruz.
const addScaledWatermark = async (input, output, watermark) => {
const metadata = await sharp(input).metadata();
await sharp(input)
.composite([{
input: watermark,
gravity: 'southeast',
// Ana görselin %20'si genişliğinde ayarla
width: Math.round(metadata.width * 0.2)
}])
.toFile(output);
};
Bu yaklaşım, farklı boyutlardaki görsellerin hepsine tutarlı bir filigran yerleştirmenize olanak tanır. metadata() fonksiyonu, görselin genişlik ve yükseklik bilgilerini almamızı sağlar.
Adım 4: Performans ve Bellek Yönetimi
Sharp, büyük dosyaları işlerken oldukça verimlidir ancak binlerce görseli aynı anda işlemek sunucu belleğini zorlayabilir. Bu nedenle, işlemleri bir kuyruk (queue) yapısı ile yönetmek veya akış (stream) kullanmak en iyi pratiktir.
const fs = require('fs');
const processStream = (inputPath, outputPath, watermarkPath) => {
const readStream = fs.createReadStream(inputPath);
const writeStream = fs.createWriteStream(outputPath);
readStream
.pipe(sharp().composite([{ input: watermarkPath, gravity: 'southeast' }]))
.pipe(writeStream);
};
Stream yapısı, dosyanın tamamını belleğe yüklemeden parça parça işlenmesini sağlar. Bu, özellikle yüksek trafikli uygulamalarda sunucu çökmesini engelleyen kritik bir yöntemdir.
Görsel İşleme Yöntemlerinin Karşılaştırması
| Yöntem | Avantaj | Dezavantaj |
|---|---|---|
| Sharp (Buffer) | Çok hızlı, basit | Bellek yoğun olabilir |
| Sharp (Stream) | Düşük bellek kullanımı | Karmaşık hata yönetimi |
| Jimp | Saf JS, kurulumu kolay | Çok yavaş |
Güvenlik Uyarısı: Kullanıcıların yüklediği görselleri işlerken mutlaka dosya türü kontrolü (MIME type) yapın. Sadece izin verilen formatları (JPEG, PNG, WebP) işleyin ve dosya ismini sunucuda rastgele bir isimle kaydederek "Path Traversal" saldırılarını önleyin.
Sıkça Sorulan Sorular
Sharp kütüphanesi SVG filigranları destekler mi?
Evet, Sharp hem PNG hem de SVG formatındaki filigranları destekler. SVG kullanmak, farklı çözünürlüklerdeki ekranlarda filigranın daha keskin görünmesini sağlar.
Filigranın opaklığını kod ile değiştirebilir miyim?
Evet, filigran görselini sharp().ensureAlpha(0.5) komutuyla işleyerek opaklığını %50 seviyesine getirebilir ve ardından ana görsele ekleyebilirsiniz.
Neden Jimp yerine Sharp tercih etmeliyim?
Sharp, libvips kütüphanesi sayesinde Jimp'e göre 5 ila 10 kat daha hızlıdır ve çok daha az CPU kullanır. Modern Node.js projelerinde performans için Sharp standarttır.
Filigranı görselin tam ortasına nasıl koyarım?
Sharp'ın gravity seçeneğine 'center' değerini atayarak filigranı görselin tam merkezine konumlandırabilirsiniz.
Büyük ölçekli uygulamalarda bu işlemi nerede yapmalıyım?
Kullanıcı deneyimini bozmamak için bu işlemleri ana iş parçacığında değil, bir "Worker Thread" veya arka plan kuyruk sistemi (BullMQ gibi) üzerinde yapmanız önerilir.
Sorumluluk Reddi: Bu rehberdeki kod örnekleri eğitim amaçlıdır. Üretim ortamına geçmeden önce tüm dosya giriş/çıkış işlemlerini güvenlik testlerinden geçirdiğinizden ve hata yakalama (try-catch) mekanizmalarını eksiksiz kurduğunuzdan emin olun.
Express.js Middleware ile Otomatik İşleme Hattı Oluşturma
Görsel işleme süreçlerini bir API uç noktasına entegre etmek, kullanıcı deneyimini iyileştirmenin en etkili yoludur. Aşağıdaki örnek, multer ile gelen dosyayı bellekte işleyip, diske yazmadan önce Sharp ile filigran ekleyen bir ara katman yapısını göstermektedir.
const express = require('express');
const multer = require('multer');
const sharp = require('sharp');
const app = express();
const upload = multer({ storage: multer.memoryStorage() });
app.post('/upload', upload.single('image'), async (req, res) => {
try {
const processedImage = await sharp(req.file.buffer)
.composite([{ input: 'watermark.png', gravity: 'southeast' }])
.jpeg({ quality: 80 })
.toBuffer();
// İşlenmiş görseli S3'e yükleyebilir veya diske kaydedebilirsiniz
res.set('Content-Type', 'image/jpeg');
res.send(processedImage);
} catch (error) {
res.status(500).send('Görsel işleme hatası: ' + error.message);
}
});
Üretim Ortamında Hata Ayıklama ve İzleme
Görsel işleme süreçleri, özellikle yüksek trafikli uygulamalarda beklenmedik bellek (memory) sızıntılarına veya CPU darboğazlarına neden olabilir. Sharp, libvips kütüphanesini kullandığı için hata ayıklama süreçlerinde standart Node.js hata ayıklayıcılarından daha derinlemesine bilgiye ihtiyaç duyabilirsiniz.
İzlenmesi Gereken Metrikler
- Event Loop Lag: Görsel işleme sırasında ana iş parçacığının ne kadar süre bloke olduğunu izleyin.
- RSS (Resident Set Size): İşlemler sırasında bellek kullanımının sınırları aşıp aşmadığını kontrol edin.
- Buffer Limitleri: Çok büyük boyutlu görsellerin işlenmesi sırasında
sharp.cache(false)komutu ile önbelleği temizleyerek bellek kullanımını optimize edin.
Hata ayıklama için sharp.queue özelliğini kullanarak o an işlenmeyi bekleyen görsel sayısını loglayabilirsiniz:
setInterval(() => {
console.log(`İşlem kuyruğundaki görsel sayısı: ${sharp.queue.length}`);
}, 5000);
İleri Seviye İpuçları: Dinamik Filigran ve Renk Uzayı
Bazen filigranın görselin renk tonuna göre otomatik olarak renk değiştirmesi gerekebilir. Sharp'ın modulate ve tint özellikleri ile filigranı dinamik olarak görselin kontrastına uyumlu hale getirebilirsiniz. Ayrıca, ICC profillerini kullanarak renk sapmalarını önlemek, profesyonel fotoğrafçılık uygulamaları için kritiktir.
| Yöntem | Avantajı | Kullanım Alanı |
|---|---|---|
| Composite | Hızlı ve basit | Logo ve basit metinler |
| OverlayWith | Daha fazla kontrol | Karmaşık katmanlar |
| SVG Injection | Vektörel kalite | Responsive tasarımlar |
Not: Filigran dosyanızın (PNG/SVG) her zaman orijinal görselden daha küçük olduğundan emin olun. Sharp, büyük bir filigranı küçük bir görselin üzerine yerleştirirken görseli bozabilir; bu nedenle resize metodunu filigran üzerinde de kullanmak en sağlıklı yaklaşımdır.
Sonuç
Node.js ve Sharp kütüphanesini kullanarak otomatik görsel filigranı eklemek, hem performanslı hem de ölçeklenebilir bir süreçtir. Bu rehberde öğrendiğiniz stream tabanlı işleme ve dinamik boyutlandırma teknikleri, profesyonel projelerinizin temelini oluşturacaktır. Bir sonraki adım olarak, bu işlemi bir Express.js middleware yapısına dönüştürerek, görseller sunucuya yüklendiği anda otomatik olarak filigranlanmasını sağlayabilirsiniz.


Yorumlar (0)
Yorum Yaz