· kaynak dev.to (home feed)
canvas.toBlob, PNG için quality argümanını yok sayıyor ve çözüm palette quantization
Bir dev.to yazısı, canvas.toBlob()'un PNG çıktısında quality argümanını sessizce yok saydığını ve gerçek boyut kazancının yeniden kodlama yerine UPNG.js ile palette quantization'dan geldiğini anlatıyor.

Hiçbir şey sıkıştırmayan bir sıkıştırıcı
Küçük, tarayıcı tabanlı bir dosya dönüştürücü işleten bir geliştirici, aracın PNG sıkıştırma özelliğindeki sessiz bir hatayı anlattı. Kod, bir görseli canvas üzerine çiziyor ve canvas.toBlob(callback, 'image/png', 0.8) ile dışa aktarıyordu; 0.8 değeri, sıkıştırma kalitesini kontrol ettiği beklentisiyle geçiriliyordu. Çıktı, girdiyle neredeyse aynı boyutta, kimi zaman daha da büyük geliyordu. dev.io'daki... pardon, dev.to'daki yazının açıkladığı gibi, quality argümanı PNG için hiçbir işe yaramıyor.
Quality argümanı yalnızca lossy formatlar için geçerli
Yazıya göre hem toBlob() hem de toDataURL(), quality parametresini yalnızca image/jpeg ve image/webp gibi lossy formatlarda dikkate alıyor. image/png için tarayıcı bu parametreyi yok sayıyor ve yerleşik PNG kodlayıcısının ürettiği her neyse onu çıkarıyor; satır filtreleri veya DEFLATE sıkıştırma düzeyi üzerinde hiçbir kontrol yok. Bu şekilde yeniden kodlanan bir PNG, kaynak dosya zaten yetkin bir kodlayıcıyla yazılmışsa neredeyse hiç kazanç sağlamıyor.
PNG'de boyut kazancı gerçekten nereden geliyor
Yazı, bir PNG'yi üç katmana ayırıyor — bir piksel ızgarası, satır başına bir filtre ve en üstte DEFLATE sıkıştırması — ve dosyayı küçültmenin iki gerçekçi yolunu belirliyor:
- Lossless yeniden kodlama: daha iyi filtreler ve daha güçlü DEFLATE ayarları denemek. Piksel verisi değişmiyor ama kazanç mütevazı; yüzde olarak genellikle tek basamaktan düşük çift basamağa kadar.
- Palette quantization: 32-bit RGBA görseli, alfa kanalını koruyarak en fazla 256 renklik indeksli bir palete indirgemek. Bu lossy bir işlem ama ekran görüntüleri, logolar, ikonlar ve diğer UI grafikleri için fark genellikle görünmez ve boyut düşüşü çok daha büyük.
Yazar, TinyPNG gibi hizmetlerin kazançlarının çoğunu ikinci stratejiye borçlu olduğuna dikkat çekiyor.
Tarayıcıda bunu yapmak
Yerine konan yaklaşım, Photopea'nın yaratıcısı tarafından yazılmış kompakt bir PNG codec'i olan UPNG.js'yi, DEFLATE için pako ile birlikte kullanıyor. İş akışı dosyayı bir Image elementine yüklüyor, canvas'a çiziyor, getImageData() ile ham pikselleri alıyor ve buffer'ı UPNG.encode()'e iletiyor; bu fonksiyon bir renk sayısı kabul ediyor: lossless çıktı için 0, palete indirmek için 256.
Birkaç uygulama detayı önemli. getImageData() premultiplied olmayan RGBA döndürüyor ve UPNG'nin beklediği tam olarak bu olduğu için şeffaflık gidiş-dönüş boyunca korunuyor. UPNG.encode(), aldığı buffer'ın sahipliğini üstlenebileceğinden, kod iki kez kodlama yaptığında taze bir kopya (rgba.slice(0)) geçiriyor. Son adım tüm adayları karşılaştırıyor ve hiçbiri daha küçük değilse orijinal dosyaya geri düşüyor; böylece araç asla büyümüş bir çıktı döndürmüyor.
Rakamlar
Yazar bilerek zor bir vakayı test etti: üstte bir şeffaflık şeridi ve gürültü yoğun bir gradyan birleştiren 1000×700 sentetik bir görsel. Orijinal 1.50 MB'di. Lossless yeniden kodlama 1.43 MB üretti; yaklaşık yüzde 5 küçüldü. 256 renklik palete indirme ise 231 KB üretti; yüzde 85'lik bir azalma. Yazar bu rakamların bir benchmark olarak değil, iki strateji arasındaki farkı göstermek için olduğunu ve gerçek dünyadaki sonuçların değişeceğini vurguluyor.
Ne zaman quantize etmemeli
Palet indirgeme, yumuşak gradyanlarda ve fotoğraflarda bantlanmaya (banding) yol açabilir. Yazı, piksel olarak birebir çıktıya ihtiyaç duyan kullanıcılar için lossless bir modu korumayı, fotoğrafları bunun yerine JPEG veya WebP'ye dönüştürmeyi — canvas.toBlob(cb, 'image/webp', 0.8) quality değerine gerçekten saygı duyuyor ve WebP şeffaflığı destekliyor — ve ekranda gösterileceğinden daha büyük görselleri küçültmeyi öneriyor. Yazarın arayüzü sonunda iki modla sonuçlandı: her iki kodlamayı da deneyip küçük olanı tutan bir mod ve kesinlikle lossless kalan bir mod.
Neden önemli
Her şey client-side çalıştığı için hiçbir görsel verisi kullanıcının makinesinden çıkmıyor — yükleme yok, güvenecek sunucu yok ve sonradan silinecek bir şey yok. Yazar bunu, aracı yapmanın ilk motivasyonu ve özel bilgiler ya da henüz yayınlanmamış tasarımlar içeren ekran görüntüleri üzerinde çalışırken gerçek bir avantaj olarak gösteriyor. Daha geniş açıdan, yazı tarayıcı API'lerinin hiçbir sinyal vermeden başarısız olabileceğinin yararlı bir hatırlatıcısı: PNG için quality argümanı reddedilmek yerine kabul ediliyor, dolayısıyla hata ne bir error ne de bir uyarı üretiyor. Canvas üzerinden PNG sıkıştırdığını iddia eden her web uygulaması sessiz bir no-op gönderiyor olabilir ve asıl kazanç, lossless bir yedekle birlikte sunulan quantization'da yatıyor.
- #png
- #javascript
- #canvas-api
- #image-compression
- #browser