[{"data":1,"prerenderedAt":143},["ShallowReactive",2],{"guide-ecommerce-product-image-compression":3},{"slug":4,"category":5,"publishDate":6,"lastModified":7,"readingTime":8,"seo":9,"languages":11,"content":116},"ecommerce-product-image-compression","ecommerce","2024-12-15","2023-01-01",8,{"canonicalUrl":10},"/guides/ecommerce-product-image-compression",{"en":12,"zh":16,"zh-tw":20,"ja":24,"ko":28,"id":32,"vi":36,"th":40,"ru":44,"pt":48,"es":52,"de":56,"fr":60,"it":64,"nl":68,"sv":72,"no":76,"da":80,"fi":84,"el":88,"pl":92,"cs":96,"ro":100,"sl":104,"tr":108,"hu":112},{"title":13,"description":14,"metaKeywords":15},"E-commerce Product Image Compression: Complete Optimization Guide for Online Stores","Master e-commerce product image compression with our comprehensive guide. Learn optimal techniques for PNG, JPEG, WebP, and GIF compression to boost site speed, improve SEO, and increase conversions while maintaining visual quality.","ecommerce image compression, product image optimization, online store image compression, ecommerce SEO images, product photo compression, web store image optimization, ecommerce performance optimization",{"title":17,"description":18,"metaKeywords":19},"电商产品图像压缩完全指南：在线商店图像优化策略","掌握电商产品图像压缩的综合指南。学习PNG、JPEG、WebP和GIF的最佳压缩技术，在保持视觉质量的同时提升网站速度、改善SEO并增加转化率。","电商图像压缩, 产品图像优化, 在线商店图像压缩, 电商SEO图像, 产品照片压缩, 网店图像优化, 电商性能优化",{"title":21,"description":22,"metaKeywords":23},"電商產品圖像壓縮完全指南：線上商店圖像優化策略","掌握電商產品圖像壓縮的綜合指南。學習PNG、JPEG、WebP和GIF的最佳壓縮技術，在保持視覺品質的同時提升網站速度、改善SEO並增加轉化率。","電商圖像壓縮, 產品圖像優化, 線上商店圖像壓縮, 電商SEO圖像, 產品照片壓縮, 網店圖像優化, 電商效能優化",{"title":25,"description":26,"metaKeywords":27},"Eコマース商品画像圧縮完全ガイド：オンラインストア画像最適化戦略","Eコマース商品画像圧縮の包括的ガイドをマスターします。視覚品質を維持しながらサイト速度を向上させ、SEOを改善し、コンバージョンを増加させるPNG、JPEG、WebP、GIFの最適な圧縮技術を学びます。","Eコマース画像圧縮, 商品画像最適化, オンラインストア画像圧縮, EコマースSEO画像, 商品写真圧縮, ウェブストア画像最適化, Eコマースパフォーマンス最適化",{"title":29,"description":30,"metaKeywords":31},"전자상거래 제품 이미지 압축 완전 가이드: 온라인 스토어 이미지 최적화 전략","전자상거래 제품 이미지 압축의 포괄적인 가이드를 마스터하세요. 시각적 품질을 유지하면서 사이트 속도를 향상시키고, SEO를 개선하며, 전환율을 증가시키는 PNG, JPEG, WebP, GIF의 최적 압축 기술을 배웁니다.","전자상거래 이미지 압축, 제품 이미지 최적화, 온라인 스토어 이미지 압축, 전자상거래 SEO 이미지, 제품 사진 압축, 웹스토어 이미지 최적화, 전자상거래 성능 최적화",{"title":33,"description":34,"metaKeywords":35},"Panduan Lengkap Kompresi Gambar Produk E-commerce: Strategi Optimasi Gambar Toko Online","Kuasai panduan komprehensif kompresi gambar produk e-commerce. Pelajari teknik kompresi optimal untuk PNG, JPEG, WebP, dan GIF untuk meningkatkan kecepatan situs, memperbaiki SEO, dan meningkatkan konversi sambil mempertahankan kualitas visual.","kompresi gambar e-commerce, optimasi gambar produk, kompresi gambar toko online, gambar SEO e-commerce, kompresi foto produk, optimasi gambar web store, optimasi performa e-commerce",{"title":37,"description":38,"metaKeywords":39},"Hướng Dẫn Hoàn Chỉnh Nén Hình Ảnh Sản Phẩm Thương Mại Điện Tử: Chiến Lược Tối Ưu Hóa Hình Ảnh Cửa Hàng Trực Tuyến","Làm chủ hướng dẫn toàn diện về nén hình ảnh sản phẩm thương mại điện tử. Học các kỹ thuật nén tối ưu cho PNG, JPEG, WebP và GIF để tăng tốc độ trang web, cải thiện SEO và tăng tỷ lệ chuyển đổi trong khi duy trì chất lượng hình ảnh.","nén hình ảnh thương mại điện tử, tối ưu hóa hình ảnh sản phẩm, nén hình ảnh cửa hàng trực tuyến, hình ảnh SEO thương mại điện tử, nén ảnh sản phẩm, tối ưu hóa hình ảnh web store, tối ưu hóa hiệu suất thương mại điện tử",{"title":41,"description":42,"metaKeywords":43},"คู่มือครบถ้วนการบีบอัดภาพสินค้าอีคอมเมิร์ซ: กลยุทธ์การเพิ่มประสิทธิภาพภาพร้านค้าออนไลน์","เชี่ยวชาญคู่มือที่ครอบคลุมเกี่ยวกับการบีบอัดภาพสินค้าอีคอมเมิร์ซ เรียนรู้เทคนิคการบีบอัดที่เหมาะสมที่สุดสำหรับ PNG, JPEG, WebP และ GIF เพื่อเพิ่มความเร็วของเว็บไซต์ ปรับปรุง SEO และเพิ่มการแปลงในขณะที่รักษาคุณภาพภาพ","การบีบอัดภาพอีคอมเมิร์ซ, การเพิ่มประสิทธิภาพภาพสินค้า, การบีบอัดภาพร้านค้าออนไลน์, ภาพ SEO อีคอมเมิร์ซ, การบีบอัดภาพถ่ายสินค้า, การเพิ่มประสิทธิภาพภาพเว็บสโตร์, การเพิ่มประสิทธิภาพอีคอมเมิร์ซ",{"title":45,"description":46,"metaKeywords":47},"Полное руководство по сжатию изображений товаров в электронной коммерции: стратегии оптимизации изображений интернет-магазинов","Освойте комплексное руководство по сжатию изображений товаров в электронной коммерции. Изучите оптимальные техники сжатия PNG, JPEG, WebP и GIF для повышения скорости сайта, улучшения SEO и увеличения конверсий при сохранении визуального качества.","сжатие изображений электронной коммерции, оптимизация изображений товаров, сжатие изображений интернет-магазина, SEO изображения электронной коммерции, сжатие фото товаров, оптимизация изображений веб-магазина, оптимизация производительности электронной коммерции",{"title":49,"description":50,"metaKeywords":51},"Guia Completo de Compressão de Imagens de Produtos E-commerce: Estratégias de Otimização de Imagens para Lojas Online","Domine o guia abrangente de compressão de imagens de produtos e-commerce. Aprenda técnicas ótimas de compressão para PNG, JPEG, WebP e GIF para aumentar a velocidade do site, melhorar SEO e aumentar conversões mantendo a qualidade visual.","compressão de imagens e-commerce, otimização de imagens de produtos, compressão de imagens loja online, imagens SEO e-commerce, compressão de fotos de produtos, otimização de imagens web store, otimização de performance e-commerce",{"title":53,"description":54,"metaKeywords":55},"Guía Completa de Compresión de Imágenes de Productos E-commerce: Estrategias de Optimización de Imágenes para Tiendas Online","Domina la guía comprehensiva de compresión de imágenes de productos e-commerce. Aprende técnicas óptimas de compresión para PNG, JPEG, WebP y GIF para aumentar la velocidad del sitio, mejorar SEO y aumentar conversiones manteniendo la calidad visual.","compresión de imágenes e-commerce, optimización de imágenes de productos, compresión de imágenes tienda online, imágenes SEO e-commerce, compresión de fotos de productos, optimización de imágenes web store, optimización de rendimiento e-commerce",{"title":57,"description":58,"metaKeywords":59},"Vollständiger Leitfaden zur E-Commerce-Produktbildkomprimierung: Bildoptimierungsstrategien für Online-Shops","Beherrschen Sie den umfassenden Leitfaden zur E-Commerce-Produktbildkomprimierung. Lernen Sie optimale Komprimierungstechniken für PNG, JPEG, WebP und GIF, um die Website-Geschwindigkeit zu steigern, SEO zu verbessern und Konversionen zu erhöhen, während die visuelle Qualität erhalten bleibt.","E-Commerce-Bildkomprimierung, Produktbildoptimierung, Online-Shop-Bildkomprimierung, E-Commerce-SEO-Bilder, Produktfotokomprimierung, Webshop-Bildoptimierung, E-Commerce-Performance-Optimierung",{"title":61,"description":62,"metaKeywords":63},"Guide Complet de Compression d'Images Produits E-commerce: Stratégies d'Optimisation d'Images pour Boutiques en Ligne","Maîtrisez le guide complet de compression d'images produits e-commerce. Apprenez les techniques optimales de compression pour PNG, JPEG, WebP et GIF pour augmenter la vitesse du site, améliorer le SEO et augmenter les conversions tout en maintenant la qualité visuelle.","compression d'images e-commerce, optimisation d'images produits, compression d'images boutique en ligne, images SEO e-commerce, compression photos produits, optimisation d'images web store, optimisation performance e-commerce",{"title":65,"description":66,"metaKeywords":67},"Guida Completa alla Compressione Immagini Prodotti E-commerce: Strategie di Ottimizzazione Immagini per Negozi Online","Padroneggia la guida completa alla compressione delle immagini prodotti e-commerce. Impara tecniche ottimali di compressione per PNG, JPEG, WebP e GIF per aumentare la velocità del sito, migliorare SEO e aumentare le conversioni mantenendo la qualità visiva.","compressione immagini e-commerce, ottimizzazione immagini prodotti, compressione immagini negozio online, immagini SEO e-commerce, compressione foto prodotti, ottimizzazione immagini web store, ottimizzazione performance e-commerce",{"title":69,"description":70,"metaKeywords":71},"Volledige Gids voor E-commerce Productafbeelding Compressie: Beeldoptimalisatiestrategieën voor Online Winkels","Beheers de uitgebreide gids voor e-commerce productafbeelding compressie. Leer optimale compressietechnieken voor PNG, JPEG, WebP en GIF om websitesnelheid te verhogen, SEO te verbeteren en conversies te verhogen terwijl visuele kwaliteit behouden blijft.","e-commerce beeldcompressie, productafbeelding optimalisatie, online winkel beeldcompressie, e-commerce SEO afbeeldingen, productfoto compressie, webshop beeldoptimalisatie, e-commerce prestatie optimalisatie",{"title":73,"description":74,"metaKeywords":75},"Fullständig Guide för E-handel Produktbildkomprimering: Bildoptimeringsstrategier för Onlinebutiker","Bemästra den omfattande guiden för e-handel produktbildkomprimering. Lär dig optimala komprimeringstekniker för PNG, JPEG, WebP och GIF för att öka webbsidans hastighet, förbättra SEO och öka konverteringar medan visuell kvalitet bibehålls.","e-handel bildkomprimering, produktbildsoptimering, onlinebutik bildkomprimering, e-handel SEO bilder, produktfotokomprimering, webshop bildoptimering, e-handel prestationsoptimering",{"title":77,"description":78,"metaKeywords":79},"Fullstendig Guide for E-handel Produktbildekomprimering: Bildeoptimaliseringsstrategier for Nettbutikker","Mestre den omfattende guiden for e-handel produktbildekomprimering. Lær optimale komprimeringstekniker for PNG, JPEG, WebP og GIF for å øke nettstedets hastighet, forbedre SEO og øke konverteringer mens visuell kvalitet opprettholdes.","e-handel bildekomprimering, produktbildeoptimalisering, nettbutikk bildekomprimering, e-handel SEO bilder, produktfotokomprimering, webshop bildeoptimalisering, e-handel ytelsesoptimalisering",{"title":81,"description":82,"metaKeywords":83},"Fuldstændig Guide til E-handel Produktbilledkomprimering: Billedoptimeringsstrategier for Onlinebutikker","Mestre den omfattende guide til e-handel produktbilledkomprimering. Lær optimale komprimeringsteknikker for PNG, JPEG, WebP og GIF for at øge webstedets hastighed, forbedre SEO og øge konverteringer mens visuel kvalitet bevares.","e-handel billedkomprimering, produktbilledoptimering, onlinebutik billedkomprimering, e-handel SEO billeder, produktfotokomprimering, webshop billedoptimering, e-handel præstationsoptimering",{"title":85,"description":86,"metaKeywords":87},"Täydellinen Opas Verkkokaupan Tuotekuvien Pakkaukseen: Kuvanoptimointistrategiat Verkkokauppoihin","Hallitse kattava opas verkkokaupan tuotekuvien pakkaukseen. Opi optimaalisia pakkaustekniikoita PNG:lle, JPEG:lle, WebP:lle ja GIF:lle verkkosivujen nopeuden kasvattamiseksi, SEO:n parantamiseksi ja konversioiden lisäämiseksi visuaalisen laadun säilyessä.","verkkokaupan kuvapakkaus, tuotekuvien optimointi, verkkokaupan kuvapakkaus, verkkokaupan SEO kuvat, tuotevalokuvien pakkaus, verkkokaupan kuvaoptimointi, verkkokaupan suorituskyvyn optimointi",{"title":89,"description":90,"metaKeywords":91},"Πλήρης Οδηγός Συμπίεσης Εικόνων Προϊόντων Ηλεκτρονικού Εμπορίου: Στρατηγικές Βελτιστοποίησης Εικόνων για Ηλεκτρονικά Καταστήματα","Κατακτήστε τον περιεκτικό οδηγό συμπίεσης εικόνων προϊόντων ηλεκτρονικού εμπορίου. Μάθετε βέλτιστες τεχνικές συμπίεσης για PNG, JPEG, WebP και GIF για να αυξήσετε την ταχύτητα του ιστότοπου, να βελτιώσετε το SEO και να αυξήσετε τις μετατροπές διατηρώντας την οπτική ποιότητα.","συμπίεση εικόνων ηλεκτρονικού εμπορίου, βελτιστοποίηση εικόνων προϊόντων, συμπίεση εικόνων ηλεκτρονικού καταστήματος, εικόνες SEO ηλεκτρονικού εμπορίου, συμπίεση φωτογραφιών προϊόντων, βελτιστοποίηση εικόνων web store, βελτιστοποίηση απόδοσης ηλεκτρονικού εμπορίου",{"title":93,"description":94,"metaKeywords":95},"Kompletny Przewodnik Kompresji Obrazów Produktów E-commerce: Strategie Optymalizacji Obrazów dla Sklepów Internetowych","Opanuj kompleksowy przewodnik kompresji obrazów produktów e-commerce. Naucz się optymalnych technik kompresji dla PNG, JPEG, WebP i GIF, aby zwiększyć prędkość strony, poprawić SEO i zwiększyć konwersje zachowując jakość wizualną.","kompresja obrazów e-commerce, optymalizacja obrazów produktów, kompresja obrazów sklepu internetowego, obrazy SEO e-commerce, kompresja zdjęć produktów, optymalizacja obrazów web store, optymalizacja wydajności e-commerce",{"title":97,"description":98,"metaKeywords":99},"Kompletní Průvodce Kompresí Obrázků Produktů E-commerce: Strategie Optimalizace Obrázků pro Internetové Obchody","Ovládněte komplexní průvodce kompresí obrázků produktů e-commerce. Naučte se optimální kompresní techniky pro PNG, JPEG, WebP a GIF pro zvýšení rychlosti webu, zlepšení SEO a zvýšení konverzí při zachování vizuální kvality.","komprese obrázků e-commerce, optimalizace obrázků produktů, komprese obrázků internetového obchodu, obrázky SEO e-commerce, komprese fotografií produktů, optimalizace obrázků web store, optimalizace výkonu e-commerce",{"title":101,"description":102,"metaKeywords":103},"Ghid Complet pentru Compresia Imaginilor Produselor E-commerce: Strategii de Optimizare Imagini pentru Magazine Online","Stăpânește ghidul comprehensiv pentru compresia imaginilor produselor e-commerce. Învață tehnici optime de compresie pentru PNG, JPEG, WebP și GIF pentru a crește viteza site-ului, îmbunătăți SEO-ul și crește conversiile menținând calitatea vizuală.","compresia imaginilor e-commerce, optimizarea imaginilor produselor, compresia imaginilor magazin online, imagini SEO e-commerce, compresia fotografiilor produselor, optimizarea imaginilor web store, optimizarea performanței e-commerce",{"title":105,"description":106,"metaKeywords":107},"Popoln Vodnik za Stiskanje Slik Izdelkov E-trgovine: Strategije Optimizacije Slik za Spletne Trgovine","Obvladajte obsežen vodnik za stiskanje slik izdelkov e-trgovine. Naučite se optimalnih tehnik stiskanja za PNG, JPEG, WebP in GIF za povečanje hitrosti spletne strani, izboljšanje SEO in povečanje konverzij ob ohranjanju vizualne kakovosti.","stiskanje slik e-trgovine, optimizacija slik izdelkov, stiskanje slik spletne trgovine, slike SEO e-trgovine, stiskanje fotografij izdelkov, optimizacija slik web store, optimizacija zmogljivosti e-trgovine",{"title":109,"description":110,"metaKeywords":111},"E-ticaret Ürün Görüntü Sıkıştırma Tam Kılavuzu: Online Mağazalar için Görüntü Optimizasyon Stratejileri","E-ticaret ürün görüntü sıkıştırma kapsamlı kılavuzunda ustalaşın. Görsel kaliteyi korurken site hızını artırmak, SEO'yu geliştirmek ve dönüşümleri artırmak için PNG, JPEG, WebP ve GIF için optimal sıkıştırma tekniklerini öğrenin.","e-ticaret görüntü sıkıştırma, ürün görüntü optimizasyonu, online mağaza görüntü sıkıştırma, e-ticaret SEO görüntüleri, ürün fotoğrafı sıkıştırma, web mağaza görüntü optimizasyonu, e-ticaret performans optimizasyonu",{"title":113,"description":114,"metaKeywords":115},"Teljes E-kereskedelmi Termékképtömörítési Útmutató: Képoptimalizálási Stratégiák Online Áruházak Számára","Sajátítsa el az e-kereskedelmi termékképtömörítés átfogó útmutatóját. Tanuljon meg optimális tömörítési technikákat PNG, JPEG, WebP és GIF formátumokhoz a webhely sebességének növelése, SEO javítása és konverziók növelése érdekében a vizuális minőség megőrzése mellett.","e-kereskedelmi képtömörítés, termékképoptimalizálás, online áruház képtömörítés, e-kereskedelmi SEO képek, termékfotó tömörítés, webáruház képoptimalizálás, e-kereskedelmi teljesítményoptimalizálás",{"zh":117,"zh-tw":118,"zh-cn":117,"en":119,"ja":120,"ko":121,"de":122,"fr":123,"es":124,"it":125,"pt":126,"ru":127,"nl":128,"pl":129,"cs":130,"hu":131,"th":132,"vi":133,"id":134,"tr":135,"sv":136,"da":137,"fi":138,"ro":139,"el":140,"sl":141,"no":142},"# 电商产品图片压缩：以销售为导向的优化\r\n\r\n电商的成功很大程度上依赖于产品图片的质量，研究显示67%的消费者在网购时认为图片质量\"非常重要\"。然而，大图片文件会显著影响页面加载速度、转化率和移动端体验。本指南将系统讲解如何在保持视觉质量的前提下，采用先进技术优化电商产品图片，助力提升销售。\r\n\r\n## 为什么电商图片优化至关重要\r\n\r\n### 对转化率的影响\r\n\r\n产品图片优化直接影响业务指标：\r\n- **转化率**：页面加载延迟1秒，转化率下降7%\r\n- **跳出率**：40%的用户会放弃加载超过3秒的网站\r\n- **移动电商**：73%的电商流量来自移动设备\r\n- **搜索排名**：Google将页面速度纳入排名因素\r\n- **客户满意度**：高质量图片提升购买信心\r\n\r\n### 电商图片的特殊需求\r\n\r\n产品图片有独特的优化挑战：\r\n- **多视角展示**：主图、缩略图、放大图、360°旋转\r\n- **色彩准确性**：对时尚、美妆、家居尤为关键\r\n- **细节保留**：用户需看清材质、工艺、纹理\r\n- **加载性能**：需平衡质量与速度\r\n- **多设备兼容**：确保各终端体验一致\r\n\r\n## 电商图片类型解析\r\n\r\n### 产品图片类别\r\n\r\n不同图片类型需采用不同优化策略：\r\n\r\n```javascript\r\nconst ecommerceImageTypes = {\r\n    hero: {\r\n        purpose: '主产品展示',\r\n        requirements: '高质量，快速加载',\r\n        sizes: ['1200x1200', '800x800', '600x600'],\r\n        quality: { jpeg: 85, webp: 80 }\r\n    },\r\n    thumbnail: {\r\n        purpose: '产品列表缩略图',\r\n        requirements: '文件小，易识别',\r\n        sizes: ['300x300', '200x200', '150x150'],\r\n        quality: { jpeg: 75, webp: 70 }\r\n    },\r\n    zoom: {\r\n        purpose: '细节放大查看',\r\n        requirements: '最大限度保留细节',\r\n        sizes: ['2000x2000', '1600x1600'],\r\n        quality: { jpeg: 90, webp: 85 }\r\n    },\r\n    gallery: {\r\n        purpose: '多角度产品图',\r\n        requirements: '质量一致，懒加载',\r\n        sizes: ['800x800', '600x600'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    },\r\n    lifestyle: {\r\n        purpose: '场景/情感图',\r\n        requirements: '优化情感/场景表达',\r\n        sizes: ['1200x800', '800x533'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    }\r\n};\r\n```\r\n\r\n### 按产品类别优化策略\r\n\r\n不同产品类别有专属图片要求：\r\n\r\n```python\r\ndef get_category_optimization_settings(product_category):\r\n    \"\"\"获取不同产品类别的优化设置\"\"\"\r\n    settings = {\r\n        'fashion': {\r\n            'priority': ['color_accuracy', 'texture_detail'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 90},\r\n            'critical_views': ['front', 'back', 'detail']\r\n        },\r\n        'electronics': {\r\n            'priority': ['detail_preservation', 'fast_loading'],\r\n            'format_preference': 'webp_or_avif',\r\n            'quality_range': {'min': 75, 'max': 85},\r\n            'critical_views': ['main', 'interfaces', 'size_comparison']\r\n        },\r\n        'home_decor': {\r\n            'priority': ['color_accuracy', 'lifestyle_context'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 88},\r\n            'critical_views': ['styled', 'closeup', 'dimensions']\r\n        },\r\n        'jewelry': {\r\n            'priority': ['maximum_detail', 'color_accuracy'],\r\n            'format_preference': 'png_for_detailed_webp_for_hero',\r\n            'quality_range': {'min': 85, 'max': 95},\r\n            'critical_views': ['macro', '360_spin', 'lifestyle']\r\n        },\r\n        'books': {\r\n            'priority': ['fast_loading', 'text_readability'],\r\n            'format_preference': 'webp_aggressive_compression',\r\n            'quality_range': {'min': 70, 'max': 80},\r\n            'critical_views': ['cover', 'back', 'spine']\r\n        }\r\n    }\r\n    return settings.get(product_category, settings['electronics'])\r\n```\r\n\r\n## 高级产品图片处理\r\n\r\n### 自动化产品图片处理流程\r\n\r\n全流程自动化处理系统：\r\n\r\n```python\r\nimport os\r\nfrom PIL import Image, ImageEnhance, ImageFilter\r\nimport numpy as np\r\n\r\nclass EcommerceImageProcessor:\r\n    def __init__(self, config=None):\r\n        self.config = config or self.get_default_config()\r\n        self.supported_formats = ['jpeg', 'webp', 'avif', 'png']\r\n        \r\n    def get_default_config(self):\r\n        return {\r\n            'background_removal': True,\r\n            'auto_crop': True,\r\n            'color_enhancement': True,\r\n            'noise_reduction': True,\r\n            'watermark': False,\r\n            'quality_thresholds': {\r\n                'hero': 85,\r\n                'gallery': 80,\r\n                'thumbnail': 75,\r\n                'zoom': 90\r\n            }\r\n        }\r\n    \r\n    def process_product_image(self, input_path, output_dir, product_id):\r\n        \"\"\"处理单张产品图片为所有所需变体\"\"\"\r\n        img = Image.open(input_path)\r\n        \r\n        # 基础预处理\r\n        processed_img = self.preprocess_image(img)\r\n        \r\n        # 生成所有所需尺寸和格式\r\n        variants = self.generate_image_variants(processed_img, product_id)\r\n        \r\n        # 保存优化版本\r\n        saved_files = self.save_variants(variants, output_dir)\r\n        \r\n        return saved_files\r\n    \r\n    def preprocess_image(self, img):\r\n        \"\"\"对产品图片进行基础预处理\"\"\"\r\n        # 如有必要，转为RGB\r\n        if img.mode in ('RGBA', 'LA', 'P'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            if img.mode == 'RGBA':\r\n                background.paste(img, mask=img.split()[-1])\r\n            else:\r\n                background.paste(img)\r\n            img = background\r\n        \r\n        # 自动裁剪去除多余空白\r\n        if self.config['auto_crop']:\r\n            img = self.smart_crop(img)\r\n        \r\n        # 增强图片质量\r\n        if self.config['color_enhancement']:\r\n            img = self.enhance_product_image(img)\r\n        \r\n        # 降噪\r\n        if self.config['noise_reduction']:\r\n            img = img.filter(ImageFilter.SMOOTH_MORE)\r\n        \r\n        return img\r\n    \r\n    def smart_crop(self, img):\r\n        \"\"\"智能裁剪去除多余背景\"\"\"\r\n        # 转为numpy数组分析\r\n        img_array = np.array(img)\r\n        \r\n        # 查找非白色像素的边界框\r\n        mask = np.any(img_array \u003C 240, axis=2)  # 非纯白\r\n        coords = np.argwhere(mask)\r\n        \r\n        if len(coords) == 0:\r\n            return img  # 无需裁剪\r\n        \r\n        # 获取边界框\r\n        y0, x0 = coords.min(axis=0)\r\n        y1, x1 = coords.max(axis=0)\r\n        \r\n        # 加padding\r\n        padding = 20\r\n        y0 = max(0, y0 - padding)\r\n        x0 = max(0, x0 - padding)\r\n        y1 = min(img.height, y1 + padding)\r\n        x1 = min(img.width, x1 + padding)\r\n        \r\n        return img.crop((x0, y0, x1, y1))\r\n    \r\n    def enhance_product_image(self, img):\r\n        \"\"\"增强产品图片以适应电商展示\"\"\"\r\n        # 轻微提升亮度\r\n        brightness_enhancer = ImageEnhance.Brightness(img)\r\n        img = brightness_enhancer.enhance(1.05)\r\n        \r\n        # 增强对比度\r\n        contrast_enhancer = ImageEnhance.Contrast(img)\r\n        img = contrast_enhancer.enhance(1.1)\r\n        \r\n        # 增强色彩饱和度\r\n        color_enhancer = ImageEnhance.Color(img)\r\n        img = color_enhancer.enhance(1.05)\r\n        \r\n        # 增强锐度\r\n        sharpness_enhancer = ImageEnhance.Sharpness(img)\r\n        img = sharpness_enhancer.enhance(1.1)\r\n        \r\n        return img\r\n    \r\n    def generate_image_variants(self, img, product_id):\r\n        \"\"\"生成所有所需图片变体\"\"\"\r\n        variants = {}\r\n        \r\n        # 定义标准电商尺寸\r\n        sizes = {\r\n            'hero': (1200, 1200),\r\n            'gallery': (800, 800),\r\n            'thumbnail': (300, 300),\r\n            'zoom': (2000, 2000),\r\n            'mobile_hero': (600, 600),\r\n            'mobile_thumb': (150, 150)\r\n        }\r\n        \r\n        for variant_name, size in sizes.items():\r\n            # 高质量重采样缩放\r\n            resized = img.resize(size, Image.Resampling.LANCZOS)\r\n            variants[variant_name] = resized\r\n        \r\n        return variants\r\n    \r\n    def save_variants(self, variants, output_dir):\r\n        \"\"\"以优化格式保存所有变体\"\"\"\r\n        saved_files = []\r\n        \r\n        for variant_name, img in variants.items():\r\n            base_path = os.path.join(output_dir, variant_name)\r\n            for format in self.supported_formats:\r\n                output_path = f\"{base_path}.{format}\"\r\n                img.save(output_path, optimize=True, quality=self.config['quality_thresholds'][variant_name])\r\n                saved_files.append(output_path)\r\n        \r\n        return saved_files\r\n","# 電商產品圖片壓縮：以銷售為導向的優化\r\n\r\n電商的成功高度依賴於產品圖片的品質，研究顯示有67%的消費者在網購時認為圖片品質「非常重要」。然而，大型圖片檔案會顯著影響頁面載入速度、轉換率與行動端體驗。本指南將全面介紹如何在維持視覺品質的前提下，運用先進技術優化電商產品圖片，助力提升銷售。\r\n\r\n## 為什麼電商圖片優化很重要\r\n\r\n### 對轉換率的影響\r\n\r\n產品圖片優化直接影響商業指標：\r\n- **轉換率**：頁面載入延遲1秒，轉換率下降7%\r\n- **跳出率**：40%的用戶會放棄載入超過3秒的網站\r\n- **行動電商**：73%的電商流量來自行動裝置\r\n- **搜尋排名**：Google將頁面速度納入排名因素\r\n- **顧客滿意度**：高品質圖片提升購買信心\r\n\r\n### 電商圖片的特殊需求\r\n\r\n產品圖片有其獨特的優化挑戰：\r\n- **多視角展示**：主圖、縮圖、放大圖、360°旋轉\r\n- **色彩準確性**：對時尚、美妝、家居尤為關鍵\r\n- **細節保留**：消費者需看清材質、工藝、紋理\r\n- **載入效能**：需平衡品質與速度\r\n- **多裝置相容**：確保各終端體驗一致\r\n\r\n## 電商圖片類型解析\r\n\r\n### 產品圖片分類\r\n\r\n不同圖片類型需採用不同優化策略：\r\n\r\n```javascript\r\nconst ecommerceImageTypes = {\r\n    hero: {\r\n        purpose: '主產品展示',\r\n        requirements: '高品質，快速載入',\r\n        sizes: ['1200x1200', '800x800', '600x600'],\r\n        quality: { jpeg: 85, webp: 80 }\r\n    },\r\n    thumbnail: {\r\n        purpose: '產品列表縮圖',\r\n        requirements: '檔案小，易辨識',\r\n        sizes: ['300x300', '200x200', '150x150'],\r\n        quality: { jpeg: 75, webp: 70 }\r\n    },\r\n    zoom: {\r\n        purpose: '細節放大檢視',\r\n        requirements: '最大程度保留細節',\r\n        sizes: ['2000x2000', '1600x1600'],\r\n        quality: { jpeg: 90, webp: 85 }\r\n    },\r\n    gallery: {\r\n        purpose: '多角度產品圖',\r\n        requirements: '品質一致，延遲載入',\r\n        sizes: ['800x800', '600x600'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    },\r\n    lifestyle: {\r\n        purpose: '情境/氛圍圖',\r\n        requirements: '優化情感/情境表現',\r\n        sizes: ['1200x800', '800x533'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    }\r\n};\r\n```\r\n\r\n### 依產品類別優化策略\r\n\r\n不同產品類別有專屬圖片需求：\r\n\r\n```python\r\ndef get_category_optimization_settings(product_category):\r\n    \"\"\"取得不同產品類別的優化設定\"\"\"\r\n    settings = {\r\n        'fashion': {\r\n            'priority': ['color_accuracy', 'texture_detail'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 90},\r\n            'critical_views': ['front', 'back', 'detail']\r\n        },\r\n        'electronics': {\r\n            'priority': ['detail_preservation', 'fast_loading'],\r\n            'format_preference': 'webp_or_avif',\r\n            'quality_range': {'min': 75, 'max': 85},\r\n            'critical_views': ['main', 'interfaces', 'size_comparison']\r\n        },\r\n        'home_decor': {\r\n            'priority': ['color_accuracy', 'lifestyle_context'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 88},\r\n            'critical_views': ['styled', 'closeup', 'dimensions']\r\n        },\r\n        'jewelry': {\r\n            'priority': ['maximum_detail', 'color_accuracy'],\r\n            'format_preference': 'png_for_detailed_webp_for_hero',\r\n            'quality_range': {'min': 85, 'max': 95},\r\n            'critical_views': ['macro', '360_spin', 'lifestyle']\r\n        },\r\n        'books': {\r\n            'priority': ['fast_loading', 'text_readability'],\r\n            'format_preference': 'webp_aggressive_compression',\r\n            'quality_range': {'min': 70, 'max': 80},\r\n            'critical_views': ['cover', 'back', 'spine']\r\n        }\r\n    }\r\n    return settings.get(product_category, settings['electronics'])\r\n```\r\n\r\n## 進階產品圖片處理\r\n\r\n### 自動化產品圖片處理流程\r\n\r\n全自動化處理系統：\r\n\r\n```python\r\nimport os\r\nfrom PIL import Image, ImageEnhance, ImageFilter\r\nimport numpy as np\r\n\r\nclass EcommerceImageProcessor:\r\n    def __init__(self, config=None):\r\n        self.config = config or self.get_default_config()\r\n        self.supported_formats = ['jpeg', 'webp', 'avif', 'png']\r\n        \r\n    def get_default_config(self):\r\n        return {\r\n            'background_removal': True,\r\n            'auto_crop': True,\r\n            'color_enhancement': True,\r\n            'noise_reduction': True,\r\n            'watermark': False,\r\n            'quality_thresholds': {\r\n                'hero': 85,\r\n                'gallery': 80,\r\n                'thumbnail': 75,\r\n                'zoom': 90\r\n            }\r\n        }\r\n    \r\n    def process_product_image(self, input_path, output_dir, product_id):\r\n        \"\"\"處理單一產品圖片為所有所需變體\"\"\"\r\n        img = Image.open(input_path)\r\n        \r\n        # 基本預處理\r\n        processed_img = self.preprocess_image(img)\r\n        \r\n        # 產生所有所需尺寸與格式\r\n        variants = self.generate_image_variants(processed_img, product_id)\r\n        \r\n        # 儲存最佳化版本\r\n        saved_files = self.save_variants(variants, output_dir)\r\n        \r\n        return saved_files\r\n    \r\n    def preprocess_image(self, img):\r\n        \"\"\"對產品圖片進行基本預處理\"\"\"\r\n        # 如有需要轉為RGB\r\n        if img.mode in ('RGBA', 'LA', 'P'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            if img.mode == 'RGBA':\r\n                background.paste(img, mask=img.split()[-1])\r\n            else:\r\n                background.paste(img)\r\n            img = background\r\n        \r\n        # 自動裁切去除多餘空白\r\n        if self.config['auto_crop']:\r\n            img = self.smart_crop(img)\r\n        \r\n        # 增強圖片品質\r\n        if self.config['color_enhancement']:\r\n            img = self.enhance_product_image(img)\r\n        \r\n        # 降噪\r\n        if self.config['noise_reduction']:\r\n            img = img.filter(ImageFilter.SMOOTH_MORE)\r\n        \r\n        return img\r\n    \r\n    def smart_crop(self, img):\r\n        \"\"\"智慧裁切去除多餘背景\"\"\"\r\n        # 轉為numpy陣列分析\r\n        img_array = np.array(img)\r\n        \r\n        # 找出非白色像素的邊界框\r\n        mask = np.any(img_array \u003C 240, axis=2)  # 非純白\r\n        coords = np.argwhere(mask)\r\n        \r\n        if len(coords) == 0:\r\n            return img  # 無需裁切\r\n        \r\n        # 取得邊界框\r\n        y0, x0 = coords.min(axis=0)\r\n        y1, x1 = coords.max(axis=0)\r\n        \r\n        # 加padding\r\n        padding = 20\r\n        y0 = max(0, y0 - padding)\r\n        x0 = max(0, x0 - padding)\r\n        y1 = min(img.height, y1 + padding)\r\n        x1 = min(img.width, x1 + padding)\r\n        \r\n        return img.crop((x0, y0, x1, y1))\r\n    \r\n    def enhance_product_image(self, img):\r\n        \"\"\"增強產品圖片以適應電商展示\"\"\"\r\n        # 輕微提升亮度\r\n        brightness_enhancer = ImageEnhance.Brightness(img)\r\n        img = brightness_enhancer.enhance(1.05)\r\n        \r\n        # 增強對比度\r\n        contrast_enhancer = ImageEnhance.Contrast(img)\r\n        img = contrast_enhancer.enhance(1.1)\r\n        \r\n        # 增強色彩飽和度\r\n        color_enhancer = ImageEnhance.Color(img)\r\n        img = color_enhancer.enhance(1.05)\r\n        \r\n        # 增強銳利度\r\n        sharpness_enhancer = ImageEnhance.Sharpness(img)\r\n        img = sharpness_enhancer.enhance(1.1)\r\n        \r\n        return img\r\n    \r\n    def generate_image_variants(self, img, product_id):\r\n        \"\"\"產生所有所需圖片變體\"\"\"\r\n        variants = {}\r\n        \r\n        # 定義標準電商尺寸\r\n        sizes = {\r\n            'hero': (1200, 1200),\r\n            'gallery': (800, 800),\r\n            'thumbnail': (300, 300),\r\n            'zoom': (2000, 2000),\r\n            'mobile_hero': (600, 600),\r\n            'mobile_thumb': (150, 150)\r\n        }\r\n        \r\n        for variant_name, size in sizes.items():\r\n            # 高品質重採樣縮放\r\n            resized = img.resize(size, Image.Resampling.LANCZOS)\r\n            variants[variant_name] = resized\r\n        \r\n        return variants\r\n    \r\n    def save_variants(self, variants, output_dir):\r\n        \"\"\"以最佳化格式儲存所有變體\"\"\"\r\n        saved_files = []\r\n        \r\n        for variant_name, img in variants.items():\r\n            base_path = os.path.join(output_dir, variant_name)\r\n            img.save(f\"{base_path}.{self.supported_formats[0]}\", optimize=True, quality=self.config['quality_thresholds'][variant_name])\r\n            img.save(f\"{base_path}.{self.supported_formats[1]}\", optimize=True, quality=self.config['quality_thresholds'][variant_name])\r\n            img.save(f\"{base_path}.{self.supported_formats[2]}\", optimize=True, quality=self.config['quality_thresholds'][variant_name])\r\n            img.save(f\"{base_path}.{self.supported_formats[3]}\", optimize=True, quality=self.config['quality_thresholds'][variant_name])\r\n            saved_files.append(f\"{base_path}.{self.supported_formats[0]}\")\r\n            saved_files.append(f\"{base_path}.{self.supported_formats[1]}\")\r\n            saved_files.append(f\"{base_path}.{self.supported_formats[2]}\")\r\n            saved_files.append(f\"{base_path}.{self.supported_formats[3]}\")\r\n        \r\n        return saved_files\r\n","# E-commerce Product Image Compression: Sales-Driven Optimization\r\n\r\nE-commerce success heavily depends on product image quality, with studies showing that 67% of consumers consider image quality \"very important\" when making online purchases. However, large image files can significantly impact page load times, conversion rates, and mobile user experience. This comprehensive guide covers advanced techniques for optimizing e-commerce product images while maintaining the visual quality needed to drive sales.\r\n\r\n## Why E-commerce Image Optimization Matters\r\n\r\n### Impact on Conversion Rates\r\n\r\nProduct image optimization directly affects business metrics:\r\n- **Conversion rates**: 1-second delay in page load time reduces conversions by 7%\r\n- **Bounce rates**: 40% of users abandon sites that take more than 3 seconds to load\r\n- **Mobile commerce**: 73% of e-commerce traffic comes from mobile devices\r\n- **Search rankings**: Google factors page speed into search rankings\r\n- **Customer satisfaction**: High-quality images increase purchase confidence\r\n\r\n### E-commerce Specific Requirements\r\n\r\nProduct images have unique optimization challenges:\r\n- **Multiple product views**: Main image, thumbnails, zoom views, 360° rotations\r\n- **Color accuracy**: Critical for fashion, cosmetics, and home decor\r\n- **Detail preservation**: Customers need to see texture, materials, and craftsmanship\r\n- **Loading performance**: Balance between quality and speed\r\n- **Cross-device compatibility**: Consistent experience across devices\r\n\r\n## Understanding E-commerce Image Types\r\n\r\n### Product Image Categories\r\n\r\nDifferent image types require different optimization approaches:\r\n\r\n```javascript\r\nconst ecommerceImageTypes = {\r\n    hero: {\r\n        purpose: 'Primary product showcase',\r\n        requirements: 'High quality, fast loading',\r\n        sizes: ['1200x1200', '800x800', '600x600'],\r\n        quality: { jpeg: 85, webp: 80 }\r\n    },\r\n    thumbnail: {\r\n        purpose: 'Product grid displays',\r\n        requirements: 'Small file size, recognizable',\r\n        sizes: ['300x300', '200x200', '150x150'],\r\n        quality: { jpeg: 75, webp: 70 }\r\n    },\r\n    zoom: {\r\n        purpose: 'Detailed product inspection',\r\n        requirements: 'Maximum detail preservation',\r\n        sizes: ['2000x2000', '1600x1600'],\r\n        quality: { jpeg: 90, webp: 85 }\r\n    },\r\n    gallery: {\r\n        purpose: 'Multiple product angles',\r\n        requirements: 'Consistent quality, lazy loading',\r\n        sizes: ['800x800', '600x600'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    },\r\n    lifestyle: {\r\n        purpose: 'Product in use/context',\r\n        requirements: 'Optimized for emotion/context',\r\n        sizes: ['1200x800', '800x533'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    }\r\n};\r\n```\r\n\r\n### Optimization Strategy by Product Category\r\n\r\nDifferent product categories have specific image requirements:\r\n\r\n```python\r\ndef get_category_optimization_settings(product_category):\r\n    \"\"\"Get optimization settings for different product categories\"\"\"\r\n    settings = {\r\n        'fashion': {\r\n            'priority': ['color_accuracy', 'texture_detail'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 90},\r\n            'critical_views': ['front', 'back', 'detail']\r\n        },\r\n        'electronics': {\r\n            'priority': ['detail_preservation', 'fast_loading'],\r\n            'format_preference': 'webp_or_avif',\r\n            'quality_range': {'min': 75, 'max': 85},\r\n            'critical_views': ['main', 'interfaces', 'size_comparison']\r\n        },\r\n        'home_decor': {\r\n            'priority': ['color_accuracy', 'lifestyle_context'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 88},\r\n            'critical_views': ['styled', 'closeup', 'dimensions']\r\n        },\r\n        'jewelry': {\r\n            'priority': ['maximum_detail', 'color_accuracy'],\r\n            'format_preference': 'png_for_detailed_webp_for_hero',\r\n            'quality_range': {'min': 85, 'max': 95},\r\n            'critical_views': ['macro', '360_spin', 'lifestyle']\r\n        },\r\n        'books': {\r\n            'priority': ['fast_loading', 'text_readability'],\r\n            'format_preference': 'webp_aggressive_compression',\r\n            'quality_range': {'min': 70, 'max': 80},\r\n            'critical_views': ['cover', 'back', 'spine']\r\n        }\r\n    }\r\n    return settings.get(product_category, settings['electronics'])\r\n```\r\n\r\n## Advanced Product Image Processing\r\n\r\n### Automated Product Image Pipeline\r\n\r\nComprehensive automated processing system:\r\n\r\n```python\r\nimport os\r\nfrom PIL import Image, ImageEnhance, ImageFilter\r\nimport numpy as np\r\n\r\nclass EcommerceImageProcessor:\r\n    def __init__(self, config=None):\r\n        self.config = config or self.get_default_config()\r\n        self.supported_formats = ['jpeg', 'webp', 'avif', 'png']\r\n        \r\n    def get_default_config(self):\r\n        return {\r\n            'background_removal': True,\r\n            'auto_crop': True,\r\n            'color_enhancement': True,\r\n            'noise_reduction': True,\r\n            'watermark': False,\r\n            'quality_thresholds': {\r\n                'hero': 85,\r\n                'gallery': 80,\r\n                'thumbnail': 75,\r\n                'zoom': 90\r\n            }\r\n        }\r\n    \r\n    def process_product_image(self, input_path, output_dir, product_id):\r\n        \"\"\"Process a single product image into all required variants\"\"\"\r\n        img = Image.open(input_path)\r\n        \r\n        # Basic preprocessing\r\n        processed_img = self.preprocess_image(img)\r\n        \r\n        # Generate all required sizes and formats\r\n        variants = self.generate_image_variants(processed_img, product_id)\r\n        \r\n        # Save optimized versions\r\n        saved_files = self.save_variants(variants, output_dir)\r\n        \r\n        return saved_files\r\n    \r\n    def preprocess_image(self, img):\r\n        \"\"\"Apply basic preprocessing to product image\"\"\"\r\n        # Convert to RGB if necessary\r\n        if img.mode in ('RGBA', 'LA', 'P'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            if img.mode == 'RGBA':\r\n                background.paste(img, mask=img.split()[-1])\r\n            else:\r\n                background.paste(img)\r\n            img = background\r\n        \r\n        # Auto-crop to remove excess whitespace\r\n        if self.config['auto_crop']:\r\n            img = self.smart_crop(img)\r\n        \r\n        # Enhance image quality\r\n        if self.config['color_enhancement']:\r\n            img = self.enhance_product_image(img)\r\n        \r\n        # Reduce noise\r\n        if self.config['noise_reduction']:\r\n            img = img.filter(ImageFilter.SMOOTH_MORE)\r\n        \r\n        return img\r\n    \r\n    def smart_crop(self, img):\r\n        \"\"\"Intelligently crop product image to remove excess background\"\"\"\r\n        # Convert to numpy array for analysis\r\n        img_array = np.array(img)\r\n        \r\n        # Find bounding box of non-white pixels\r\n        mask = np.any(img_array \u003C 240, axis=2)  # Not pure white\r\n        coords = np.argwhere(mask)\r\n        \r\n        if len(coords) == 0:\r\n            return img  # No cropping needed\r\n        \r\n        # Get bounding box\r\n        y0, x0 = coords.min(axis=0)\r\n        y1, x1 = coords.max(axis=0)\r\n        \r\n        # Add padding\r\n        padding = 20\r\n        y0 = max(0, y0 - padding)\r\n        x0 = max(0, x0 - padding)\r\n        y1 = min(img.height, y1 + padding)\r\n        x1 = min(img.width, x1 + padding)\r\n        \r\n        return img.crop((x0, y0, x1, y1))\r\n    \r\n    def enhance_product_image(self, img):\r\n        \"\"\"Enhance product image for e-commerce display\"\"\"\r\n        # Enhance brightness slightly\r\n        brightness_enhancer = ImageEnhance.Brightness(img)\r\n        img = brightness_enhancer.enhance(1.05)\r\n        \r\n        # Enhance contrast\r\n        contrast_enhancer = ImageEnhance.Contrast(img)\r\n        img = contrast_enhancer.enhance(1.1)\r\n        \r\n        # Enhance color saturation\r\n        color_enhancer = ImageEnhance.Color(img)\r\n        img = color_enhancer.enhance(1.05)\r\n        \r\n        # Enhance sharpness\r\n        sharpness_enhancer = ImageEnhance.Sharpness(img)\r\n        img = sharpness_enhancer.enhance(1.1)\r\n        \r\n        return img\r\n    \r\n    def generate_image_variants(self, img, product_id):\r\n        \"\"\"Generate all required image variants\"\"\"\r\n        variants = {}\r\n        \r\n        # Define standard e-commerce sizes\r\n        sizes = {\r\n            'hero': (1200, 1200),\r\n            'gallery': (800, 800),\r\n            'thumbnail': (300, 300),\r\n            'zoom': (2000, 2000),\r\n            'mobile_hero': (600, 600),\r\n            'mobile_thumb': (150, 150)\r\n        }\r\n        \r\n        for variant_name, size in sizes.items():\r\n            # Resize with high-quality resampling\r\n            resized = img.resize(size, Image.Resampling.LANCZOS)\r\n            variants[variant_name] = resized\r\n        \r\n        return variants\r\n    \r\n    def save_variants(self, variants, output_dir):\r\n        \"\"\"Save all variants in optimized formats\"\"\"\r\n        saved_files = []\r\n        \r\n        for variant_name, img in variants.items():\r\n            base_path = os.path.join(output_dir, variant_name)\r\n            \r\n            # Save in multiple formats\r\n            for format_type in ['jpeg', 'webp']:\r\n                filename = f\"{base_path}.{format_type}\"\r\n                quality = self.get_quality_for_variant(variant_name, format_type)\r\n                \r\n                if format_type == 'jpeg':\r\n                    img.save(filename, 'JPEG', quality=quality, optimize=True, progressive=True)\r\n                elif format_type == 'webp':\r\n                    img.save(filename, 'WebP', quality=quality, optimize=True)\r\n                \r\n                saved_files.append(filename)\r\n        \r\n        return saved_files\r\n    \r\n    def get_quality_for_variant(self, variant_name, format_type):\r\n        \"\"\"Get optimal quality setting for specific variant and format\"\"\"\r\n        base_quality = self.config['quality_thresholds'].get(variant_name, 80)\r\n        \r\n        # Adjust for format\r\n        if format_type == 'webp':\r\n            return base_quality - 5  # WebP can achieve same quality at lower setting\r\n        elif format_type == 'avif':\r\n            return base_quality - 10  # AVIF is even more efficient\r\n        \r\n        return base_quality\r\n\r\n# Usage example\r\nprocessor = EcommerceImageProcessor()\r\nprocessor.process_product_image('product_raw.jpg', 'output/', 'product_123')\r\n```\r\n\r\n### Background Removal and Standardization\r\n\r\nAutomated background processing for consistent product display:\r\n\r\n```python\r\ndef remove_product_background(image_path, output_path):\r\n    \"\"\"Remove background from product image using edge detection\"\"\"\r\n    import cv2\r\n    import numpy as np\r\n    \r\n    # Read image\r\n    img = cv2.imread(image_path)\r\n    original = img.copy()\r\n    \r\n    # Convert to grayscale\r\n    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\r\n    \r\n    # Apply GaussianBlur to reduce noise\r\n    blurred = cv2.GaussianBlur(gray, (5, 5), 0)\r\n    \r\n    # Edge detection\r\n    edges = cv2.Canny(blurred, 50, 150)\r\n    \r\n    # Find contours\r\n    contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\r\n    \r\n    if contours:\r\n        # Find the largest contour (assumed to be the product)\r\n        largest_contour = max(contours, key=cv2.contourArea)\r\n        \r\n        # Create mask\r\n        mask = np.zeros(gray.shape, np.uint8)\r\n        cv2.fillPoly(mask, [largest_contour], 255)\r\n        \r\n        # Apply mask to original image\r\n        result = cv2.bitwise_and(original, original, mask=mask)\r\n        \r\n        # Convert background to white\r\n        result[mask == 0] = [255, 255, 255]\r\n        \r\n        cv2.imwrite(output_path, result)\r\n        return True\r\n    \r\n    return False\r\n\r\ndef standardize_product_backgrounds(input_dir, output_dir, background_color=(255, 255, 255)):\r\n    \"\"\"Standardize all product backgrounds to consistent color\"\"\"\r\n    for filename in os.listdir(input_dir):\r\n        if filename.lower().endswith(('.jpg', '.jpeg', '.png')):\r\n            input_path = os.path.join(input_dir, filename)\r\n            output_path = os.path.join(output_dir, filename)\r\n            \r\n            # Try automated background removal\r\n            if not remove_product_background(input_path, output_path):\r\n                # Fallback: simple white background\r\n                img = Image.open(input_path)\r\n                if img.mode == 'RGBA':\r\n                    background = Image.new('RGB', img.size, background_color)\r\n                    background.paste(img, mask=img.split()[-1])\r\n                    background.save(output_path, 'JPEG', quality=85)\r\n                else:\r\n                    img.save(output_path)\r\n```\r\n\r\n## Platform-Specific Optimization\r\n\r\n### Amazon Marketplace Optimization\r\n\r\nAmazon has specific image requirements and algorithms:\r\n\r\n```python\r\nclass AmazonImageOptimizer:\r\n    def __init__(self):\r\n        self.requirements = {\r\n            'main_image': {\r\n                'min_size': (1000, 1000),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'background': 'pure_white',\r\n                'product_coverage': 85  # Minimum percentage of image\r\n            },\r\n            'additional_images': {\r\n                'min_size': (500, 500),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'lifestyle_allowed': True\r\n            }\r\n        }\r\n    \r\n    def optimize_for_amazon(self, image_path, output_path, image_type='main'):\r\n        \"\"\"Optimize image specifically for Amazon listing\"\"\"\r\n        img = Image.open(image_path)\r\n        \r\n        if image_type == 'main':\r\n            img = self.ensure_white_background(img)\r\n            img = self.ensure_minimum_size(img, (1000, 1000))\r\n        \r\n        # Amazon prefers sRGB color space\r\n        if img.mode != 'RGB':\r\n            img = img.convert('RGB')\r\n        \r\n        # Optimize file size while maintaining quality\r\n        quality = 90 if image_type == 'main' else 85\r\n        img.save(output_path, 'JPEG', quality=quality, optimize=True)\r\n        \r\n        return self.validate_amazon_requirements(output_path, image_type)\r\n    \r\n    def ensure_white_background(self, img):\r\n        \"\"\"Ensure image has pure white background\"\"\"\r\n        if img.mode == 'RGBA':\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            background.paste(img, mask=img.split()[-1])\r\n            return background\r\n        return img\r\n    \r\n    def ensure_minimum_size(self, img, min_size):\r\n        \"\"\"Ensure image meets minimum size requirements\"\"\"\r\n        if img.size[0] \u003C min_size[0] or img.size[1] \u003C min_size[1]:\r\n            img = img.resize(min_size, Image.Resampling.LANCZOS)\r\n        return img\r\n    \r\n    def validate_amazon_requirements(self, image_path, image_type):\r\n        \"\"\"Validate image meets Amazon requirements\"\"\"\r\n        img = Image.open(image_path)\r\n        requirements = self.requirements[image_type]\r\n        \r\n        validation_results = {\r\n            'size_valid': (\r\n                img.size[0] >= requirements['min_size'][0] and \r\n                img.size[1] >= requirements['min_size'][1]\r\n            ),\r\n            'format_valid': image_path.upper().endswith(tuple(requirements['formats'])),\r\n            'file_size_valid': os.path.getsize(image_path) \u003C= 10 * 1024 * 1024  # 10MB limit\r\n        }\r\n        \r\n        return all(validation_results.values()), validation_results\r\n```\r\n\r\n### Shopify Store Optimization\r\n\r\nOptimizing for Shopify themes and performance:\r\n\r\n```javascript\r\nclass ShopifyImageOptimizer {\r\n    constructor() {\r\n        this.themeRequirements = {\r\n            'product_card': { width: 600, height: 600, quality: 80 },\r\n            'product_detail': { width: 1200, height: 1200, quality: 85 },\r\n            'product_zoom': { width: 2048, height: 2048, quality: 90 },\r\n            'collection_featured': { width: 800, height: 600, quality: 80 }\r\n        };\r\n    }\r\n    \r\n    generateShopifyImageUrls(baseImageUrl, productHandle) {\r\n        const urls = {};\r\n        \r\n        Object.entries(this.themeRequirements).forEach(([variant, specs]) => {\r\n            // Shopify image transformation URL format\r\n            const transformedUrl = baseImageUrl.replace('.jpg', \r\n                `_${specs.width}x${specs.height}_crop_center.jpg`);\r\n            urls[variant] = transformedUrl;\r\n        });\r\n        \r\n        return urls;\r\n    }\r\n    \r\n    generateShopifyPictureElement(productData) {\r\n        const { images, title, handle } = productData;\r\n        const mainImage = images[0];\r\n        \r\n        return `\r\n            \u003Cpicture>\r\n                \u003Csource media=\"(min-width: 1200px)\" \r\n                        srcset=\"${mainImage}_1200x1200.webp 1x, ${mainImage}_2400x2400.webp 2x\"\r\n                        type=\"image/webp\">\r\n                \u003Csource media=\"(min-width: 768px)\" \r\n                        srcset=\"${mainImage}_800x800.webp 1x, ${mainImage}_1600x1600.webp 2x\"\r\n                        type=\"image/webp\">\r\n                \u003Csource media=\"(max-width: 767px)\" \r\n                        srcset=\"${mainImage}_600x600.webp 1x, ${mainImage}_1200x1200.webp 2x\"\r\n                        type=\"image/webp\">\r\n                \u003Cimg src=\"${mainImage}_800x800.jpg\"\r\n                     srcset=\"${mainImage}_400x400.jpg 400w,\r\n                             ${mainImage}_600x600.jpg 600w,\r\n                             ${mainImage}_800x800.jpg 800w,\r\n                             ${mainImage}_1200x1200.jpg 1200w\"\r\n                     sizes=\"(max-width: 767px) 100vw, (max-width: 1023px) 50vw, 33vw\"\r\n                     alt=\"${title}\"\r\n                     loading=\"lazy\"\r\n                     data-product-handle=\"${handle}\">\r\n            \u003C/picture>\r\n        `;\r\n    }\r\n}\r\n```\r\n\r\n## Advanced Loading Strategies for E-commerce\r\n\r\n### Smart Product Image Loading\r\n\r\nIntelligent loading based on user behavior and device capabilities:\r\n\r\n```javascript\r\nclass EcommerceImageLoader {\r\n    constructor() {\r\n        this.userBehavior = this.trackUserBehavior();\r\n        this.deviceCapabilities = this.analyzeDevice();\r\n        this.loadingStrategies = this.initializeStrategies();\r\n    }\r\n    \r\n    trackUserBehavior() {\r\n        return {\r\n            isReturningCustomer: localStorage.getItem('visited') === 'true',\r\n            viewingHistory: JSON.parse(localStorage.getItem('viewedProducts') || '[]'),\r\n            averageSessionTime: parseInt(localStorage.getItem('avgSessionTime') || '0'),\r\n            purchaseHistory: JSON.parse(localStorage.getItem('purchases') || '[]')\r\n        };\r\n    }\r\n    \r\n    analyzeDevice() {\r\n        const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;\r\n        \r\n        return {\r\n            connectionSpeed: connection ? connection.effectiveType : '4g',\r\n            deviceMemory: navigator.deviceMemory || 4,\r\n            isLowEndDevice: navigator.deviceMemory \u003C 2,\r\n            isMobile: window.innerWidth \u003C= 768,\r\n            isSlowConnection: connection && (connection.effectiveType === 'slow-2g' || connection.effectiveType === '2g')\r\n        };\r\n    }\r\n    \r\n    initializeStrategies() {\r\n        return {\r\n            eager: this.eagerLoadingStrategy.bind(this),\r\n            progressive: this.progressiveLoadingStrategy.bind(this),\r\n            lazy: this.lazyLoadingStrategy.bind(this),\r\n            adaptive: this.adaptiveLoadingStrategy.bind(this)\r\n        };\r\n    }\r\n    \r\n    selectOptimalStrategy(productData, context) {\r\n        const { deviceCapabilities, userBehavior } = this;\r\n        \r\n        // High-value returning customers with good connections\r\n        if (userBehavior.isReturningCustomer && \r\n            userBehavior.purchaseHistory.length > 0 && \r\n            !deviceCapabilities.isSlowConnection) {\r\n            return 'eager';\r\n        }\r\n        \r\n        // Low-end devices or slow connections\r\n        if (deviceCapabilities.isLowEndDevice || deviceCapabilities.isSlowConnection) {\r\n            return 'lazy';\r\n        }\r\n        \r\n        // Mobile devices with good connections\r\n        if (deviceCapabilities.isMobile && !deviceCapabilities.isSlowConnection) {\r\n            return 'progressive';\r\n        }\r\n        \r\n        // Default: adaptive strategy\r\n        return 'adaptive';\r\n    }\r\n    \r\n    eagerLoadingStrategy(productImages) {\r\n        // Load all product images immediately for premium experience\r\n        productImages.forEach(img => {\r\n            const imageLoader = new Image();\r\n            imageLoader.src = img.dataset.src;\r\n            \r\n            if (img.dataset.srcset) {\r\n                imageLoader.srcset = img.dataset.srcset;\r\n            }\r\n            \r\n            imageLoader.onload = () => {\r\n                img.src = imageLoader.src;\r\n                if (img.dataset.srcset) {\r\n                    img.srcset = imageLoader.srcset;\r\n                }\r\n                img.classList.add('loaded');\r\n            };\r\n        });\r\n    }\r\n    \r\n    progressiveLoadingStrategy(productImages) {\r\n        // Load low-quality first, then high-quality\r\n        productImages.forEach(img => {\r\n            // Load low-quality placeholder\r\n            const lowQualitySrc = img.dataset.lowSrc || img.dataset.src.replace('_q85', '_q40');\r\n            const highQualitySrc = img.dataset.src;\r\n            \r\n            img.src = lowQualitySrc;\r\n            img.classList.add('loading');\r\n            \r\n            // Load high-quality version\r\n            const highQualityLoader = new Image();\r\n            highQualityLoader.onload = () => {\r\n                img.src = highQualitySrc;\r\n                img.classList.remove('loading');\r\n                img.classList.add('loaded');\r\n            };\r\n            highQualityLoader.src = highQualitySrc;\r\n        });\r\n    }\r\n    \r\n    lazyLoadingStrategy(productImages) {\r\n        // Use Intersection Observer for lazy loading\r\n        const observer = new IntersectionObserver((entries) => {\r\n            entries.forEach(entry => {\r\n                if (entry.isIntersecting) {\r\n                    this.loadImage(entry.target);\r\n                    observer.unobserve(entry.target);\r\n                }\r\n            });\r\n        }, { rootMargin: '100px' });\r\n        \r\n        productImages.forEach(img => observer.observe(img));\r\n    }\r\n    \r\n    adaptiveLoadingStrategy(productImages) {\r\n        // Adapt based on user interaction and scroll behavior\r\n        let scrollTimeout;\r\n        let isScrolling = false;\r\n        \r\n        window.addEventListener('scroll', () => {\r\n            if (!isScrolling) {\r\n                isScrolling = true;\r\n                // Load visible images immediately when scrolling starts\r\n                this.loadVisibleImages(productImages);\r\n            }\r\n            \r\n            clearTimeout(scrollTimeout);\r\n            scrollTimeout = setTimeout(() => {\r\n                isScrolling = false;\r\n            }, 150);\r\n        });\r\n        \r\n        // Load critical above-fold images immediately\r\n        this.loadCriticalImages(productImages);\r\n        \r\n        // Lazy load remaining images\r\n        this.lazyLoadingStrategy(productImages.filter(img => !img.dataset.critical));\r\n    }\r\n    \r\n    loadCriticalImages(productImages) {\r\n        const criticalImages = productImages.filter(img => \r\n            img.dataset.critical === 'true' || \r\n            img.getBoundingClientRect().top \u003C window.innerHeight\r\n        );\r\n        \r\n        criticalImages.forEach(img => this.loadImage(img));\r\n    }\r\n    \r\n    loadVisibleImages(productImages) {\r\n        const visibleImages = productImages.filter(img => {\r\n            const rect = img.getBoundingClientRect();\r\n            return rect.top \u003C window.innerHeight && rect.bottom > 0;\r\n        });\r\n        \r\n        visibleImages.forEach(img => this.loadImage(img));\r\n    }\r\n    \r\n    loadImage(img) {\r\n        if (img.dataset.loaded) return;\r\n        \r\n        const imageLoader = new Image();\r\n        imageLoader.onload = () => {\r\n            img.src = imageLoader.src;\r\n            if (img.dataset.srcset) {\r\n                img.srcset = img.dataset.srcset;\r\n            }\r\n            img.classList.add('loaded');\r\n            img.dataset.loaded = 'true';\r\n        };\r\n        \r\n        imageLoader.src = img.dataset.src;\r\n    }\r\n}\r\n\r\n// Initialize for product pages\r\ndocument.addEventListener('DOMContentLoaded', () => {\r\n    const imageLoader = new EcommerceImageLoader();\r\n    const productImages = document.querySelectorAll('.product-image[data-src]');\r\n    \r\n    if (productImages.length > 0) {\r\n        const strategy = imageLoader.selectOptimalStrategy();\r\n        imageLoader.loadingStrategies[strategy](productImages);\r\n    }\r\n});\r\n```\r\n\r\n## Image Zoom and 360° View Optimization\r\n\r\n### Efficient Zoom Implementation\r\n\r\nOptimized image zoom functionality for product detail pages:\r\n\r\n```javascript\r\nclass ProductImageZoom {\r\n    constructor(options = {}) {\r\n        this.container = options.container;\r\n        this.zoomLevel = options.zoomLevel || 2;\r\n        this.loadingStrategy = options.loadingStrategy || 'on-demand';\r\n        this.highResImages = new Map();\r\n        \r\n        this.initializeZoom();\r\n    }\r\n    \r\n    initializeZoom() {\r\n        const zoomImages = this.container.querySelectorAll('.zoomable-image');\r\n        \r\n        zoomImages.forEach(img => {\r\n            img.addEventListener('mouseenter', this.handleMouseEnter.bind(this));\r\n            img.addEventListener('mouseleave', this.handleMouseLeave.bind(this));\r\n            img.addEventListener('mousemove', this.handleMouseMove.bind(this));\r\n        });\r\n    }\r\n    \r\n    async handleMouseEnter(event) {\r\n        const img = event.target;\r\n        const highResUrl = img.dataset.zoomSrc;\r\n        \r\n        if (!highResUrl) return;\r\n        \r\n        // Load high-resolution image on demand\r\n        if (!this.highResImages.has(highResUrl)) {\r\n            this.loadHighResImage(highResUrl);\r\n        }\r\n        \r\n        this.showZoomOverlay(img);\r\n    }\r\n    \r\n    loadHighResImage(url) {\r\n        return new Promise((resolve, reject) => {\r\n            const img = new Image();\r\n            img.onload = () => {\r\n                this.highResImages.set(url, img);\r\n                resolve(img);\r\n            };\r\n            img.onerror = reject;\r\n            img.src = url;\r\n        });\r\n    }\r\n    \r\n    showZoomOverlay(img) {\r\n        // Create zoom overlay if it doesn't exist\r\n        let overlay = img.parentNode.querySelector('.zoom-overlay');\r\n        if (!overlay) {\r\n            overlay = document.createElement('div');\r\n            overlay.className = 'zoom-overlay';\r\n            overlay.style.cssText = `\r\n                position: absolute;\r\n                top: 0;\r\n                left: 100%;\r\n                width: 300px;\r\n                height: 300px;\r\n                border: 1px solid #ddd;\r\n                background: white;\r\n                overflow: hidden;\r\n                z-index: 1000;\r\n                display: none;\r\n            `;\r\n            img.parentNode.appendChild(overlay);\r\n        }\r\n        \r\n        overlay.style.display = 'block';\r\n    }\r\n    \r\n    handleMouseMove(event) {\r\n        const img = event.target;\r\n        const overlay = img.parentNode.querySelector('.zoom-overlay');\r\n        const highResUrl = img.dataset.zoomSrc;\r\n        \r\n        if (!overlay || !this.highResImages.has(highResUrl)) return;\r\n        \r\n        const rect = img.getBoundingClientRect();\r\n        const x = (event.clientX - rect.left) / rect.width;\r\n        const y = (event.clientY - rect.top) / rect.height;\r\n        \r\n        const highResImg = this.highResImages.get(highResUrl);\r\n        \r\n        // Update zoom overlay\r\n        overlay.style.backgroundImage = `url(${highResUrl})`;\r\n        overlay.style.backgroundSize = `${highResImg.width}px ${highResImg.height}px`;\r\n        overlay.style.backgroundPosition = `-${x * (highResImg.width - 300)}px -${y * (highResImg.height - 300)}px`;\r\n    }\r\n    \r\n    handleMouseLeave(event) {\r\n        const img = event.target;\r\n        const overlay = img.parentNode.querySelector('.zoom-overlay');\r\n        \r\n        if (overlay) {\r\n            overlay.style.display = 'none';\r\n        }\r\n    }\r\n}\r\n\r\n// 360° product view optimization\r\nclass Product360View {\r\n    constructor(container, options = {}) {\r\n        this.container = container;\r\n        this.frameCount = options.frameCount || 36;\r\n        this.autoPlay = options.autoPlay || false;\r\n        this.frames = [];\r\n        this.currentFrame = 0;\r\n        this.isLoading = false;\r\n        \r\n        this.initialize();\r\n    }\r\n    \r\n    async initialize() {\r\n        await this.loadFrames();\r\n        this.setupControls();\r\n        this.setupInteraction();\r\n    }\r\n    \r\n    async loadFrames() {\r\n        this.isLoading = true;\r\n        const baseUrl = this.container.dataset.baseUrl;\r\n        \r\n        // Load frames progressively\r\n        const loadPromises = [];\r\n        \r\n        for (let i = 1; i \u003C= this.frameCount; i++) {\r\n            const frameUrl = `${baseUrl}/frame_${i.toString().padStart(3, '0')}.jpg`;\r\n            loadPromises.push(this.loadFrame(frameUrl, i - 1));\r\n        }\r\n        \r\n        // Load first few frames immediately, rest progressively\r\n        await Promise.all(loadPromises.slice(0, 8));\r\n        \r\n        // Load remaining frames in background\r\n        Promise.all(loadPromises.slice(8));\r\n        \r\n        this.isLoading = false;\r\n        this.displayFrame(0);\r\n    }\r\n    \r\n    loadFrame(url, index) {\r\n        return new Promise((resolve) => {\r\n            const img = new Image();\r\n            img.onload = () => {\r\n                this.frames[index] = img;\r\n                resolve();\r\n            };\r\n            img.onerror = () => {\r\n                // Create placeholder for failed loads\r\n                this.frames[index] = null;\r\n                resolve();\r\n            };\r\n            img.src = url;\r\n        });\r\n    }\r\n    \r\n    displayFrame(frameIndex) {\r\n        if (!this.frames[frameIndex]) return;\r\n        \r\n        const img = this.container.querySelector('.view-360-image') || \r\n                   this.createImageElement();\r\n        \r\n        img.src = this.frames[frameIndex].src;\r\n        this.currentFrame = frameIndex;\r\n    }\r\n    \r\n    createImageElement() {\r\n        const img = document.createElement('img');\r\n        img.className = 'view-360-image';\r\n        img.style.cssText = 'width: 100%; height: auto; display: block;';\r\n        this.container.appendChild(img);\r\n        return img;\r\n    }\r\n    \r\n    setupInteraction() {\r\n        let isDragging = false;\r\n        let startX = 0;\r\n        let startFrame = 0;\r\n        \r\n        this.container.addEventListener('mousedown', (e) => {\r\n            isDragging = true;\r\n            startX = e.clientX;\r\n            startFrame = this.currentFrame;\r\n            e.preventDefault();\r\n        });\r\n        \r\n        document.addEventListener('mousemove', (e) => {\r\n            if (!isDragging) return;\r\n            \r\n            const deltaX = e.clientX - startX;\r\n            const sensitivity = 2; // Pixels per frame\r\n            const frameChange = Math.floor(deltaX / sensitivity);\r\n            \r\n            let newFrame = (startFrame + frameChange) % this.frameCount;\r\n            if (newFrame \u003C 0) newFrame += this.frameCount;\r\n            \r\n            this.displayFrame(newFrame);\r\n        });\r\n        \r\n        document.addEventListener('mouseup', () => {\r\n            isDragging = false;\r\n        });\r\n    }\r\n}\r\n```\r\n\r\n## Performance Monitoring and Analytics\r\n\r\n### E-commerce Image Performance Tracking\r\n\r\nComprehensive performance monitoring for e-commerce images:\r\n\r\n```javascript\r\nclass EcommerceImageAnalytics {\r\n    constructor() {\r\n        this.metrics = {\r\n            imageLoadTimes: [],\r\n            conversionTracking: new Map(),\r\n            userInteractions: [],\r\n            performanceImpact: []\r\n        };\r\n        \r\n        this.startMonitoring();\r\n    }\r\n    \r\n    startMonitoring() {\r\n        // Monitor image loading performance\r\n        new PerformanceObserver((list) => {\r\n            const entries = list.getEntries();\r\n            entries.forEach(entry => {\r\n                if (this.isProductImage(entry.name)) {\r\n                    this.trackImagePerformance(entry);\r\n                }\r\n            });\r\n        }).observe({ entryTypes: ['resource'] });\r\n        \r\n        // Monitor user interactions with images\r\n        this.trackImageInteractions();\r\n        \r\n        // Monitor conversion correlation\r\n        this.trackConversionCorrelation();\r\n    }\r\n    \r\n    isProductImage(url) {\r\n        return url.includes('/products/') || \r\n               url.includes('product-images') ||\r\n               url.match(/\\/(hero|gallery|thumbnail|zoom)\\//);\r\n    }\r\n    \r\n    trackImagePerformance(entry) {\r\n        const imageData = {\r\n            url: entry.name,\r\n            loadTime: entry.responseEnd - entry.requestStart,\r\n            fileSize: entry.transferSize,\r\n            renderTime: entry.responseEnd,\r\n            imageType: this.categorizeImage(entry.name),\r\n            timestamp: Date.now()\r\n        };\r\n        \r\n        this.metrics.imageLoadTimes.push(imageData);\r\n        \r\n        // Send to analytics if load time is concerning\r\n        if (imageData.loadTime > 2000) {\r\n            this.reportSlowImage(imageData);\r\n        }\r\n    }\r\n    \r\n    categorizeImage(url) {\r\n        if (url.includes('hero')) return 'hero';\r\n        if (url.includes('thumbnail')) return 'thumbnail';\r\n        if (url.includes('gallery')) return 'gallery';\r\n        if (url.includes('zoom')) return 'zoom';\r\n        return 'other';\r\n    }\r\n    \r\n    trackImageInteractions() {\r\n        // Track image zoom usage\r\n        document.addEventListener('mouseenter', (e) => {\r\n            if (e.target.classList.contains('zoomable-image')) {\r\n                this.recordInteraction('zoom_hover', e.target);\r\n            }\r\n        });\r\n        \r\n        // Track image gallery navigation\r\n        document.addEventListener('click', (e) => {\r\n            if (e.target.classList.contains('gallery-thumbnail')) {\r\n                this.recordInteraction('gallery_click', e.target);\r\n            }\r\n        });\r\n        \r\n        // Track 360° view interactions\r\n        document.addEventListener('mousedown', (e) => {\r\n            if (e.target.closest('.view-360')) {\r\n                this.recordInteraction('360_interact', e.target);\r\n            }\r\n        });\r\n    }\r\n    \r\n    recordInteraction(type, element) {\r\n        const interaction = {\r\n            type: type,\r\n            productId: element.dataset.productId || this.extractProductId(element),\r\n            timestamp: Date.now(),\r\n            elementSrc: element.src || element.dataset.src,\r\n            loadTime: this.getImageLoadTime(element.src)\r\n        };\r\n        \r\n        this.metrics.userInteractions.push(interaction);\r\n    }\r\n    \r\n    trackConversionCorrelation() {\r\n        // Track when users add to cart after image interactions\r\n        document.addEventListener('click', (e) => {\r\n            if (e.target.matches('.add-to-cart, .buy-now')) {\r\n                const productId = this.extractProductId(e.target);\r\n                this.correlateWithImageInteractions(productId);\r\n            }\r\n        });\r\n    }\r\n    \r\n    correlateWithImageInteractions(productId) {\r\n        const recentInteractions = this.metrics.userInteractions\r\n            .filter(interaction => \r\n                interaction.productId === productId &&\r\n                Date.now() - interaction.timestamp \u003C 300000 // Last 5 minutes\r\n            );\r\n        \r\n        if (recentInteractions.length > 0) {\r\n            this.metrics.conversionTracking.set(productId, {\r\n                interactions: recentInteractions,\r\n                conversionTime: Date.now()\r\n            });\r\n        }\r\n    }\r\n    \r\n    generatePerformanceReport() {\r\n        const avgLoadTime = this.calculateAverageLoadTime();\r\n        const slowImages = this.identifySlowImages();\r\n        const interactionCorrelation = this.analyzeInteractionCorrelation();\r\n        \r\n        return {\r\n            averageImageLoadTime: avgLoadTime,\r\n            slowestImages: slowImages,\r\n            interactionToConversionRate: interactionCorrelation,\r\n            recommendations: this.generateRecommendations(avgLoadTime, slowImages)\r\n        };\r\n    }\r\n    \r\n    calculateAverageLoadTime() {\r\n        const loadTimes = this.metrics.imageLoadTimes.map(img => img.loadTime);\r\n        return loadTimes.reduce((sum, time) => sum + time, 0) / loadTimes.length;\r\n    }\r\n    \r\n    identifySlowImages() {\r\n        return this.metrics.imageLoadTimes\r\n            .filter(img => img.loadTime > 2000)\r\n            .sort((a, b) => b.loadTime - a.loadTime)\r\n            .slice(0, 10);\r\n    }\r\n    \r\n    analyzeInteractionCorrelation() {\r\n        const totalInteractions = this.metrics.userInteractions.length;\r\n        const conversionsWithInteractions = this.metrics.conversionTracking.size;\r\n        \r\n        return totalInteractions > 0 ? \r\n            (conversionsWithInteractions / totalInteractions) * 100 : 0;\r\n    }\r\n    \r\n    generateRecommendations(avgLoadTime, slowImages) {\r\n        const recommendations = [];\r\n        \r\n        if (avgLoadTime > 1500) {\r\n            recommendations.push('Consider more aggressive image compression');\r\n            recommendations.push('Implement WebP format for better compression');\r\n        }\r\n        \r\n        if (slowImages.length > 0) {\r\n            recommendations.push('Optimize the slowest loading product images');\r\n            recommendations.push('Consider lazy loading for gallery images');\r\n        }\r\n        \r\n        const heroImages = slowImages.filter(img => img.imageType === 'hero');\r\n        if (heroImages.length > 0) {\r\n            recommendations.push('Prioritize hero image optimization for faster first impressions');\r\n        }\r\n        \r\n        return recommendations;\r\n    }\r\n    \r\n    extractProductId(element) {\r\n        // Try various methods to extract product ID\r\n        return element.dataset.productId ||\r\n               element.closest('[data-product-id]')?.dataset.productId ||\r\n               window.location.pathname.match(/\\/products\\/([^\\/]+)/)?.[1] ||\r\n               'unknown';\r\n    }\r\n    \r\n    getImageLoadTime(src) {\r\n        const imageMetric = this.metrics.imageLoadTimes.find(img => img.url.includes(src));\r\n        return imageMetric ? imageMetric.loadTime : null;\r\n    }\r\n    \r\n    reportSlowImage(imageData) {\r\n        // Send to analytics service\r\n        if (typeof gtag !== 'undefined') {\r\n            gtag('event', 'slow_image_load', {\r\n                'url': imageData.url,\r\n                'load_time': imageData.loadTime,\r\n                'file_size': imageData.fileSize,\r\n                'image_type': imageData.imageType\r\n            });\r\n        }\r\n    }\r\n}\r\n\r\n// Initialize analytics\r\nconst imageAnalytics = new EcommerceImageAnalytics();\r\n\r\n// Generate report periodically\r\nsetInterval(() => {\r\n    const report = imageAnalytics.generatePerformanceReport();\r\n    console.log('E-commerce Image Performance Report:', report);\r\n}, 300000); // Every 5 minutes\r\n```\r\n\r\n## Conclusion\r\n\r\nE-commerce product image optimization is a critical factor in online retail success, directly impacting conversion rates, user experience, and search rankings. The key is finding the optimal balance between image quality and performance while considering the specific requirements of different product categories and platforms.\r\n\r\nSuccessful e-commerce image optimization requires:\r\n\r\n1. **Category-specific approaches**: Different product types need different optimization strategies\r\n2. **Platform compliance**: Understanding and adhering to marketplace requirements\r\n3. **Performance monitoring**: Continuous tracking of image performance and user behavior\r\n4. **Advanced loading strategies**: Intelligent loading based on user context and device capabilities\r\n5. **Quality preservation**: Maintaining visual appeal while optimizing file sizes\r\n\r\nAs e-commerce continues to evolve with new technologies like AR product visualization, better compression algorithms, and improved mobile experiences, staying current with optimization techniques while maintaining focus on conversion-driven results will remain essential for competitive advantage.\r\n\r\nThe future of e-commerce image optimization lies in AI-powered systems that can automatically optimize images based on user behavior, device capabilities, and conversion patterns while maintaining the visual quality necessary to drive sales and customer satisfaction. ","# Eコマース商品画像圧縮：売上重視の最適化\r\n\r\nEコマースの成功は商品画像の品質に大きく依存しており、研究によると消費者の67%がオンライン購入時に画像品質を「非常に重要」と考えています。しかし、大きな画像ファイルはページの読み込み時間、コンバージョン率、モバイルユーザーエクスペリエンスに大きな影響を与える可能性があります。この包括的なガイドでは、売上促進に必要な視覚品質を維持しながら、Eコマース商品画像を最適化する高度な技術について説明します。\r\n\r\n## なぜEコマース画像最適化が重要なのか\r\n\r\n### コンバージョン率への影響\r\n\r\n商品画像の最適化はビジネス指標に直接影響します：\r\n- **コンバージョン率**: ページ読み込み時間の1秒の遅延でコンバージョンが7%減少\r\n- **直帰率**: ユーザーの40%が3秒以上かかるサイトを離脱\r\n- **モバイルコマース**: Eコマーストラフィックの73%がモバイルデバイスから\r\n- **検索ランキング**: Googleは検索ランキングにページ速度を考慮\r\n- **顧客満足度**: 高品質な画像は購入信頼度を向上\r\n\r\n### Eコマース固有の要件\r\n\r\n商品画像には独特の最適化課題があります：\r\n- **複数の商品ビュー**: メイン画像、サムネイル、ズームビュー、360°回転\r\n- **色精度**: ファッション、化粧品、インテリアにとって重要\r\n- **詳細保持**: 顧客はテクスチャ、素材、職人技を見る必要がある\r\n- **読み込みパフォーマンス**: 品質と速度のバランス\r\n- **クロスデバイス互換性**: すべてのデバイスで一貫した体験\r\n\r\n## Eコマース画像タイプの理解\r\n\r\n### 商品画像カテゴリ\r\n\r\n異なる画像タイプには異なる最適化アプローチが必要です：\r\n\r\n```javascript\r\nconst ecommerceImageTypes = {\r\n    hero: {\r\n        purpose: '主要商品ショーケース',\r\n        requirements: '高品質、高速読み込み',\r\n        sizes: ['1200x1200', '800x800', '600x600'],\r\n        quality: { jpeg: 85, webp: 80 }\r\n    },\r\n    thumbnail: {\r\n        purpose: '商品グリッド表示',\r\n        requirements: '小さなファイルサイズ、認識可能',\r\n        sizes: ['300x300', '200x200', '150x150'],\r\n        quality: { jpeg: 75, webp: 70 }\r\n    },\r\n    zoom: {\r\n        purpose: '詳細商品検査',\r\n        requirements: '最大詳細保持',\r\n        sizes: ['2000x2000', '1600x1600'],\r\n        quality: { jpeg: 90, webp: 85 }\r\n    },\r\n    gallery: {\r\n        purpose: '複数商品アングル',\r\n        requirements: '一貫した品質、遅延読み込み',\r\n        sizes: ['800x800', '600x600'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    },\r\n    lifestyle: {\r\n        purpose: '使用中/コンテキスト内の商品',\r\n        requirements: '感情/コンテキスト最適化',\r\n        sizes: ['1200x800', '800x533'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    }\r\n};\r\n```\r\n\r\n### 商品カテゴリ別最適化戦略\r\n\r\n異なる商品カテゴリには特定の画像要件があります：\r\n\r\n```python\r\ndef get_category_optimization_settings(product_category):\r\n    \"\"\"異なる商品カテゴリの最適化設定を取得\"\"\"\r\n    settings = {\r\n        'fashion': {\r\n            'priority': ['color_accuracy', 'texture_detail'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 90},\r\n            'critical_views': ['front', 'back', 'detail']\r\n        },\r\n        'electronics': {\r\n            'priority': ['detail_preservation', 'fast_loading'],\r\n            'format_preference': 'webp_or_avif',\r\n            'quality_range': {'min': 75, 'max': 85},\r\n            'critical_views': ['main', 'interfaces', 'size_comparison']\r\n        },\r\n        'home_decor': {\r\n            'priority': ['color_accuracy', 'lifestyle_context'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 88},\r\n            'critical_views': ['styled', 'closeup', 'dimensions']\r\n        },\r\n        'jewelry': {\r\n            'priority': ['maximum_detail', 'color_accuracy'],\r\n            'format_preference': 'png_for_detailed_webp_for_hero',\r\n            'quality_range': {'min': 85, 'max': 95},\r\n            'critical_views': ['macro', '360_spin', 'lifestyle']\r\n        },\r\n        'books': {\r\n            'priority': ['fast_loading', 'text_readability'],\r\n            'format_preference': 'webp_aggressive_compression',\r\n            'quality_range': {'min': 70, 'max': 80},\r\n            'critical_views': ['cover', 'back', 'spine']\r\n        }\r\n    }\r\n    return settings.get(product_category, settings['electronics'])\r\n```\r\n\r\n## 高度な商品画像処理\r\n\r\n### 自動商品画像パイプライン\r\n\r\n包括的な自動処理システム：\r\n\r\n```python\r\nimport os\r\nfrom PIL import Image, ImageEnhance, ImageFilter\r\nimport numpy as np\r\n\r\nclass EcommerceImageProcessor:\r\n    def __init__(self, config=None):\r\n        self.config = config or self.get_default_config()\r\n        self.supported_formats = ['jpeg', 'webp', 'avif', 'png']\r\n        \r\n    def get_default_config(self):\r\n        return {\r\n            'background_removal': True,\r\n            'auto_crop': True,\r\n            'color_enhancement': True,\r\n            'noise_reduction': True,\r\n            'watermark': False,\r\n            'quality_thresholds': {\r\n                'hero': 85,\r\n                'gallery': 80,\r\n                'thumbnail': 75,\r\n                'zoom': 90\r\n            }\r\n        }\r\n    \r\n    def process_product_image(self, input_path, output_dir, product_id):\r\n        \"\"\"単一商品画像を必要なすべてのバリアントに処理\"\"\"\r\n        img = Image.open(input_path)\r\n        \r\n        # 基本前処理\r\n        processed_img = self.preprocess_image(img)\r\n        \r\n        # 必要なすべてのサイズと形式を生成\r\n        variants = self.generate_image_variants(processed_img, product_id)\r\n        \r\n        # 最適化されたバージョンを保存\r\n        saved_files = self.save_variants(variants, output_dir)\r\n        \r\n        return saved_files\r\n    \r\n    def preprocess_image(self, img):\r\n        \"\"\"商品画像に基本前処理を適用\"\"\"\r\n        # 必要に応じてRGBに変換\r\n        if img.mode in ('RGBA', 'LA', 'P'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            if img.mode == 'RGBA':\r\n                background.paste(img, mask=img.split()[-1])\r\n            else:\r\n                background.paste(img)\r\n            img = background\r\n        \r\n        # 余分な空白を削除するための自動クロップ\r\n        if self.config['auto_crop']:\r\n            img = self.smart_crop(img)\r\n        \r\n        # 画像品質を向上\r\n        if self.config['color_enhancement']:\r\n            img = self.enhance_product_image(img)\r\n        \r\n        # ノイズを削減\r\n        if self.config['noise_reduction']:\r\n            img = img.filter(ImageFilter.SMOOTH_MORE)\r\n        \r\n        return img\r\n    \r\n    def smart_crop(self, img):\r\n        \"\"\"余分な背景を削除するために商品画像をスマートクロップ\"\"\"\r\n        # 分析のためにnumpy配列に変換\r\n        img_array = np.array(img)\r\n        \r\n        # 非白ピクセルのバウンディングボックスを見つける\r\n        mask = np.any(img_array \u003C 240, axis=2)  # 純白ではない\r\n        coords = np.argwhere(mask)\r\n        \r\n        if len(coords) == 0:\r\n            return img  # クロップ不要\r\n        \r\n        # バウンディングボックスを取得\r\n        y0, x0 = coords.min(axis=0)\r\n        y1, x1 = coords.max(axis=0)\r\n        \r\n        # パディングを追加\r\n        padding = 20\r\n        y0 = max(0, y0 - padding)\r\n        x0 = max(0, x0 - padding)\r\n        y1 = min(img.height, y1 + padding)\r\n        x1 = min(img.width, x1 + padding)\r\n        \r\n        return img.crop((x0, y0, x1, y1))\r\n    \r\n    def enhance_product_image(self, img):\r\n        \"\"\"商品画像の品質を向上\"\"\"\r\n        # コントラストを向上\r\n        enhancer = ImageEnhance.Contrast(img)\r\n        img = enhancer.enhance(1.1)\r\n        \r\n        # 色彩度を微調整\r\n        enhancer = ImageEnhance.Color(img)\r\n        img = enhancer.enhance(1.05)\r\n        \r\n        # シャープネスを向上\r\n        enhancer = ImageEnhance.Sharpness(img)\r\n        img = enhancer.enhance(1.1)\r\n        \r\n        return img\r\n    \r\n    def generate_image_variants(self, img, product_id):\r\n        \"\"\"異なるサイズと形式で画像バリアントを生成\"\"\"\r\n        variants = {}\r\n        \r\n        # 標準サイズを定義\r\n        sizes = {\r\n            'hero': [(1200, 1200), (800, 800), (600, 600)],\r\n            'thumbnail': [(300, 300), (200, 200), (150, 150)],\r\n            'zoom': [(2000, 2000), (1600, 1600)],\r\n            'gallery': [(800, 800), (600, 600)]\r\n        }\r\n        \r\n        for variant_type, size_list in sizes.items():\r\n            variants[variant_type] = {}\r\n            for size in size_list:\r\n                # 適切な品質で画像をリサイズ\r\n                resized_img = self.resize_with_quality(img, size)\r\n                variants[variant_type][f\"{size[0]}x{size[1]}\"] = resized_img\r\n        \r\n        return variants\r\n    \r\n    def resize_with_quality(self, img, target_size):\r\n        \"\"\"高品質で画像をリサイズ\"\"\"\r\n        # アスペクト比を維持\r\n        img.thumbnail(target_size, Image.Resampling.LANCZOS)\r\n        \r\n        # 必要に応じて白い背景で新しい画像を作成\r\n        if img.size != target_size:\r\n            new_img = Image.new('RGB', target_size, (255, 255, 255))\r\n            # 画像を中央に配置\r\n            paste_x = (target_size[0] - img.size[0]) // 2\r\n            paste_y = (target_size[1] - img.size[1]) // 2\r\n            new_img.paste(img, (paste_x, paste_y))\r\n            return new_img\r\n        \r\n        return img\r\n    \r\n    def save_variants(self, variants, output_dir):\r\n        \"\"\"最適化された形式で画像バリアントを保存\"\"\"\r\n        saved_files = []\r\n        \r\n        for variant_type, sizes in variants.items():\r\n            variant_dir = os.path.join(output_dir, variant_type)\r\n            os.makedirs(variant_dir, exist_ok=True)\r\n            \r\n            for size_name, img in sizes.items():\r\n                # JPEGを保存\r\n                jpeg_path = os.path.join(variant_dir, f\"{size_name}.jpg\")\r\n                quality = self.config['quality_thresholds'].get(variant_type, 80)\r\n                img.save(jpeg_path, 'JPEG', quality=quality, optimize=True)\r\n                saved_files.append(jpeg_path)\r\n                \r\n                # WebPを保存\r\n                webp_path = os.path.join(variant_dir, f\"{size_name}.webp\")\r\n                webp_quality = max(quality - 5, 70)  # WebPは通常より良い圧縮\r\n                img.save(webp_path, 'WebP', quality=webp_quality, optimize=True)\r\n                saved_files.append(webp_path)\r\n        \r\n        return saved_files\r\n```\r\n\r\n## Amazonマーケットプレイス最適化\r\n\r\n### Amazon画像要件\r\n\r\nAmazon固有の画像最適化要件：\r\n\r\n```python\r\nclass AmazonImageOptimizer:\r\n    def __init__(self):\r\n        self.amazon_requirements = {\r\n            'main_image': {\r\n                'min_size': (1000, 1000),\r\n                'max_size': (10000, 10000),\r\n                'background': 'pure_white',\r\n                'format': ['JPEG', 'PNG', 'GIF'],\r\n                'quality_min': 85\r\n            },\r\n            'additional_images': {\r\n                'min_size': (500, 500),\r\n                'recommended_size': (1600, 1600),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'max_count': 8\r\n            },\r\n            'zoom_functionality': {\r\n                'min_size': (1001, 1001),\r\n                'recommended_size': (2000, 2000),\r\n                'enables_zoom': True\r\n            }\r\n        }\r\n    \r\n    def optimize_for_amazon(self, image_path, image_type='main'):\r\n        \"\"\"Amazon要件に合わせて画像を最適化\"\"\"\r\n        img = Image.open(image_path)\r\n        requirements = self.amazon_requirements[f\"{image_type}_image\"]\r\n        \r\n        # サイズをチェックして修正\r\n        if img.size[0] \u003C requirements['min_size'][0] or img.size[1] \u003C requirements['min_size'][1]:\r\n            # 小さすぎる場合は画像を拡大\r\n            img = self.upscale_image(img, requirements['min_size'])\r\n        \r\n        # メイン画像の白い背景を確保\r\n        if image_type == 'main' and requirements.get('background') == 'pure_white':\r\n            img = self.ensure_white_background(img)\r\n        \r\n        # 最適化して保存\r\n        return self.save_amazon_optimized(img, image_path, image_type)\r\n    \r\n    def ensure_white_background(self, img):\r\n        \"\"\"純白の背景を確保\"\"\"\r\n        if img.mode in ('RGBA', 'LA'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            background.paste(img, mask=img.split()[-1])\r\n            return background\r\n        elif img.mode == 'P':\r\n            return img.convert('RGB')\r\n        return img\r\n    \r\n    def upscale_image(self, img, min_size):\r\n        \"\"\"画像を最小サイズまで拡大\"\"\"\r\n        scale_factor = max(min_size[0] / img.size[0], min_size[1] / img.size[1])\r\n        new_size = (int(img.size[0] * scale_factor), int(img.size[1] * scale_factor))\r\n        return img.resize(new_size, Image.Resampling.LANCZOS)\r\n```\r\n\r\n## パフォーマンス測定とモニタリング\r\n\r\n### 画像最適化メトリクス\r\n\r\n主要パフォーマンス指標の追跡：\r\n\r\n```python\r\nimport time\r\nimport requests\r\nfrom PIL import Image\r\nimport os\r\n\r\nclass ImagePerformanceMonitor:\r\n    def __init__(self):\r\n        self.metrics = {\r\n            'file_sizes': {},\r\n            'load_times': {},\r\n            'quality_scores': {},\r\n            'conversion_impact': {}\r\n        }\r\n    \r\n    def measure_optimization_impact(self, original_path, optimized_path):\r\n        \"\"\"最適化の影響を測定\"\"\"\r\n        # ファイルサイズ比較\r\n        original_size = os.path.getsize(original_path)\r\n        optimized_size = os.path.getsize(optimized_path)\r\n        size_reduction = ((original_size - optimized_size) / original_size) * 100\r\n        \r\n        # 画像品質評価\r\n        quality_score = self.calculate_quality_score(original_path, optimized_path)\r\n        \r\n        # 読み込み時間改善のシミュレーション\r\n        load_time_improvement = self.simulate_load_time_improvement(\r\n            original_size, optimized_size\r\n        )\r\n        \r\n        return {\r\n            'size_reduction_percent': size_reduction,\r\n            'quality_retention_percent': quality_score,\r\n            'load_time_improvement_ms': load_time_improvement,\r\n            'optimization_ratio': size_reduction / (100 - quality_score) if quality_score \u003C 100 else size_reduction\r\n        }\r\n    \r\n    def calculate_quality_score(self, original_path, optimized_path):\r\n        \"\"\"画像品質スコアを計算\"\"\"\r\n        try:\r\n            from skimage.metrics import structural_similarity as ssim\r\n            import numpy as np\r\n            \r\n            # 画像を読み込んで変換\r\n            original = np.array(Image.open(original_path).convert('RGB'))\r\n            optimized = np.array(Image.open(optimized_path).convert('RGB'))\r\n            \r\n            # SSIMを計算\r\n            ssim_score = ssim(original, optimized, multichannel=True, channel_axis=2)\r\n            return ssim_score * 100\r\n        except ImportError:\r\n            # scikit-imageがない場合のサイズベースの簡単な推定\r\n            return 85.0  # デフォルト値\r\n    \r\n    def simulate_load_time_improvement(self, original_size, optimized_size):\r\n        \"\"\"読み込み時間改善をシミュレート\"\"\"\r\n        # 平均インターネット速度に基づく（5 Mbps）\r\n        avg_speed_bytes_per_ms = 5 * 1024 * 1024 / 8 / 1000  # 5 Mbpsをbytes/msに\r\n        \r\n        original_load_time = original_size / avg_speed_bytes_per_ms\r\n        optimized_load_time = optimized_size / avg_speed_bytes_per_ms\r\n        \r\n        return original_load_time - optimized_load_time\r\n    \r\n    def generate_performance_report(self, optimization_results):\r\n        \"\"\"パフォーマンスレポートを生成\"\"\"\r\n        report = {\r\n            'summary': {\r\n                'total_images_processed': len(optimization_results),\r\n                'average_size_reduction': sum(r['size_reduction_percent'] for r in optimization_results) / len(optimization_results),\r\n                'average_quality_retention': sum(r['quality_retention_percent'] for r in optimization_results) / len(optimization_results),\r\n                'total_load_time_saved_ms': sum(r['load_time_improvement_ms'] for r in optimization_results)\r\n            },\r\n            'recommendations': self.generate_recommendations(optimization_results)\r\n        }\r\n        return report\r\n    \r\n    def generate_recommendations(self, results):\r\n        \"\"\"最適化推奨事項を生成\"\"\"\r\n        recommendations = []\r\n        \r\n        avg_size_reduction = sum(r['size_reduction_percent'] for r in results) / len(results)\r\n        avg_quality = sum(r['quality_retention_percent'] for r in results) / len(results)\r\n        \r\n        if avg_size_reduction \u003C 30:\r\n            recommendations.append(\"より積極的な圧縮設定を適用\")\r\n        \r\n        if avg_quality \u003C 85:\r\n            recommendations.append(\"より良い視覚結果のために品質設定を微調整\")\r\n        \r\n        if any(r['load_time_improvement_ms'] > 500 for r in results):\r\n            recommendations.append(\"重要な画像の最適化を優先\")\r\n        \r\n        return recommendations\r\n```\r\n\r\n## 大規模カタログのバッチ処理\r\n\r\n### 並列画像処理\r\n\r\n大量の商品画像の効率的な処理：\r\n\r\n```python\r\nimport concurrent.futures\r\nimport multiprocessing\r\nfrom pathlib import Path\r\nimport logging\r\n\r\nclass BatchImageProcessor:\r\n    def __init__(self, max_workers=None):\r\n        self.max_workers = max_workers or multiprocessing.cpu_count()\r\n        self.processed_count = 0\r\n        self.failed_count = 0\r\n        \r\n        # ログ設定\r\n        logging.basicConfig(level=logging.INFO)\r\n        self.logger = logging.getLogger(__name__)\r\n    \r\n    def process_catalog(self, input_directory, output_directory, product_categories=None):\r\n        \"\"\"商品カタログ全体を処理\"\"\"\r\n        input_path = Path(input_directory)\r\n        output_path = Path(output_directory)\r\n        output_path.mkdir(parents=True, exist_ok=True)\r\n        \r\n        # 画像ファイルを収集\r\n        image_files = self.collect_image_files(input_path)\r\n        self.logger.info(f\"合計{len(image_files)}枚の画像が処理待ち\")\r\n        \r\n        # 並列処理\r\n        with concurrent.futures.ThreadPoolExecutor(max_workers=self.max_workers) as executor:\r\n            # タスクを送信\r\n            future_to_file = {\r\n                executor.submit(\r\n                    self.process_single_product_image, \r\n                    img_file, \r\n                    output_path,\r\n                    product_categories.get(img_file.stem) if product_categories else None\r\n                ): img_file \r\n                for img_file in image_files\r\n            }\r\n            \r\n            # 結果を処理\r\n            for future in concurrent.futures.as_completed(future_to_file):\r\n                img_file = future_to_file[future]\r\n                try:\r\n                    result = future.result()\r\n                    self.processed_count += 1\r\n                    if self.processed_count % 100 == 0:\r\n                        self.logger.info(f\"処理済み: {self.processed_count}/{len(image_files)}\")\r\n                except Exception as exc:\r\n                    self.failed_count += 1\r\n                    self.logger.error(f\"{img_file}の処理エラー: {exc}\")\r\n        \r\n        # サマリーレポートを生成\r\n        self.generate_batch_report(len(image_files))\r\n    \r\n    def collect_image_files(self, input_path):\r\n        \"\"\"入力ディレクトリから画像ファイルを収集\"\"\"\r\n        supported_extensions = {'.jpg', '.jpeg', '.png', '.webp', '.tiff', '.bmp'}\r\n        image_files = []\r\n        \r\n        for ext in supported_extensions:\r\n            image_files.extend(input_path.glob(f\"**/*{ext}\"))\r\n            image_files.extend(input_path.glob(f\"**/*{ext.upper()}\"))\r\n        \r\n        return image_files\r\n    \r\n    def process_single_product_image(self, image_path, output_dir, category=None):\r\n        \"\"\"単一商品画像を処理\"\"\"\r\n        try:\r\n            processor = EcommerceImageProcessor()\r\n            \r\n            # カテゴリ固有の設定を適用\r\n            if category:\r\n                category_settings = get_category_optimization_settings(category)\r\n                processor.config.update(category_settings)\r\n            \r\n            # 画像を処理\r\n            product_id = image_path.stem\r\n            result = processor.process_product_image(\r\n                str(image_path), \r\n                str(output_dir), \r\n                product_id\r\n            )\r\n            \r\n            return {\r\n                'status': 'success',\r\n                'input_file': str(image_path),\r\n                'output_files': result,\r\n                'product_id': product_id\r\n            }\r\n            \r\n        except Exception as e:\r\n            return {\r\n                'status': 'error',\r\n                'input_file': str(image_path),\r\n                'error': str(e)\r\n            }\r\n    \r\n    def generate_batch_report(self, total_files):\r\n        \"\"\"バッチ処理レポートを生成\"\"\"\r\n        success_rate = (self.processed_count / total_files) * 100\r\n        \r\n        report = f\"\"\"\r\n        バッチ画像処理レポート\r\n        ======================\r\n        総ファイル数: {total_files}\r\n        成功処理数: {self.processed_count}\r\n        失敗数: {self.failed_count}\r\n        成功率: {success_rate:.2f}%\r\n        \r\n        処理速度: {self.processed_count / self.max_workers:.2f} 画像/ワーカー\r\n        \"\"\"\r\n        \r\n        self.logger.info(report)\r\n        return report\r\n\r\n# 使用例\r\ndef optimize_ecommerce_catalog():\r\n    \"\"\"Eコマースカタログを最適化\"\"\"\r\n    # 商品カテゴリを定義\r\n    product_categories = {\r\n        'shirt_001': 'fashion',\r\n        'laptop_002': 'electronics',\r\n        'sofa_003': 'home_decor',\r\n        'ring_004': 'jewelry'\r\n    }\r\n    \r\n    # バッチプロセッサを初期化\r\n    batch_processor = BatchImageProcessor(max_workers=8)\r\n    \r\n    # カタログを処理\r\n    batch_processor.process_catalog(\r\n        input_directory='./raw_product_images',\r\n        output_directory='./optimized_product_images',\r\n        product_categories=product_categories\r\n    )\r\n\r\nif __name__ == \"__main__\":\r\n    optimize_ecommerce_catalog()\r\n```\r\n\r\n## 自動化と統合\r\n\r\n### Eコマースプラットフォーム統合\r\n\r\nEコマースシステム用の自動画像最適化：\r\n\r\n```python\r\nimport requests\r\nimport json\r\nfrom datetime import datetime\r\n\r\nclass EcommerceIntegration:\r\n    def __init__(self, platform_config):\r\n        self.platform = platform_config['platform']  # 'shopify', 'woocommerce', 'magento'\r\n        self.api_key = platform_config['api_key']\r\n        self.store_url = platform_config['store_url']\r\n        self.headers = self.setup_headers()\r\n    \r\n    def setup_headers(self):\r\n        \"\"\"プラットフォームに基づいてAPIヘッダーを設定\"\"\"\r\n        if self.platform == 'shopify':\r\n            return {\r\n                'X-Shopify-Access-Token': self.api_key,\r\n                'Content-Type': 'application/json'\r\n            }\r\n        elif self.platform == 'woocommerce':\r\n            return {\r\n                'Authorization': f'Bearer {self.api_key}',\r\n                'Content-Type': 'application/json'\r\n            }\r\n        return {'Content-Type': 'application/json'}\r\n    \r\n    def get_products_needing_optimization(self):\r\n        \"\"\"最適化が必要な商品を取得\"\"\"\r\n        if self.platform == 'shopify':\r\n            return self.get_shopify_products()\r\n        elif self.platform == 'woocommerce':\r\n            return self.get_woocommerce_products()\r\n        return []\r\n    \r\n    def get_shopify_products(self):\r\n        \"\"\"Shopify商品を取得\"\"\"\r\n        url = f\"{self.store_url}/admin/api/2023-01/products.json\"\r\n        response = requests.get(url, headers=self.headers)\r\n        \r\n        if response.status_code == 200:\r\n            products = response.json()['products']\r\n            return [\r\n                {\r\n                    'id': product['id'],\r\n                    'title': product['title'],\r\n                    'images': [img['src'] for img in product['images']]\r\n                }\r\n                for product in products\r\n            ]\r\n        return []\r\n    \r\n    def optimize_product_images(self, product_data):\r\n        \"\"\"商品画像を最適化してアップロード\"\"\"\r\n        optimized_images = []\r\n        \r\n        for image_url in product_data['images']:\r\n            try:\r\n                # 画像をダウンロード\r\n                response = requests.get(image_url)\r\n                if response.status_code == 200:\r\n                    # 一時ファイルを保存\r\n                    temp_path = f\"temp_{product_data['id']}.jpg\"\r\n                    with open(temp_path, 'wb') as f:\r\n                        f.write(response.content)\r\n                    \r\n                    # 最適化\r\n                    processor = EcommerceImageProcessor()\r\n                    optimized_files = processor.process_product_image(\r\n                        temp_path, \r\n                        f\"optimized_{product_data['id']}\", \r\n                        str(product_data['id'])\r\n                    )\r\n                    \r\n                    # 最適化された画像をアップロード\r\n                    uploaded_urls = self.upload_optimized_images(\r\n                        optimized_files, \r\n                        product_data['id']\r\n                    )\r\n                    optimized_images.extend(uploaded_urls)\r\n                    \r\n                    # 一時ファイルを削除\r\n                    os.remove(temp_path)\r\n                    \r\n            except Exception as e:\r\n                print(f\"画像最適化エラー: {e}\")\r\n        \r\n        return optimized_images\r\n    \r\n    def upload_optimized_images(self, image_files, product_id):\r\n        \"\"\"最適化された画像をプラットフォームにアップロード\"\"\"\r\n        uploaded_urls = []\r\n        \r\n        for image_file in image_files:\r\n            if self.platform == 'shopify':\r\n                url = self.upload_to_shopify(image_file, product_id)\r\n            elif self.platform == 'woocommerce':\r\n                url = self.upload_to_woocommerce(image_file, product_id)\r\n            \r\n            if url:\r\n                uploaded_urls.append(url)\r\n        \r\n        return uploaded_urls\r\n    \r\n    def schedule_optimization(self, schedule_config):\r\n        \"\"\"最適化をスケジュール\"\"\"\r\n        import schedule\r\n        import time\r\n        \r\n        def run_optimization():\r\n            products = self.get_products_needing_optimization()\r\n            for product in products:\r\n                self.optimize_product_images(product)\r\n                time.sleep(1)  # レート制限\r\n        \r\n        # スケジュールを設定\r\n        if schedule_config['frequency'] == 'daily':\r\n            schedule.every().day.at(schedule_config['time']).do(run_optimization)\r\n        elif schedule_config['frequency'] == 'weekly':\r\n            schedule.every().week.do(run_optimization)\r\n        \r\n        # スケジューラーを実行\r\n        while True:\r\n            schedule.run_pending()\r\n            time.sleep(60)\r\n```\r\n\r\n## 結論\r\n\r\nEコマース商品画像の最適化は、オンライン販売の成功にとって重要です。適切な圧縮技術を適用することで、画像品質を犠牲にすることなく、サイトのパフォーマンスを大幅に改善できます。\r\n\r\n### 主要な発見\r\n\r\n1. **カテゴリ固有の最適化**: 各商品カテゴリには独特の画像要件がある\r\n2. **自動化の重要性**: 大規模カタログにはバッチ処理が不可欠\r\n3. **パフォーマンス測定**: 最適な結果には定期的なモニタリングが必要\r\n4. **プラットフォーム統合**: Eコマースシステムとのスムーズなワークフロー\r\n5. **品質対速度**: ビジネス目標に適したバランスを見つける\r\n\r\n### 実装推奨事項\r\n\r\n- 最も重要な商品画像（メイン画像、ベストセラー商品）から始める\r\n- 小さなサンプルで最適化設定をテストする\r\n- コンバージョン率への影響を測定する\r\n- 一貫性のためにプロセスを自動化する\r\n- 最適化戦略を定期的に更新する\r\n\r\n適切に実装された画像最適化戦略は、サイト速度、ユーザーエクスペリエンス、そして最終的には販売結果の大幅な改善をもたらすことができます。","# 전자상거래 제품 이미지 압축: 판매 중심 최적화\r\n\r\n전자상거래의 성공은 제품 이미지 품질에 크게 의존하며, 연구에 따르면 소비자의 67%가 온라인 구매 시 이미지 품질을 \"매우 중요하다\"고 여깁니다. 그러나 큰 이미지 파일은 페이지 로딩 시간, 전환율, 모바일 사용자 경험에 상당한 영향을 미칠 수 있습니다. 이 포괄적인 가이드는 판매 촉진에 필요한 시각적 품질을 유지하면서 전자상거래 제품 이미지를 최적화하는 고급 기술을 다룹니다.\r\n\r\n## 전자상거래 이미지 최적화가 중요한 이유\r\n\r\n### 전환율에 미치는 영향\r\n\r\n제품 이미지 최적화는 비즈니스 지표에 직접적으로 영향을 미칩니다:\r\n- **전환율**: 페이지 로딩 시간 1초 지연으로 전환율이 7% 감소\r\n- **이탈률**: 사용자의 40%가 로딩에 3초 이상 걸리는 사이트를 떠남\r\n- **모바일 커머스**: 전자상거래 트래픽의 73%가 모바일 기기에서 발생\r\n- **검색 순위**: Google은 검색 순위에 페이지 속도를 고려\r\n- **고객 만족도**: 고품질 이미지는 구매 신뢰도를 높임\r\n\r\n### 전자상거래 특화 요구사항\r\n\r\n제품 이미지는 고유한 최적화 과제를 가지고 있습니다:\r\n- **다중 제품 뷰**: 메인 이미지, 썸네일, 줌 뷰, 360° 회전\r\n- **색상 정확도**: 패션, 화장품, 홈 데코에 중요\r\n- **세부사항 보존**: 고객이 질감, 소재, 장인정신을 볼 수 있어야 함\r\n- **로딩 성능**: 품질과 속도 간의 균형\r\n- **크로스 디바이스 호환성**: 모든 기기에서 일관된 경험\r\n\r\n## 전자상거래 이미지 유형 이해\r\n\r\n### 제품 이미지 카테고리\r\n\r\n다양한 이미지 유형은 서로 다른 최적화 접근법이 필요합니다:\r\n\r\n```javascript\r\nconst ecommerceImageTypes = {\r\n    hero: {\r\n        purpose: '주요 제품 쇼케이스',\r\n        requirements: '고품질, 빠른 로딩',\r\n        sizes: ['1200x1200', '800x800', '600x600'],\r\n        quality: { jpeg: 85, webp: 80 }\r\n    },\r\n    thumbnail: {\r\n        purpose: '제품 그리드 디스플레이',\r\n        requirements: '작은 파일 크기, 인식 가능',\r\n        sizes: ['300x300', '200x200', '150x150'],\r\n        quality: { jpeg: 75, webp: 70 }\r\n    },\r\n    zoom: {\r\n        purpose: '상세 제품 검사',\r\n        requirements: '최대 세부사항 보존',\r\n        sizes: ['2000x2000', '1600x1600'],\r\n        quality: { jpeg: 90, webp: 85 }\r\n    },\r\n    gallery: {\r\n        purpose: '다중 제품 각도',\r\n        requirements: '일관된 품질, 지연 로딩',\r\n        sizes: ['800x800', '600x600'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    },\r\n    lifestyle: {\r\n        purpose: '사용 중/맥락 내 제품',\r\n        requirements: '감정/맥락 최적화',\r\n        sizes: ['1200x800', '800x533'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    }\r\n};\r\n```\r\n\r\n### 제품 카테고리별 최적화 전략\r\n\r\n다양한 제품 카테고리는 특정 이미지 요구사항을 가집니다:\r\n\r\n```python\r\ndef get_category_optimization_settings(product_category):\r\n    \"\"\"다양한 제품 카테고리의 최적화 설정 가져오기\"\"\"\r\n    settings = {\r\n        'fashion': {\r\n            'priority': ['color_accuracy', 'texture_detail'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 90},\r\n            'critical_views': ['front', 'back', 'detail']\r\n        },\r\n        'electronics': {\r\n            'priority': ['detail_preservation', 'fast_loading'],\r\n            'format_preference': 'webp_or_avif',\r\n            'quality_range': {'min': 75, 'max': 85},\r\n            'critical_views': ['main', 'interfaces', 'size_comparison']\r\n        },\r\n        'home_decor': {\r\n            'priority': ['color_accuracy', 'lifestyle_context'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 88},\r\n            'critical_views': ['styled', 'closeup', 'dimensions']\r\n        },\r\n        'jewelry': {\r\n            'priority': ['maximum_detail', 'color_accuracy'],\r\n            'format_preference': 'png_for_detailed_webp_for_hero',\r\n            'quality_range': {'min': 85, 'max': 95},\r\n            'critical_views': ['macro', '360_spin', 'lifestyle']\r\n        },\r\n        'books': {\r\n            'priority': ['fast_loading', 'text_readability'],\r\n            'format_preference': 'webp_aggressive_compression',\r\n            'quality_range': {'min': 70, 'max': 80},\r\n            'critical_views': ['cover', 'back', 'spine']\r\n        }\r\n    }\r\n    return settings.get(product_category, settings['electronics'])\r\n```\r\n\r\n## 고급 제품 이미지 처리\r\n\r\n### 자동화된 제품 이미지 파이프라인\r\n\r\n포괄적인 자동 처리 시스템:\r\n\r\n```python\r\nimport os\r\nfrom PIL import Image, ImageEnhance, ImageFilter\r\nimport numpy as np\r\n\r\nclass EcommerceImageProcessor:\r\n    def __init__(self, config=None):\r\n        self.config = config or self.get_default_config()\r\n        self.supported_formats = ['jpeg', 'webp', 'avif', 'png']\r\n        \r\n    def get_default_config(self):\r\n        return {\r\n            'background_removal': True,\r\n            'auto_crop': True,\r\n            'color_enhancement': True,\r\n            'noise_reduction': True,\r\n            'watermark': False,\r\n            'quality_thresholds': {\r\n                'hero': 85,\r\n                'gallery': 80,\r\n                'thumbnail': 75,\r\n                'zoom': 90\r\n            }\r\n        }\r\n    \r\n    def process_product_image(self, input_path, output_dir, product_id):\r\n        \"\"\"단일 제품 이미지를 필요한 모든 변형으로 처리\"\"\"\r\n        img = Image.open(input_path)\r\n        \r\n        # 기본 전처리\r\n        processed_img = self.preprocess_image(img)\r\n        \r\n        # 필요한 모든 크기와 형식 생성\r\n        variants = self.generate_image_variants(processed_img, product_id)\r\n        \r\n        # 최적화된 버전 저장\r\n        saved_files = self.save_variants(variants, output_dir)\r\n        \r\n        return saved_files\r\n    \r\n    def preprocess_image(self, img):\r\n        \"\"\"제품 이미지에 기본 전처리 적용\"\"\"\r\n        # 필요시 RGB로 변환\r\n        if img.mode in ('RGBA', 'LA', 'P'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            if img.mode == 'RGBA':\r\n                background.paste(img, mask=img.split()[-1])\r\n            else:\r\n                background.paste(img)\r\n            img = background\r\n        \r\n        # 여분의 공백 제거를 위한 자동 크롭\r\n        if self.config['auto_crop']:\r\n            img = self.smart_crop(img)\r\n        \r\n        # 이미지 품질 향상\r\n        if self.config['color_enhancement']:\r\n            img = self.enhance_product_image(img)\r\n        \r\n        # 노이즈 감소\r\n        if self.config['noise_reduction']:\r\n            img = img.filter(ImageFilter.SMOOTH_MORE)\r\n        \r\n        return img\r\n    \r\n    def smart_crop(self, img):\r\n        \"\"\"여분의 배경 제거를 위한 제품 이미지 스마트 크롭\"\"\"\r\n        # 분석을 위해 numpy 배열로 변환\r\n        img_array = np.array(img)\r\n        \r\n        # 비흰색 픽셀의 경계 상자 찾기\r\n        mask = np.any(img_array \u003C 240, axis=2)  # 순백색이 아님\r\n        coords = np.argwhere(mask)\r\n        \r\n        if len(coords) == 0:\r\n            return img  # 크롭 불필요\r\n        \r\n        # 경계 상자 가져오기\r\n        y0, x0 = coords.min(axis=0)\r\n        y1, x1 = coords.max(axis=0)\r\n        \r\n        # 패딩 추가\r\n        padding = 20\r\n        y0 = max(0, y0 - padding)\r\n        x0 = max(0, x0 - padding)\r\n        y1 = min(img.height, y1 + padding)\r\n        x1 = min(img.width, x1 + padding)\r\n        \r\n        return img.crop((x0, y0, x1, y1))\r\n    \r\n    def enhance_product_image(self, img):\r\n        \"\"\"제품 이미지 품질 향상\"\"\"\r\n        # 대비 향상\r\n        enhancer = ImageEnhance.Contrast(img)\r\n        img = enhancer.enhance(1.1)\r\n        \r\n        # 색상 채도 미세 조정\r\n        enhancer = ImageEnhance.Color(img)\r\n        img = enhancer.enhance(1.05)\r\n        \r\n        # 선명도 향상\r\n        enhancer = ImageEnhance.Sharpness(img)\r\n        img = enhancer.enhance(1.1)\r\n        \r\n        return img\r\n    \r\n    def generate_image_variants(self, img, product_id):\r\n        \"\"\"다양한 크기와 형식으로 이미지 변형 생성\"\"\"\r\n        variants = {}\r\n        \r\n        # 표준 크기 정의\r\n        sizes = {\r\n            'hero': [(1200, 1200), (800, 800), (600, 600)],\r\n            'thumbnail': [(300, 300), (200, 200), (150, 150)],\r\n            'zoom': [(2000, 2000), (1600, 1600)],\r\n            'gallery': [(800, 800), (600, 600)]\r\n        }\r\n        \r\n        for variant_type, size_list in sizes.items():\r\n            variants[variant_type] = {}\r\n            for size in size_list:\r\n                # 적절한 품질로 이미지 크기 조정\r\n                resized_img = self.resize_with_quality(img, size)\r\n                variants[variant_type][f\"{size[0]}x{size[1]}\"] = resized_img\r\n        \r\n        return variants\r\n    \r\n    def resize_with_quality(self, img, target_size):\r\n        \"\"\"고품질로 이미지 크기 조정\"\"\"\r\n        # 종횡비 유지\r\n        img.thumbnail(target_size, Image.Resampling.LANCZOS)\r\n        \r\n        # 필요시 흰 배경으로 새 이미지 생성\r\n        if img.size != target_size:\r\n            new_img = Image.new('RGB', target_size, (255, 255, 255))\r\n            # 이미지 중앙 배치\r\n            paste_x = (target_size[0] - img.size[0]) // 2\r\n            paste_y = (target_size[1] - img.size[1]) // 2\r\n            new_img.paste(img, (paste_x, paste_y))\r\n            return new_img\r\n        \r\n        return img\r\n    \r\n    def save_variants(self, variants, output_dir):\r\n        \"\"\"최적화된 형식으로 이미지 변형 저장\"\"\"\r\n        saved_files = []\r\n        \r\n        for variant_type, sizes in variants.items():\r\n            variant_dir = os.path.join(output_dir, variant_type)\r\n            os.makedirs(variant_dir, exist_ok=True)\r\n            \r\n            for size_name, img in sizes.items():\r\n                # JPEG 저장\r\n                jpeg_path = os.path.join(variant_dir, f\"{size_name}.jpg\")\r\n                quality = self.config['quality_thresholds'].get(variant_type, 80)\r\n                img.save(jpeg_path, 'JPEG', quality=quality, optimize=True)\r\n                saved_files.append(jpeg_path)\r\n                \r\n                # WebP 저장\r\n                webp_path = os.path.join(variant_dir, f\"{size_name}.webp\")\r\n                webp_quality = max(quality - 5, 70)  # WebP는 일반적으로 더 나은 압축\r\n                img.save(webp_path, 'WebP', quality=webp_quality, optimize=True)\r\n                saved_files.append(webp_path)\r\n        \r\n        return saved_files\r\n```\r\n\r\n## 아마존 마켓플레이스 최적화\r\n\r\n### 아마존 이미지 요구사항\r\n\r\n아마존 특화 이미지 최적화 요구사항:\r\n\r\n```python\r\nclass AmazonImageOptimizer:\r\n    def __init__(self):\r\n        self.amazon_requirements = {\r\n            'main_image': {\r\n                'min_size': (1000, 1000),\r\n                'max_size': (10000, 10000),\r\n                'background': 'pure_white',\r\n                'format': ['JPEG', 'PNG', 'GIF'],\r\n                'quality_min': 85\r\n            },\r\n            'additional_images': {\r\n                'min_size': (500, 500),\r\n                'recommended_size': (1600, 1600),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'max_count': 8\r\n            },\r\n            'zoom_functionality': {\r\n                'min_size': (1001, 1001),\r\n                'recommended_size': (2000, 2000),\r\n                'enables_zoom': True\r\n            }\r\n        }\r\n    \r\n    def optimize_for_amazon(self, image_path, image_type='main'):\r\n        \"\"\"아마존 요구사항에 맞게 이미지 최적화\"\"\"\r\n        img = Image.open(image_path)\r\n        requirements = self.amazon_requirements[f\"{image_type}_image\"]\r\n        \r\n        # 크기 확인 및 수정\r\n        if img.size[0] \u003C requirements['min_size'][0] or img.size[1] \u003C requirements['min_size'][1]:\r\n            # 너무 작으면 이미지 확대\r\n            img = self.upscale_image(img, requirements['min_size'])\r\n        \r\n        # 메인 이미지의 흰 배경 보장\r\n        if image_type == 'main' and requirements.get('background') == 'pure_white':\r\n            img = self.ensure_white_background(img)\r\n        \r\n        # 최적화하여 저장\r\n        return self.save_amazon_optimized(img, image_path, image_type)\r\n    \r\n    def ensure_white_background(self, img):\r\n        \"\"\"순백색 배경 보장\"\"\"\r\n        if img.mode in ('RGBA', 'LA'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            background.paste(img, mask=img.split()[-1])\r\n            return background\r\n        elif img.mode == 'P':\r\n            return img.convert('RGB')\r\n        return img\r\n    \r\n    def upscale_image(self, img, min_size):\r\n        \"\"\"이미지를 최소 크기로 확대\"\"\"\r\n        scale_factor = max(min_size[0] / img.size[0], min_size[1] / img.size[1])\r\n        new_size = (int(img.size[0] * scale_factor), int(img.size[1] * scale_factor))\r\n        return img.resize(new_size, Image.Resampling.LANCZOS)\r\n```\r\n\r\n## 성능 측정 및 모니터링\r\n\r\n### 이미지 최적화 메트릭\r\n\r\n핵심 성능 지표 추적:\r\n\r\n```python\r\nimport time\r\nimport requests\r\nfrom PIL import Image\r\nimport os\r\n\r\nclass ImagePerformanceMonitor:\r\n    def __init__(self):\r\n        self.metrics = {\r\n            'file_sizes': {},\r\n            'load_times': {},\r\n            'quality_scores': {},\r\n            'conversion_impact': {}\r\n        }\r\n    \r\n    def measure_optimization_impact(self, original_path, optimized_path):\r\n        \"\"\"최적화 영향 측정\"\"\"\r\n        # 파일 크기 비교\r\n        original_size = os.path.getsize(original_path)\r\n        optimized_size = os.path.getsize(optimized_path)\r\n        size_reduction = ((original_size - optimized_size) / original_size) * 100\r\n        \r\n        # 이미지 품질 평가\r\n        quality_score = self.calculate_quality_score(original_path, optimized_path)\r\n        \r\n        # 로딩 시간 개선 시뮬레이션\r\n        load_time_improvement = self.simulate_load_time_improvement(\r\n            original_size, optimized_size\r\n        )\r\n        \r\n        return {\r\n            'size_reduction_percent': size_reduction,\r\n            'quality_retention_percent': quality_score,\r\n            'load_time_improvement_ms': load_time_improvement,\r\n            'optimization_ratio': size_reduction / (100 - quality_score) if quality_score \u003C 100 else size_reduction\r\n        }\r\n    \r\n    def calculate_quality_score(self, original_path, optimized_path):\r\n        \"\"\"이미지 품질 점수 계산\"\"\"\r\n        try:\r\n            from skimage.metrics import structural_similarity as ssim\r\n            import numpy as np\r\n            \r\n            # 이미지 로드 및 변환\r\n            original = np.array(Image.open(original_path).convert('RGB'))\r\n            optimized = np.array(Image.open(optimized_path).convert('RGB'))\r\n            \r\n            # SSIM 계산\r\n            ssim_score = ssim(original, optimized, multichannel=True, channel_axis=2)\r\n            return ssim_score * 100\r\n        except ImportError:\r\n            # scikit-image가 없는 경우 크기 기반 간단 추정\r\n            return 85.0  # 기본값\r\n    \r\n    def simulate_load_time_improvement(self, original_size, optimized_size):\r\n        \"\"\"로딩 시간 개선 시뮬레이션\"\"\"\r\n        # 평균 인터넷 속도 기반 (5 Mbps)\r\n        avg_speed_bytes_per_ms = 5 * 1024 * 1024 / 8 / 1000  # 5 Mbps를 bytes/ms로\r\n        \r\n        original_load_time = original_size / avg_speed_bytes_per_ms\r\n        optimized_load_time = optimized_size / avg_speed_bytes_per_ms\r\n        \r\n        return original_load_time - optimized_load_time\r\n    \r\n    def generate_performance_report(self, optimization_results):\r\n        \"\"\"성능 보고서 생성\"\"\"\r\n        report = {\r\n            'summary': {\r\n                'total_images_processed': len(optimization_results),\r\n                'average_size_reduction': sum(r['size_reduction_percent'] for r in optimization_results) / len(optimization_results),\r\n                'average_quality_retention': sum(r['quality_retention_percent'] for r in optimization_results) / len(optimization_results),\r\n                'total_load_time_saved_ms': sum(r['load_time_improvement_ms'] for r in optimization_results)\r\n            },\r\n            'recommendations': self.generate_recommendations(optimization_results)\r\n        }\r\n        return report\r\n    \r\n    def generate_recommendations(self, results):\r\n        \"\"\"최적화 권장사항 생성\"\"\"\r\n        recommendations = []\r\n        \r\n        avg_size_reduction = sum(r['size_reduction_percent'] for r in results) / len(results)\r\n        avg_quality = sum(r['quality_retention_percent'] for r in results) / len(results)\r\n        \r\n        if avg_size_reduction \u003C 30:\r\n            recommendations.append(\"더 적극적인 압축 설정 적용\")\r\n        \r\n        if avg_quality \u003C 85:\r\n            recommendations.append(\"더 나은 시각적 결과를 위한 품질 설정 미세 조정\")\r\n        \r\n        if any(r['load_time_improvement_ms'] > 500 for r in results):\r\n            recommendations.append(\"중요한 이미지 최적화 우선순위 지정\")\r\n        \r\n        return recommendations\r\n```\r\n\r\n## 대규모 카탈로그를 위한 배치 처리\r\n\r\n### 병렬 이미지 처리\r\n\r\n대량의 제품 이미지를 위한 효율적인 처리:\r\n\r\n```python\r\nimport concurrent.futures\r\nimport multiprocessing\r\nfrom pathlib import Path\r\nimport logging\r\n\r\nclass BatchImageProcessor:\r\n    def __init__(self, max_workers=None):\r\n        self.max_workers = max_workers or multiprocessing.cpu_count()\r\n        self.processed_count = 0\r\n        self.failed_count = 0\r\n        \r\n        # 로깅 설정\r\n        logging.basicConfig(level=logging.INFO)\r\n        self.logger = logging.getLogger(__name__)\r\n    \r\n    def process_catalog(self, input_directory, output_directory, product_categories=None):\r\n        \"\"\"전체 제품 카탈로그 처리\"\"\"\r\n        input_path = Path(input_directory)\r\n        output_path = Path(output_directory)\r\n        output_path.mkdir(parents=True, exist_ok=True)\r\n        \r\n        # 이미지 파일 수집\r\n        image_files = self.collect_image_files(input_path)\r\n        self.logger.info(f\"총 {len(image_files)}개 이미지가 처리 대기 중\")\r\n        \r\n        # 병렬 처리\r\n        with concurrent.futures.ThreadPoolExecutor(max_workers=self.max_workers) as executor:\r\n            # 작업 제출\r\n            future_to_file = {\r\n                executor.submit(\r\n                    self.process_single_product_image, \r\n                    img_file, \r\n                    output_path,\r\n                    product_categories.get(img_file.stem) if product_categories else None\r\n                ): img_file \r\n                for img_file in image_files\r\n            }\r\n            \r\n            # 결과 처리\r\n            for future in concurrent.futures.as_completed(future_to_file):\r\n                img_file = future_to_file[future]\r\n                try:\r\n                    result = future.result()\r\n                    self.processed_count += 1\r\n                    if self.processed_count % 100 == 0:\r\n                        self.logger.info(f\"처리됨: {self.processed_count}/{len(image_files)}\")\r\n                except Exception as exc:\r\n                    self.failed_count += 1\r\n                    self.logger.error(f\"{img_file} 처리 오류: {exc}\")\r\n        \r\n        # 요약 보고서 생성\r\n        self.generate_batch_report(len(image_files))\r\n    \r\n    def collect_image_files(self, input_path):\r\n        \"\"\"입력 디렉토리에서 이미지 파일 수집\"\"\"\r\n        supported_extensions = {'.jpg', '.jpeg', '.png', '.webp', '.tiff', '.bmp'}\r\n        image_files = []\r\n        \r\n        for ext in supported_extensions:\r\n            image_files.extend(input_path.glob(f\"**/*{ext}\"))\r\n            image_files.extend(input_path.glob(f\"**/*{ext.upper()}\"))\r\n        \r\n        return image_files\r\n    \r\n    def process_single_product_image(self, image_path, output_dir, category=None):\r\n        \"\"\"단일 제품 이미지 처리\"\"\"\r\n        try:\r\n            processor = EcommerceImageProcessor()\r\n            \r\n            # 카테고리별 설정 적용\r\n            if category:\r\n                category_settings = get_category_optimization_settings(category)\r\n                processor.config.update(category_settings)\r\n            \r\n            # 이미지 처리\r\n            product_id = image_path.stem\r\n            result = processor.process_product_image(\r\n                str(image_path), \r\n                str(output_dir), \r\n                product_id\r\n            )\r\n            \r\n            return {\r\n                'status': 'success',\r\n                'input_file': str(image_path),\r\n                'output_files': result,\r\n                'product_id': product_id\r\n            }\r\n            \r\n        except Exception as e:\r\n            return {\r\n                'status': 'error',\r\n                'input_file': str(image_path),\r\n                'error': str(e)\r\n            }\r\n    \r\n    def generate_batch_report(self, total_files):\r\n        \"\"\"배치 처리 보고서 생성\"\"\"\r\n        success_rate = (self.processed_count / total_files) * 100\r\n        \r\n        report = f\"\"\"\r\n        배치 이미지 처리 보고서\r\n        ======================\r\n        총 파일: {total_files}\r\n        성공적으로 처리됨: {self.processed_count}\r\n        실패: {self.failed_count}\r\n        성공률: {success_rate:.2f}%\r\n        \r\n        처리 속도: {self.processed_count / self.max_workers:.2f} 이미지/워커\r\n        \"\"\"\r\n        \r\n        self.logger.info(report)\r\n        return report\r\n\r\n# 사용 예시\r\ndef optimize_ecommerce_catalog():\r\n    \"\"\"전자상거래 카탈로그 최적화\"\"\"\r\n    # 제품 카테고리 정의\r\n    product_categories = {\r\n        'shirt_001': 'fashion',\r\n        'laptop_002': 'electronics',\r\n        'sofa_003': 'home_decor',\r\n        'ring_004': 'jewelry'\r\n    }\r\n    \r\n    # 배치 프로세서 초기화\r\n    batch_processor = BatchImageProcessor(max_workers=8)\r\n    \r\n    # 카탈로그 처리\r\n    batch_processor.process_catalog(\r\n        input_directory='./raw_product_images',\r\n        output_directory='./optimized_product_images',\r\n        product_categories=product_categories\r\n    )\r\n\r\nif __name__ == \"__main__\":\r\n    optimize_ecommerce_catalog()\r\n```\r\n\r\n## 자동화 및 통합\r\n\r\n### 전자상거래 플랫폼 통합\r\n\r\n전자상거래 시스템을 위한 자동 이미지 최적화:\r\n\r\n```python\r\nimport requests\r\nimport json\r\nfrom datetime import datetime\r\n\r\nclass EcommerceIntegration:\r\n    def __init__(self, platform_config):\r\n        self.platform = platform_config['platform']  # 'shopify', 'woocommerce', 'magento'\r\n        self.api_key = platform_config['api_key']\r\n        self.store_url = platform_config['store_url']\r\n        self.headers = self.setup_headers()\r\n    \r\n    def setup_headers(self):\r\n        \"\"\"플랫폼에 따른 API 헤더 설정\"\"\"\r\n        if self.platform == 'shopify':\r\n            return {\r\n                'X-Shopify-Access-Token': self.api_key,\r\n                'Content-Type': 'application/json'\r\n            }\r\n        elif self.platform == 'woocommerce':\r\n            return {\r\n                'Authorization': f'Bearer {self.api_key}',\r\n                'Content-Type': 'application/json'\r\n            }\r\n        return {'Content-Type': 'application/json'}\r\n    \r\n    def get_products_needing_optimization(self):\r\n        \"\"\"최적화가 필요한 제품 가져오기\"\"\"\r\n        if self.platform == 'shopify':\r\n            return self.get_shopify_products()\r\n        elif self.platform == 'woocommerce':\r\n            return self.get_woocommerce_products()\r\n        return []\r\n    \r\n    def get_shopify_products(self):\r\n        \"\"\"Shopify 제품 가져오기\"\"\"\r\n        url = f\"{self.store_url}/admin/api/2023-01/products.json\"\r\n        response = requests.get(url, headers=self.headers)\r\n        \r\n        if response.status_code == 200:\r\n            products = response.json()['products']\r\n            return [\r\n                {\r\n                    'id': product['id'],\r\n                    'title': product['title'],\r\n                    'images': [img['src'] for img in product['images']]\r\n                }\r\n                for product in products\r\n            ]\r\n        return []\r\n    \r\n    def optimize_product_images(self, product_data):\r\n        \"\"\"제품 이미지 최적화 및 업로드\"\"\"\r\n        optimized_images = []\r\n        \r\n        for image_url in product_data['images']:\r\n            try:\r\n                # 이미지 다운로드\r\n                response = requests.get(image_url)\r\n                if response.status_code == 200:\r\n                    # 임시 파일 저장\r\n                    temp_path = f\"temp_{product_data['id']}.jpg\"\r\n                    with open(temp_path, 'wb') as f:\r\n                        f.write(response.content)\r\n                    \r\n                    # 최적화\r\n                    processor = EcommerceImageProcessor()\r\n                    optimized_files = processor.process_product_image(\r\n                        temp_path, \r\n                        f\"optimized_{product_data['id']}\", \r\n                        str(product_data['id'])\r\n                    )\r\n                    \r\n                    # 최적화된 이미지 업로드\r\n                    uploaded_urls = self.upload_optimized_images(\r\n                        optimized_files, \r\n                        product_data['id']\r\n                    )\r\n                    optimized_images.extend(uploaded_urls)\r\n                    \r\n                    # 임시 파일 제거\r\n                    os.remove(temp_path)\r\n                    \r\n            except Exception as e:\r\n                print(f\"이미지 최적화 오류: {e}\")\r\n        \r\n        return optimized_images\r\n    \r\n    def upload_optimized_images(self, image_files, product_id):\r\n        \"\"\"최적화된 이미지를 플랫폼에 업로드\"\"\"\r\n        uploaded_urls = []\r\n        \r\n        for image_file in image_files:\r\n            if self.platform == 'shopify':\r\n                url = self.upload_to_shopify(image_file, product_id)\r\n            elif self.platform == 'woocommerce':\r\n                url = self.upload_to_woocommerce(image_file, product_id)\r\n            \r\n            if url:\r\n                uploaded_urls.append(url)\r\n        \r\n        return uploaded_urls\r\n    \r\n    def schedule_optimization(self, schedule_config):\r\n        \"\"\"최적화 스케줄링\"\"\"\r\n        import schedule\r\n        import time\r\n        \r\n        def run_optimization():\r\n            products = self.get_products_needing_optimization()\r\n            for product in products:\r\n                self.optimize_product_images(product)\r\n                time.sleep(1)  # 속도 제한\r\n        \r\n        # 스케줄 설정\r\n        if schedule_config['frequency'] == 'daily':\r\n            schedule.every().day.at(schedule_config['time']).do(run_optimization)\r\n        elif schedule_config['frequency'] == 'weekly':\r\n            schedule.every().week.do(run_optimization)\r\n        \r\n        # 스케줄러 실행\r\n        while True:\r\n            schedule.run_pending()\r\n            time.sleep(60)\r\n```\r\n\r\n## 결론\r\n\r\n전자상거래 제품 이미지 최적화는 온라인 판매 성공에 중요합니다. 적절한 압축 기술을 적용함으로써 이미지 품질을 희생하지 않고도 사이트 성능을 크게 향상시킬 수 있습니다.\r\n\r\n### 주요 발견사항\r\n\r\n1. **카테고리별 최적화**: 각 제품 카테고리는 고유한 이미지 요구사항을 가짐\r\n2. **자동화의 중요성**: 대규모 카탈로그에는 배치 처리가 필수\r\n3. **성능 측정**: 최적의 결과를 위해서는 정기적인 모니터링이 필요\r\n4. **플랫폼 통합**: 전자상거래 시스템과의 원활한 워크플로우\r\n5. **품질 대 속도**: 비즈니스 목표에 적합한 균형 찾기\r\n\r\n### 구현 권장사항\r\n\r\n- 가장 중요한 제품 이미지(메인 이미지, 베스트셀러 제품)부터 시작\r\n- 작은 샘플에서 최적화 설정 테스트\r\n- 전환율에 미치는 영향 측정\r\n- 일관성을 위해 프로세스 자동화\r\n- 최적화 전략을 정기적으로 업데이트\r\n\r\n적절히 구현된 이미지 최적화 전략은 사이트 속도, 사용자 경험, 그리고 궁극적으로 판매 결과에서 상당한 개선을 가져올 수 있습니다.","# E-Commerce Produktbild-Komprimierung: Verkaufsorientierte Optimierung\r\n\r\nDer E-Commerce-Erfolg hängt stark von der Qualität der Produktbilder ab, wobei Studien zeigen, dass 67% der Verbraucher die Bildqualität als \"sehr wichtig\" beim Online-Kauf betrachten. Große Bilddateien können jedoch die Seitenladezeiten, Konversionsraten und die mobile Benutzererfahrung erheblich beeinträchtigen. Dieser umfassende Leitfaden behandelt fortgeschrittene Techniken zur Optimierung von E-Commerce-Produktbildern unter Beibehaltung der visuellen Qualität, die für den Verkaufserfolg erforderlich ist.\r\n\r\n## Warum E-Commerce-Bildoptimierung wichtig ist\r\n\r\n### Auswirkungen auf Konversionsraten\r\n\r\nDie Optimierung von Produktbildern wirkt sich direkt auf Geschäftskennzahlen aus:\r\n- **Konversionsraten**: 1 Sekunde Verzögerung bei der Seitenladezeit reduziert Konversionen um 7%\r\n- **Absprungraten**: 40% der Nutzer verlassen Websites, die länger als 3 Sekunden zum Laden benötigen\r\n- **Mobile Commerce**: 73% des E-Commerce-Traffics stammt von mobilen Geräten\r\n- **Suchmaschinenrankings**: Google berücksichtigt die Seitengeschwindigkeit in den Suchrankings\r\n- **Kundenzufriedenheit**: Hochwertige Bilder erhöhen das Kaufvertrauen\r\n\r\n### E-Commerce-spezifische Anforderungen\r\n\r\nProduktbilder haben einzigartige Optimierungsherausforderungen:\r\n- **Mehrere Produktansichten**: Hauptbild, Thumbnails, Zoom-Ansichten, 360°-Rotationen\r\n- **Farbgenauigkeit**: Kritisch für Mode, Kosmetik und Wohnkultur\r\n- **Detailerhaltung**: Kunden müssen Textur, Materialien und Handwerkskunst sehen können\r\n- **Ladeleistung**: Balance zwischen Qualität und Geschwindigkeit\r\n- **Geräteübergreifende Kompatibilität**: Konsistente Erfahrung auf allen Geräten\r\n\r\n## Verständnis von E-Commerce-Bildtypen\r\n\r\n### Produktbildkategorien\r\n\r\nVerschiedene Bildtypen erfordern unterschiedliche Optimierungsansätze:\r\n\r\n```javascript\r\nconst ecommerceImageTypes = {\r\n    hero: {\r\n        purpose: 'Primäre Produktpräsentation',\r\n        requirements: 'Hohe Qualität, schnelles Laden',\r\n        sizes: ['1200x1200', '800x800', '600x600'],\r\n        quality: { jpeg: 85, webp: 80 }\r\n    },\r\n    thumbnail: {\r\n        purpose: 'Produktraster-Anzeigen',\r\n        requirements: 'Kleine Dateigröße, erkennbar',\r\n        sizes: ['300x300', '200x200', '150x150'],\r\n        quality: { jpeg: 75, webp: 70 }\r\n    },\r\n    zoom: {\r\n        purpose: 'Detaillierte Produktinspektion',\r\n        requirements: 'Maximale Detailerhaltung',\r\n        sizes: ['2000x2000', '1600x1600'],\r\n        quality: { jpeg: 90, webp: 85 }\r\n    },\r\n    gallery: {\r\n        purpose: 'Mehrere Produktwinkel',\r\n        requirements: 'Konsistente Qualität, Lazy Loading',\r\n        sizes: ['800x800', '600x600'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    },\r\n    lifestyle: {\r\n        purpose: 'Produkt in Verwendung/Kontext',\r\n        requirements: 'Optimiert für Emotion/Kontext',\r\n        sizes: ['1200x800', '800x533'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    }\r\n};\r\n```\r\n\r\n### Optimierungsstrategie nach Produktkategorie\r\n\r\nVerschiedene Produktkategorien haben spezifische Bildanforderungen:\r\n\r\n```python\r\ndef get_category_optimization_settings(product_category):\r\n    \"\"\"Optimierungseinstellungen für verschiedene Produktkategorien abrufen\"\"\"\r\n    settings = {\r\n        'fashion': {\r\n            'priority': ['color_accuracy', 'texture_detail'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 90},\r\n            'critical_views': ['front', 'back', 'detail']\r\n        },\r\n        'electronics': {\r\n            'priority': ['detail_preservation', 'fast_loading'],\r\n            'format_preference': 'webp_or_avif',\r\n            'quality_range': {'min': 75, 'max': 85},\r\n            'critical_views': ['main', 'interfaces', 'size_comparison']\r\n        },\r\n        'home_decor': {\r\n            'priority': ['color_accuracy', 'lifestyle_context'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 88},\r\n            'critical_views': ['styled', 'closeup', 'dimensions']\r\n        },\r\n        'jewelry': {\r\n            'priority': ['maximum_detail', 'color_accuracy'],\r\n            'format_preference': 'png_for_detailed_webp_for_hero',\r\n            'quality_range': {'min': 85, 'max': 95},\r\n            'critical_views': ['macro', '360_spin', 'lifestyle']\r\n        },\r\n        'books': {\r\n            'priority': ['fast_loading', 'text_readability'],\r\n            'format_preference': 'webp_aggressive_compression',\r\n            'quality_range': {'min': 70, 'max': 80},\r\n            'critical_views': ['cover', 'back', 'spine']\r\n        }\r\n    }\r\n    return settings.get(product_category, settings['electronics'])\r\n```\r\n\r\n## Erweiterte Produktbildverarbeitung\r\n\r\n### Automatisierte Produktbild-Pipeline\r\n\r\nUmfassendes automatisiertes Verarbeitungssystem:\r\n\r\n```python\r\nimport os\r\nfrom PIL import Image, ImageEnhance, ImageFilter\r\nimport numpy as np\r\n\r\nclass EcommerceImageProcessor:\r\n    def __init__(self, config=None):\r\n        self.config = config or self.get_default_config()\r\n        self.supported_formats = ['jpeg', 'webp', 'avif', 'png']\r\n        \r\n    def get_default_config(self):\r\n        return {\r\n            'background_removal': True,\r\n            'auto_crop': True,\r\n            'color_enhancement': True,\r\n            'noise_reduction': True,\r\n            'watermark': False,\r\n            'quality_thresholds': {\r\n                'hero': 85,\r\n                'gallery': 80,\r\n                'thumbnail': 75,\r\n                'zoom': 90\r\n            }\r\n        }\r\n    \r\n    def process_product_image(self, input_path, output_dir, product_id):\r\n        \"\"\"Ein einzelnes Produktbild in alle erforderlichen Varianten verarbeiten\"\"\"\r\n        img = Image.open(input_path)\r\n        \r\n        # Grundlegende Vorverarbeitung\r\n        processed_img = self.preprocess_image(img)\r\n        \r\n        # Alle erforderlichen Größen und Formate generieren\r\n        variants = self.generate_image_variants(processed_img, product_id)\r\n        \r\n        # Optimierte Versionen speichern\r\n        saved_files = self.save_variants(variants, output_dir)\r\n        \r\n        return saved_files\r\n    \r\n    def preprocess_image(self, img):\r\n        \"\"\"Grundlegende Vorverarbeitung auf Produktbild anwenden\"\"\"\r\n        # Bei Bedarf zu RGB konvertieren\r\n        if img.mode in ('RGBA', 'LA', 'P'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            if img.mode == 'RGBA':\r\n                background.paste(img, mask=img.split()[-1])\r\n            else:\r\n                background.paste(img)\r\n            img = background\r\n        \r\n        # Auto-Zuschnitt zur Entfernung überschüssiger Leerräume\r\n        if self.config['auto_crop']:\r\n            img = self.smart_crop(img)\r\n        \r\n        # Bildqualität verbessern\r\n        if self.config['color_enhancement']:\r\n            img = self.enhance_product_image(img)\r\n        \r\n        # Rauschen reduzieren\r\n        if self.config['noise_reduction']:\r\n            img = img.filter(ImageFilter.SMOOTH_MORE)\r\n        \r\n        return img\r\n    \r\n    def smart_crop(self, img):\r\n        \"\"\"Intelligenter Zuschnitt des Produktbildes zur Entfernung überschüssigen Hintergrunds\"\"\"\r\n        # Zu numpy Array für Analyse konvertieren\r\n        img_array = np.array(img)\r\n        \r\n        # Bounding Box nicht-weißer Pixel finden\r\n        mask = np.any(img_array \u003C 240, axis=2)  # Nicht reinweiß\r\n        coords = np.argwhere(mask)\r\n        \r\n        if len(coords) == 0:\r\n            return img  # Kein Zuschnitt erforderlich\r\n        \r\n        # Bounding Box erhalten\r\n        y0, x0 = coords.min(axis=0)\r\n        y1, x1 = coords.max(axis=0)\r\n        \r\n        # Padding hinzufügen\r\n        padding = 20\r\n        y0 = max(0, y0 - padding)\r\n        x0 = max(0, x0 - padding)\r\n        y1 = min(img.height, y1 + padding)\r\n        x1 = min(img.width, x1 + padding)\r\n        \r\n        return img.crop((x0, y0, x1, y1))\r\n    \r\n    def enhance_product_image(self, img):\r\n        \"\"\"Produktbild für E-Commerce-Anzeige verbessern\"\"\"\r\n        # Helligkeit leicht erhöhen\r\n        brightness_enhancer = ImageEnhance.Brightness(img)\r\n        img = brightness_enhancer.enhance(1.05)\r\n        \r\n        # Kontrast verbessern\r\n        contrast_enhancer = ImageEnhance.Contrast(img)\r\n        img = contrast_enhancer.enhance(1.1)\r\n        \r\n        # Farbsättigung verbessern\r\n        color_enhancer = ImageEnhance.Color(img)\r\n        img = color_enhancer.enhance(1.05)\r\n        \r\n        # Schärfe verbessern\r\n        sharpness_enhancer = ImageEnhance.Sharpness(img)\r\n        img = sharpness_enhancer.enhance(1.1)\r\n        \r\n        return img\r\n```\r\n\r\n## Plattformspezifische Optimierung\r\n\r\n### Amazon Marketplace-Optimierung\r\n\r\nAmazon hat spezifische Bildanforderungen und Algorithmen:\r\n\r\n```python\r\nclass AmazonImageOptimizer:\r\n    def __init__(self):\r\n        self.requirements = {\r\n            'main_image': {\r\n                'min_size': (1000, 1000),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'background': 'pure_white',\r\n                'product_coverage': 85  # Mindestprozentsatz des Bildes\r\n            },\r\n            'additional_images': {\r\n                'min_size': (500, 500),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'lifestyle_allowed': True\r\n            }\r\n        }\r\n    \r\n    def optimize_for_amazon(self, image_path, output_path, image_type='main'):\r\n        \"\"\"Bild speziell für Amazon-Listing optimieren\"\"\"\r\n        img = Image.open(image_path)\r\n        \r\n        if image_type == 'main':\r\n            img = self.ensure_white_background(img)\r\n            img = self.ensure_minimum_size(img, (1000, 1000))\r\n        \r\n        # Amazon bevorzugt sRGB-Farbraum\r\n        if img.mode != 'RGB':\r\n            img = img.convert('RGB')\r\n        \r\n        # Dateigröße bei Qualitätserhaltung optimieren\r\n        quality = 90 if image_type == 'main' else 85\r\n        img.save(output_path, 'JPEG', quality=quality, optimize=True)\r\n        \r\n        return self.validate_amazon_requirements(output_path, image_type)\r\n```\r\n\r\n## Leistungsmessung und Optimierung\r\n\r\n### Metriken zur Erfolgsverfolgung\r\n\r\nWichtige Leistungsindikatoren für Bildoptimierung:\r\n\r\n```javascript\r\nclass EcommerceImageMetrics {\r\n    constructor() {\r\n        this.metrics = {\r\n            technical: {\r\n                'load_time': 'Bildladezeit',\r\n                'file_size': 'Dateigröße',\r\n                'compression_ratio': 'Komprimierungsverhältnis',\r\n                'quality_score': 'Qualitätsbewertung'\r\n            },\r\n            business: {\r\n                'conversion_rate': 'Konversionsrate',\r\n                'bounce_rate': 'Absprungrate',\r\n                'time_on_page': 'Verweildauer auf Seite',\r\n                'cart_addition_rate': 'Warenkorb-Hinzufügungsrate'\r\n            }\r\n        };\r\n    }\r\n    \r\n    measureImagePerformance(imageUrl, callback) {\r\n        const startTime = performance.now();\r\n        const img = new Image();\r\n        \r\n        img.onload = () => {\r\n            const loadTime = performance.now() - startTime;\r\n            const fileSize = this.getImageFileSize(imageUrl);\r\n            \r\n            callback({\r\n                loadTime: loadTime,\r\n                fileSize: fileSize,\r\n                dimensions: { width: img.width, height: img.height },\r\n                timestamp: new Date().toISOString()\r\n            });\r\n        };\r\n        \r\n        img.src = imageUrl;\r\n    }\r\n}\r\n```\r\n\r\n## Automatisierung und Skalierung\r\n\r\n### Batch-Verarbeitung für große Kataloge\r\n\r\nEffiziente Verarbeitung tausender Produktbilder:\r\n\r\n```python\r\nimport concurrent.futures\r\nimport multiprocessing\r\nfrom pathlib import Path\r\n\r\nclass BatchImageProcessor:\r\n    def __init__(self, max_workers=None):\r\n        self.max_workers = max_workers or multiprocessing.cpu_count()\r\n        self.processor = EcommerceImageProcessor()\r\n    \r\n    def process_catalog(self, input_directory, output_directory, progress_callback=None):\r\n        \"\"\"Gesamten Katalog von Produktbildern verarbeiten\"\"\"\r\n        input_path = Path(input_directory)\r\n        output_path = Path(output_directory)\r\n        output_path.mkdir(parents=True, exist_ok=True)\r\n        \r\n        # Alle Bilder finden\r\n        image_files = list(input_path.glob('**/*.{jpg,jpeg,png,webp}'))\r\n        total_files = len(image_files)\r\n        \r\n        processed_count = 0\r\n        failed_files = []\r\n        \r\n        with concurrent.futures.ThreadPoolExecutor(max_workers=self.max_workers) as executor:\r\n            # Alle Aufgaben einreichen\r\n            future_to_file = {\r\n                executor.submit(self.process_single_image, img_file, output_path): img_file\r\n                for img_file in image_files\r\n            }\r\n            \r\n            # Ergebnisse verarbeiten\r\n            for future in concurrent.futures.as_completed(future_to_file):\r\n                img_file = future_to_file[future]\r\n                try:\r\n                    result = future.result()\r\n                    processed_count += 1\r\n                    \r\n                    if progress_callback:\r\n                        progress_callback(processed_count, total_files, img_file.name)\r\n                        \r\n                except Exception as exc:\r\n                    failed_files.append((img_file, str(exc)))\r\n                    print(f'Datei {img_file} erzeugte Ausnahme: {exc}')\r\n        \r\n        return {\r\n            'total_files': total_files,\r\n            'processed_count': processed_count,\r\n            'failed_files': failed_files,\r\n            'success_rate': (processed_count / total_files) * 100 if total_files > 0 else 0\r\n        }\r\n```\r\n\r\n## Fazit\r\n\r\nDie Optimierung von Produktbildern für E-Commerce ist ein kritischer Faktor für den Erfolg von Online-Shops. Die ordnungsgemäße Implementierung von Komprimierungstechniken, Automatisierung der Verarbeitung und Leistungsmessung kann Konversionsraten erheblich verbessern, Absprungraten reduzieren und die Kundenzufriedenheit steigern.\r\n\r\nWichtige Punkte zum Merken:\r\n\r\n1. **Qualität und Leistung ausbalancieren**: Den optimalen Punkt zwischen visueller Qualität und Ladegeschwindigkeit finden\r\n2. **Automatisierung ist der Schlüssel**: Automatisierte Pipelines für Skalierung implementieren\r\n3. **Testen und Messen**: A/B-Tests verwenden, um Optimierungsauswirkungen zu verifizieren\r\n4. **Plattformspezifische Anforderungen**: Optimierung an spezifische Marktplatzanforderungen anpassen\r\n5. **Kontinuierliche Verbesserung**: Strategien regelmäßig basierend auf neuen Technologien und Daten aktualisieren\r\n\r\nInvestitionen in professionelle Bildoptimierung zahlen sich schnell durch verbesserte Geschäftsergebnisse und bessere Benutzererfahrung aus.\r\n","# Compression d'Images Produits E-commerce : Optimisation Orientée Ventes\r\n\r\nLe succès du e-commerce dépend fortement de la qualité des images produits, avec des études montrant que 67% des consommateurs considèrent la qualité d'image comme \"très importante\" lors d'achats en ligne. Cependant, les gros fichiers d'images peuvent impacter significativement les temps de chargement des pages, les taux de conversion et l'expérience utilisateur mobile. Ce guide complet couvre les techniques avancées pour optimiser les images produits e-commerce tout en maintenant la qualité visuelle nécessaire pour stimuler les ventes.\r\n\r\n## Pourquoi l'Optimisation d'Images E-commerce Compte\r\n\r\n### Impact sur les Taux de Conversion\r\n\r\nL'optimisation d'images produits affecte directement les métriques business :\r\n- **Taux de conversion** : 1 seconde de délai dans le temps de chargement de page réduit les conversions de 7%\r\n- **Taux de rebond** : 40% des utilisateurs abandonnent les sites qui prennent plus de 3 secondes à charger\r\n- **Commerce mobile** : 73% du trafic e-commerce provient d'appareils mobiles\r\n- **Classements de recherche** : Google prend en compte la vitesse de page dans les classements de recherche\r\n- **Satisfaction client** : Les images de haute qualité augmentent la confiance d'achat\r\n\r\n### Exigences Spécifiques E-commerce\r\n\r\nLes images produits ont des défis d'optimisation uniques :\r\n- **Vues produit multiples** : Image principale, vignettes, vues zoom, rotations 360°\r\n- **Précision des couleurs** : Critique pour la mode, les cosmétiques et la décoration\r\n- **Préservation des détails** : Les clients doivent voir la texture, les matériaux et l'artisanat\r\n- **Performance de chargement** : Équilibre entre qualité et vitesse\r\n- **Compatibilité multi-appareils** : Expérience cohérente sur tous les appareils\r\n\r\n## Compréhension des Types d'Images E-commerce\r\n\r\n### Catégories d'Images Produits\r\n\r\nDifférents types d'images nécessitent différentes approches d'optimisation :\r\n\r\n```javascript\r\nconst ecommerceImageTypes = {\r\n    hero: {\r\n        purpose: 'Présentation produit principale',\r\n        requirements: 'Haute qualité, chargement rapide',\r\n        sizes: ['1200x1200', '800x800', '600x600'],\r\n        quality: { jpeg: 85, webp: 80 }\r\n    },\r\n    thumbnail: {\r\n        purpose: 'Affichages grille produits',\r\n        requirements: 'Petite taille fichier, reconnaissable',\r\n        sizes: ['300x300', '200x200', '150x150'],\r\n        quality: { jpeg: 75, webp: 70 }\r\n    },\r\n    zoom: {\r\n        purpose: 'Inspection produit détaillée',\r\n        requirements: 'Préservation maximale des détails',\r\n        sizes: ['2000x2000', '1600x1600'],\r\n        quality: { jpeg: 90, webp: 85 }\r\n    },\r\n    gallery: {\r\n        purpose: 'Angles produit multiples',\r\n        requirements: 'Qualité cohérente, lazy loading',\r\n        sizes: ['800x800', '600x600'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    },\r\n    lifestyle: {\r\n        purpose: 'Produit en usage/contexte',\r\n        requirements: 'Optimisé pour émotion/contexte',\r\n        sizes: ['1200x800', '800x533'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    }\r\n};\r\n```\r\n\r\n### Stratégie d'Optimisation par Catégorie Produit\r\n\r\nDifférentes catégories de produits ont des exigences d'image spécifiques :\r\n\r\n```python\r\ndef get_category_optimization_settings(product_category):\r\n    \"\"\"Obtenir les paramètres d'optimisation pour différentes catégories de produits\"\"\"\r\n    settings = {\r\n        'fashion': {\r\n            'priority': ['color_accuracy', 'texture_detail'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 90},\r\n            'critical_views': ['front', 'back', 'detail']\r\n        },\r\n        'electronics': {\r\n            'priority': ['detail_preservation', 'fast_loading'],\r\n            'format_preference': 'webp_or_avif',\r\n            'quality_range': {'min': 75, 'max': 85},\r\n            'critical_views': ['main', 'interfaces', 'size_comparison']\r\n        },\r\n        'home_decor': {\r\n            'priority': ['color_accuracy', 'lifestyle_context'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 88},\r\n            'critical_views': ['styled', 'closeup', 'dimensions']\r\n        },\r\n        'jewelry': {\r\n            'priority': ['maximum_detail', 'color_accuracy'],\r\n            'format_preference': 'png_for_detailed_webp_for_hero',\r\n            'quality_range': {'min': 85, 'max': 95},\r\n            'critical_views': ['macro', '360_spin', 'lifestyle']\r\n        },\r\n        'books': {\r\n            'priority': ['fast_loading', 'text_readability'],\r\n            'format_preference': 'webp_aggressive_compression',\r\n            'quality_range': {'min': 70, 'max': 80},\r\n            'critical_views': ['cover', 'back', 'spine']\r\n        }\r\n    }\r\n    return settings.get(product_category, settings['electronics'])\r\n```\r\n\r\n## Traitement Avancé d'Images Produits\r\n\r\n### Pipeline Automatisé d'Images Produits\r\n\r\nSystème de traitement automatisé complet :\r\n\r\n```python\r\nimport os\r\nfrom PIL import Image, ImageEnhance, ImageFilter\r\nimport numpy as np\r\n\r\nclass EcommerceImageProcessor:\r\n    def __init__(self, config=None):\r\n        self.config = config or self.get_default_config()\r\n        self.supported_formats = ['jpeg', 'webp', 'avif', 'png']\r\n        \r\n    def get_default_config(self):\r\n        return {\r\n            'background_removal': True,\r\n            'auto_crop': True,\r\n            'color_enhancement': True,\r\n            'noise_reduction': True,\r\n            'watermark': False,\r\n            'quality_thresholds': {\r\n                'hero': 85,\r\n                'gallery': 80,\r\n                'thumbnail': 75,\r\n                'zoom': 90\r\n            }\r\n        }\r\n    \r\n    def process_product_image(self, input_path, output_dir, product_id):\r\n        \"\"\"Traiter une seule image produit en toutes les variantes requises\"\"\"\r\n        img = Image.open(input_path)\r\n        \r\n        # Prétraitement de base\r\n        processed_img = self.preprocess_image(img)\r\n        \r\n        # Générer toutes les tailles et formats requis\r\n        variants = self.generate_image_variants(processed_img, product_id)\r\n        \r\n        # Sauvegarder les versions optimisées\r\n        saved_files = self.save_variants(variants, output_dir)\r\n        \r\n        return saved_files\r\n    \r\n    def preprocess_image(self, img):\r\n        \"\"\"Appliquer le prétraitement de base à l'image produit\"\"\"\r\n        # Convertir en RGB si nécessaire\r\n        if img.mode in ('RGBA', 'LA', 'P'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            if img.mode == 'RGBA':\r\n                background.paste(img, mask=img.split()[-1])\r\n            else:\r\n                background.paste(img)\r\n            img = background\r\n        \r\n        # Recadrage automatique pour supprimer l'espace blanc excessif\r\n        if self.config['auto_crop']:\r\n            img = self.smart_crop(img)\r\n        \r\n        # Améliorer la qualité d'image\r\n        if self.config['color_enhancement']:\r\n            img = self.enhance_product_image(img)\r\n        \r\n        # Réduire le bruit\r\n        if self.config['noise_reduction']:\r\n            img = img.filter(ImageFilter.SMOOTH_MORE)\r\n        \r\n        return img\r\n    \r\n    def smart_crop(self, img):\r\n        \"\"\"Recadrage intelligent d'image produit pour supprimer l'arrière-plan excessif\"\"\"\r\n        # Convertir en tableau numpy pour analyse\r\n        img_array = np.array(img)\r\n        \r\n        # Trouver la boîte englobante des pixels non-blancs\r\n        mask = np.any(img_array \u003C 240, axis=2)  # Pas blanc pur\r\n        coords = np.argwhere(mask)\r\n        \r\n        if len(coords) == 0:\r\n            return img  # Pas de recadrage nécessaire\r\n        \r\n        # Obtenir la boîte englobante\r\n        y0, x0 = coords.min(axis=0)\r\n        y1, x1 = coords.max(axis=0)\r\n        \r\n        # Ajouter du padding\r\n        padding = 20\r\n        y0 = max(0, y0 - padding)\r\n        x0 = max(0, x0 - padding)\r\n        y1 = min(img.height, y1 + padding)\r\n        x1 = min(img.width, x1 + padding)\r\n        \r\n        return img.crop((x0, y0, x1, y1))\r\n```\r\n\r\n## Optimisation Spécifique à la Plateforme\r\n\r\n### Optimisation Amazon Marketplace\r\n\r\nAmazon a des exigences d'image spécifiques et des algorithmes :\r\n\r\n```python\r\nclass AmazonImageOptimizer:\r\n    def __init__(self):\r\n        self.requirements = {\r\n            'main_image': {\r\n                'min_size': (1000, 1000),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'background': 'pure_white',\r\n                'product_coverage': 85  # Pourcentage minimum de l'image\r\n            },\r\n            'additional_images': {\r\n                'min_size': (500, 500),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'lifestyle_allowed': True\r\n            }\r\n        }\r\n    \r\n    def optimize_for_amazon(self, image_path, output_path, image_type='main'):\r\n        \"\"\"Optimiser l'image spécifiquement pour le listing Amazon\"\"\"\r\n        img = Image.open(image_path)\r\n        \r\n        if image_type == 'main':\r\n            img = self.ensure_white_background(img)\r\n            img = self.ensure_minimum_size(img, (1000, 1000))\r\n        \r\n        # Amazon préfère l'espace colorimétrique sRGB\r\n        if img.mode != 'RGB':\r\n            img = img.convert('RGB')\r\n        \r\n        # Optimiser la taille de fichier en maintenant la qualité\r\n        quality = 90 if image_type == 'main' else 85\r\n        img.save(output_path, 'JPEG', quality=quality, optimize=True)\r\n        \r\n        return self.validate_amazon_requirements(output_path, image_type)\r\n```\r\n\r\n## Mesure de Performance et Optimisation\r\n\r\n### Métriques pour Suivi du Succès\r\n\r\nIndicateurs clés de performance pour l'optimisation d'images :\r\n\r\n```javascript\r\nclass EcommerceImageMetrics {\r\n    constructor() {\r\n        this.metrics = {\r\n            technical: {\r\n                'load_time': 'Temps de chargement image',\r\n                'file_size': 'Taille de fichier',\r\n                'compression_ratio': 'Ratio de compression',\r\n                'quality_score': 'Score de qualité'\r\n            },\r\n            business: {\r\n                'conversion_rate': 'Taux de conversion',\r\n                'bounce_rate': 'Taux de rebond',\r\n                'time_on_page': 'Temps sur page',\r\n                'cart_addition_rate': 'Taux d\\'ajout au panier'\r\n            }\r\n        };\r\n    }\r\n    \r\n    measureImagePerformance(imageUrl, callback) {\r\n        const startTime = performance.now();\r\n        const img = new Image();\r\n        \r\n        img.onload = () => {\r\n            const loadTime = performance.now() - startTime;\r\n            const fileSize = this.getImageFileSize(imageUrl);\r\n            \r\n            callback({\r\n                loadTime: loadTime,\r\n                fileSize: fileSize,\r\n                dimensions: { width: img.width, height: img.height },\r\n                timestamp: new Date().toISOString()\r\n            });\r\n        };\r\n        \r\n        img.src = imageUrl;\r\n    }\r\n}\r\n```\r\n\r\n## Automatisation et Mise à l'Échelle\r\n\r\n### Traitement par Lots pour Gros Catalogues\r\n\r\nTraitement efficace de milliers d'images produits :\r\n\r\n```python\r\nimport concurrent.futures\r\nimport multiprocessing\r\nfrom pathlib import Path\r\n\r\nclass BatchImageProcessor:\r\n    def __init__(self, max_workers=None):\r\n        self.max_workers = max_workers or multiprocessing.cpu_count()\r\n        self.processor = EcommerceImageProcessor()\r\n    \r\n    def process_catalog(self, input_directory, output_directory, progress_callback=None):\r\n        \"\"\"Traiter le catalogue complet d'images produits\"\"\"\r\n        input_path = Path(input_directory)\r\n        output_path = Path(output_directory)\r\n        output_path.mkdir(parents=True, exist_ok=True)\r\n        \r\n        # Trouver toutes les images\r\n        image_files = list(input_path.glob('**/*.{jpg,jpeg,png,webp}'))\r\n        total_files = len(image_files)\r\n        \r\n        processed_count = 0\r\n        failed_files = []\r\n        \r\n        with concurrent.futures.ThreadPoolExecutor(max_workers=self.max_workers) as executor:\r\n            # Soumettre toutes les tâches\r\n            future_to_file = {\r\n                executor.submit(self.process_single_image, img_file, output_path): img_file\r\n                for img_file in image_files\r\n            }\r\n            \r\n            # Traiter les résultats\r\n            for future in concurrent.futures.as_completed(future_to_file):\r\n                img_file = future_to_file[future]\r\n                try:\r\n                    result = future.result()\r\n                    processed_count += 1\r\n                    \r\n                    if progress_callback:\r\n                        progress_callback(processed_count, total_files, img_file.name)\r\n                        \r\n                except Exception as exc:\r\n                    failed_files.append((img_file, str(exc)))\r\n                    print(f'Fichier {img_file} a généré une exception : {exc}')\r\n        \r\n        return {\r\n            'total_files': total_files,\r\n            'processed_count': processed_count,\r\n            'failed_files': failed_files,\r\n            'success_rate': (processed_count / total_files) * 100 if total_files > 0 else 0\r\n        }\r\n```\r\n\r\n## Conclusion\r\n\r\nL'optimisation d'images produits pour l'e-commerce est un facteur critique pour le succès des boutiques en ligne. La mise en œuvre appropriée des techniques de compression, l'automatisation du traitement et la mesure de performance peuvent améliorer significativement les taux de conversion, réduire les taux de rebond et augmenter la satisfaction client.\r\n\r\nPoints clés à retenir :\r\n\r\n1. **Équilibrer qualité et performance** : Trouver le point optimal entre qualité visuelle et vitesse de chargement\r\n2. **L'automatisation est clé** : Implémenter des pipelines automatisés pour la mise à l'échelle\r\n3. **Tester et mesurer** : Utiliser les tests A/B pour vérifier l'impact de l'optimisation\r\n4. **Exigences spécifiques à la plateforme** : Adapter l'optimisation aux exigences spécifiques des marketplaces\r\n5. **Amélioration continue** : Mettre à jour régulièrement les stratégies basées sur les nouvelles technologies et données\r\n\r\nL'investissement dans l'optimisation professionnelle d'images se remboursera rapidement grâce à de meilleurs résultats business et une meilleure expérience utilisateur.\r\n","# Compresión de Imágenes de Productos E-commerce: Optimización Orientada a Ventas\r\n\r\nEl éxito del e-commerce depende en gran medida de la calidad de las imágenes de productos, con estudios que muestran que el 67% de los consumidores considera la calidad de imagen \"muy importante\" al realizar compras en línea. Sin embargo, los archivos de imagen grandes pueden impactar significativamente los tiempos de carga de páginas, las tasas de conversión y la experiencia del usuario móvil. Esta guía completa cubre técnicas avanzadas para optimizar imágenes de productos de e-commerce mientras se mantiene la calidad visual necesaria para impulsar las ventas.\r\n\r\n## Por Qué Importa la Optimización de Imágenes E-commerce\r\n\r\n### Impacto en las Tasas de Conversión\r\n\r\nLa optimización de imágenes de productos afecta directamente las métricas comerciales:\r\n- **Tasas de conversión**: 1 segundo de retraso en el tiempo de carga de página reduce las conversiones en un 7%\r\n- **Tasas de rebote**: 40% de los usuarios abandonan sitios que tardan más de 3 segundos en cargar\r\n- **Comercio móvil**: 73% del tráfico de e-commerce proviene de dispositivos móviles\r\n- **Rankings de búsqueda**: Google considera la velocidad de página en los rankings de búsqueda\r\n- **Satisfacción del cliente**: Las imágenes de alta calidad aumentan la confianza de compra\r\n\r\n### Requisitos Específicos del E-commerce\r\n\r\nLas imágenes de productos tienen desafíos únicos de optimización:\r\n- **Múltiples vistas de producto**: Imagen principal, miniaturas, vistas de zoom, rotaciones 360°\r\n- **Precisión de color**: Crítica para moda, cosméticos y decoración del hogar\r\n- **Preservación de detalles**: Los clientes necesitan ver textura, materiales y artesanía\r\n- **Rendimiento de carga**: Balance entre calidad y velocidad\r\n- **Compatibilidad entre dispositivos**: Experiencia consistente en todos los dispositivos\r\n\r\n## Comprensión de Tipos de Imágenes E-commerce\r\n\r\n### Categorías de Imágenes de Productos\r\n\r\nDiferentes tipos de imágenes requieren diferentes enfoques de optimización:\r\n\r\n```javascript\r\nconst ecommerceImageTypes = {\r\n    hero: {\r\n        purpose: 'Presentación principal del producto',\r\n        requirements: 'Alta calidad, carga rápida',\r\n        sizes: ['1200x1200', '800x800', '600x600'],\r\n        quality: { jpeg: 85, webp: 80 }\r\n    },\r\n    thumbnail: {\r\n        purpose: 'Visualizaciones de cuadrícula de productos',\r\n        requirements: 'Tamaño de archivo pequeño, reconocible',\r\n        sizes: ['300x300', '200x200', '150x150'],\r\n        quality: { jpeg: 75, webp: 70 }\r\n    },\r\n    zoom: {\r\n        purpose: 'Inspección detallada del producto',\r\n        requirements: 'Máxima preservación de detalles',\r\n        sizes: ['2000x2000', '1600x1600'],\r\n        quality: { jpeg: 90, webp: 85 }\r\n    },\r\n    gallery: {\r\n        purpose: 'Múltiples ángulos del producto',\r\n        requirements: 'Calidad consistente, lazy loading',\r\n        sizes: ['800x800', '600x600'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    },\r\n    lifestyle: {\r\n        purpose: 'Producto en uso/contexto',\r\n        requirements: 'Optimizado para emoción/contexto',\r\n        sizes: ['1200x800', '800x533'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    }\r\n};\r\n```\r\n\r\n### Estrategia de Optimización por Categoría de Producto\r\n\r\nDiferentes categorías de productos tienen requisitos específicos de imagen:\r\n\r\n```python\r\ndef get_category_optimization_settings(product_category):\r\n    \"\"\"Obtener configuraciones de optimización para diferentes categorías de productos\"\"\"\r\n    settings = {\r\n        'fashion': {\r\n            'priority': ['color_accuracy', 'texture_detail'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 90},\r\n            'critical_views': ['front', 'back', 'detail']\r\n        },\r\n        'electronics': {\r\n            'priority': ['detail_preservation', 'fast_loading'],\r\n            'format_preference': 'webp_or_avif',\r\n            'quality_range': {'min': 75, 'max': 85},\r\n            'critical_views': ['main', 'interfaces', 'size_comparison']\r\n        },\r\n        'home_decor': {\r\n            'priority': ['color_accuracy', 'lifestyle_context'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 88},\r\n            'critical_views': ['styled', 'closeup', 'dimensions']\r\n        },\r\n        'jewelry': {\r\n            'priority': ['maximum_detail', 'color_accuracy'],\r\n            'format_preference': 'png_for_detailed_webp_for_hero',\r\n            'quality_range': {'min': 85, 'max': 95},\r\n            'critical_views': ['macro', '360_spin', 'lifestyle']\r\n        },\r\n        'books': {\r\n            'priority': ['fast_loading', 'text_readability'],\r\n            'format_preference': 'webp_aggressive_compression',\r\n            'quality_range': {'min': 70, 'max': 80},\r\n            'critical_views': ['cover', 'back', 'spine']\r\n        }\r\n    }\r\n    return settings.get(product_category, settings['electronics'])\r\n```\r\n\r\n## Procesamiento Avanzado de Imágenes de Productos\r\n\r\n### Pipeline Automatizado de Imágenes de Productos\r\n\r\nSistema de procesamiento automatizado integral:\r\n\r\n```python\r\nimport os\r\nfrom PIL import Image, ImageEnhance, ImageFilter\r\nimport numpy as np\r\n\r\nclass EcommerceImageProcessor:\r\n    def __init__(self, config=None):\r\n        self.config = config or self.get_default_config()\r\n        self.supported_formats = ['jpeg', 'webp', 'avif', 'png']\r\n        \r\n    def get_default_config(self):\r\n        return {\r\n            'background_removal': True,\r\n            'auto_crop': True,\r\n            'color_enhancement': True,\r\n            'noise_reduction': True,\r\n            'watermark': False,\r\n            'quality_thresholds': {\r\n                'hero': 85,\r\n                'gallery': 80,\r\n                'thumbnail': 75,\r\n                'zoom': 90\r\n            }\r\n        }\r\n    \r\n    def process_product_image(self, input_path, output_dir, product_id):\r\n        \"\"\"Procesar una sola imagen de producto en todas las variantes requeridas\"\"\"\r\n        img = Image.open(input_path)\r\n        \r\n        # Preprocesamiento básico\r\n        processed_img = self.preprocess_image(img)\r\n        \r\n        # Generar todos los tamaños y formatos requeridos\r\n        variants = self.generate_image_variants(processed_img, product_id)\r\n        \r\n        # Guardar versiones optimizadas\r\n        saved_files = self.save_variants(variants, output_dir)\r\n        \r\n        return saved_files\r\n    \r\n    def preprocess_image(self, img):\r\n        \"\"\"Aplicar preprocesamiento básico a imagen de producto\"\"\"\r\n        # Convertir a RGB si es necesario\r\n        if img.mode in ('RGBA', 'LA', 'P'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            if img.mode == 'RGBA':\r\n                background.paste(img, mask=img.split()[-1])\r\n            else:\r\n                background.paste(img)\r\n            img = background\r\n        \r\n        # Auto-recorte para eliminar espacio en blanco excesivo\r\n        if self.config['auto_crop']:\r\n            img = self.smart_crop(img)\r\n        \r\n        # Mejorar calidad de imagen\r\n        if self.config['color_enhancement']:\r\n            img = self.enhance_product_image(img)\r\n        \r\n        # Reducir ruido\r\n        if self.config['noise_reduction']:\r\n            img = img.filter(ImageFilter.SMOOTH_MORE)\r\n        \r\n        return img\r\n    \r\n    def smart_crop(self, img):\r\n        \"\"\"Recorte inteligente de imagen de producto para eliminar fondo excesivo\"\"\"\r\n        # Convertir a array numpy para análisis\r\n        img_array = np.array(img)\r\n        \r\n        # Encontrar bounding box de píxeles no blancos\r\n        mask = np.any(img_array \u003C 240, axis=2)  # No blanco puro\r\n        coords = np.argwhere(mask)\r\n        \r\n        if len(coords) == 0:\r\n            return img  # No se necesita recorte\r\n        \r\n        # Obtener bounding box\r\n        y0, x0 = coords.min(axis=0)\r\n        y1, x1 = coords.max(axis=0)\r\n        \r\n        # Agregar padding\r\n        padding = 20\r\n        y0 = max(0, y0 - padding)\r\n        x0 = max(0, x0 - padding)\r\n        y1 = min(img.height, y1 + padding)\r\n        x1 = min(img.width, x1 + padding)\r\n        \r\n        return img.crop((x0, y0, x1, y1))\r\n    \r\n    def enhance_product_image(self, img):\r\n        \"\"\"Mejorar imagen de producto para visualización e-commerce\"\"\"\r\n        # Mejorar brillo ligeramente\r\n        brightness_enhancer = ImageEnhance.Brightness(img)\r\n        img = brightness_enhancer.enhance(1.05)\r\n        \r\n        # Mejorar contraste\r\n        contrast_enhancer = ImageEnhance.Contrast(img)\r\n        img = contrast_enhancer.enhance(1.1)\r\n        \r\n        # Mejorar saturación de color\r\n        color_enhancer = ImageEnhance.Color(img)\r\n        img = color_enhancer.enhance(1.05)\r\n        \r\n        # Mejorar nitidez\r\n        sharpness_enhancer = ImageEnhance.Sharpness(img)\r\n        img = sharpness_enhancer.enhance(1.1)\r\n        \r\n        return img\r\n```\r\n\r\n## Optimización Específica de Plataforma\r\n\r\n### Optimización de Amazon Marketplace\r\n\r\nAmazon tiene requisitos específicos de imagen y algoritmos:\r\n\r\n```python\r\nclass AmazonImageOptimizer:\r\n    def __init__(self):\r\n        self.requirements = {\r\n            'main_image': {\r\n                'min_size': (1000, 1000),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'background': 'pure_white',\r\n                'product_coverage': 85  # Porcentaje mínimo de imagen\r\n            },\r\n            'additional_images': {\r\n                'min_size': (500, 500),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'lifestyle_allowed': True\r\n            }\r\n        }\r\n    \r\n    def optimize_for_amazon(self, image_path, output_path, image_type='main'):\r\n        \"\"\"Optimizar imagen específicamente para listado de Amazon\"\"\"\r\n        img = Image.open(image_path)\r\n        \r\n        if image_type == 'main':\r\n            img = self.ensure_white_background(img)\r\n            img = self.ensure_minimum_size(img, (1000, 1000))\r\n        \r\n        # Amazon prefiere espacio de color sRGB\r\n        if img.mode != 'RGB':\r\n            img = img.convert('RGB')\r\n        \r\n        # Optimizar tamaño de archivo manteniendo calidad\r\n        quality = 90 if image_type == 'main' else 85\r\n        img.save(output_path, 'JPEG', quality=quality, optimize=True)\r\n        \r\n        return self.validate_amazon_requirements(output_path, image_type)\r\n```\r\n\r\n## Medición de Rendimiento y Optimización\r\n\r\n### Métricas para Seguimiento de Éxito\r\n\r\nIndicadores clave de rendimiento para optimización de imágenes:\r\n\r\n```javascript\r\nclass EcommerceImageMetrics {\r\n    constructor() {\r\n        this.metrics = {\r\n            technical: {\r\n                'load_time': 'Tiempo de carga de imagen',\r\n                'file_size': 'Tamaño de archivo',\r\n                'compression_ratio': 'Ratio de compresión',\r\n                'quality_score': 'Puntuación de calidad'\r\n            },\r\n            business: {\r\n                'conversion_rate': 'Tasa de conversión',\r\n                'bounce_rate': 'Tasa de rebote',\r\n                'time_on_page': 'Tiempo en página',\r\n                'cart_addition_rate': 'Tasa de adición al carrito'\r\n            }\r\n        };\r\n    }\r\n    \r\n    measureImagePerformance(imageUrl, callback) {\r\n        const startTime = performance.now();\r\n        const img = new Image();\r\n        \r\n        img.onload = () => {\r\n            const loadTime = performance.now() - startTime;\r\n            const fileSize = this.getImageFileSize(imageUrl);\r\n            \r\n            callback({\r\n                loadTime: loadTime,\r\n                fileSize: fileSize,\r\n                dimensions: { width: img.width, height: img.height },\r\n                timestamp: new Date().toISOString()\r\n            });\r\n        };\r\n        \r\n        img.src = imageUrl;\r\n    }\r\n}\r\n```\r\n\r\n## Automatización y Escalado\r\n\r\n### Procesamiento por Lotes para Catálogos Grandes\r\n\r\nProcesamiento eficiente de miles de imágenes de productos:\r\n\r\n```python\r\nimport concurrent.futures\r\nimport multiprocessing\r\nfrom pathlib import Path\r\n\r\nclass BatchImageProcessor:\r\n    def __init__(self, max_workers=None):\r\n        self.max_workers = max_workers or multiprocessing.cpu_count()\r\n        self.processor = EcommerceImageProcessor()\r\n    \r\n    def process_catalog(self, input_directory, output_directory, progress_callback=None):\r\n        \"\"\"Procesar catálogo completo de imágenes de productos\"\"\"\r\n        input_path = Path(input_directory)\r\n        output_path = Path(output_directory)\r\n        output_path.mkdir(parents=True, exist_ok=True)\r\n        \r\n        # Encontrar todas las imágenes\r\n        image_files = list(input_path.glob('**/*.{jpg,jpeg,png,webp}'))\r\n        total_files = len(image_files)\r\n        \r\n        processed_count = 0\r\n        failed_files = []\r\n        \r\n        with concurrent.futures.ThreadPoolExecutor(max_workers=self.max_workers) as executor:\r\n            # Enviar todas las tareas\r\n            future_to_file = {\r\n                executor.submit(self.process_single_image, img_file, output_path): img_file\r\n                for img_file in image_files\r\n            }\r\n            \r\n            # Procesar resultados\r\n            for future in concurrent.futures.as_completed(future_to_file):\r\n                img_file = future_to_file[future]\r\n                try:\r\n                    result = future.result()\r\n                    processed_count += 1\r\n                    \r\n                    if progress_callback:\r\n                        progress_callback(processed_count, total_files, img_file.name)\r\n                        \r\n                except Exception as exc:\r\n                    failed_files.append((img_file, str(exc)))\r\n                    print(f'Archivo {img_file} generó excepción: {exc}')\r\n        \r\n        return {\r\n            'total_files': total_files,\r\n            'processed_count': processed_count,\r\n            'failed_files': failed_files,\r\n            'success_rate': (processed_count / total_files) * 100 if total_files > 0 else 0\r\n        }\r\n```\r\n\r\n## Conclusión\r\n\r\nLa optimización de imágenes de productos para e-commerce es un factor crítico para el éxito de las tiendas en línea. La implementación adecuada de técnicas de compresión, automatización de procesamiento y medición de rendimiento puede mejorar significativamente las tasas de conversión, reducir las tasas de rebote y aumentar la satisfacción del cliente.\r\n\r\nPuntos clave para recordar:\r\n\r\n1. **Equilibrar calidad y rendimiento**: Encontrar el punto óptimo entre calidad visual y velocidad de carga\r\n2. **La automatización es clave**: Implementar pipelines automatizados para escalado\r\n3. **Probar y medir**: Usar pruebas A/B para verificar el impacto de la optimización\r\n4. **Requisitos específicos de plataforma**: Adaptar la optimización a los requisitos específicos del marketplace\r\n5. **Mejora continua**: Actualizar regularmente las estrategias basadas en nuevas tecnologías y datos\r\n\r\nLa inversión en optimización profesional de imágenes se pagará rápidamente a través de mejores resultados comerciales y mejor experiencia del usuario.","# Compressione Immagini Prodotto E-commerce: Ottimizzazione Orientata alle Vendite\r\n\r\nIl successo dell'e-commerce dipende fortemente dalla qualità delle immagini dei prodotti, con studi che mostrano che il 67% dei consumatori considera la qualità delle immagini \"molto importante\" quando effettua acquisti online. Tuttavia, file di immagini di grandi dimensioni possono influenzare significativamente i tempi di caricamento delle pagine, i tassi di conversione e l'esperienza utente mobile. Questa guida completa copre tecniche avanzate per ottimizzare le immagini dei prodotti e-commerce mantenendo la qualità visiva necessaria per guidare le vendite.\r\n\r\n## Perché l'Ottimizzazione delle Immagini E-commerce è Importante\r\n\r\n### Impatto sui Tassi di Conversione\r\n\r\nL'ottimizzazione delle immagini dei prodotti influenza direttamente le metriche aziendali:\r\n- **Tassi di conversione**: 1 secondo di ritardo nel tempo di caricamento della pagina riduce le conversioni del 7%\r\n- **Tassi di rimbalzo**: Il 40% degli utenti abbandona i siti che impiegano più di 3 secondi per caricarsi\r\n- **Mobile commerce**: Il 73% del traffico e-commerce proviene da dispositivi mobili\r\n- **Classifiche di ricerca**: Google considera la velocità della pagina nelle classifiche di ricerca\r\n- **Soddisfazione del cliente**: Le immagini di alta qualità aumentano la fiducia nell'acquisto\r\n\r\n### Requisiti Specifici dell'E-commerce\r\n\r\nLe immagini dei prodotti hanno sfide di ottimizzazione uniche:\r\n- **Visualizzazioni multiple del prodotto**: Immagine principale, miniature, visualizzazioni zoom, rotazioni a 360°\r\n- **Accuratezza del colore**: Critica per moda, cosmetici e arredamento\r\n- **Preservazione dei dettagli**: I clienti devono vedere texture, materiali e lavorazione\r\n- **Prestazioni di caricamento**: Equilibrio tra qualità e velocità\r\n- **Compatibilità cross-device**: Esperienza coerente su tutti i dispositivi\r\n\r\n## Comprendere i Tipi di Immagini E-commerce\r\n\r\n### Categorie di Immagini Prodotto\r\n\r\nDiversi tipi di immagini richiedono approcci di ottimizzazione diversi:\r\n\r\n```javascript\r\nconst ecommerceImageTypes = {\r\n    hero: {\r\n        purpose: 'Showcase principale del prodotto',\r\n        requirements: 'Alta qualità, caricamento veloce',\r\n        sizes: ['1200x1200', '800x800', '600x600'],\r\n        quality: { jpeg: 85, webp: 80 }\r\n    },\r\n    thumbnail: {\r\n        purpose: 'Visualizzazioni griglia prodotti',\r\n        requirements: 'Dimensione file piccola, riconoscibile',\r\n        sizes: ['300x300', '200x200', '150x150'],\r\n        quality: { jpeg: 75, webp: 70 }\r\n    },\r\n    zoom: {\r\n        purpose: 'Ispezione dettagliata del prodotto',\r\n        requirements: 'Massima preservazione dei dettagli',\r\n        sizes: ['2000x2000', '1600x1600'],\r\n        quality: { jpeg: 90, webp: 85 }\r\n    },\r\n    gallery: {\r\n        purpose: 'Angolazioni multiple del prodotto',\r\n        requirements: 'Qualità coerente, lazy loading',\r\n        sizes: ['800x800', '600x600'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    },\r\n    lifestyle: {\r\n        purpose: 'Prodotto in uso/contesto',\r\n        requirements: 'Ottimizzato per emozione/contesto',\r\n        sizes: ['1200x800', '800x533'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    }\r\n};\r\n```\r\n\r\n### Strategia di Ottimizzazione per Categoria Prodotto\r\n\r\nDiverse categorie di prodotti hanno requisiti specifici per le immagini:\r\n\r\n```python\r\ndef get_category_optimization_settings(product_category):\r\n    \"\"\"Ottieni impostazioni di ottimizzazione per diverse categorie di prodotti\"\"\"\r\n    settings = {\r\n        'fashion': {\r\n            'priority': ['color_accuracy', 'texture_detail'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 90},\r\n            'critical_views': ['front', 'back', 'detail']\r\n        },\r\n        'electronics': {\r\n            'priority': ['detail_preservation', 'fast_loading'],\r\n            'format_preference': 'webp_or_avif',\r\n            'quality_range': {'min': 75, 'max': 85},\r\n            'critical_views': ['main', 'interfaces', 'size_comparison']\r\n        },\r\n        'home_decor': {\r\n            'priority': ['color_accuracy', 'lifestyle_context'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 88},\r\n            'critical_views': ['styled', 'closeup', 'dimensions']\r\n        },\r\n        'jewelry': {\r\n            'priority': ['maximum_detail', 'color_accuracy'],\r\n            'format_preference': 'png_for_detailed_webp_for_hero',\r\n            'quality_range': {'min': 85, 'max': 95},\r\n            'critical_views': ['macro', '360_spin', 'lifestyle']\r\n        },\r\n        'books': {\r\n            'priority': ['fast_loading', 'text_readability'],\r\n            'format_preference': 'webp_aggressive_compression',\r\n            'quality_range': {'min': 70, 'max': 80},\r\n            'critical_views': ['cover', 'back', 'spine']\r\n        }\r\n    }\r\n    return settings.get(product_category, settings['electronics'])\r\n```\r\n\r\n## Elaborazione Avanzata delle Immagini Prodotto\r\n\r\n### Pipeline Automatizzata per Immagini Prodotto\r\n\r\nSistema di elaborazione automatizzata completo:\r\n\r\n```python\r\nimport os\r\nfrom PIL import Image, ImageEnhance, ImageFilter\r\nimport numpy as np\r\n\r\nclass EcommerceImageProcessor:\r\n    def __init__(self, config=None):\r\n        self.config = config or self.get_default_config()\r\n        self.supported_formats = ['jpeg', 'webp', 'avif', 'png']\r\n        \r\n    def get_default_config(self):\r\n        return {\r\n            'background_removal': True,\r\n            'auto_crop': True,\r\n            'color_enhancement': True,\r\n            'noise_reduction': True,\r\n            'watermark': False,\r\n            'quality_thresholds': {\r\n                'hero': 85,\r\n                'gallery': 80,\r\n                'thumbnail': 75,\r\n                'zoom': 90\r\n            }\r\n        }\r\n    \r\n    def process_product_image(self, input_path, output_dir, product_id):\r\n        \"\"\"Elabora una singola immagine prodotto in tutte le varianti richieste\"\"\"\r\n        img = Image.open(input_path)\r\n        \r\n        # Preprocessing di base\r\n        processed_img = self.preprocess_image(img)\r\n        \r\n        # Genera tutte le dimensioni e formati richiesti\r\n        variants = self.generate_image_variants(processed_img, product_id)\r\n        \r\n        # Salva versioni ottimizzate\r\n        saved_files = self.save_variants(variants, output_dir)\r\n        \r\n        return saved_files\r\n    \r\n    def preprocess_image(self, img):\r\n        \"\"\"Applica preprocessing di base all'immagine prodotto\"\"\"\r\n        # Converti in RGB se necessario\r\n        if img.mode in ('RGBA', 'LA', 'P'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            if img.mode == 'RGBA':\r\n                background.paste(img, mask=img.split()[-1])\r\n            else:\r\n                background.paste(img)\r\n            img = background\r\n        \r\n        # Auto-crop per rimuovere spazio bianco in eccesso\r\n        if self.config['auto_crop']:\r\n            img = self.smart_crop(img)\r\n        \r\n        # Migliora qualità immagine\r\n        if self.config['color_enhancement']:\r\n            img = self.enhance_product_image(img)\r\n        \r\n        # Riduci rumore\r\n        if self.config['noise_reduction']:\r\n            img = img.filter(ImageFilter.SMOOTH_MORE)\r\n        \r\n        return img\r\n    \r\n    def smart_crop(self, img):\r\n        \"\"\"Ritaglia intelligentemente l'immagine prodotto per rimuovere sfondo in eccesso\"\"\"\r\n        # Converti in array numpy per analisi\r\n        img_array = np.array(img)\r\n        \r\n        # Trova bounding box di pixel non bianchi\r\n        mask = np.any(img_array \u003C 240, axis=2)  # Non bianco puro\r\n        coords = np.argwhere(mask)\r\n        \r\n        if len(coords) == 0:\r\n            return img  # Nessun ritaglio necessario\r\n        \r\n        # Ottieni bounding box\r\n        y0, x0 = coords.min(axis=0)\r\n        y1, x1 = coords.max(axis=0)\r\n        \r\n        # Aggiungi padding\r\n        padding = 20\r\n        y0 = max(0, y0 - padding)\r\n        x0 = max(0, x0 - padding)\r\n        y1 = min(img.height, y1 + padding)\r\n        x1 = min(img.width, x1 + padding)\r\n        \r\n        return img.crop((x0, y0, x1, y1))\r\n    \r\n    def enhance_product_image(self, img):\r\n        \"\"\"Migliora la qualità dell'immagine prodotto\"\"\"\r\n        # Migliora contrasto\r\n        enhancer = ImageEnhance.Contrast(img)\r\n        img = enhancer.enhance(1.1)\r\n        \r\n        # Fine-tune saturazione colore\r\n        enhancer = ImageEnhance.Color(img)\r\n        img = enhancer.enhance(1.05)\r\n        \r\n        # Migliora nitidezza\r\n        enhancer = ImageEnhance.Sharpness(img)\r\n        img = enhancer.enhance(1.1)\r\n        \r\n        return img\r\n    \r\n    def generate_image_variants(self, img, product_id):\r\n        \"\"\"Genera varianti immagine in diverse dimensioni e formati\"\"\"\r\n        variants = {}\r\n        \r\n        # Definisci dimensioni standard\r\n        sizes = {\r\n            'hero': [(1200, 1200), (800, 800), (600, 600)],\r\n            'thumbnail': [(300, 300), (200, 200), (150, 150)],\r\n            'zoom': [(2000, 2000), (1600, 1600)],\r\n            'gallery': [(800, 800), (600, 600)]\r\n        }\r\n        \r\n        for variant_type, size_list in sizes.items():\r\n            variants[variant_type] = {}\r\n            for size in size_list:\r\n                # Ridimensiona immagine con qualità appropriata\r\n                resized_img = self.resize_with_quality(img, size)\r\n                variants[variant_type][f\"{size[0]}x{size[1]}\"] = resized_img\r\n        \r\n        return variants\r\n    \r\n    def resize_with_quality(self, img, target_size):\r\n        \"\"\"Ridimensiona immagine con alta qualità\"\"\"\r\n        # Mantieni aspect ratio\r\n        img.thumbnail(target_size, Image.Resampling.LANCZOS)\r\n        \r\n        # Crea nuova immagine con sfondo bianco se necessario\r\n        if img.size != target_size:\r\n            new_img = Image.new('RGB', target_size, (255, 255, 255))\r\n            # Centra immagine\r\n            paste_x = (target_size[0] - img.size[0]) // 2\r\n            paste_y = (target_size[1] - img.size[1]) // 2\r\n            new_img.paste(img, (paste_x, paste_y))\r\n            return new_img\r\n        \r\n        return img\r\n    \r\n    def save_variants(self, variants, output_dir):\r\n        \"\"\"Salva varianti immagine in formati ottimizzati\"\"\"\r\n        saved_files = []\r\n        \r\n        for variant_type, sizes in variants.items():\r\n            variant_dir = os.path.join(output_dir, variant_type)\r\n            os.makedirs(variant_dir, exist_ok=True)\r\n            \r\n            for size_name, img in sizes.items():\r\n                # Salva JPEG\r\n                jpeg_path = os.path.join(variant_dir, f\"{size_name}.jpg\")\r\n                quality = self.config['quality_thresholds'].get(variant_type, 80)\r\n                img.save(jpeg_path, 'JPEG', quality=quality, optimize=True)\r\n                saved_files.append(jpeg_path)\r\n                \r\n                # Salva WebP\r\n                webp_path = os.path.join(variant_dir, f\"{size_name}.webp\")\r\n                webp_quality = max(quality - 5, 70)  # WebP solitamente compressione migliore\r\n                img.save(webp_path, 'WebP', quality=webp_quality, optimize=True)\r\n                saved_files.append(webp_path)\r\n        \r\n        return saved_files\r\n```\r\n\r\n## Ottimizzazione Amazon Marketplace\r\n\r\n### Requisiti Immagini Amazon\r\n\r\nRequisiti specifici di ottimizzazione immagini Amazon:\r\n\r\n```python\r\nclass AmazonImageOptimizer:\r\n    def __init__(self):\r\n        self.amazon_requirements = {\r\n            'main_image': {\r\n                'min_size': (1000, 1000),\r\n                'max_size': (10000, 10000),\r\n                'background': 'pure_white',\r\n                'format': ['JPEG', 'PNG', 'GIF'],\r\n                'quality_min': 85\r\n            },\r\n            'additional_images': {\r\n                'min_size': (500, 500),\r\n                'recommended_size': (1600, 1600),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'max_count': 8\r\n            },\r\n            'zoom_functionality': {\r\n                'min_size': (1001, 1001),\r\n                'recommended_size': (2000, 2000),\r\n                'enables_zoom': True\r\n            }\r\n        }\r\n    \r\n    def optimize_for_amazon(self, image_path, image_type='main'):\r\n        \"\"\"Ottimizza immagine per requisiti Amazon\"\"\"\r\n        img = Image.open(image_path)\r\n        requirements = self.amazon_requirements[f\"{image_type}_image\"]\r\n        \r\n        # Controlla e modifica dimensioni\r\n        if img.size[0] \u003C requirements['min_size'][0] or img.size[1] \u003C requirements['min_size'][1]:\r\n            # Ingrandisci immagine se troppo piccola\r\n            img = self.upscale_image(img, requirements['min_size'])\r\n        \r\n        # Assicura sfondo bianco per immagine principale\r\n        if image_type == 'main' and requirements.get('background') == 'pure_white':\r\n            img = self.ensure_white_background(img)\r\n        \r\n        # Salva con ottimizzazione\r\n        return self.save_amazon_optimized(img, image_path, image_type)\r\n    \r\n    def ensure_white_background(self, img):\r\n        \"\"\"Assicura sfondo bianco puro\"\"\"\r\n        if img.mode in ('RGBA', 'LA'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            background.paste(img, mask=img.split()[-1])\r\n            return background\r\n        elif img.mode == 'P':\r\n            return img.convert('RGB')\r\n        return img\r\n    \r\n    def upscale_image(self, img, min_size):\r\n        \"\"\"Ingrandisci immagine a dimensione minima\"\"\"\r\n        scale_factor = max(min_size[0] / img.size[0], min_size[1] / img.size[1])\r\n        new_size = (int(img.size[0] * scale_factor), int(img.size[1] * scale_factor))\r\n        return img.resize(new_size, Image.Resampling.LANCZOS)\r\n```\r\n\r\n## Misurazione e Monitoraggio delle Prestazioni\r\n\r\n### Metriche di Ottimizzazione Immagini\r\n\r\nTracciamento degli indicatori chiave di prestazione:\r\n\r\n```python\r\nimport time\r\nimport requests\r\nfrom PIL import Image\r\nimport os\r\n\r\nclass ImagePerformanceMonitor:\r\n    def __init__(self):\r\n        self.metrics = {\r\n            'file_sizes': {},\r\n            'load_times': {},\r\n            'quality_scores': {},\r\n            'conversion_impact': {}\r\n        }\r\n    \r\n    def measure_optimization_impact(self, original_path, optimized_path):\r\n        \"\"\"Misura impatto dell'ottimizzazione\"\"\"\r\n        # Confronto dimensioni file\r\n        original_size = os.path.getsize(original_path)\r\n        optimized_size = os.path.getsize(optimized_path)\r\n        size_reduction = ((original_size - optimized_size) / original_size) * 100\r\n        \r\n        # Valutazione qualità immagine\r\n        quality_score = self.calculate_quality_score(original_path, optimized_path)\r\n        \r\n        # Simulazione miglioramento tempo caricamento\r\n        load_time_improvement = self.simulate_load_time_improvement(\r\n            original_size, optimized_size\r\n        )\r\n        \r\n        return {\r\n            'size_reduction_percent': size_reduction,\r\n            'quality_retention_percent': quality_score,\r\n            'load_time_improvement_ms': load_time_improvement,\r\n            'optimization_ratio': size_reduction / (100 - quality_score) if quality_score \u003C 100 else size_reduction\r\n        }\r\n    \r\n    def calculate_quality_score(self, original_path, optimized_path):\r\n        \"\"\"Calcola punteggio qualità immagine\"\"\"\r\n        try:\r\n            from skimage.metrics import structural_similarity as ssim\r\n            import numpy as np\r\n            \r\n            # Carica e converti immagini\r\n            original = np.array(Image.open(original_path).convert('RGB'))\r\n            optimized = np.array(Image.open(optimized_path).convert('RGB'))\r\n            \r\n            # Calcola SSIM\r\n            ssim_score = ssim(original, optimized, multichannel=True, channel_axis=2)\r\n            return ssim_score * 100\r\n        except ImportError:\r\n            # Stima semplice basata su dimensioni se non c'è scikit-image\r\n            return 85.0  # Valore predefinito\r\n    \r\n    def simulate_load_time_improvement(self, original_size, optimized_size):\r\n        \"\"\"Simula miglioramento tempo caricamento\"\"\"\r\n        # Basato su velocità internet media (5 Mbps)\r\n        avg_speed_bytes_per_ms = 5 * 1024 * 1024 / 8 / 1000  # 5 Mbps a bytes/ms\r\n        \r\n        original_load_time = original_size / avg_speed_bytes_per_ms\r\n        optimized_load_time = optimized_size / avg_speed_bytes_per_ms\r\n        \r\n        return original_load_time - optimized_load_time\r\n    \r\n    def generate_performance_report(self, optimization_results):\r\n        \"\"\"Genera report prestazioni\"\"\"\r\n        report = {\r\n            'summary': {\r\n                'total_images_processed': len(optimization_results),\r\n                'average_size_reduction': sum(r['size_reduction_percent'] for r in optimization_results) / len(optimization_results),\r\n                'average_quality_retention': sum(r['quality_retention_percent'] for r in optimization_results) / len(optimization_results),\r\n                'total_load_time_saved_ms': sum(r['load_time_improvement_ms'] for r in optimization_results)\r\n            },\r\n            'recommendations': self.generate_recommendations(optimization_results)\r\n        }\r\n        return report\r\n    \r\n    def generate_recommendations(self, results):\r\n        \"\"\"Genera raccomandazioni ottimizzazione\"\"\"\r\n        recommendations = []\r\n        \r\n        avg_size_reduction = sum(r['size_reduction_percent'] for r in results) / len(results)\r\n        avg_quality = sum(r['quality_retention_percent'] for r in results) / len(results)\r\n        \r\n        if avg_size_reduction \u003C 30:\r\n            recommendations.append(\"Applica impostazioni di compressione più aggressive\")\r\n        \r\n        if avg_quality \u003C 85:\r\n            recommendations.append(\"Fine-tune impostazioni qualità per risultati visivi migliori\")\r\n        \r\n        if any(r['load_time_improvement_ms'] > 500 for r in results):\r\n            recommendations.append(\"Prioritizza ottimizzazione immagini critiche\")\r\n        \r\n        return recommendations\r\n```\r\n\r\n## Elaborazione Batch per Cataloghi Grandi\r\n\r\n### Elaborazione Immagini Parallela\r\n\r\nElaborazione efficiente per grandi volumi di immagini prodotto:\r\n\r\n```python\r\nimport concurrent.futures\r\nimport multiprocessing\r\nfrom pathlib import Path\r\nimport logging\r\n\r\nclass BatchImageProcessor:\r\n    def __init__(self, max_workers=None):\r\n        self.max_workers = max_workers or multiprocessing.cpu_count()\r\n        self.processed_count = 0\r\n        self.failed_count = 0\r\n        \r\n        # Setup logging\r\n        logging.basicConfig(level=logging.INFO)\r\n        self.logger = logging.getLogger(__name__)\r\n    \r\n    def process_catalog(self, input_directory, output_directory, product_categories=None):\r\n        \"\"\"Elabora intero catalogo prodotti\"\"\"\r\n        input_path = Path(input_directory)\r\n        output_path = Path(output_directory)\r\n        output_path.mkdir(parents=True, exist_ok=True)\r\n        \r\n        # Raccogli file immagini\r\n        image_files = self.collect_image_files(input_path)\r\n        self.logger.info(f\"Totale {len(image_files)} immagini in attesa di elaborazione\")\r\n        \r\n        # Elaborazione parallela\r\n        with concurrent.futures.ThreadPoolExecutor(max_workers=self.max_workers) as executor:\r\n            # Invia task\r\n            future_to_file = {\r\n                executor.submit(\r\n                    self.process_single_product_image, \r\n                    img_file, \r\n                    output_path,\r\n                    product_categories.get(img_file.stem) if product_categories else None\r\n                ): img_file \r\n                for img_file in image_files\r\n            }\r\n            \r\n            # Elabora risultati\r\n            for future in concurrent.futures.as_completed(future_to_file):\r\n                img_file = future_to_file[future]\r\n                try:\r\n                    result = future.result()\r\n                    self.processed_count += 1\r\n                    if self.processed_count % 100 == 0:\r\n                        self.logger.info(f\"Elaborate: {self.processed_count}/{len(image_files)}\")\r\n                except Exception as exc:\r\n                    self.failed_count += 1\r\n                    self.logger.error(f\"Errore elaborando {img_file}: {exc}\")\r\n        \r\n        # Genera report riassuntivo\r\n        self.generate_batch_report(len(image_files))\r\n    \r\n    def collect_image_files(self, input_path):\r\n        \"\"\"Raccogli file immagini da directory input\"\"\"\r\n        supported_extensions = {'.jpg', '.jpeg', '.png', '.webp', '.tiff', '.bmp'}\r\n        image_files = []\r\n        \r\n        for ext in supported_extensions:\r\n            image_files.extend(input_path.glob(f\"**/*{ext}\"))\r\n            image_files.extend(input_path.glob(f\"**/*{ext.upper()}\"))\r\n        \r\n        return image_files\r\n    \r\n    def process_single_product_image(self, image_path, output_dir, category=None):\r\n        \"\"\"Elabora singola immagine prodotto\"\"\"\r\n        try:\r\n            processor = EcommerceImageProcessor()\r\n            \r\n            # Applica impostazioni specifiche categoria\r\n            if category:\r\n                category_settings = get_category_optimization_settings(category)\r\n                processor.config.update(category_settings)\r\n            \r\n            # Elabora immagine\r\n            product_id = image_path.stem\r\n            result = processor.process_product_image(\r\n                str(image_path), \r\n                str(output_dir), \r\n                product_id\r\n            )\r\n            \r\n            return {\r\n                'status': 'success',\r\n                'input_file': str(image_path),\r\n                'output_files': result,\r\n                'product_id': product_id\r\n            }\r\n            \r\n        except Exception as e:\r\n            return {\r\n                'status': 'error',\r\n                'input_file': str(image_path),\r\n                'error': str(e)\r\n            }\r\n    \r\n    def generate_batch_report(self, total_files):\r\n        \"\"\"Genera report elaborazione batch\"\"\"\r\n        success_rate = (self.processed_count / total_files) * 100\r\n        \r\n        report = f\"\"\"\r\n        Report Elaborazione Immagini Batch\r\n        ==================================\r\n        File totali: {total_files}\r\n        Elaborate con successo: {self.processed_count}\r\n        Fallite: {self.failed_count}\r\n        Tasso di successo: {success_rate:.2f}%\r\n        \r\n        Velocità elaborazione: {self.processed_count / self.max_workers:.2f} immagini/worker\r\n        \"\"\"\r\n        \r\n        self.logger.info(report)\r\n        return report\r\n\r\n# Esempio utilizzo\r\ndef optimize_ecommerce_catalog():\r\n    \"\"\"Ottimizza catalogo e-commerce\"\"\"\r\n    # Definisci categorie prodotti\r\n    product_categories = {\r\n        'shirt_001': 'fashion',\r\n        'laptop_002': 'electronics',\r\n        'sofa_003': 'home_decor',\r\n        'ring_004': 'jewelry'\r\n    }\r\n    \r\n    # Inizializza batch processor\r\n    batch_processor = BatchImageProcessor(max_workers=8)\r\n    \r\n    # Elabora catalogo\r\n    batch_processor.process_catalog(\r\n        input_directory='./raw_product_images',\r\n        output_directory='./optimized_product_images',\r\n        product_categories=product_categories\r\n    )\r\n\r\nif __name__ == \"__main__\":\r\n    optimize_ecommerce_catalog()\r\n```\r\n\r\n## Automazione e Integrazione\r\n\r\n### Integrazione Piattaforma E-commerce\r\n\r\nOttimizzazione immagini automatica per sistemi e-commerce:\r\n\r\n```python\r\nimport requests\r\nimport json\r\nfrom datetime import datetime\r\n\r\nclass EcommerceIntegration:\r\n    def __init__(self, platform_config):\r\n        self.platform = platform_config['platform']  # 'shopify', 'woocommerce', 'magento'\r\n        self.api_key = platform_config['api_key']\r\n        self.store_url = platform_config['store_url']\r\n        self.headers = self.setup_headers()\r\n    \r\n    def setup_headers(self):\r\n        \"\"\"Setup header API basati su piattaforma\"\"\"\r\n        if self.platform == 'shopify':\r\n            return {\r\n                'X-Shopify-Access-Token': self.api_key,\r\n                'Content-Type': 'application/json'\r\n            }\r\n        elif self.platform == 'woocommerce':\r\n            return {\r\n                'Authorization': f'Bearer {self.api_key}',\r\n                'Content-Type': 'application/json'\r\n            }\r\n        return {'Content-Type': 'application/json'}\r\n    \r\n    def get_products_needing_optimization(self):\r\n        \"\"\"Ottieni prodotti che necessitano ottimizzazione\"\"\"\r\n        if self.platform == 'shopify':\r\n            return self.get_shopify_products()\r\n        elif self.platform == 'woocommerce':\r\n            return self.get_woocommerce_products()\r\n        return []\r\n    \r\n    def get_shopify_products(self):\r\n        \"\"\"Ottieni prodotti Shopify\"\"\"\r\n        url = f\"{self.store_url}/admin/api/2023-01/products.json\"\r\n        response = requests.get(url, headers=self.headers)\r\n        \r\n        if response.status_code == 200:\r\n            products = response.json()['products']\r\n            return [\r\n                {\r\n                    'id': product['id'],\r\n                    'title': product['title'],\r\n                    'images': [img['src'] for img in product['images']]\r\n                }\r\n                for product in products\r\n            ]\r\n        return []\r\n    \r\n    def optimize_product_images(self, product_data):\r\n        \"\"\"Ottimizza e carica immagini prodotto\"\"\"\r\n        optimized_images = []\r\n        \r\n        for image_url in product_data['images']:\r\n            try:\r\n                # Scarica immagine\r\n                response = requests.get(image_url)\r\n                if response.status_code == 200:\r\n                    # Salva file temporaneo\r\n                    temp_path = f\"temp_{product_data['id']}.jpg\"\r\n                    with open(temp_path, 'wb') as f:\r\n                        f.write(response.content)\r\n                    \r\n                    # Ottimizza\r\n                    processor = EcommerceImageProcessor()\r\n                    optimized_files = processor.process_product_image(\r\n                        temp_path, \r\n                        f\"optimized_{product_data['id']}\", \r\n                        str(product_data['id'])\r\n                    )\r\n                    \r\n                    # Carica immagini ottimizzate\r\n                    uploaded_urls = self.upload_optimized_images(\r\n                        optimized_files, \r\n                        product_data['id']\r\n                    )\r\n                    optimized_images.extend(uploaded_urls)\r\n                    \r\n                    # Rimuovi file temporaneo\r\n                    os.remove(temp_path)\r\n                    \r\n            except Exception as e:\r\n                print(f\"Errore ottimizzando immagine: {e}\")\r\n        \r\n        return optimized_images\r\n    \r\n    def upload_optimized_images(self, image_files, product_id):\r\n        \"\"\"Carica immagini ottimizzate su piattaforma\"\"\"\r\n        uploaded_urls = []\r\n        \r\n        for image_file in image_files:\r\n            if self.platform == 'shopify':\r\n                url = self.upload_to_shopify(image_file, product_id)\r\n            elif self.platform == 'woocommerce':\r\n                url = self.upload_to_woocommerce(image_file, product_id)\r\n            \r\n            if url:\r\n                uploaded_urls.append(url)\r\n        \r\n        return uploaded_urls\r\n    \r\n    def schedule_optimization(self, schedule_config):\r\n        \"\"\"Programma ottimizzazione\"\"\"\r\n        import schedule\r\n        import time\r\n        \r\n        def run_optimization():\r\n            products = self.get_products_needing_optimization()\r\n            for product in products:\r\n                self.optimize_product_images(product)\r\n                time.sleep(1)  # Rate limiting\r\n        \r\n        # Setup programmazione\r\n        if schedule_config['frequency'] == 'daily':\r\n            schedule.every().day.at(schedule_config['time']).do(run_optimization)\r\n        elif schedule_config['frequency'] == 'weekly':\r\n            schedule.every().week.do(run_optimization)\r\n        \r\n        # Esegui scheduler\r\n        while True:\r\n            schedule.run_pending()\r\n            time.sleep(60)\r\n```\r\n\r\n## Conclusione\r\n\r\nL'ottimizzazione delle immagini dei prodotti e-commerce è fondamentale per il successo delle vendite online. Applicando le tecniche di compressione appropriate, possiamo migliorare significativamente le prestazioni del sito senza sacrificare la qualità delle immagini.\r\n\r\n### Risultati Chiave\r\n\r\n1. **Ottimizzazione specifica per categoria**: Ogni categoria di prodotto ha requisiti unici per le immagini\r\n2. **Importanza dell'automazione**: L'elaborazione batch è essenziale per cataloghi grandi\r\n3. **Misurazione delle prestazioni**: Il monitoraggio regolare è necessario per risultati ottimali\r\n4. **Integrazione piattaforma**: Workflow fluido con sistemi e-commerce\r\n5. **Qualità vs velocità**: Trovare l'equilibrio giusto per gli obiettivi aziendali\r\n\r\n### Raccomandazioni di Implementazione\r\n\r\n- Inizia con le immagini prodotto più critiche (immagini principali, prodotti bestseller)\r\n- Testa le impostazioni di ottimizzazione su un piccolo campione\r\n- Misura l'impatto sui tassi di conversione\r\n- Automatizza il processo per coerenza\r\n- Aggiorna regolarmente le strategie di ottimizzazione\r\n\r\nUna strategia di ottimizzazione immagini implementata correttamente può portare a miglioramenti significativi nella velocità del sito, nell'esperienza utente e infine nei risultati di vendita.","# Compressão de Imagens de Produtos para E-commerce: Otimização Orientada para Vendas\r\n\r\nO sucesso do e-commerce depende fortemente da qualidade das imagens dos produtos, com estudos mostrando que 67% dos consumidores consideram a qualidade da imagem \"muito importante\" ao fazer compras online. No entanto, arquivos de imagem grandes podem impactar significativamente o tempo de carregamento da página, as taxas de conversão e a experiência do usuário móvel. Este guia abrangente cobre técnicas avançadas para otimizar imagens de produtos de e-commerce, mantendo a qualidade visual necessária para impulsionar as vendas.\r\n\r\n## Por que a Otimização de Imagens para E-commerce é Importante\r\n\r\n### Impacto nas Taxas de Conversão\r\n\r\nA otimização das imagens dos produtos afeta diretamente os indicadores de negócios:\r\n- **Taxas de conversão**: 1 segundo de atraso no carregamento da página reduz as conversões em 7%\r\n- **Taxas de rejeição**: 40% dos usuários abandonam sites que demoram mais de 3 segundos para carregar\r\n- **Comércio móvel**: 73% do tráfego de e-commerce vem de dispositivos móveis\r\n- **Classificação em buscas**: O Google considera a velocidade da página no ranking de buscas\r\n- **Satisfação do cliente**: Imagens de alta qualidade aumentam a confiança na compra\r\n\r\n### Requisitos Específicos do E-commerce\r\n\r\nImagens de produtos apresentam desafios únicos de otimização:\r\n- **Múltiplas visualizações do produto**: Imagem principal, miniaturas, visualizações de zoom, rotações 360°\r\n- **Precisão de cor**: Fundamental para moda, cosméticos e decoração\r\n- **Preservação de detalhes**: Os clientes precisam ver textura, materiais e acabamento\r\n- **Desempenho de carregamento**: Equilíbrio entre qualidade e velocidade\r\n- **Compatibilidade entre dispositivos**: Experiência consistente em todos os dispositivos\r\n\r\n## Compreendendo os Tipos de Imagens para E-commerce\r\n\r\n### Categorias de Imagens de Produto\r\n\r\nDiferentes tipos de imagem exigem abordagens de otimização distintas:\r\n\r\n```javascript\r\nconst ecommerceImageTypes = {\r\n    hero: {\r\n        purpose: 'Exibição principal do produto',\r\n        requirements: 'Alta qualidade, carregamento rápido',\r\n        sizes: ['1200x1200', '800x800', '600x600'],\r\n        quality: { jpeg: 85, webp: 80 }\r\n    },\r\n    thumbnail: {\r\n        purpose: 'Exibição em grade de produtos',\r\n        requirements: 'Tamanho de arquivo pequeno, reconhecível',\r\n        sizes: ['300x300', '200x200', '150x150'],\r\n        quality: { jpeg: 75, webp: 70 }\r\n    },\r\n    zoom: {\r\n        purpose: 'Inspeção detalhada do produto',\r\n        requirements: 'Máxima preservação de detalhes',\r\n        sizes: ['2000x2000', '1600x1600'],\r\n        quality: { jpeg: 90, webp: 85 }\r\n    },\r\n    gallery: {\r\n        purpose: 'Múltiplos ângulos do produto',\r\n        requirements: 'Qualidade consistente, carregamento preguiçoso',\r\n        sizes: ['800x800', '600x600'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    },\r\n    lifestyle: {\r\n        purpose: 'Produto em uso/contexto',\r\n        requirements: 'Otimizado para emoção/contexto',\r\n        sizes: ['1200x800', '800x533'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    }\r\n};\r\n```\r\n\r\n### Estratégia de Otimização por Categoria de Produto\r\n\r\nDiferentes categorias de produtos possuem requisitos específicos de imagem:\r\n\r\n```python\r\ndef get_category_optimization_settings(product_category):\r\n    \"\"\"Obter configurações de otimização para diferentes categorias de produtos\"\"\"\r\n    settings = {\r\n        'fashion': {\r\n            'priority': ['precisão_de_cor', 'detalhe_de_textura'],\r\n            'format_preference': 'webp_com_fallback_jpeg',\r\n            'quality_range': {'min': 80, 'max': 90},\r\n            'critical_views': ['frente', 'costas', 'detalhe']\r\n        },\r\n        'electronics': {\r\n            'priority': ['preservação_de_detalhes', 'carregamento_rápido'],\r\n            'format_preference': 'webp_ou_avif',\r\n            'quality_range': {'min': 75, 'max': 85},\r\n            'critical_views': ['principal', 'interfaces', 'comparação_de_tamanho']\r\n        },\r\n        'home_decor': {\r\n            'priority': ['precisão_de_cor', 'contexto_lifestyle'],\r\n            'format_preference': 'webp_com_fallback_jpeg',\r\n            'quality_range': {'min': 80, 'max': 88},\r\n            'critical_views': ['ambientado', 'closeup', 'dimensões']\r\n        },\r\n        'jewelry': {\r\n            'priority': ['máximo_detalhe', 'precisão_de_cor'],\r\n            'format_preference': 'png_para_detalhado_webp_para_hero',\r\n            'quality_range': {'min': 85, 'max': 95},\r\n            'critical_views': ['macro', '360_giro', 'lifestyle']\r\n        },\r\n        'books': {\r\n            'priority': ['carregamento_rápido', 'legibilidade_do_texto'],\r\n            'format_preference': 'webp_compressão_agressiva',\r\n            'quality_range': {'min': 70, 'max': 80},\r\n            'critical_views': ['capa', 'costas', 'lombada']\r\n        }\r\n    }\r\n    return settings.get(product_category, settings['electronics'])\r\n```\r\n\r\n## Processamento Avançado de Imagens de Produtos\r\n\r\n### Pipeline Automatizado de Imagens de Produtos\r\n\r\nSistema abrangente de processamento automatizado:\r\n\r\n```python\r\nimport os\r\nfrom PIL import Image, ImageEnhance, ImageFilter\r\nimport numpy as np\r\n\r\nclass EcommerceImageProcessor:\r\n    def __init__(self, config=None):\r\n        self.config = config or self.get_default_config()\r\n        self.supported_formats = ['jpeg', 'webp', 'avif', 'png']\r\n        \r\n    def get_default_config(self):\r\n        return {\r\n            'background_removal': True,\r\n            'auto_crop': True,\r\n            'color_enhancement': True,\r\n            'noise_reduction': True,\r\n            'watermark': False,\r\n            'quality_thresholds': {\r\n                'hero': 85,\r\n                'gallery': 80,\r\n                'thumbnail': 75,\r\n                'zoom': 90\r\n            }\r\n        }\r\n    \r\n    def process_product_image(self, input_path, output_dir, product_id):\r\n        \"\"\"Processar uma única imagem de produto em todas as variantes necessárias\"\"\"\r\n        img = Image.open(input_path)\r\n        \r\n        # Pré-processamento básico\r\n        processed_img = self.preprocess_image(img)\r\n        \r\n        # Gerar todos os tamanhos e formatos necessários\r\n        variants = self.generate_image_variants(processed_img, product_id)\r\n        \r\n        # Salvar versões otimizadas\r\n        saved_files = self.save_variants(variants, output_dir)\r\n        \r\n        return saved_files\r\n    \r\n    def preprocess_image(self, img):\r\n        \"\"\"Aplicar pré-processamento básico à imagem do produto\"\"\"\r\n        # Converter para RGB se necessário\r\n        if img.mode in ('RGBA', 'LA', 'P'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            if img.mode == 'RGBA':\r\n                background.paste(img, mask=img.split()[-1])\r\n            else:\r\n                background.paste(img)\r\n            img = background\r\n        \r\n        # Corte automático para remover espaços em branco\r\n        if self.config['auto_crop']:\r\n            img = self.smart_crop(img)\r\n        \r\n        # Realçar a qualidade da imagem\r\n        if self.config['color_enhancement']:\r\n            img = self.enhance_product_image(img)\r\n        \r\n        # Reduzir ruído\r\n        if self.config['noise_reduction']:\r\n            img = img.filter(ImageFilter.SMOOTH_MORE)\r\n        \r\n        return img\r\n    \r\n    def smart_crop(self, img):\r\n        \"\"\"Cortar inteligentemente a imagem do produto para remover fundo em excesso\"\"\"\r\n        # Converter para array numpy para análise\r\n        img_array = np.array(img)\r\n        \r\n        # Encontrar caixa delimitadora de pixels não brancos\r\n        mask = np.any(img_array \u003C 240, axis=2)  # Não é branco puro\r\n        coords = np.argwhere(mask)\r\n        \r\n        if len(coords) == 0:\r\n            return img  # Nenhum corte necessário\r\n        \r\n        # Obter caixa delimitadora\r\n        y0, x0 = coords.min(axis=0)\r\n        y1, x1 = coords.max(axis=0)\r\n        \r\n        # Adicionar padding\r\n        padding = 20\r\n        y0 = max(0, y0 - padding)\r\n        x0 = max(0, x0 - padding)\r\n        y1 = min(img.height, y1 + padding)\r\n        x1 = min(img.width, x1 + padding)\r\n        \r\n        return img.crop((x0, y0, x1, y1))\r\n    \r\n    def enhance_product_image(self, img):\r\n        \"\"\"Aprimorar imagem do produto para exibição em e-commerce\"\"\"\r\n        # Aumentar ligeiramente o brilho\r\n        brightness_enhancer = ImageEnhance.Brightness(img)\r\n        img = brightness_enhancer.enhance(1.05)\r\n        \r\n        # Aumentar o contraste\r\n        contrast_enhancer = ImageEnhance.Contrast(img)\r\n        img = contrast_enhancer.enhance(1.1)\r\n        \r\n        # Aumentar a saturação de cor\r\n        color_enhancer = ImageEnhance.Color(img)\r\n        img = color_enhancer.enhance(1.05)\r\n        \r\n        # Aumentar a nitidez\r\n        sharpness_enhancer = ImageEnhance.Sharpness(img)\r\n        img = sharpness_enhancer.enhance(1.1)\r\n        \r\n        return img\r\n    \r\n    def generate_image_variants(self, img, product_id):\r\n        \"\"\"Gerar todas as variantes de imagem necessárias\"\"\"\r\n        variants = {}\r\n        \r\n        # Definir tamanhos padrão para e-commerce\r\n        sizes = {\r\n            'hero': (1200, 1200),\r\n            'gallery': (800, 800),\r\n            'thumbnail': (300, 300),\r\n            'zoom': (2000, 2000),\r\n            'mobile_hero': (600, 600),\r\n            'mobile_thumb': (150, 150)\r\n        }\r\n        \r\n        for variant_name, size in sizes.items():\r\n            # Redimensionar com reamostragem de alta qualidade\r\n            resized = img.resize(size, Image.Resampling.LANCZOS)\r\n            variants[variant_name] = resized\r\n        \r\n        return variants\r\n    \r\n    def save_variants(self, variants, output_dir):\r\n        \"\"\"Salvar todas as variantes em formatos otimizados\"\"\"\r\n        saved_files = []\r\n        \r\n        for variant_name, img in variants.items():\r\n            base_path = os.path.join(output_dir, variant_name)\r\n            \r\n            # Salvar em múltiplos formatos\r\n            for format_type in ['jpeg', 'webp']:\r\n                filename = f\"{base_path}.{format_type}\"\r\n                quality = self.get_quality_for_variant(variant_name, format_type)\r\n                \r\n                if format_type == 'jpeg':\r\n                    img.save(filename, 'JPEG', quality=quality, optimize=True, progressive=True)\r\n                elif format_type == 'webp':\r\n                    img.save(filename, 'WebP', quality=quality, optimize=True)\r\n                \r\n                saved_files.append(filename)\r\n        \r\n        return saved_files\r\n    \r\n    def get_quality_for_variant(self, variant_name, format_type):\r\n        \"\"\"Obter configuração de qualidade ideal para variante e formato específicos\"\"\"\r\n        base_quality = self.config['quality_thresholds'].get(variant_name, 80)\r\n        \r\n        # Ajustar para o formato\r\n        if format_type == 'webp':\r\n            return base_quality - 5  # WebP pode atingir mesma qualidade com configuração menor\r\n        elif format_type == 'avif':\r\n            return base_quality - 10  # AVIF é ainda mais eficiente\r\n        \r\n        return base_quality\r\n\r\n# Exemplo de uso\r\nprocessor = EcommerceImageProcessor()\r\nprocessor.process_product_image('product_raw.jpg', 'output/', 'product_123')\r\n```\r\n\r\n### Remoção e Padronização de Fundo\r\n\r\nProcessamento automatizado de fundo para exibição consistente do produto:\r\n\r\n```python\r\ndef remove_product_background(image_path, output_path):\r\n    \"\"\"Remover fundo da imagem do produto usando detecção de bordas\"\"\"\r\n    import cv2\r\n    import numpy as np\r\n    \r\n    # Ler imagem\r\n    img = cv2.imread(image_path)\r\n    original = img.copy()\r\n    \r\n    # Converter para escala de cinza\r\n    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\r\n    \r\n    # Aplicar GaussianBlur para reduzir ruído\r\n    blurred = cv2.GaussianBlur(gray, (5, 5), 0)\r\n    \r\n    # Detecção de bordas\r\n    edges = cv2.Canny(blurred, 50, 150)\r\n    \r\n    # Encontrar contornos\r\n    contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\r\n    \r\n    if contours:\r\n        # Encontrar o maior contorno (assumido como o produto)\r\n        largest_contour = max(contours, key=cv2.contourArea)\r\n        \r\n        # Criar máscara\r\n        mask = np.zeros(gray.shape, np.uint8)\r\n        cv2.fillPoly(mask, [largest_contour], 255)\r\n        \r\n        # Aplicar máscara à imagem original\r\n        result = cv2.bitwise_and(original, original, mask=mask)\r\n        \r\n        # Converter fundo para branco\r\n        result[mask == 0] = [255, 255, 255]\r\n        \r\n        cv2.imwrite(output_path, result)\r\n        return True\r\n    \r\n    return False\r\n\r\ndef standardize_product_backgrounds(input_dir, output_dir, background_color=(255, 255, 255)):\r\n    \"\"\"Padronizar todos os fundos de produtos para cor consistente\"\"\"\r\n    for filename in os.listdir(input_dir):\r\n        if filename.lower().endswith(('.jpg', '.jpeg', '.png')):\r\n            input_path = os.path.join(input_dir, filename)\r\n            output_path = os.path.join(output_dir, filename)\r\n            \r\n            # Tentar remoção automatizada de fundo\r\n            if not remove_product_background(input_path, output_path):\r\n                # Alternativa: fundo branco simples\r\n                img = Image.open(input_path)\r\n                if img.mode == 'RGBA':\r\n                    background = Image.new('RGB', img.size, background_color)\r\n                    background.paste(img, mask=img.split()[-1])\r\n                    background.save(output_path, 'JPEG', quality=85)\r\n                else:\r\n                    img.save(output_path)\r\n```\r\n\r\n## Otimização Específica por Plataforma\r\n\r\n### Otimização para Marketplace da Amazon\r\n\r\nA Amazon possui requisitos e algoritmos específicos para imagens:\r\n\r\n```python\r\nclass AmazonImageOptimizer:\r\n    def __init__(self):\r\n        self.requirements = {\r\n            'main_image': {\r\n                'min_size': (1000, 1000),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'background': 'pure_white',\r\n                'product_coverage': 85  # Percentual mínimo da imagem\r\n            },\r\n            'additional_images': {\r\n                'min_size': (500, 500),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'lifestyle_allowed': True\r\n            }\r\n        }\r\n    \r\n    def optimize_for_amazon(self, image_path, output_path, image_type='main'):\r\n        \"\"\"Otimizar imagem especificamente para listagem na Amazon\"\"\"\r\n        img = Image.open(image_path)\r\n        \r\n        if image_type == 'main':\r\n            img = self.ensure_white_background(img)\r\n            img = self.ensure_minimum_size(img, (1000, 1000))\r\n        \r\n        # A Amazon prefere espaço de cor sRGB\r\n        if img.mode != 'RGB':\r\n            img = img.convert('RGB')\r\n        \r\n        # Otimizar tamanho do arquivo mantendo a qualidade\r\n        quality = 90 if image_type == 'main' else 85\r\n        img.save(output_path, 'JPEG', quality=quality, optimize=True)\r\n        \r\n        return self.validate_amazon_requirements(output_path, image_type)\r\n    \r\n    def ensure_white_background(self, img):\r\n        \"\"\"Garantir que a imagem tenha fundo branco puro\"\"\"\r\n        if img.mode == 'RGBA':\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            background.paste(img, mask=img.split()[-1])\r\n            return background\r\n        return img\r\n    \r\n    def ensure_minimum_size(self, img, min_size):\r\n        \"\"\"Garantir que a imagem atenda aos requisitos mínimos de tamanho\"\"\"\r\n        if img.size[0] \u003C min_size[0] or img.size[1] \u003C min_size[1]:\r\n            img = img.resize(min_size, Image.Resampling.LANCZOS)\r\n        return img\r\n    \r\n    def validate_amazon_requirements(self, image_path, image_type):\r\n        \"\"\"Validar se a imagem atende aos requisitos da Amazon\"\"\"\r\n        img = Image.open(image_path)\r\n        requirements = self.requirements[image_type]\r\n        \r\n        validation_results = {\r\n            'size_valid': (\r\n                img.size[0] >= requirements['min_size'][0] and \r\n                img.size[1] >= requirements['min_size'][1]\r\n            ),\r\n            'format_valid': image_path.upper().endswith(tuple(requirements['formats'])),\r\n            'file_size_valid': os.path.getsize(image_path) \u003C= 10 * 1024 * 1024  # Limite de 10MB\r\n        }\r\n        \r\n        return all(validation_results.values()), validation_results\r\n```\r\n\r\n### Otimização para Loja Shopify\r\n\r\nOtimização para temas e desempenho do Shopify:\r\n\r\n```javascript\r\nclass ShopifyImageOptimizer {\r\n    constructor() {\r\n        this.themeRequirements = {\r\n            'product_card': { width: 600, height: 600, quality: 80 },\r\n            'product_detail': { width: 1200, height: 1200, quality: 85 },\r\n            'product_zoom': { width: 2048, height: 2048, quality: 90 },\r\n            'collection_featured': { width: 800, height: 600, quality: 80 }\r\n        };\r\n    }\r\n    \r\n    generateShopifyImageUrls(baseImageUrl, productHandle) {\r\n        const urls = {};\r\n        \r\n        Object.entries(this.themeRequirements).forEach(([variant, specs]) => {\r\n            // Formato de URL de transformação de imagem do Shopify\r\n            const transformedUrl = baseImageUrl.replace('.jpg', \r\n                `_${specs.width}x${specs.height}_crop_center.jpg`);\r\n            urls[variant] = transformedUrl;\r\n        });\r\n        \r\n        return urls;\r\n    }\r\n    \r\n    generateShopifyPictureElement(productData) {\r\n        const { images, title, handle } = productData;\r\n        const mainImage = images[0];\r\n        \r\n        return `\r\n            \u003Cpicture>\r\n                \u003Csource media=\"(min-width: 1200px)\" \r\n                        srcset=\"${mainImage}_1200x1200.webp 1x, ${mainImage}_2400x2400.webp 2x\"\r\n                        type=\"image/webp\">\r\n                \u003Csource media=\"(min-width: 768px)\" \r\n                        srcset=\"${mainImage}_800x800.webp 1x, ${mainImage}_1600x1600.webp 2x\"\r\n                        type=\"image/webp\">\r\n                \u003Csource media=\"(max-width: 767px)\" \r\n                        srcset=\"${mainImage}_600x600.webp 1x, ${mainImage}_1200x1200.webp 2x\"\r\n                        type=\"image/webp\">\r\n                \u003Cimg src=\"${mainImage}_800x800.jpg\"\r\n                     srcset=\"${mainImage}_400x400.jpg 400w,\r\n                             ${mainImage}_600x600.jpg 600w,\r\n                             ${mainImage}_800x800.jpg 800w,\r\n                             ${mainImage}_1200x1200.jpg 1200w\"\r\n                     sizes=\"(max-width: 767px) 100vw, (max-width: 1023px) 50vw, 33vw\"\r\n                     alt=\"${title}\"\r\n                     loading=\"lazy\"\r\n                     data-product-handle=\"${handle}\">\r\n            \u003C/picture>\r\n        `;\r\n    }\r\n}\r\n```\r\n\r\n## Estratégias Avançadas de Carregamento para E-commerce\r\n\r\n### Carregamento Inteligente de Imagens de Produtos\r\n\r\nCarregamento inteligente baseado no comportamento do usuário e nas capacidades do dispositivo:\r\n\r\n```javascript\r\nclass EcommerceImageLoader {\r\n    constructor() {\r\n        this.userBehavior = this.trackUserBehavior();\r\n        this.deviceCapabilities = this.analyzeDevice();\r\n        this.loadingStrategies = this.initializeStrategies();\r\n    }\r\n    \r\n    trackUserBehavior() {\r\n        return {\r\n            isReturningCustomer: localStorage.getItem('visited') === 'true',\r\n            viewingHistory: JSON.parse(localStorage.getItem('viewedProducts') || '[]'),\r\n            averageSessionTime: parseInt(localStorage.getItem('avgSessionTime') || '0'),\r\n            purchaseHistory: JSON.parse(localStorage.getItem('purchases') || '[]')\r\n        };\r\n    }\r\n    \r\n    analyzeDevice() {\r\n        const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;\r\n        \r\n        return {\r\n            connectionSpeed: connection ? connection.effectiveType : '4g',\r\n            deviceMemory: navigator.deviceMemory || 4,\r\n            isLowEndDevice: navigator.deviceMemory \u003C 2,\r\n            isMobile: window.innerWidth \u003C= 768,\r\n            isSlowConnection: connection && (connection.effectiveType === 'slow-2g' || connection.effectiveType === '2g')\r\n        };\r\n    }\r\n    \r\n    initializeStrategies() {\r\n        return {\r\n            eager: this.eagerLoadingStrategy.bind(this),\r\n            progressive: this.progressiveLoadingStrategy.bind(this),\r\n            lazy: this.lazyLoadingStrategy.bind(this),\r\n            adaptive: this.adaptiveLoadingStrategy.bind(this)\r\n        };\r\n    }\r\n    \r\n    selectOptimalStrategy(productData, context) {\r\n        const { deviceCapabilities, userBehavior } = this;\r\n        \r\n        // Clientes recorrentes de alto valor com boas conexões\r\n        if (userBehavior.isReturningCustomer && \r\n            userBehavior.purchaseHistory.length > 0 && \r\n            !deviceCapabilities.isSlowConnection) {\r\n            return 'eager';\r\n        }\r\n        \r\n        // Dispositivos de baixo desempenho ou conexões lentas\r\n        if (deviceCapabilities.isLowEndDevice || deviceCapabilities.isSlowConnection) {\r\n            return 'lazy';\r\n        }\r\n        \r\n        // Dispositivos móveis com boas conexões\r\n        if (deviceCapabilities.isMobile && !deviceCapabilities.isSlowConnection) {\r\n            return 'progressive';\r\n        }\r\n        \r\n        // Padrão: estratégia adaptativa\r\n        return 'adaptive';\r\n    }\r\n    \r\n    eagerLoadingStrategy(productImages) {\r\n        // Carregar todas as imagens do produto imediatamente para experiência premium\r\n        productImages.forEach(img => {\r\n            const imageLoader = new Image();\r\n            imageLoader.src = img.dataset.src;\r\n            \r\n            if (img.dataset.srcset) {\r\n                imageLoader.srcset = img.dataset.srcset;\r\n            }\r\n            \r\n            imageLoader.onload = () => {\r\n                img.src = imageLoader.src;\r\n                if (img.dataset.srcset) {\r\n                    img.srcset = imageLoader.srcset;\r\n                }\r\n                img.classList.add('loaded');\r\n            };\r\n        });\r\n    }\r\n    \r\n    progressiveLoadingStrategy(productImages) {\r\n        // Carregar primeiro em baixa qualidade, depois em alta qualidade\r\n        productImages.forEach(img => {\r\n            // Carregar placeholder de baixa qualidade\r\n            const lowQualitySrc = img.dataset.lowSrc || img.dataset.src.replace('_q85', '_q40');\r\n            const highQualitySrc = img.dataset.src;\r\n            \r\n            img.src = lowQualitySrc;\r\n            img.classList.add('loading');\r\n            \r\n            // Carregar versão de alta qualidade\r\n            const highQualityLoader = new Image();\r\n            highQualityLoader.onload = () => {\r\n                img.src = highQualitySrc;\r\n                img.classList.remove('loading');\r\n                img.classList.add('loaded');\r\n            };\r\n            highQualityLoader.src = highQualitySrc;\r\n        });\r\n    }\r\n    \r\n    lazyLoadingStrategy(productImages) {\r\n        // Usar Intersection Observer para lazy loading\r\n        const observer = new IntersectionObserver((entries) => {\r\n            entries.forEach(entry => {\r\n                if (entry.isIntersecting) {\r\n                    this.loadImage(entry.target);\r\n                    observer.unobserve(entry.target);\r\n                }\r\n            });\r\n        }, { rootMargin: '100px' });\r\n        \r\n        productImages.forEach(img => observer.observe(img));\r\n    }\r\n    \r\n    adaptiveLoadingStrategy(productImages) {\r\n        // Adaptar com base na interação do usuário e no comportamento de rolagem\r\n        let scrollTimeout;\r\n        let isScrolling = false;\r\n        \r\n        window.addEventListener('scroll', () => {\r\n            if (!isScrolling) {\r\n                isScrolling = true;\r\n                // Carregar imagens visíveis imediatamente ao iniciar a rolagem\r\n                this.loadVisibleImages(productImages);\r\n            }\r\n            \r\n            clearTimeout(scrollTimeout);\r\n            scrollTimeout = setTimeout(() => {\r\n                isScrolling = false;\r\n            }, 150);\r\n        });\r\n        \r\n        // Carregar imagens críticas acima da dobra imediatamente\r\n        this.loadCriticalImages(productImages);\r\n        \r\n        // Lazy load para imagens restantes\r\n        this.lazyLoadingStrategy(productImages.filter(img => !img.dataset.critical));\r\n    }\r\n    \r\n    loadCriticalImages(productImages) {\r\n        const criticalImages = productImages.filter(img => \r\n            img.dataset.critical === 'true' || \r\n            img.getBoundingClientRect().top \u003C window.innerHeight\r\n        );\r\n        \r\n        criticalImages.forEach(img => this.loadImage(img));\r\n    }\r\n    \r\n    loadVisibleImages(productImages) {\r\n        const visibleImages = productImages.filter(img => {\r\n            const rect = img.getBoundingClientRect();\r\n            return rect.top \u003C window.innerHeight && rect.bottom > 0;\r\n        });\r\n        \r\n        visibleImages.forEach(img => this.loadImage(img));\r\n    }\r\n    \r\n    loadImage(img) {\r\n        if (img.dataset.loaded) return;\r\n        \r\n        const imageLoader = new Image();\r\n        imageLoader.onload = () => {\r\n            img.src = imageLoader.src;\r\n            if (img.dataset.srcset) {\r\n                img.srcset = img.dataset.srcset;\r\n            }\r\n            img.classList.add('loaded');\r\n            img.dataset.loaded = 'true';\r\n        };\r\n        \r\n        imageLoader.src = img.dataset.src;\r\n    }\r\n}\r\n\r\n// Inicializar para páginas de produtos\r\n// document.addEventListener('DOMContentLoaded', () => {\r\n//     const imageLoader = new EcommerceImageLoader();\r\n//     const productImages = document.querySelectorAll('.product-image[data-src]');\r\n//     \r\n//     if (productImages.length > 0) {\r\n//         const strategy = imageLoader.selectOptimalStrategy();\r\n//         imageLoader.loadingStrategies[strategy](productImages);\r\n//     }\r\n// });\r\n```\r\n\r\n## Otimização de Zoom de Imagem e Visualização 360°\r\n\r\n### Implementação Eficiente de Zoom\r\n\r\nFuncionalidade de zoom otimizada para páginas de detalhes de produtos:\r\n\r\n```javascript\r\nclass ProductImageZoom {\r\n    constructor(options = {}) {\r\n        this.container = options.container;\r\n        this.zoomLevel = options.zoomLevel || 2;\r\n        this.loadingStrategy = options.loadingStrategy || 'on-demand';\r\n        this.highResImages = new Map();\r\n        \r\n        this.initializeZoom();\r\n    }\r\n    \r\n    initializeZoom() {\r\n        const zoomImages = this.container.querySelectorAll('.zoomable-image');\r\n        \r\n        zoomImages.forEach(img => {\r\n            img.addEventListener('mouseenter', this.handleMouseEnter.bind(this));\r\n            img.addEventListener('mouseleave', this.handleMouseLeave.bind(this));\r\n            img.addEventListener('mousemove', this.handleMouseMove.bind(this));\r\n        });\r\n    }\r\n    \r\n    async handleMouseEnter(event) {\r\n        const img = event.target;\r\n        const highResUrl = img.dataset.zoomSrc;\r\n        \r\n        if (!highResUrl) return;\r\n        \r\n        // Carregar imagem de alta resolução sob demanda\r\n        if (!this.highResImages.has(highResUrl)) {\r\n            this.loadHighResImage(highResUrl);\r\n        }\r\n        \r\n        this.showZoomOverlay(img);\r\n    }\r\n    \r\n    loadHighResImage(url) {\r\n        return new Promise((resolve, reject) => {\r\n            const img = new Image();\r\n            img.onload = () => {\r\n                this.highResImages.set(url, img);\r\n                resolve(img);\r\n            };\r\n            img.onerror = reject;\r\n            img.src = url;\r\n        });\r\n    }\r\n    \r\n    showZoomOverlay(img) {\r\n        // Criar overlay de zoom se não existir\r\n        let overlay = img.parentNode.querySelector('.zoom-overlay');\r\n        if (!overlay) {\r\n            overlay = document.createElement('div');\r\n            overlay.className = 'zoom-overlay';\r\n            overlay.style.cssText = `\r\n                position: absolute;\r\n                top: 0;\r\n                left: 100%;\r\n                width: 300px;\r\n                height: 300px;\r\n                border: 1px solid #ddd;\r\n                background: white;\r\n                overflow: hidden;\r\n                z-index: 1000;\r\n                display: none;\r\n            `;\r\n            img.parentNode.appendChild(overlay);\r\n        }\r\n        \r\n        overlay.style.display = 'block';\r\n    }\r\n    \r\n    handleMouseMove(event) {\r\n        const img = event.target;\r\n        const overlay = img.parentNode.querySelector('.zoom-overlay');\r\n        const highResUrl = img.dataset.zoomSrc;\r\n        \r\n        if (!overlay || !this.highResImages.has(highResUrl)) return;\r\n        \r\n        const rect = img.getBoundingClientRect();\r\n        const x = (event.clientX - rect.left) / rect.width;\r\n        const y = (event.clientY - rect.top) / rect.height;\r\n        \r\n        const highResImg = this.highResImages.get(highResUrl);\r\n        \r\n        // Atualizar overlay de zoom\r\n        overlay.style.backgroundImage = `url(${highResUrl})`;\r\n        overlay.style.backgroundSize = `${highResImg.width}px ${highResImg.height}px`;\r\n        overlay.style.backgroundPosition = `-${x * (highResImg.width - 300)}px -${y * (highResImg.height - 300)}px`;\r\n    }\r\n    \r\n    handleMouseLeave(event) {\r\n        const img = event.target;\r\n        const overlay = img.parentNode.querySelector('.zoom-overlay');\r\n        \r\n        if (overlay) {\r\n            overlay.style.display = 'none';\r\n        }\r\n    }\r\n}\r\n\r\n// Otimização de visualização 360° do produto\r\nclass Product360View {\r\n    constructor(container, options = {}) {\r\n        this.container = container;\r\n        this.frameCount = options.frameCount || 36;\r\n        this.autoPlay = options.autoPlay || false;\r\n        this.frames = [];\r\n        this.currentFrame = 0;\r\n        this.isLoading = false;\r\n        \r\n        this.initialize();\r\n    }\r\n    \r\n    async initialize() {\r\n        await this.loadFrames();\r\n        this.setupControls();\r\n        this.setupInteraction();\r\n    }\r\n    \r\n    async loadFrames() {\r\n        this.isLoading = true;\r\n        const baseUrl = this.container.dataset.baseUrl;\r\n        \r\n        // Carregar frames progressivamente\r\n        const loadPromises = [];\r\n        \r\n        for (let i = 1; i \u003C= this.frameCount; i++) {\r\n            const frameUrl = `${baseUrl}/frame_${i.toString().padStart(3, '0')}.jpg`;\r\n            loadPromises.push(this.loadFrame(frameUrl, i - 1));\r\n        }\r\n        \r\n        // Carregar os primeiros frames imediatamente, o restante em background\r\n        await Promise.all(loadPromises.slice(0, 8));\r\n        \r\n        // Carregar frames restantes em background\r\n        Promise.all(loadPromises.slice(8));\r\n        \r\n        this.isLoading = false;\r\n        this.displayFrame(0);\r\n    }\r\n    \r\n    loadFrame(url, index) {\r\n        return new Promise((resolve) => {\r\n            const img = new Image();\r\n            img.onload = () => {\r\n                this.frames[index] = img;\r\n                resolve();\r\n            };\r\n            img.onerror = () => {\r\n                // Criar placeholder para falhas de carregamento\r\n                this.frames[index] = null;\r\n                resolve();\r\n            };\r\n            img.src = url;\r\n        });\r\n    }\r\n    \r\n    displayFrame(frameIndex) {\r\n        if (!this.frames[frameIndex]) return;\r\n        \r\n        const img = this.container.querySelector('.view-360-image') || \r\n                   this.createImageElement();\r\n        \r\n        img.src = this.frames[frameIndex].src;\r\n        this.currentFrame = frameIndex;\r\n    }\r\n    \r\n    createImageElement() {\r\n        const img = document.createElement('img');\r\n        img.className = 'view-360-image';\r\n        img.style.cssText = 'width: 100%; height: auto; display: block;';\r\n        this.container.appendChild(img);\r\n        return img;\r\n    }\r\n    \r\n    setupInteraction() {\r\n        let isDragging = false;\r\n        let startX = 0;\r\n        let startFrame = 0;\r\n        \r\n        this.container.addEventListener('mousedown', (e) => {\r\n            isDragging = true;\r\n            startX = e.clientX;\r\n            startFrame = this.currentFrame;\r\n            e.preventDefault();\r\n        });\r\n        \r\n        document.addEventListener('mousemove', (e) => {\r\n            if (!isDragging) return;\r\n            \r\n            const deltaX = e.clientX - startX;\r\n            const sensitivity = 2; // Pixels por frame\r\n            const frameChange = Math.floor(deltaX / sensitivity);\r\n            \r\n            let newFrame = (startFrame + frameChange) % this.frameCount;\r\n            if (newFrame \u003C 0) newFrame += this.frameCount;\r\n            \r\n            this.displayFrame(newFrame);\r\n        });\r\n        \r\n        document.addEventListener('mouseup', () => {\r\n            isDragging = false;\r\n        });\r\n    }\r\n}\r\n```\r\n\r\n## Monitoramento de Performance e Analytics\r\n\r\n### Rastreamento de Performance de Imagens para E-commerce\r\n\r\nMonitoramento abrangente de performance para imagens de e-commerce:\r\n\r\n```javascript\r\nclass EcommerceImageAnalytics {\r\n    constructor() {\r\n        this.metrics = {\r\n            imageLoadTimes: [],\r\n            conversionTracking: new Map(),\r\n            userInteractions: [],\r\n            performanceImpact: []\r\n        };\r\n        \r\n        this.startMonitoring();\r\n    }\r\n    \r\n    startMonitoring() {\r\n        // Monitorar performance de carregamento de imagens\r\n        new PerformanceObserver((list) => {\r\n            const entries = list.getEntries();\r\n            entries.forEach(entry => {\r\n                if (this.isProductImage(entry.name)) {\r\n                    this.trackImagePerformance(entry);\r\n                }\r\n            });\r\n        }).observe({ entryTypes: ['resource'] });\r\n        \r\n        // Monitorar interações do usuário com imagens\r\n        this.trackImageInteractions();\r\n        \r\n        // Monitorar correlação de conversão\r\n        this.trackConversionCorrelation();\r\n    }\r\n    \r\n    isProductImage(url) {\r\n        return url.includes('/products/') || \r\n               url.includes('product-images') ||\r\n               url.match(/\\/(hero|gallery|thumbnail|zoom)\\//);\r\n    }\r\n    \r\n    trackImagePerformance(entry) {\r\n        const imageData = {\r\n            url: entry.name,\r\n            loadTime: entry.responseEnd - entry.requestStart,\r\n            fileSize: entry.transferSize,\r\n            renderTime: entry.responseEnd,\r\n            imageType: this.categorizeImage(entry.name),\r\n            timestamp: Date.now()\r\n        };\r\n        \r\n        this.metrics.imageLoadTimes.push(imageData);\r\n        \r\n        // Enviar para analytics se o tempo de carregamento for preocupante\r\n        if (imageData.loadTime > 2000) {\r\n            this.reportSlowImage(imageData);\r\n        }\r\n    }\r\n    \r\n    categorizeImage(url) {\r\n        if (url.includes('hero')) return 'hero';\r\n        if (url.includes('thumbnail')) return 'thumbnail';\r\n        if (url.includes('gallery')) return 'gallery';\r\n        if (url.includes('zoom')) return 'zoom';\r\n        return 'other';\r\n    }\r\n    \r\n    trackImageInteractions() {\r\n        // Rastrear uso de zoom em imagem\r\n        document.addEventListener('mouseenter', (e) => {\r\n            if (e.target.classList.contains('zoomable-image')) {\r\n                this.recordInteraction('zoom_hover', e.target);\r\n            }\r\n        });\r\n        \r\n        // Rastrear navegação em galeria de imagens\r\n        document.addEventListener('click', (e) => {\r\n            if (e.target.classList.contains('gallery-thumbnail')) {\r\n                this.recordInteraction('gallery_click', e.target);\r\n            }\r\n        });\r\n        \r\n        // Rastrear interações de visualização 360°\r\n        document.addEventListener('mousedown', (e) => {\r\n            if (e.target.closest('.view-360')) {\r\n                this.recordInteraction('360_interact', e.target);\r\n            }\r\n        });\r\n    }\r\n    \r\n    recordInteraction(type, element) {\r\n        const interaction = {\r\n            type: type,\r\n            productId: element.dataset.productId || this.extractProductId(element),\r\n            timestamp: Date.now(),\r\n            elementSrc: element.src || element.dataset.src,\r\n            loadTime: this.getImageLoadTime(element.src)\r\n        };\r\n        \r\n        this.metrics.userInteractions.push(interaction);\r\n    }\r\n    \r\n    trackConversionCorrelation() {\r\n        // Rastrear quando usuários adicionam ao carrinho após interações com imagens\r\n        document.addEventListener('click', (e) => {\r\n            if (e.target.matches('.add-to-cart, .buy-now')) {\r\n                const productId = this.extractProductId(e.target);\r\n                this.correlateWithImageInteractions(productId);\r\n            }\r\n        });\r\n    }\r\n    \r\n    correlateWithImageInteractions(productId) {\r\n        const recentInteractions = this.metrics.userInteractions\r\n            .filter(interaction => \r\n                interaction.productId === productId &&\r\n                Date.now() - interaction.timestamp \u003C 300000 // Últimos 5 minutos\r\n            );\r\n        \r\n        if (recentInteractions.length > 0) {\r\n            this.metrics.conversionTracking.set(productId, {\r\n                interactions: recentInteractions,\r\n                conversionTime: Date.now()\r\n            });\r\n        }\r\n    }\r\n    \r\n    generatePerformanceReport() {\r\n        const avgLoadTime = this.calculateAverageLoadTime();\r\n        const slowImages = this.identifySlowImages();\r\n        const interactionCorrelation = this.analyzeInteractionCorrelation();\r\n        \r\n        return {\r\n            averageImageLoadTime: avgLoadTime,\r\n            slowestImages: slowImages,\r\n            interactionToConversionRate: interactionCorrelation,\r\n            recommendations: this.generateRecommendations(avgLoadTime, slowImages)\r\n        };\r\n    }\r\n    \r\n    calculateAverageLoadTime() {\r\n        const loadTimes = this.metrics.imageLoadTimes.map(img => img.loadTime);\r\n        return loadTimes.reduce((sum, time) => sum + time, 0) / loadTimes.length;\r\n    }\r\n    \r\n    identifySlowImages() {\r\n        return this.metrics.imageLoadTimes\r\n            .filter(img => img.loadTime > 2000)\r\n            .sort((a, b) => b.loadTime - a.loadTime)\r\n            .slice(0, 10);\r\n    }\r\n    \r\n    analyzeInteractionCorrelation() {\r\n        const totalInteractions = this.metrics.userInteractions.length;\r\n        const conversionsWithInteractions = this.metrics.conversionTracking.size;\r\n        \r\n        return totalInteractions > 0 ? \r\n            (conversionsWithInteractions / totalInteractions) * 100 : 0;\r\n    }\r\n    \r\n    generateRecommendations(avgLoadTime, slowImages) {\r\n        const recommendations = [];\r\n        \r\n        if (avgLoadTime > 1500) {\r\n            recommendations.push('Considere uma compressão de imagem mais agressiva');\r\n            recommendations.push('Implemente o formato WebP para melhor compressão');\r\n        }\r\n        \r\n        if (slowImages.length > 0) {\r\n            recommendations.push('Otimize as imagens de produtos com carregamento mais lento');\r\n            recommendations.push('Considere lazy loading para imagens de galeria');\r\n        }\r\n        \r\n        const heroImages = slowImages.filter(img => img.imageType === 'hero');\r\n        if (heroImages.length > 0) {\r\n            recommendations.push('Priorize a otimização da imagem principal para uma melhor primeira impressão');\r\n        }\r\n        \r\n        return recommendations;\r\n    }\r\n    \r\n    extractProductId(element) {\r\n        // Tente vários métodos para extrair o ID do produto\r\n        return element.dataset.productId ||\r\n               element.closest('[data-product-id]')?.dataset.productId ||\r\n               window.location.pathname.match(/\\/products\\/([^\\/]+)/)?.[1] ||\r\n               'unknown';\r\n    }\r\n    \r\n    getImageLoadTime(src) {\r\n        const imageMetric = this.metrics.imageLoadTimes.find(img => img.url.includes(src));\r\n        return imageMetric ? imageMetric.loadTime : null;\r\n    }\r\n    \r\n    reportSlowImage(imageData) {\r\n        // Envie para o serviço de analytics\r\n        if (typeof gtag !== 'undefined') {\r\n            gtag('event', 'slow_image_load', {\r\n                'url': imageData.url,\r\n                'load_time': imageData.loadTime,\r\n                'file_size': imageData.fileSize,\r\n                'image_type': imageData.imageType\r\n            });\r\n        }\r\n    }\r\n}\r\n\r\n// Inicializar analytics\r\nconst imageAnalytics = new EcommerceImageAnalytics();\r\n\r\n// Gerar relatório periodicamente\r\nsetInterval(() => {\r\n    const report = imageAnalytics.generatePerformanceReport();\r\n    console.log('Relatório de Performance de Imagens para E-commerce:', report);\r\n}, 300000); // A cada 5 minutos\r\n```\r\n\r\n## Conclusão\r\n\r\nA otimização de imagens de produtos para e-commerce é um fator crítico para o sucesso no varejo online, impactando diretamente as taxas de conversão, a experiência do usuário e o posicionamento nas buscas. O segredo está em encontrar o equilíbrio ideal entre qualidade da imagem e performance, considerando os requisitos específicos de diferentes categorias de produtos e plataformas.\r\n\r\nO sucesso na otimização de imagens para e-commerce exige:\r\n\r\n1. **Abordagens específicas por categoria**: Diferentes tipos de produtos exigem estratégias de otimização distintas\r\n2. **Conformidade com plataformas**: Entender e seguir os requisitos dos marketplaces\r\n3. **Monitoramento de performance**: Acompanhamento contínuo do desempenho das imagens e do comportamento do usuário\r\n4. **Estratégias avançadas de carregamento**: Carregamento inteligente baseado no contexto do usuário e nas capacidades do dispositivo\r\n5. **Preservação da qualidade**: Manter o apelo visual enquanto otimiza o tamanho dos arquivos\r\n\r\nÀ medida que o e-commerce evolui com novas tecnologias como visualização de produtos em AR, melhores algoritmos de compressão e experiências móveis aprimoradas, manter-se atualizado com técnicas de otimização e focar em resultados orientados à conversão continuará sendo essencial para obter vantagem competitiva.\r\n\r\nO futuro da otimização de imagens para e-commerce está em sistemas baseados em IA que podem otimizar automaticamente as imagens com base no comportamento do usuário, capacidades do dispositivo e padrões de conversão, mantendo a qualidade visual necessária para impulsionar vendas e satisfação do cliente.\r\n","# Сжатие изображений товаров для электронной коммерции: оптимизация, ориентированная на продажи\r\n\r\nУспех в электронной коммерции во многом зависит от качества изображений товаров: исследования показывают, что 67% потребителей считают качество изображений «очень важным» при совершении онлайн-покупок. Однако большие файлы изображений могут значительно повлиять на время загрузки страниц, конверсию и опыт мобильных пользователей. Это подробное руководство охватывает передовые методы оптимизации изображений товаров для e-commerce при сохранении визуального качества, необходимого для увеличения продаж.\r\n\r\n## Почему оптимизация изображений для e-commerce важна\r\n\r\n### Влияние на конверсию\r\n\r\nОптимизация изображений товаров напрямую влияет на бизнес-показатели:\r\n- **Конверсия**: задержка загрузки страницы на 1 секунду снижает конверсию на 7%\r\n- **Показатель отказов**: 40% пользователей покидают сайты, которые загружаются дольше 3 секунд\r\n- **Мобильная коммерция**: 73% трафика e-commerce приходится на мобильные устройства\r\n- **Ранжирование в поиске**: Google учитывает скорость загрузки страниц при ранжировании\r\n- **Удовлетворенность клиентов**: качественные изображения повышают уверенность в покупке\r\n\r\n### Специфические требования e-commerce\r\n\r\nИзображения товаров имеют уникальные задачи оптимизации:\r\n- **Множественные ракурсы товара**: основное изображение, миниатюры, zoom, 360°-обзор\r\n- **Точность передачи цвета**: критично для моды, косметики и товаров для дома\r\n- **Сохранение деталей**: покупатели хотят видеть текстуру, материалы и качество исполнения\r\n- **Производительность загрузки**: баланс между качеством и скоростью\r\n- **Кроссплатформенность**: единый опыт на всех устройствах\r\n\r\n## Виды изображений для e-commerce\r\n\r\n### Категории изображений товаров\r\n\r\nРазные типы изображений требуют разных подходов к оптимизации:\r\n\r\n```javascript\r\nconst ecommerceImageTypes = {\r\n    hero: {\r\n        purpose: 'Основная демонстрация товара',\r\n        requirements: 'Высокое качество, быстрая загрузка',\r\n        sizes: ['1200x1200', '800x800', '600x600'],\r\n        quality: { jpeg: 85, webp: 80 }\r\n    },\r\n    thumbnail: {\r\n        purpose: 'Сетка товаров',\r\n        requirements: 'Малый размер файла, узнаваемость',\r\n        sizes: ['300x300', '200x200', '150x150'],\r\n        quality: { jpeg: 75, webp: 70 }\r\n    },\r\n    zoom: {\r\n        purpose: 'Детальный просмотр товара',\r\n        requirements: 'Максимальное сохранение деталей',\r\n        sizes: ['2000x2000', '1600x1600'],\r\n        quality: { jpeg: 90, webp: 85 }\r\n    },\r\n    gallery: {\r\n        purpose: 'Несколько ракурсов товара',\r\n        requirements: 'Стабильное качество, отложенная загрузка',\r\n        sizes: ['800x800', '600x600'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    },\r\n    lifestyle: {\r\n        purpose: 'Товар в использовании/контексте',\r\n        requirements: 'Оптимизация под эмоции/контекст',\r\n        sizes: ['1200x800', '800x533'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    }\r\n};\r\n```\r\n\r\n### Стратегия оптимизации по категориям товаров\r\n\r\nРазные категории товаров имеют свои требования к изображениям:\r\n\r\n```python\r\ndef get_category_optimization_settings(product_category):\r\n    \"\"\"Получить настройки оптимизации для разных категорий товаров\"\"\"\r\n    settings = {\r\n        'fashion': {\r\n            'priority': ['точность_цвета', 'детализация_текстуры'],\r\n            'format_preference': 'webp_с_резервом_jpeg',\r\n            'quality_range': {'min': 80, 'max': 90},\r\n            'critical_views': ['спереди', 'сзади', 'детали']\r\n        },\r\n        'electronics': {\r\n            'priority': ['сохранение_деталей', 'быстрая_загрузка'],\r\n            'format_preference': 'webp_или_avif',\r\n            'quality_range': {'min': 75, 'max': 85},\r\n            'critical_views': ['основное', 'интерфейсы', 'сравнение_размера']\r\n        },\r\n        'home_decor': {\r\n            'priority': ['точность_цвета', 'контекст_использования'],\r\n            'format_preference': 'webp_с_резервом_jpeg',\r\n            'quality_range': {'min': 80, 'max': 88},\r\n            'critical_views': ['интерьер', 'крупный_план', 'размеры']\r\n        },\r\n        'jewelry': {\r\n            'priority': ['максимальная_детализация', 'точность_цвета'],\r\n            'format_preference': 'png_для_деталей_webp_для_hero',\r\n            'quality_range': {'min': 85, 'max': 95},\r\n            'critical_views': ['макро', '360_обзор', 'lifestyle']\r\n        },\r\n        'books': {\r\n            'priority': ['быстрая_загрузка', 'читаемость_текста'],\r\n            'format_preference': 'webp_агрессивное_сжатие',\r\n            'quality_range': {'min': 70, 'max': 80},\r\n            'critical_views': ['обложка', 'задник', 'корешок']\r\n        }\r\n    }\r\n    return settings.get(product_category, settings['electronics'])\r\n```\r\n\r\n## Продвинутая обработка изображений товаров\r\n\r\n### Автоматизированный pipeline обработки изображений\r\n\r\nКомплексная система автоматизированной обработки:\r\n\r\n```python\r\nimport os\r\nfrom PIL import Image, ImageEnhance, ImageFilter\r\nimport numpy as np\r\n\r\nclass EcommerceImageProcessor:\r\n    def __init__(self, config=None):\r\n        self.config = config or self.get_default_config()\r\n        self.supported_formats = ['jpeg', 'webp', 'avif', 'png']\r\n        \r\n    def get_default_config(self):\r\n        return {\r\n            'background_removal': True,\r\n            'auto_crop': True,\r\n            'color_enhancement': True,\r\n            'noise_reduction': True,\r\n            'watermark': False,\r\n            'quality_thresholds': {\r\n                'hero': 85,\r\n                'gallery': 80,\r\n                'thumbnail': 75,\r\n                'zoom': 90\r\n            }\r\n        }\r\n    \r\n    def process_product_image(self, input_path, output_dir, product_id):\r\n        \"\"\"Обработать одно изображение товара во все необходимые варианты\"\"\"\r\n        img = Image.open(input_path)\r\n        \r\n        # Базовая предобработка\r\n        processed_img = self.preprocess_image(img)\r\n        \r\n        # Генерация всех необходимых размеров и форматов\r\n        variants = self.generate_image_variants(processed_img, product_id)\r\n        \r\n        # Сохранение оптимизированных версий\r\n        saved_files = self.save_variants(variants, output_dir)\r\n        \r\n        return saved_files\r\n    \r\n    def preprocess_image(self, img):\r\n        \"\"\"Базовая предобработка изображения товара\"\"\"\r\n        # Преобразование в RGB при необходимости\r\n        if img.mode in ('RGBA', 'LA', 'P'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            if img.mode == 'RGBA':\r\n                background.paste(img, mask=img.split()[-1])\r\n            else:\r\n                background.paste(img)\r\n            img = background\r\n        \r\n        # Автообрезка для удаления лишнего фона\r\n        if self.config['auto_crop']:\r\n            img = self.smart_crop(img)\r\n        \r\n        # Улучшение качества изображения\r\n        if self.config['color_enhancement']:\r\n            img = self.enhance_product_image(img)\r\n        \r\n        # Уменьшение шума\r\n        if self.config['noise_reduction']:\r\n            img = img.filter(ImageFilter.SMOOTH_MORE)\r\n        \r\n        return img\r\n    \r\n    def smart_crop(self, img):\r\n        \"\"\"Интеллектуальная обрезка для удаления лишнего фона\"\"\"\r\n        # Преобразование в numpy-массив для анализа\r\n        img_array = np.array(img)\r\n        \r\n        # Поиск ограничивающего прямоугольника не-белых пикселей\r\n        mask = np.any(img_array \u003C 240, axis=2)  # Не чисто белый\r\n        coords = np.argwhere(mask)\r\n        \r\n        if len(coords) == 0:\r\n            return img  # Обрезка не требуется\r\n        \r\n        # Получение ограничивающего прямоугольника\r\n        y0, x0 = coords.min(axis=0)\r\n        y1, x1 = coords.max(axis=0)\r\n        \r\n        # Добавление отступа\r\n        padding = 20\r\n        y0 = max(0, y0 - padding)\r\n        x0 = max(0, x0 - padding)\r\n        y1 = min(img.height, y1 + padding)\r\n        x1 = min(img.width, x1 + padding)\r\n        \r\n        return img.crop((x0, y0, x1, y1))\r\n    \r\n    def enhance_product_image(self, img):\r\n        \"\"\"Улучшение изображения товара для e-commerce\"\"\"\r\n        # Легкое увеличение яркости\r\n        brightness_enhancer = ImageEnhance.Brightness(img)\r\n        img = brightness_enhancer.enhance(1.05)\r\n        \r\n        # Повышение контраста\r\n        contrast_enhancer = ImageEnhance.Contrast(img)\r\n        img = contrast_enhancer.enhance(1.1)\r\n        \r\n        # Усиление насыщенности цвета\r\n        color_enhancer = ImageEnhance.Color(img)\r\n        img = color_enhancer.enhance(1.05)\r\n        \r\n        # Повышение резкости\r\n        sharpness_enhancer = ImageEnhance.Sharpness(img)\r\n        img = sharpness_enhancer.enhance(1.1)\r\n        \r\n        return img\r\n    \r\n    def generate_image_variants(self, img, product_id):\r\n        \"\"\"Генерация всех необходимых вариантов изображения\"\"\"\r\n        variants = {}\r\n        \r\n        # Стандартные размеры для e-commerce\r\n        sizes = {\r\n            'hero': (1200, 1200),\r\n            'gallery': (800, 800),\r\n            'thumbnail': (300, 300),\r\n            'zoom': (2000, 2000),\r\n            'mobile_hero': (600, 600),\r\n            'mobile_thumb': (150, 150)\r\n        }\r\n        \r\n        for variant_name, size in sizes.items():\r\n            # Изменение размера с высоким качеством ресемплинга\r\n            resized = img.resize(size, Image.Resampling.LANCZOS)\r\n            variants[variant_name] = resized\r\n        \r\n        return variants\r\n    \r\n    def save_variants(self, variants, output_dir):\r\n        \"\"\"Сохранение всех вариантов в оптимизированных форматах\"\"\"\r\n        saved_files = []\r\n        \r\n        for variant_name, img in variants.items():\r\n            base_path = os.path.join(output_dir, variant_name)\r\n            \r\n            # Сохранение в нескольких форматах\r\n            for format_type in ['jpeg', 'webp']:\r\n                filename = f\"{base_path}.{format_type}\"\r\n                quality = self.get_quality_for_variant(variant_name, format_type)\r\n                \r\n                if format_type == 'jpeg':\r\n                    img.save(filename, 'JPEG', quality=quality, optimize=True, progressive=True)\r\n                elif format_type == 'webp':\r\n                    img.save(filename, 'WebP', quality=quality, optimize=True)\r\n                \r\n                saved_files.append(filename)\r\n        \r\n        return saved_files\r\n    \r\n    def get_quality_for_variant(self, variant_name, format_type):\r\n        \"\"\"Получить оптимальное качество для варианта и формата\"\"\"\r\n        base_quality = self.config['quality_thresholds'].get(variant_name, 80)\r\n        \r\n        # Корректировка для формата\r\n        if format_type == 'webp':\r\n            return base_quality - 5  # WebP позволяет достичь того же качества при меньшем значении\r\n        elif format_type == 'avif':\r\n            return base_quality - 10  # AVIF еще эффективнее\r\n        \r\n        return base_quality\r\n\r\n# Пример использования\r\nprocessor = EcommerceImageProcessor()\r\nprocessor.process_product_image('product_raw.jpg', 'output/', 'product_123')\r\n```\r\n\r\n### Удаление и стандартизация фона\r\n\r\nАвтоматизированная обработка фона для единообразного отображения товаров:\r\n\r\n```python\r\ndef remove_product_background(image_path, output_path):\r\n    \"\"\"Удалить фон изображения товара с помощью обнаружения границ\"\"\"\r\n    import cv2\r\n    import numpy as np\r\n    \r\n    # Чтение изображения\r\n    img = cv2.imread(image_path)\r\n    original = img.copy()\r\n    \r\n    # Преобразование в оттенки серого\r\n    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\r\n    \r\n    # Гауссово размытие для уменьшения шума\r\n    blurred = cv2.GaussianBlur(gray, (5, 5), 0)\r\n    \r\n    # Обнаружение границ\r\n    edges = cv2.Canny(blurred, 50, 150)\r\n    \r\n    # Поиск контуров\r\n    contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\r\n    \r\n    if contours:\r\n        # Поиск самого большого контура (предположительно товар)\r\n        largest_contour = max(contours, key=cv2.contourArea)\r\n        \r\n        # Создание маски\r\n        mask = np.zeros(gray.shape, np.uint8)\r\n        cv2.fillPoly(mask, [largest_contour], 255)\r\n        \r\n        # Применение маски к оригинальному изображению\r\n        result = cv2.bitwise_and(original, original, mask=mask)\r\n        \r\n        # Замена фона на белый\r\n        result[mask == 0] = [255, 255, 255]\r\n        \r\n        cv2.imwrite(output_path, result)\r\n        return True\r\n    \r\n    return False\r\n\r\ndef standardize_product_backgrounds(input_dir, output_dir, background_color=(255, 255, 255)):\r\n    \"\"\"Стандартизировать все фоны товаров до единого цвета\"\"\"\r\n    for filename in os.listdir(input_dir):\r\n        if filename.lower().endswith(('.jpg', '.jpeg', '.png')):\r\n            input_path = os.path.join(input_dir, filename)\r\n            output_path = os.path.join(output_dir, filename)\r\n            \r\n            # Попытка автоматического удаления фона\r\n            if not remove_product_background(input_path, output_path):\r\n                # Альтернатива: просто белый фон\r\n                img = Image.open(input_path)\r\n                if img.mode == 'RGBA':\r\n                    background = Image.new('RGB', img.size, background_color)\r\n                    background.paste(img, mask=img.split()[-1])\r\n                    background.save(output_path, 'JPEG', quality=85)\r\n                else:\r\n                    img.save(output_path)\r\n```\r\n\r\n## Оптимизация под платформу\r\n\r\n### Оптимизация для Amazon Marketplace\r\n\r\nAmazon предъявляет особые требования к изображениям и использует собственные алгоритмы:\r\n\r\n```python\r\nclass AmazonImageOptimizer:\r\n    def __init__(self):\r\n        self.requirements = {\r\n            'main_image': {\r\n                'min_size': (1000, 1000),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'background': 'pure_white',\r\n                'product_coverage': 85  # Минимальный процент изображения\r\n            },\r\n            'additional_images': {\r\n                'min_size': (500, 500),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'lifestyle_allowed': True\r\n            }\r\n        }\r\n    \r\n    def optimize_for_amazon(self, image_path, output_path, image_type='main'):\r\n        \"\"\"Оптимизировать изображение специально для листинга на Amazon\"\"\"\r\n        img = Image.open(image_path)\r\n        \r\n        if image_type == 'main':\r\n            img = self.ensure_white_background(img)\r\n            img = self.ensure_minimum_size(img, (1000, 1000))\r\n        \r\n        # Amazon предпочитает цветовое пространство sRGB\r\n        if img.mode != 'RGB':\r\n            img = img.convert('RGB')\r\n        \r\n        # Оптимизация размера файла при сохранении качества\r\n        quality = 90 if image_type == 'main' else 85\r\n        img.save(output_path, 'JPEG', quality=quality, optimize=True)\r\n        \r\n        return self.validate_amazon_requirements(output_path, image_type)\r\n    \r\n    def ensure_white_background(self, img):\r\n        \"\"\"Убедиться, что изображение имеет чисто белый фон\"\"\"\r\n        if img.mode == 'RGBA':\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            background.paste(img, mask=img.split()[-1])\r\n            return background\r\n        return img\r\n    \r\n    def ensure_minimum_size(self, img, min_size):\r\n        \"\"\"Убедиться, что изображение соответствует минимальным размерам\"\"\"\r\n        if img.size[0] \u003C min_size[0] or img.size[1] \u003C min_size[1]:\r\n            img = img.resize(min_size, Image.Resampling.LANCZOS)\r\n        return img\r\n    \r\n    def validate_amazon_requirements(self, image_path, image_type):\r\n        \"\"\"Проверить соответствие изображения требованиям Amazon\"\"\"\r\n        img = Image.open(image_path)\r\n        requirements = self.requirements[image_type]\r\n        \r\n        validation_results = {\r\n            'size_valid': (\r\n                img.size[0] >= requirements['min_size'][0] and \r\n                img.size[1] >= requirements['min_size'][1]\r\n            ),\r\n            'format_valid': image_path.upper().endswith(tuple(requirements['formats'])),\r\n            'file_size_valid': os.path.getsize(image_path) \u003C= 10 * 1024 * 1024  # Лимит 10МБ\r\n        }\r\n        \r\n        return all(validation_results.values()), validation_results\r\n```\r\n\r\n### Оптимизация для магазинов Shopify\r\n\r\nОптимизация для тем и производительности Shopify:\r\n\r\n```javascript\r\nclass ShopifyImageOptimizer {\r\n    constructor() {\r\n        this.themeRequirements = {\r\n            'product_card': { width: 600, height: 600, quality: 80 },\r\n            'product_detail': { width: 1200, height: 1200, quality: 85 },\r\n            'product_zoom': { width: 2048, height: 2048, quality: 90 },\r\n            'collection_featured': { width: 800, height: 600, quality: 80 }\r\n        };\r\n    }\r\n    \r\n    generateShopifyImageUrls(baseImageUrl, productHandle) {\r\n        const urls = {};\r\n        \r\n        Object.entries(this.themeRequirements).forEach(([variant, specs]) => {\r\n            // Формирование URL для преобразования изображений Shopify\r\n            const transformedUrl = baseImageUrl.replace('.jpg', \r\n                `_${specs.width}x${specs.height}_crop_center.jpg`);\r\n            urls[variant] = transformedUrl;\r\n        });\r\n        \r\n        return urls;\r\n    }\r\n    \r\n    generateShopifyPictureElement(productData) {\r\n        const { images, title, handle } = productData;\r\n        const mainImage = images[0];\r\n        \r\n        return `\r\n            \u003Cpicture>\r\n                \u003Csource media=\"(min-width: 1200px)\" \r\n                        srcset=\"${mainImage}_1200x1200.webp 1x, ${mainImage}_2400x2400.webp 2x\"\r\n                        type=\"image/webp\">\r\n                \u003Csource media=\"(min-width: 768px)\" \r\n                        srcset=\"${mainImage}_800x800.webp 1x, ${mainImage}_1600x1600.webp 2x\"\r\n                        type=\"image/webp\">\r\n                \u003Csource media=\"(max-width: 767px)\" \r\n                        srcset=\"${mainImage}_600x600.webp 1x, ${mainImage}_1200x1200.webp 2x\"\r\n                        type=\"image/webp\">\r\n                \u003Cimg src=\"${mainImage}_800x800.jpg\"\r\n                     srcset=\"${mainImage}_400x400.jpg 400w,\r\n                             ${mainImage}_600x600.jpg 600w,\r\n                             ${mainImage}_800x800.jpg 800w,\r\n                             ${mainImage}_1200x1200.jpg 1200w\"\r\n                     sizes=\"(max-width: 767px) 100vw, (max-width: 1023px) 50vw, 33vw\"\r\n                     alt=\"${title}\"\r\n                     loading=\"lazy\"\r\n                     data-product-handle=\"${handle}\">\r\n            \u003C/picture>\r\n        `;\r\n    }\r\n}\r\n```\r\n\r\n## Продвинутые стратегии загрузки для e-commerce\r\n\r\n### Интеллектуальная загрузка изображений товаров\r\n\r\nИнтеллектуальная загрузка на основе поведения пользователя и возможностей устройства:\r\n\r\n```javascript\r\nclass EcommerceImageLoader {\r\n    constructor() {\r\n        this.userBehavior = this.trackUserBehavior();\r\n        this.deviceCapabilities = this.analyzeDevice();\r\n        this.loadingStrategies = this.initializeStrategies();\r\n    }\r\n    \r\n    trackUserBehavior() {\r\n        return {\r\n            isReturningCustomer: localStorage.getItem('visited') === 'true',\r\n            viewingHistory: JSON.parse(localStorage.getItem('viewedProducts') || '[]'),\r\n            averageSessionTime: parseInt(localStorage.getItem('avgSessionTime') || '0'),\r\n            purchaseHistory: JSON.parse(localStorage.getItem('purchases') || '[]')\r\n        };\r\n    }\r\n    \r\n    analyzeDevice() {\r\n        const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;\r\n        \r\n        return {\r\n            connectionSpeed: connection ? connection.effectiveType : '4g',\r\n            deviceMemory: navigator.deviceMemory || 4,\r\n            isLowEndDevice: navigator.deviceMemory \u003C 2,\r\n            isMobile: window.innerWidth \u003C= 768,\r\n            isSlowConnection: connection && (connection.effectiveType === 'slow-2g' || connection.effectiveType === '2g')\r\n        };\r\n    }\r\n    \r\n    initializeStrategies() {\r\n        return {\r\n            eager: this.eagerLoadingStrategy.bind(this),\r\n            progressive: this.progressiveLoadingStrategy.bind(this),\r\n            lazy: this.lazyLoadingStrategy.bind(this),\r\n            adaptive: this.adaptiveLoadingStrategy.bind(this)\r\n        };\r\n    }\r\n    \r\n    selectOptimalStrategy(productData, context) {\r\n        const { deviceCapabilities, userBehavior } = this;\r\n        \r\n        // Постоянные клиенты с хорошим соединением\r\n        if (userBehavior.isReturningCustomer && \r\n            userBehavior.purchaseHistory.length > 0 && \r\n            !deviceCapabilities.isSlowConnection) {\r\n            return 'eager';\r\n        }\r\n        \r\n        // Слабые устройства или медленное соединение\r\n        if (deviceCapabilities.isLowEndDevice || deviceCapabilities.isSlowConnection) {\r\n            return 'lazy';\r\n        }\r\n        \r\n        // Мобильные устройства с хорошим соединением\r\n        if (deviceCapabilities.isMobile && !deviceCapabilities.isSlowConnection) {\r\n            return 'progressive';\r\n        }\r\n        \r\n        // По умолчанию: адаптивная стратегия\r\n        return 'adaptive';\r\n    }\r\n    \r\n    eagerLoadingStrategy(productImages) {\r\n        // Загрузка всех изображений сразу для премиального опыта\r\n        productImages.forEach(img => {\r\n            const imageLoader = new Image();\r\n            imageLoader.src = img.dataset.src;\r\n            \r\n            if (img.dataset.srcset) {\r\n                imageLoader.srcset = img.dataset.srcset;\r\n            }\r\n            \r\n            imageLoader.onload = () => {\r\n                img.src = imageLoader.src;\r\n                if (img.dataset.srcset) {\r\n                    img.srcset = imageLoader.srcset;\r\n                }\r\n                img.classList.add('loaded');\r\n            };\r\n        });\r\n    }\r\n    \r\n    progressiveLoadingStrategy(productImages) {\r\n        // Сначала загрузка низкого качества, затем высокого\r\n        productImages.forEach(img => {\r\n            // Загрузка низкокачественного placeholder\r\n            const lowQualitySrc = img.dataset.lowSrc || img.dataset.src.replace('_q85', '_q40');\r\n            const highQualitySrc = img.dataset.src;\r\n            \r\n            img.src = lowQualitySrc;\r\n            img.classList.add('loading');\r\n            \r\n            // Загрузка версии высокого качества\r\n            const highQualityLoader = new Image();\r\n            highQualityLoader.onload = () => {\r\n                img.src = highQualitySrc;\r\n                img.classList.remove('loading');\r\n                img.classList.add('loaded');\r\n            };\r\n            highQualityLoader.src = highQualitySrc;\r\n        });\r\n    }\r\n    \r\n    lazyLoadingStrategy(productImages) {\r\n        // Использование Intersection Observer для отложенной загрузки\r\n        const observer = new IntersectionObserver((entries) => {\r\n            entries.forEach(entry => {\r\n                if (entry.isIntersecting) {\r\n                    this.loadImage(entry.target);\r\n                    observer.unobserve(entry.target);\r\n                }\r\n            });\r\n        }, { rootMargin: '100px' });\r\n        \r\n        productImages.forEach(img => observer.observe(img));\r\n    }\r\n    \r\n    adaptiveLoadingStrategy(productImages) {\r\n        // Адаптация на основе взаимодействия пользователя и прокрутки\r\n        let scrollTimeout;\r\n        let isScrolling = false;\r\n        \r\n        window.addEventListener('scroll', () => {\r\n            if (!isScrolling) {\r\n                isScrolling = true;\r\n                // Немедленная загрузка видимых изображений при начале прокрутки\r\n                this.loadVisibleImages(productImages);\r\n            }\r\n            \r\n            clearTimeout(scrollTimeout);\r\n            scrollTimeout = setTimeout(() => {\r\n                isScrolling = false;\r\n            }, 150);\r\n        });\r\n        \r\n        // Немедленная загрузка критичных изображений выше fold\r\n        this.loadCriticalImages(productImages);\r\n        \r\n        // Отложенная загрузка остальных изображений\r\n        this.lazyLoadingStrategy(productImages.filter(img => !img.dataset.critical));\r\n    }\r\n    \r\n    loadCriticalImages(productImages) {\r\n        const criticalImages = productImages.filter(img => \r\n            img.dataset.critical === 'true' || \r\n            img.getBoundingClientRect().top \u003C window.innerHeight\r\n        );\r\n        \r\n        criticalImages.forEach(img => this.loadImage(img));\r\n    }\r\n    \r\n    loadVisibleImages(productImages) {\r\n        const visibleImages = productImages.filter(img => {\r\n            const rect = img.getBoundingClientRect();\r\n            return rect.top \u003C window.innerHeight && rect.bottom > 0;\r\n        });\r\n        \r\n        visibleImages.forEach(img => this.loadImage(img));\r\n    }\r\n    \r\n    loadImage(img) {\r\n        if (img.dataset.loaded) return;\r\n        \r\n        const imageLoader = new Image();\r\n        imageLoader.onload = () => {\r\n            img.src = imageLoader.src;\r\n            if (img.dataset.srcset) {\r\n                img.srcset = img.dataset.srcset;\r\n            }\r\n            img.classList.add('loaded');\r\n            img.dataset.loaded = 'true';\r\n        };\r\n        \r\n        imageLoader.src = img.dataset.src;\r\n    }\r\n}\r\n\r\n// Инициализация для страниц товаров\r\n// document.addEventListener('DOMContentLoaded', () => {\r\n//     const imageLoader = new EcommerceImageLoader();\r\n//     const productImages = document.querySelectorAll('.product-image[data-src]');\r\n//     \r\n//     if (productImages.length > 0) {\r\n//         const strategy = imageLoader.selectOptimalStrategy();\r\n//         imageLoader.loadingStrategies[strategy](productImages);\r\n//     }\r\n// });\r\n```\r\n\r\n## Оптимизация zoom и 360°-просмотра\r\n\r\n### Эффективная реализация zoom\r\n\r\nОптимизированная функция zoom для страниц с деталями товара:\r\n\r\n```javascript\r\nclass ProductImageZoom {\r\n    constructor(options = {}) {\r\n        this.container = options.container;\r\n        this.zoomLevel = options.zoomLevel || 2;\r\n        this.loadingStrategy = options.loadingStrategy || 'on-demand';\r\n        this.highResImages = new Map();\r\n        \r\n        this.initializeZoom();\r\n    }\r\n    \r\n    initializeZoom() {\r\n        const zoomImages = this.container.querySelectorAll('.zoomable-image');\r\n        \r\n        zoomImages.forEach(img => {\r\n            img.addEventListener('mouseenter', this.handleMouseEnter.bind(this));\r\n            img.addEventListener('mouseleave', this.handleMouseLeave.bind(this));\r\n            img.addEventListener('mousemove', this.handleMouseMove.bind(this));\r\n        });\r\n    }\r\n    \r\n    async handleMouseEnter(event) {\r\n        const img = event.target;\r\n        const highResUrl = img.dataset.zoomSrc;\r\n        \r\n        if (!highResUrl) return;\r\n        \r\n        // Загрузка изображения высокого разрешения по требованию\r\n        if (!this.highResImages.has(highResUrl)) {\r\n            this.loadHighResImage(highResUrl);\r\n        }\r\n        \r\n        this.showZoomOverlay(img);\r\n    }\r\n    \r\n    loadHighResImage(url) {\r\n        return new Promise((resolve, reject) => {\r\n            const img = new Image();\r\n            img.onload = () => {\r\n                this.highResImages.set(url, img);\r\n                resolve(img);\r\n            };\r\n            img.onerror = reject;\r\n            img.src = url;\r\n        });\r\n    }\r\n    \r\n    showZoomOverlay(img) {\r\n        // Создать overlay для zoom, если не существует\r\n        let overlay = img.parentNode.querySelector('.zoom-overlay');\r\n        if (!overlay) {\r\n            overlay = document.createElement('div');\r\n            overlay.className = 'zoom-overlay';\r\n            overlay.style.cssText = `\r\n                position: absolute;\r\n                top: 0;\r\n                left: 100%;\r\n                width: 300px;\r\n                height: 300px;\r\n                border: 1px solid #ddd;\r\n                background: white;\r\n                overflow: hidden;\r\n                z-index: 1000;\r\n                display: none;\r\n            `;\r\n            img.parentNode.appendChild(overlay);\r\n        }\r\n        \r\n        overlay.style.display = 'block';\r\n    }\r\n    \r\n    handleMouseMove(event) {\r\n        const img = event.target;\r\n        const overlay = img.parentNode.querySelector('.zoom-overlay');\r\n        const highResUrl = img.dataset.zoomSrc;\r\n        \r\n        if (!overlay || !this.highResImages.has(highResUrl)) return;\r\n        \r\n        const rect = img.getBoundingClientRect();\r\n        const x = (event.clientX - rect.left) / rect.width;\r\n        const y = (event.clientY - rect.top) / rect.height;\r\n        \r\n        const highResImg = this.highResImages.get(highResUrl);\r\n        \r\n        // Обновить overlay zoom\r\n        overlay.style.backgroundImage = `url(${highResUrl})`;\r\n        overlay.style.backgroundSize = `${highResImg.width}px ${highResImg.height}px`;\r\n        overlay.style.backgroundPosition = `-${x * (highResImg.width - 300)}px -${y * (highResImg.height - 300)}px`;\r\n    }\r\n    \r\n    handleMouseLeave(event) {\r\n        const img = event.target;\r\n        const overlay = img.parentNode.querySelector('.zoom-overlay');\r\n        \r\n        if (overlay) {\r\n            overlay.style.display = 'none';\r\n        }\r\n    }\r\n}\r\n\r\n// Оптимизация 360°-просмотра товара\r\nclass Product360View {\r\n    constructor(container, options = {}) {\r\n        this.container = container;\r\n        this.frameCount = options.frameCount || 36;\r\n        this.autoPlay = options.autoPlay || false;\r\n        this.frames = [];\r\n        this.currentFrame = 0;\r\n        this.isLoading = false;\r\n        \r\n        this.initialize();\r\n    }\r\n    \r\n    async initialize() {\r\n        await this.loadFrames();\r\n        this.setupControls();\r\n        this.setupInteraction();\r\n    }\r\n    \r\n    async loadFrames() {\r\n        this.isLoading = true;\r\n        const baseUrl = this.container.dataset.baseUrl;\r\n        \r\n        // Прогрессивная загрузка кадров\r\n        const loadPromises = [];\r\n        \r\n        for (let i = 1; i \u003C= this.frameCount; i++) {\r\n            const frameUrl = `${baseUrl}/frame_${i.toString().padStart(3, '0')}.jpg`;\r\n            loadPromises.push(this.loadFrame(frameUrl, i - 1));\r\n        }\r\n        \r\n        // Первые несколько кадров загружаются сразу, остальные — в фоне\r\n        await Promise.all(loadPromises.slice(0, 8));\r\n        \r\n        // Оставшиеся кадры загружаются в фоне\r\n        Promise.all(loadPromises.slice(8));\r\n        \r\n        this.isLoading = false;\r\n        this.displayFrame(0);\r\n    }\r\n    \r\n    loadFrame(url, index) {\r\n        return new Promise((resolve) => {\r\n            const img = new Image();\r\n            img.onload = () => {\r\n                this.frames[index] = img;\r\n                resolve();\r\n            };\r\n            img.onerror = () => {\r\n                // Заглушка для неудачных загрузок\r\n                this.frames[index] = null;\r\n                resolve();\r\n            };\r\n            img.src = url;\r\n        });\r\n    }\r\n    \r\n    displayFrame(frameIndex) {\r\n        if (!this.frames[frameIndex]) return;\r\n        \r\n        const img = this.container.querySelector('.view-360-image') || \r\n                   this.createImageElement();\r\n        \r\n        img.src = this.frames[frameIndex].src;\r\n        this.currentFrame = frameIndex;\r\n    }\r\n    \r\n    createImageElement() {\r\n        const img = document.createElement('img');\r\n        img.className = 'view-360-image';\r\n        img.style.cssText = 'width: 100%; height: auto; display: block;';\r\n        this.container.appendChild(img);\r\n        return img;\r\n    }\r\n    \r\n    setupInteraction() {\r\n        let isDragging = false;\r\n        let startX = 0;\r\n        let startFrame = 0;\r\n        \r\n        this.container.addEventListener('mousedown', (e) => {\r\n            isDragging = true;\r\n            startX = e.clientX;\r\n            startFrame = this.currentFrame;\r\n            e.preventDefault();\r\n        });\r\n        \r\n        document.addEventListener('mousemove', (e) => {\r\n            if (!isDragging) return;\r\n            \r\n            const deltaX = e.clientX - startX;\r\n            const sensitivity = 2; // Пикселей на кадр\r\n            const frameChange = Math.floor(deltaX / sensitivity);\r\n            \r\n            let newFrame = (startFrame + frameChange) % this.frameCount;\r\n            if (newFrame \u003C 0) newFrame += this.frameCount;\r\n            \r\n            this.displayFrame(newFrame);\r\n        });\r\n        \r\n        document.addEventListener('mouseup', () => {\r\n            isDragging = false;\r\n        });\r\n    }\r\n}\r\n```\r\n\r\n## Мониторинг производительности и аналитика\r\n\r\n### Отслеживание производительности изображений для e-commerce\r\n\r\nКомплексный мониторинг производительности изображений для e-commerce:\r\n\r\n```javascript\r\nclass EcommerceImageAnalytics {\r\n    constructor() {\r\n        this.metrics = {\r\n            imageLoadTimes: [],\r\n            conversionTracking: new Map(),\r\n            userInteractions: [],\r\n            performanceImpact: []\r\n        };\r\n        \r\n        this.startMonitoring();\r\n    }\r\n    \r\n    startMonitoring() {\r\n        // Мониторинг производительности загрузки изображений\r\n        new PerformanceObserver((list) => {\r\n            const entries = list.getEntries();\r\n            entries.forEach(entry => {\r\n                if (this.isProductImage(entry.name)) {\r\n                    this.trackImagePerformance(entry);\r\n                }\r\n            });\r\n        }).observe({ entryTypes: ['resource'] });\r\n        \r\n        // Мониторинг взаимодействий пользователей с изображениями\r\n        this.trackImageInteractions();\r\n        \r\n        // Мониторинг корреляции с конверсиями\r\n        this.trackConversionCorrelation();\r\n    }\r\n    \r\n    isProductImage(url) {\r\n        return url.includes('/products/') || \r\n               url.includes('product-images') ||\r\n               url.match(/\\/(hero|gallery|thumbnail|zoom)\\//);\r\n    }\r\n    \r\n    trackImagePerformance(entry) {\r\n        const imageData = {\r\n            url: entry.name,\r\n            loadTime: entry.responseEnd - entry.requestStart,\r\n            fileSize: entry.transferSize,\r\n            renderTime: entry.responseEnd,\r\n            imageType: this.categorizeImage(entry.name),\r\n            timestamp: Date.now()\r\n        };\r\n        \r\n        this.metrics.imageLoadTimes.push(imageData);\r\n        \r\n        // Отправка в аналитику, если время загрузки слишком велико\r\n        if (imageData.loadTime > 2000) {\r\n            this.reportSlowImage(imageData);\r\n        }\r\n    }\r\n    \r\n    categorizeImage(url) {\r\n        if (url.includes('hero')) return 'hero';\r\n        if (url.includes('thumbnail')) return 'thumbnail';\r\n        if (url.includes('gallery')) return 'gallery';\r\n        if (url.includes('zoom')) return 'zoom';\r\n        return 'other';\r\n    }\r\n    \r\n    trackImageInteractions() {\r\n        // Отслеживание использования zoom\r\n        document.addEventListener('mouseenter', (e) => {\r\n            if (e.target.classList.contains('zoomable-image')) {\r\n                this.recordInteraction('zoom_hover', e.target);\r\n            }\r\n        });\r\n        \r\n        // Отслеживание навигации по галерее\r\n        document.addEventListener('click', (e) => {\r\n            if (e.target.classList.contains('gallery-thumbnail')) {\r\n                this.recordInteraction('gallery_click', e.target);\r\n            }\r\n        });\r\n        \r\n        // Отслеживание взаимодействий с 360°-просмотром\r\n        document.addEventListener('mousedown', (e) => {\r\n            if (e.target.closest('.view-360')) {\r\n                this.recordInteraction('360_interact', e.target);\r\n            }\r\n        });\r\n    }\r\n    \r\n    recordInteraction(type, element) {\r\n        const interaction = {\r\n            type: type,\r\n            productId: element.dataset.productId || this.extractProductId(element),\r\n            timestamp: Date.now(),\r\n            elementSrc: element.src || element.dataset.src,\r\n            loadTime: this.getImageLoadTime(element.src)\r\n        };\r\n        \r\n        this.metrics.userInteractions.push(interaction);\r\n    }\r\n    \r\n    trackConversionCorrelation() {\r\n        // Отслеживание добавления в корзину после взаимодействия с изображениями\r\n        document.addEventListener('click', (e) => {\r\n            if (e.target.matches('.add-to-cart, .buy-now')) {\r\n                const productId = this.extractProductId(e.target);\r\n                this.correlateWithImageInteractions(productId);\r\n            }\r\n        });\r\n    }\r\n    \r\n    correlateWithImageInteractions(productId) {\r\n        const recentInteractions = this.metrics.userInteractions\r\n            .filter(interaction => \r\n                interaction.productId === productId &&\r\n                Date.now() - interaction.timestamp \u003C 300000 // Последние 5 минут\r\n            );\r\n        \r\n        if (recentInteractions.length > 0) {\r\n            this.metrics.conversionTracking.set(productId, {\r\n                interactions: recentInteractions,\r\n                conversionTime: Date.now()\r\n            });\r\n        }\r\n    }\r\n    \r\n    generatePerformanceReport() {\r\n        const avgLoadTime = this.calculateAverageLoadTime();\r\n        const slowImages = this.identifySlowImages();\r\n        const interactionCorrelation = this.analyzeInteractionCorrelation();\r\n        \r\n        return {\r\n            averageImageLoadTime: avgLoadTime,\r\n            slowestImages: slowImages,\r\n            interactionToConversionRate: interactionCorrelation,\r\n            recommendations: this.generateRecommendations(avgLoadTime, slowImages)\r\n        };\r\n    }\r\n    \r\n    calculateAverageLoadTime() {\r\n        const loadTimes = this.metrics.imageLoadTimes.map(img => img.loadTime);\r\n        return loadTimes.reduce((sum, time) => sum + time, 0) / loadTimes.length;\r\n    }\r\n    \r\n    identifySlowImages() {\r\n        return this.metrics.imageLoadTimes\r\n            .filter(img => img.loadTime > 2000)\r\n            .sort((a, b) => b.loadTime - a.loadTime)\r\n            .slice(0, 10);\r\n    }\r\n    \r\n    analyzeInteractionCorrelation() {\r\n        const totalInteractions = this.metrics.userInteractions.length;\r\n        const conversionsWithInteractions = this.metrics.conversionTracking.size;\r\n        \r\n        return totalInteractions > 0 ? \r\n            (conversionsWithInteractions / totalInteractions) * 100 : 0;\r\n    }\r\n    \r\n    generateRecommendations(avgLoadTime, slowImages) {\r\n        const recommendations = [];\r\n        \r\n        if (avgLoadTime > 1500) {\r\n            recommendations.push('Рассмотрите более агрессивное сжатие изображений');\r\n            recommendations.push('Внедрите формат WebP для лучшего сжатия');\r\n        }\r\n        \r\n        if (slowImages.length > 0) {\r\n            recommendations.push('Оптимизируйте самые медленно загружаемые изображения товаров');\r\n            recommendations.push('Рассмотрите отложенную загрузку для изображений галереи');\r\n        }\r\n        \r\n        const heroImages = slowImages.filter(img => img.imageType === 'hero');\r\n        if (heroImages.length > 0) {\r\n            recommendations.push('Приоритезируйте оптимизацию основного изображения для лучшего первого впечатления');\r\n        }\r\n        \r\n        return recommendations;\r\n    }\r\n    \r\n    extractProductId(element) {\r\n        // Попробуйте разные методы для извлечения ID товара\r\n        return element.dataset.productId ||\r\n               element.closest('[data-product-id]')?.dataset.productId ||\r\n               window.location.pathname.match(/\\/products\\/([^\\/]+)/)?.[1] ||\r\n               'unknown';\r\n    }\r\n    \r\n    getImageLoadTime(src) {\r\n        const imageMetric = this.metrics.imageLoadTimes.find(img => img.url.includes(src));\r\n        return imageMetric ? imageMetric.loadTime : null;\r\n    }\r\n    \r\n    reportSlowImage(imageData) {\r\n        // Отправка в сервис аналитики\r\n        if (typeof gtag !== 'undefined') {\r\n            gtag('event', 'slow_image_load', {\r\n                'url': imageData.url,\r\n                'load_time': imageData.loadTime,\r\n                'file_size': imageData.fileSize,\r\n                'image_type': imageData.imageType\r\n            });\r\n        }\r\n    }\r\n}\r\n\r\n// Инициализация аналитики\r\nconst imageAnalytics = new EcommerceImageAnalytics();\r\n\r\n// Периодическая генерация отчета\r\nsetInterval(() => {\r\n    const report = imageAnalytics.generatePerformanceReport();\r\n    console.log('Отчет о производительности изображений для e-commerce:', report);\r\n}, 300000); // Каждые 5 минут\r\n```\r\n\r\n## Заключение\r\n\r\nОптимизация изображений товаров для электронной коммерции — критически важный фактор успеха онлайн-ритейла, напрямую влияющий на конверсию, пользовательский опыт и поисковое ранжирование. Ключ — найти оптимальный баланс между качеством изображения и производительностью, учитывая особенности разных категорий товаров и платформ.\r\n\r\nУспешная оптимизация изображений для e-commerce требует:\r\n\r\n1. **Подходы, специфичные для категории**: Разные типы товаров требуют разных стратегий оптимизации\r\n2. **Соответствие платформе**: Понимание и соблюдение требований маркетплейсов\r\n3. **Мониторинг производительности**: Постоянное отслеживание производительности изображений и поведения пользователей\r\n4. **Продвинутые стратегии загрузки**: Интеллектуальная загрузка с учетом контекста пользователя и возможностей устройства\r\n5. **Сохранение качества**: Поддержание визуальной привлекательности при оптимизации размера файлов\r\n\r\nПо мере развития e-commerce с новыми технологиями, такими как AR-визуализация товаров, более эффективные алгоритмы сжатия и улучшенный мобильный опыт, актуальность современных методов оптимизации и ориентация на конверсию останутся ключевыми для конкурентного преимущества.\r\n\r\nБудущее оптимизации изображений для e-commerce — за системами на базе ИИ, которые могут автоматически оптимизировать изображения с учетом поведения пользователя, возможностей устройства и паттернов конверсии, сохраняя необходимое визуальное качество для увеличения продаж и удовлетворенности клиентов.\r\n","# E-commerce Productafbeelding Compressie: Verkoop-Gedreven Optimalisatie\r\n\r\nE-commerce succes hangt sterk af van de kwaliteit van productafbeeldingen, waarbij studies aantonen dat 67% van de consumenten beeldkwaliteit \"zeer belangrijk\" vindt bij online aankopen. Echter, grote afbeeldingsbestanden kunnen de laadtijden van pagina's, conversieratio's en mobiele gebruikerservaring aanzienlijk beïnvloeden. Deze uitgebreide gids behandelt geavanceerde technieken voor het optimaliseren van e-commerce productafbeeldingen terwijl de visuele kwaliteit behouden blijft die nodig is om verkopen te stimuleren.\r\n\r\n## Waarom E-commerce Afbeelding Optimalisatie Belangrijk Is\r\n\r\n### Impact op Conversieratio's\r\n\r\nProductafbeelding optimalisatie beïnvloedt direct bedrijfsmetrieken:\r\n- **Conversieratio's**: 1 seconde vertraging in pagina laadtijd vermindert conversies met 7%\r\n- **Bounce rates**: 40% van gebruikers verlaat sites die meer dan 3 seconden nodig hebben om te laden\r\n- **Mobiele handel**: 73% van e-commerce verkeer komt van mobiele apparaten\r\n- **Zoekrangschikking**: Google houdt rekening met paginasnelheid in zoekrankings\r\n- **Klanttevredenheid**: Hoogwaardige afbeeldingen verhogen aankoopvertrouwen\r\n\r\n### E-commerce Specifieke Vereisten\r\n\r\nProductafbeeldingen hebben unieke optimalisatie-uitdagingen:\r\n- **Meerdere productweergaven**: Hoofdafbeelding, thumbnails, zoomweergaven, 360° rotaties\r\n- **Kleurnauwkeurigheid**: Cruciaal voor mode, cosmetica en woninginrichting\r\n- **Detailbehoud**: Klanten moeten textuur, materialen en vakmanschap kunnen zien\r\n- **Laadprestaties**: Balans tussen kwaliteit en snelheid\r\n- **Cross-device compatibiliteit**: Consistente ervaring op alle apparaten\r\n\r\n## E-commerce Afbeeldingstypen Begrijpen\r\n\r\n### Productafbeelding Categorieën\r\n\r\nVerschillende afbeeldingstypen vereisen verschillende optimalisatiebenaderingen:\r\n\r\n```javascript\r\nconst ecommerceImageTypes = {\r\n    hero: {\r\n        purpose: 'Primaire product showcase',\r\n        requirements: 'Hoge kwaliteit, snelle laadtijd',\r\n        sizes: ['1200x1200', '800x800', '600x600'],\r\n        quality: { jpeg: 85, webp: 80 }\r\n    },\r\n    thumbnail: {\r\n        purpose: 'Product grid displays',\r\n        requirements: 'Kleine bestandsgrootte, herkenbaar',\r\n        sizes: ['300x300', '200x200', '150x150'],\r\n        quality: { jpeg: 75, webp: 70 }\r\n    },\r\n    zoom: {\r\n        purpose: 'Gedetailleerde product inspectie',\r\n        requirements: 'Maximaal detailbehoud',\r\n        sizes: ['2000x2000', '1600x1600'],\r\n        quality: { jpeg: 90, webp: 85 }\r\n    },\r\n    gallery: {\r\n        purpose: 'Meerdere producthoeken',\r\n        requirements: 'Consistente kwaliteit, lazy loading',\r\n        sizes: ['800x800', '600x600'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    },\r\n    lifestyle: {\r\n        purpose: 'Product in gebruik/context',\r\n        requirements: 'Geoptimaliseerd voor emotie/context',\r\n        sizes: ['1200x800', '800x533'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    }\r\n};\r\n```\r\n\r\n### Optimalisatiestrategie per Productcategorie\r\n\r\nVerschillende productcategorieën hebben specifieke afbeeldingsvereisten:\r\n\r\n```python\r\ndef get_category_optimization_settings(product_category):\r\n    \"\"\"Krijg optimalisatie-instellingen voor verschillende productcategorieën\"\"\"\r\n    settings = {\r\n        'fashion': {\r\n            'priority': ['color_accuracy', 'texture_detail'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 90},\r\n            'critical_views': ['front', 'back', 'detail']\r\n        },\r\n        'electronics': {\r\n            'priority': ['detail_preservation', 'fast_loading'],\r\n            'format_preference': 'webp_or_avif',\r\n            'quality_range': {'min': 75, 'max': 85},\r\n            'critical_views': ['main', 'interfaces', 'size_comparison']\r\n        },\r\n        'home_decor': {\r\n            'priority': ['color_accuracy', 'lifestyle_context'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 88},\r\n            'critical_views': ['styled', 'closeup', 'dimensions']\r\n        },\r\n        'jewelry': {\r\n            'priority': ['maximum_detail', 'color_accuracy'],\r\n            'format_preference': 'png_for_detailed_webp_for_hero',\r\n            'quality_range': {'min': 85, 'max': 95},\r\n            'critical_views': ['macro', '360_spin', 'lifestyle']\r\n        },\r\n        'books': {\r\n            'priority': ['fast_loading', 'text_readability'],\r\n            'format_preference': 'webp_aggressive_compression',\r\n            'quality_range': {'min': 70, 'max': 80},\r\n            'critical_views': ['cover', 'back', 'spine']\r\n        }\r\n    }\r\n    return settings.get(product_category, settings['electronics'])\r\n```\r\n\r\n## Geavanceerde Productafbeelding Verwerking\r\n\r\n### Geautomatiseerde Productafbeelding Pipeline\r\n\r\nUitgebreid geautomatiseerd verwerkingssysteem:\r\n\r\n```python\r\nimport os\r\nfrom PIL import Image, ImageEnhance, ImageFilter\r\nimport numpy as np\r\n\r\nclass EcommerceImageProcessor:\r\n    def __init__(self, config=None):\r\n        self.config = config or self.get_default_config()\r\n        self.supported_formats = ['jpeg', 'webp', 'avif', 'png']\r\n        \r\n    def get_default_config(self):\r\n        return {\r\n            'background_removal': True,\r\n            'auto_crop': True,\r\n            'color_enhancement': True,\r\n            'noise_reduction': True,\r\n            'watermark': False,\r\n            'quality_thresholds': {\r\n                'hero': 85,\r\n                'gallery': 80,\r\n                'thumbnail': 75,\r\n                'zoom': 90\r\n            }\r\n        }\r\n    \r\n    def process_product_image(self, input_path, output_dir, product_id):\r\n        \"\"\"Verwerk een enkele productafbeelding naar alle vereiste varianten\"\"\"\r\n        img = Image.open(input_path)\r\n        \r\n        # Basis voorverwerking\r\n        processed_img = self.preprocess_image(img)\r\n        \r\n        # Genereer alle vereiste groottes en formaten\r\n        variants = self.generate_image_variants(processed_img, product_id)\r\n        \r\n        # Sla geoptimaliseerde versies op\r\n        saved_files = self.save_variants(variants, output_dir)\r\n        \r\n        return saved_files\r\n    \r\n    def preprocess_image(self, img):\r\n        \"\"\"Pas basis voorverwerking toe op productafbeelding\"\"\"\r\n        # Converteer naar RGB indien nodig\r\n        if img.mode in ('RGBA', 'LA', 'P'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            if img.mode == 'RGBA':\r\n                background.paste(img, mask=img.split()[-1])\r\n            else:\r\n                background.paste(img)\r\n            img = background\r\n        \r\n        # Auto-crop om overtollige witruimte te verwijderen\r\n        if self.config['auto_crop']:\r\n            img = self.smart_crop(img)\r\n        \r\n        # Verbeter afbeeldingskwaliteit\r\n        if self.config['color_enhancement']:\r\n            img = self.enhance_product_image(img)\r\n        \r\n        # Verminder ruis\r\n        if self.config['noise_reduction']:\r\n            img = img.filter(ImageFilter.SMOOTH_MORE)\r\n        \r\n        return img\r\n    \r\n    def smart_crop(self, img):\r\n        \"\"\"Slim bijsnijden van productafbeelding om overtollige achtergrond te verwijderen\"\"\"\r\n        # Converteer naar numpy array voor analyse\r\n        img_array = np.array(img)\r\n        \r\n        # Vind bounding box van niet-witte pixels\r\n        mask = np.any(img_array \u003C 240, axis=2)  # Niet puur wit\r\n        coords = np.argwhere(mask)\r\n        \r\n        if len(coords) == 0:\r\n            return img  # Geen bijsnijden nodig\r\n        \r\n        # Krijg bounding box\r\n        y0, x0 = coords.min(axis=0)\r\n        y1, x1 = coords.max(axis=0)\r\n        \r\n        # Voeg padding toe\r\n        padding = 20\r\n        y0 = max(0, y0 - padding)\r\n        x0 = max(0, x0 - padding)\r\n        y1 = min(img.height, y1 + padding)\r\n        x1 = min(img.width, x1 + padding)\r\n        \r\n        return img.crop((x0, y0, x1, y1))\r\n    \r\n    def enhance_product_image(self, img):\r\n        \"\"\"Verbeter productafbeelding kwaliteit\"\"\"\r\n        # Verbeter contrast\r\n        enhancer = ImageEnhance.Contrast(img)\r\n        img = enhancer.enhance(1.1)\r\n        \r\n        # Fine-tune kleurverzadiging\r\n        enhancer = ImageEnhance.Color(img)\r\n        img = enhancer.enhance(1.05)\r\n        \r\n        # Verbeter scherpte\r\n        enhancer = ImageEnhance.Sharpness(img)\r\n        img = enhancer.enhance(1.1)\r\n        \r\n        return img\r\n    \r\n    def generate_image_variants(self, img, product_id):\r\n        \"\"\"Genereer afbeeldingsvarianten in verschillende groottes en formaten\"\"\"\r\n        variants = {}\r\n        \r\n        # Definieer standaard groottes\r\n        sizes = {\r\n            'hero': [(1200, 1200), (800, 800), (600, 600)],\r\n            'thumbnail': [(300, 300), (200, 200), (150, 150)],\r\n            'zoom': [(2000, 2000), (1600, 1600)],\r\n            'gallery': [(800, 800), (600, 600)]\r\n        }\r\n        \r\n        for variant_type, size_list in sizes.items():\r\n            variants[variant_type] = {}\r\n            for size in size_list:\r\n                # Schaal afbeelding met juiste kwaliteit\r\n                resized_img = self.resize_with_quality(img, size)\r\n                variants[variant_type][f\"{size[0]}x{size[1]}\"] = resized_img\r\n        \r\n        return variants\r\n    \r\n    def resize_with_quality(self, img, target_size):\r\n        \"\"\"Schaal afbeelding met hoge kwaliteit\"\"\"\r\n        # Behoud aspect ratio\r\n        img.thumbnail(target_size, Image.Resampling.LANCZOS)\r\n        \r\n        # Maak nieuwe afbeelding met witte achtergrond indien nodig\r\n        if img.size != target_size:\r\n            new_img = Image.new('RGB', target_size, (255, 255, 255))\r\n            # Centreer afbeelding\r\n            paste_x = (target_size[0] - img.size[0]) // 2\r\n            paste_y = (target_size[1] - img.size[1]) // 2\r\n            new_img.paste(img, (paste_x, paste_y))\r\n            return new_img\r\n        \r\n        return img\r\n    \r\n    def save_variants(self, variants, output_dir):\r\n        \"\"\"Sla afbeeldingsvarianten op in geoptimaliseerde formaten\"\"\"\r\n        saved_files = []\r\n        \r\n        for variant_type, sizes in variants.items():\r\n            variant_dir = os.path.join(output_dir, variant_type)\r\n            os.makedirs(variant_dir, exist_ok=True)\r\n            \r\n            for size_name, img in sizes.items():\r\n                # Sla JPEG op\r\n                jpeg_path = os.path.join(variant_dir, f\"{size_name}.jpg\")\r\n                quality = self.config['quality_thresholds'].get(variant_type, 80)\r\n                img.save(jpeg_path, 'JPEG', quality=quality, optimize=True)\r\n                saved_files.append(jpeg_path)\r\n                \r\n                # Sla WebP op\r\n                webp_path = os.path.join(variant_dir, f\"{size_name}.webp\")\r\n                webp_quality = max(quality - 5, 70)  # WebP meestal betere compressie\r\n                img.save(webp_path, 'WebP', quality=webp_quality, optimize=True)\r\n                saved_files.append(webp_path)\r\n        \r\n        return saved_files\r\n```\r\n\r\n## Amazon Marketplace Optimalisatie\r\n\r\n### Amazon Afbeelding Vereisten\r\n\r\nAmazon-specifieke afbeelding optimalisatie vereisten:\r\n\r\n```python\r\nclass AmazonImageOptimizer:\r\n    def __init__(self):\r\n        self.amazon_requirements = {\r\n            'main_image': {\r\n                'min_size': (1000, 1000),\r\n                'max_size': (10000, 10000),\r\n                'background': 'pure_white',\r\n                'format': ['JPEG', 'PNG', 'GIF'],\r\n                'quality_min': 85\r\n            },\r\n            'additional_images': {\r\n                'min_size': (500, 500),\r\n                'recommended_size': (1600, 1600),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'max_count': 8\r\n            },\r\n            'zoom_functionality': {\r\n                'min_size': (1001, 1001),\r\n                'recommended_size': (2000, 2000),\r\n                'enables_zoom': True\r\n            }\r\n        }\r\n    \r\n    def optimize_for_amazon(self, image_path, image_type='main'):\r\n        \"\"\"Optimaliseer afbeelding voor Amazon vereisten\"\"\"\r\n        img = Image.open(image_path)\r\n        requirements = self.amazon_requirements[f\"{image_type}_image\"]\r\n        \r\n        # Controleer en wijzig grootte\r\n        if img.size[0] \u003C requirements['min_size'][0] or img.size[1] \u003C requirements['min_size'][1]:\r\n            # Vergroot afbeelding als te klein\r\n            img = self.upscale_image(img, requirements['min_size'])\r\n        \r\n        # Zorg voor witte achtergrond voor hoofdafbeelding\r\n        if image_type == 'main' and requirements.get('background') == 'pure_white':\r\n            img = self.ensure_white_background(img)\r\n        \r\n        # Sla geoptimaliseerd op\r\n        return self.save_amazon_optimized(img, image_path, image_type)\r\n    \r\n    def ensure_white_background(self, img):\r\n        \"\"\"Zorg voor puur witte achtergrond\"\"\"\r\n        if img.mode in ('RGBA', 'LA'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            background.paste(img, mask=img.split()[-1])\r\n            return background\r\n        elif img.mode == 'P':\r\n            return img.convert('RGB')\r\n        return img\r\n    \r\n    def upscale_image(self, img, min_size):\r\n        \"\"\"Vergroot afbeelding naar minimale grootte\"\"\"\r\n        scale_factor = max(min_size[0] / img.size[0], min_size[1] / img.size[1])\r\n        new_size = (int(img.size[0] * scale_factor), int(img.size[1] * scale_factor))\r\n        return img.resize(new_size, Image.Resampling.LANCZOS)\r\n```\r\n\r\n## Prestatiemeting en Monitoring\r\n\r\n### Afbeelding Optimalisatie Metrieken\r\n\r\nVolgen van belangrijke prestatie-indicatoren:\r\n\r\n```python\r\nimport time\r\nimport requests\r\nfrom PIL import Image\r\nimport os\r\n\r\nclass ImagePerformanceMonitor:\r\n    def __init__(self):\r\n        self.metrics = {\r\n            'file_sizes': {},\r\n            'load_times': {},\r\n            'quality_scores': {},\r\n            'conversion_impact': {}\r\n        }\r\n    \r\n    def measure_optimization_impact(self, original_path, optimized_path):\r\n        \"\"\"Meet optimalisatie impact\"\"\"\r\n        # Bestandsgrootte vergelijking\r\n        original_size = os.path.getsize(original_path)\r\n        optimized_size = os.path.getsize(optimized_path)\r\n        size_reduction = ((original_size - optimized_size) / original_size) * 100\r\n        \r\n        # Afbeeldingskwaliteit evaluatie\r\n        quality_score = self.calculate_quality_score(original_path, optimized_path)\r\n        \r\n        # Laadtijd verbetering simulatie\r\n        load_time_improvement = self.simulate_load_time_improvement(\r\n            original_size, optimized_size\r\n        )\r\n        \r\n        return {\r\n            'size_reduction_percent': size_reduction,\r\n            'quality_retention_percent': quality_score,\r\n            'load_time_improvement_ms': load_time_improvement,\r\n            'optimization_ratio': size_reduction / (100 - quality_score) if quality_score \u003C 100 else size_reduction\r\n        }\r\n    \r\n    def calculate_quality_score(self, original_path, optimized_path):\r\n        \"\"\"Bereken afbeeldingskwaliteit score\"\"\"\r\n        try:\r\n            from skimage.metrics import structural_similarity as ssim\r\n            import numpy as np\r\n            \r\n            # Laad en converteer afbeeldingen\r\n            original = np.array(Image.open(original_path).convert('RGB'))\r\n            optimized = np.array(Image.open(optimized_path).convert('RGB'))\r\n            \r\n            # Bereken SSIM\r\n            ssim_score = ssim(original, optimized, multichannel=True, channel_axis=2)\r\n            return ssim_score * 100\r\n        except ImportError:\r\n            # Eenvoudige grootte-gebaseerde schatting als geen scikit-image\r\n            return 85.0  # Standaardwaarde\r\n    \r\n    def simulate_load_time_improvement(self, original_size, optimized_size):\r\n        \"\"\"Simuleer laadtijd verbetering\"\"\"\r\n        # Gebaseerd op gemiddelde internetsnelheid (5 Mbps)\r\n        avg_speed_bytes_per_ms = 5 * 1024 * 1024 / 8 / 1000  # 5 Mbps naar bytes/ms\r\n        \r\n        original_load_time = original_size / avg_speed_bytes_per_ms\r\n        optimized_load_time = optimized_size / avg_speed_bytes_per_ms\r\n        \r\n        return original_load_time - optimized_load_time\r\n    \r\n    def generate_performance_report(self, optimization_results):\r\n        \"\"\"Genereer prestatierapport\"\"\"\r\n        report = {\r\n            'summary': {\r\n                'total_images_processed': len(optimization_results),\r\n                'average_size_reduction': sum(r['size_reduction_percent'] for r in optimization_results) / len(optimization_results),\r\n                'average_quality_retention': sum(r['quality_retention_percent'] for r in optimization_results) / len(optimization_results),\r\n                'total_load_time_saved_ms': sum(r['load_time_improvement_ms'] for r in optimization_results)\r\n            },\r\n            'recommendations': self.generate_recommendations(optimization_results)\r\n        }\r\n        return report\r\n    \r\n    def generate_recommendations(self, results):\r\n        \"\"\"Genereer optimalisatie aanbevelingen\"\"\"\r\n        recommendations = []\r\n        \r\n        avg_size_reduction = sum(r['size_reduction_percent'] for r in results) / len(results)\r\n        avg_quality = sum(r['quality_retention_percent'] for r in results) / len(results)\r\n        \r\n        if avg_size_reduction \u003C 30:\r\n            recommendations.append(\"Pas agressievere compressie-instellingen toe\")\r\n        \r\n        if avg_quality \u003C 85:\r\n            recommendations.append(\"Fine-tune kwaliteitsinstellingen voor betere visuele resultaten\")\r\n        \r\n        if any(r['load_time_improvement_ms'] > 500 for r in results):\r\n            recommendations.append(\"Prioriteer optimalisatie van kritieke afbeeldingen\")\r\n        \r\n        return recommendations\r\n```\r\n\r\n## Batch Verwerking voor Grote Catalogi\r\n\r\n### Parallelle Afbeelding Verwerking\r\n\r\nEfficiënte verwerking voor grote volumes productafbeeldingen:\r\n\r\n```python\r\nimport concurrent.futures\r\nimport multiprocessing\r\nfrom pathlib import Path\r\nimport logging\r\n\r\nclass BatchImageProcessor:\r\n    def __init__(self, max_workers=None):\r\n        self.max_workers = max_workers or multiprocessing.cpu_count()\r\n        self.processed_count = 0\r\n        self.failed_count = 0\r\n        \r\n        # Setup logging\r\n        logging.basicConfig(level=logging.INFO)\r\n        self.logger = logging.getLogger(__name__)\r\n    \r\n    def process_catalog(self, input_directory, output_directory, product_categories=None):\r\n        \"\"\"Verwerk volledige productcatalogus\"\"\"\r\n        input_path = Path(input_directory)\r\n        output_path = Path(output_directory)\r\n        output_path.mkdir(parents=True, exist_ok=True)\r\n        \r\n        # Verzamel afbeeldingsbestanden\r\n        image_files = self.collect_image_files(input_path)\r\n        self.logger.info(f\"Totaal {len(image_files)} afbeeldingen wachten op verwerking\")\r\n        \r\n        # Parallelle verwerking\r\n        with concurrent.futures.ThreadPoolExecutor(max_workers=self.max_workers) as executor:\r\n            # Submit taken\r\n            future_to_file = {\r\n                executor.submit(\r\n                    self.process_single_product_image, \r\n                    img_file, \r\n                    output_path,\r\n                    product_categories.get(img_file.stem) if product_categories else None\r\n                ): img_file \r\n                for img_file in image_files\r\n            }\r\n            \r\n            # Verwerk resultaten\r\n            for future in concurrent.futures.as_completed(future_to_file):\r\n                img_file = future_to_file[future]\r\n                try:\r\n                    result = future.result()\r\n                    self.processed_count += 1\r\n                    if self.processed_count % 100 == 0:\r\n                        self.logger.info(f\"Verwerkt: {self.processed_count}/{len(image_files)}\")\r\n                except Exception as exc:\r\n                    self.failed_count += 1\r\n                    self.logger.error(f\"Fout bij verwerken {img_file}: {exc}\")\r\n        \r\n        # Genereer samenvattingsrapport\r\n        self.generate_batch_report(len(image_files))\r\n    \r\n    def collect_image_files(self, input_path):\r\n        \"\"\"Verzamel afbeeldingsbestanden uit input directory\"\"\"\r\n        supported_extensions = {'.jpg', '.jpeg', '.png', '.webp', '.tiff', '.bmp'}\r\n        image_files = []\r\n        \r\n        for ext in supported_extensions:\r\n            image_files.extend(input_path.glob(f\"**/*{ext}\"))\r\n            image_files.extend(input_path.glob(f\"**/*{ext.upper()}\"))\r\n        \r\n        return image_files\r\n    \r\n    def process_single_product_image(self, image_path, output_dir, category=None):\r\n        \"\"\"Verwerk enkele productafbeelding\"\"\"\r\n        try:\r\n            processor = EcommerceImageProcessor()\r\n            \r\n            # Pas categorie-specifieke instellingen toe\r\n            if category:\r\n                category_settings = get_category_optimization_settings(category)\r\n                processor.config.update(category_settings)\r\n            \r\n            # Verwerk afbeelding\r\n            product_id = image_path.stem\r\n            result = processor.process_product_image(\r\n                str(image_path), \r\n                str(output_dir), \r\n                product_id\r\n            )\r\n            \r\n            return {\r\n                'status': 'success',\r\n                'input_file': str(image_path),\r\n                'output_files': result,\r\n                'product_id': product_id\r\n            }\r\n            \r\n        except Exception as e:\r\n            return {\r\n                'status': 'error',\r\n                'input_file': str(image_path),\r\n                'error': str(e)\r\n            }\r\n    \r\n    def generate_batch_report(self, total_files):\r\n        \"\"\"Genereer batch verwerkingsrapport\"\"\"\r\n        success_rate = (self.processed_count / total_files) * 100\r\n        \r\n        report = f\"\"\"\r\n        Batch Afbeelding Verwerkingsrapport\r\n        ===================================\r\n        Totaal bestanden: {total_files}\r\n        Succesvol verwerkt: {self.processed_count}\r\n        Mislukt: {self.failed_count}\r\n        Succespercentage: {success_rate:.2f}%\r\n        \r\n        Verwerkingssnelheid: {self.processed_count / self.max_workers:.2f} afbeeldingen/worker\r\n        \"\"\"\r\n        \r\n        self.logger.info(report)\r\n        return report\r\n\r\n# Gebruiksvoorbeeld\r\ndef optimize_ecommerce_catalog():\r\n    \"\"\"Optimaliseer e-commerce catalogus\"\"\"\r\n    # Definieer productcategorieën\r\n    product_categories = {\r\n        'shirt_001': 'fashion',\r\n        'laptop_002': 'electronics',\r\n        'sofa_003': 'home_decor',\r\n        'ring_004': 'jewelry'\r\n    }\r\n    \r\n    # Initialiseer batch processor\r\n    batch_processor = BatchImageProcessor(max_workers=8)\r\n    \r\n    # Verwerk catalogus\r\n    batch_processor.process_catalog(\r\n        input_directory='./raw_product_images',\r\n        output_directory='./optimized_product_images',\r\n        product_categories=product_categories\r\n    )\r\n\r\nif __name__ == \"__main__\":\r\n    optimize_ecommerce_catalog()\r\n```\r\n\r\n## Automatisering en Integratie\r\n\r\n### E-commerce Platform Integratie\r\n\r\nAutomatische afbeelding optimalisatie voor e-commerce systemen:\r\n\r\n```python\r\nimport requests\r\nimport json\r\nfrom datetime import datetime\r\n\r\nclass EcommerceIntegration:\r\n    def __init__(self, platform_config):\r\n        self.platform = platform_config['platform']  # 'shopify', 'woocommerce', 'magento'\r\n        self.api_key = platform_config['api_key']\r\n        self.store_url = platform_config['store_url']\r\n        self.headers = self.setup_headers()\r\n    \r\n    def setup_headers(self):\r\n        \"\"\"Setup API headers gebaseerd op platform\"\"\"\r\n        if self.platform == 'shopify':\r\n            return {\r\n                'X-Shopify-Access-Token': self.api_key,\r\n                'Content-Type': 'application/json'\r\n            }\r\n        elif self.platform == 'woocommerce':\r\n            return {\r\n                'Authorization': f'Bearer {self.api_key}',\r\n                'Content-Type': 'application/json'\r\n            }\r\n        return {'Content-Type': 'application/json'}\r\n    \r\n    def get_products_needing_optimization(self):\r\n        \"\"\"Krijg producten die optimalisatie nodig hebben\"\"\"\r\n        if self.platform == 'shopify':\r\n            return self.get_shopify_products()\r\n        elif self.platform == 'woocommerce':\r\n            return self.get_woocommerce_products()\r\n        return []\r\n    \r\n    def get_shopify_products(self):\r\n        \"\"\"Krijg Shopify producten\"\"\"\r\n        url = f\"{self.store_url}/admin/api/2023-01/products.json\"\r\n        response = requests.get(url, headers=self.headers)\r\n        \r\n        if response.status_code == 200:\r\n            products = response.json()['products']\r\n            return [\r\n                {\r\n                    'id': product['id'],\r\n                    'title': product['title'],\r\n                    'images': [img['src'] for img in product['images']]\r\n                }\r\n                for product in products\r\n            ]\r\n        return []\r\n    \r\n    def optimize_product_images(self, product_data):\r\n        \"\"\"Optimaliseer en upload productafbeeldingen\"\"\"\r\n        optimized_images = []\r\n        \r\n        for image_url in product_data['images']:\r\n            try:\r\n                # Download afbeelding\r\n                response = requests.get(image_url)\r\n                if response.status_code == 200:\r\n                    # Sla tijdelijk bestand op\r\n                    temp_path = f\"temp_{product_data['id']}.jpg\"\r\n                    with open(temp_path, 'wb') as f:\r\n                        f.write(response.content)\r\n                    \r\n                    # Optimaliseer\r\n                    processor = EcommerceImageProcessor()\r\n                    optimized_files = processor.process_product_image(\r\n                        temp_path, \r\n                        f\"optimized_{product_data['id']}\", \r\n                        str(product_data['id'])\r\n                    )\r\n                    \r\n                    # Upload geoptimaliseerde afbeeldingen\r\n                    uploaded_urls = self.upload_optimized_images(\r\n                        optimized_files, \r\n                        product_data['id']\r\n                    )\r\n                    optimized_images.extend(uploaded_urls)\r\n                    \r\n                    # Verwijder tijdelijk bestand\r\n                    os.remove(temp_path)\r\n                    \r\n            except Exception as e:\r\n                print(f\"Fout bij optimaliseren afbeelding: {e}\")\r\n        \r\n        return optimized_images\r\n    \r\n    def upload_optimized_images(self, image_files, product_id):\r\n        \"\"\"Upload geoptimaliseerde afbeeldingen naar platform\"\"\"\r\n        uploaded_urls = []\r\n        \r\n        for image_file in image_files:\r\n            if self.platform == 'shopify':\r\n                url = self.upload_to_shopify(image_file, product_id)\r\n            elif self.platform == 'woocommerce':\r\n                url = self.upload_to_woocommerce(image_file, product_id)\r\n            \r\n            if url:\r\n                uploaded_urls.append(url)\r\n        \r\n        return uploaded_urls\r\n    \r\n    def schedule_optimization(self, schedule_config):\r\n        \"\"\"Plan optimalisatie\"\"\"\r\n        import schedule\r\n        import time\r\n        \r\n        def run_optimization():\r\n            products = self.get_products_needing_optimization()\r\n            for product in products:\r\n                self.optimize_product_images(product)\r\n                time.sleep(1)  # Rate limiting\r\n        \r\n        # Setup planning\r\n        if schedule_config['frequency'] == 'daily':\r\n            schedule.every().day.at(schedule_config['time']).do(run_optimization)\r\n        elif schedule_config['frequency'] == 'weekly':\r\n            schedule.every().week.do(run_optimization)\r\n        \r\n        # Run scheduler\r\n        while True:\r\n            schedule.run_pending()\r\n            time.sleep(60)\r\n```\r\n\r\n## Conclusie\r\n\r\nE-commerce productafbeelding optimalisatie is cruciaal voor online verkoop succes. Door de juiste compressietechnieken toe te passen, kunnen we de site prestaties aanzienlijk verbeteren zonder afbeeldingskwaliteit op te offeren.\r\n\r\n### Belangrijkste Bevindingen\r\n\r\n1. **Categorie-specifieke optimalisatie**: Elke productcategorie heeft unieke afbeeldingsvereisten\r\n2. **Belang van automatisering**: Batch verwerking is essentieel voor grote catalogi\r\n3. **Prestatiemeting**: Regelmatige monitoring is nodig voor optimale resultaten\r\n4. **Platform integratie**: Naadloze workflow met e-commerce systemen\r\n5. **Kwaliteit vs snelheid**: Het vinden van de juiste balans voor bedrijfsdoelen\r\n\r\n### Implementatie Aanbevelingen\r\n\r\n- Begin met de meest kritieke productafbeeldingen (hoofdafbeeldingen, bestseller producten)\r\n- Test optimalisatie-instellingen op een kleine steekproef\r\n- Meet de impact op conversieratio's\r\n- Automatiseer het proces voor consistentie\r\n- Update optimalisatiestrategieën regelmatig\r\n\r\nEen goed geïmplementeerde afbeelding optimalisatiestrategie kan leiden tot aanzienlijke verbeteringen in site snelheid, gebruikerservaring en uiteindelijk verkoopresultaten.","# Kompresja Obrazów Produktów E-commerce: Optymalizacja Zorientowana na Sprzedaż\r\n\r\nSukces e-commerce w dużej mierze zależy od jakości obrazów produktów, a badania pokazują, że 67% konsumentów uważa jakość obrazu za \"bardzo ważną\" przy dokonywaniu zakupów online. Jednak duże pliki obrazów mogą znacząco wpływać na czasy ładowania stron, współczynniki konwersji i doświadczenie użytkowników mobilnych. Ten kompleksowy przewodnik obejmuje zaawansowane techniki optymalizacji obrazów produktów e-commerce przy zachowaniu jakości wizualnej potrzebnej do zwiększenia sprzedaży.\r\n\r\n## Dlaczego Optymalizacja Obrazów E-commerce Ma Znaczenie\r\n\r\n### Wpływ na Współczynniki Konwersji\r\n\r\nOptymalizacja obrazów produktów bezpośrednio wpływa na metryki biznesowe:\r\n- **Współczynniki konwersji**: 1-sekundowe opóźnienie w czasie ładowania strony zmniejsza konwersje o 7%\r\n- **Współczynniki odrzuceń**: 40% użytkowników porzuca strony, które ładują się dłużej niż 3 sekundy\r\n- **Handel mobilny**: 73% ruchu e-commerce pochodzi z urządzeń mobilnych\r\n- **Rankingi wyszukiwania**: Google uwzględnia szybkość strony w rankingach wyszukiwania\r\n- **Zadowolenie klientów**: Wysokiej jakości obrazy zwiększają zaufanie do zakupu\r\n\r\n### Specyficzne Wymagania E-commerce\r\n\r\nObrazy produktów mają unikalne wyzwania optymalizacyjne:\r\n- **Wiele widoków produktu**: Główny obraz, miniatury, widoki powiększenia, rotacje 360°\r\n- **Dokładność kolorów**: Krytyczna dla mody, kosmetyków i wystroju wnętrz\r\n- **Zachowanie szczegółów**: Klienci muszą widzieć teksturę, materiały i wykonanie\r\n- **Wydajność ładowania**: Równowaga między jakością a szybkością\r\n- **Kompatybilność między urządzeniami**: Spójne doświadczenie na różnych urządzeniach\r\n\r\n## Zrozumienie Typów Obrazów E-commerce\r\n\r\n### Kategorie Obrazów Produktów\r\n\r\nRóżne typy obrazów wymagają różnych podejść do optymalizacji:\r\n\r\n```javascript\r\nconst ecommerceImageTypes = {\r\n    hero: {\r\n        purpose: 'Główna prezentacja produktu',\r\n        requirements: 'Wysoka jakość, szybkie ładowanie',\r\n        sizes: ['1200x1200', '800x800', '600x600'],\r\n        quality: { jpeg: 85, webp: 80 }\r\n    },\r\n    thumbnail: {\r\n        purpose: 'Wyświetlanie siatki produktów',\r\n        requirements: 'Mały rozmiar pliku, rozpoznawalny',\r\n        sizes: ['300x300', '200x200', '150x150'],\r\n        quality: { jpeg: 75, webp: 70 }\r\n    },\r\n    zoom: {\r\n        purpose: 'Szczegółowa inspekcja produktu',\r\n        requirements: 'Maksymalne zachowanie szczegółów',\r\n        sizes: ['2000x2000', '1600x1600'],\r\n        quality: { jpeg: 90, webp: 85 }\r\n    },\r\n    gallery: {\r\n        purpose: 'Wiele kątów produktu',\r\n        requirements: 'Spójna jakość, lazy loading',\r\n        sizes: ['800x800', '600x600'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    },\r\n    lifestyle: {\r\n        purpose: 'Produkt w użyciu/kontekście',\r\n        requirements: 'Zoptymalizowany pod kątem emocji/kontekstu',\r\n        sizes: ['1200x800', '800x533'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    }\r\n};\r\n```\r\n\r\n### Strategia Optymalizacji według Kategorii Produktu\r\n\r\nRóżne kategorie produktów mają specyficzne wymagania dotyczące obrazów:\r\n\r\n```python\r\ndef get_category_optimization_settings(product_category):\r\n    \"\"\"Pobierz ustawienia optymalizacji dla różnych kategorii produktów\"\"\"\r\n    settings = {\r\n        'fashion': {\r\n            'priority': ['color_accuracy', 'texture_detail'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 90},\r\n            'critical_views': ['front', 'back', 'detail']\r\n        },\r\n        'electronics': {\r\n            'priority': ['detail_preservation', 'fast_loading'],\r\n            'format_preference': 'webp_or_avif',\r\n            'quality_range': {'min': 75, 'max': 85},\r\n            'critical_views': ['main', 'interfaces', 'size_comparison']\r\n        },\r\n        'home_decor': {\r\n            'priority': ['color_accuracy', 'lifestyle_context'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 88},\r\n            'critical_views': ['styled', 'closeup', 'dimensions']\r\n        },\r\n        'jewelry': {\r\n            'priority': ['maximum_detail', 'color_accuracy'],\r\n            'format_preference': 'png_for_detailed_webp_for_hero',\r\n            'quality_range': {'min': 85, 'max': 95},\r\n            'critical_views': ['macro', '360_spin', 'lifestyle']\r\n        },\r\n        'books': {\r\n            'priority': ['fast_loading', 'text_readability'],\r\n            'format_preference': 'webp_aggressive_compression',\r\n            'quality_range': {'min': 70, 'max': 80},\r\n            'critical_views': ['cover', 'back', 'spine']\r\n        }\r\n    }\r\n    return settings.get(product_category, settings['electronics'])\r\n```\r\n","# Komprese obrázků produktů pro e-commerce: Optimalizace zaměřená na prodej\r\n\r\nE-commerce úspěch výrazně závisí na kvalitě obrázků produktů, přičemž studie ukazují, že 67 % spotřebitelů považuje kvalitu obrázků za \"velmi důležitou\" při online nákupech. Velké soubory obrázků však mohou výrazně ovlivnit rychlost načítání stránek, konverzní poměry a uživatelskou zkušenost na mobilních zařízeních. Tento komplexní průvodce pokrývá pokročilé techniky pro optimalizaci obrázků produktů e-commerce při zachování vizuální kvality potřebné pro zvýšení prodeje.\r\n\r\n## Proč záleží na optimalizaci obrázků pro e-commerce\r\n\r\n### Dopad na konverzní poměry\r\n\r\nOptimalizace obrázků produktů přímo ovlivňuje obchodní metriky:\r\n- **Konverzní poměry**: 1sekundové zpoždění při načítání stránky snižuje konverze o 7 %\r\n- **Míra opuštění**: 40 % uživatelů opustí stránky, které se načítají déle než 3 sekundy\r\n- **Mobilní obchod**: 73 % provozu e-commerce pochází z mobilních zařízení\r\n- **Hodnocení ve vyhledávačích**: Google zohledňuje rychlost stránky v hodnocení vyhledávání\r\n- **Spokojenost zákazníků**: Vysoce kvalitní obrázky zvyšují důvěru v nákup\r\n\r\n### Specifické požadavky e-commerce\r\n\r\nObrázky produktů mají jedinečné optimalizační výzvy:\r\n- **Více pohledů na produkt**: Hlavní obrázek, miniatury, přiblížené pohledy, 360° rotace\r\n- **Přesnost barev**: Kritická pro módu, kosmetiku a domácí dekorace\r\n- **Zachování detailů**: Zákazníci potřebují vidět texturu, materiály a řemeslné zpracování\r\n- **Výkon načítání**: Rovnováha mezi kvalitou a rychlostí\r\n- **Kompatibilita napříč zařízeními**: Konzistentní zkušenost na všech zařízeních\r\n\r\n## Porozumění typům obrázků pro e-commerce\r\n\r\n### Kategorie obrázků produktů\r\n\r\nRůzné typy obrázků vyžadují různé přístupy k optimalizaci:\r\n\r\n```javascript\r\nconst ecommerceImageTypes = {\r\n    hero: {\r\n        purpose: 'Primární prezentace produktu',\r\n        requirements: 'Vysoká kvalita, rychlé načítání',\r\n        sizes: ['1200x1200', '800x800', '600x600'],\r\n        quality: { jpeg: 85, webp: 80 }\r\n    },\r\n    thumbnail: {\r\n        purpose: 'Zobrazení v mřížce produktů',\r\n        requirements: 'Malá velikost souboru, rozpoznatelnost',\r\n        sizes: ['300x300', '200x200', '150x150'],\r\n        quality: { jpeg: 75, webp: 70 }\r\n    },\r\n    zoom: {\r\n        purpose: 'Detailní prohlížení produktu',\r\n        requirements: 'Maximální zachování detailů',\r\n        sizes: ['2000x2000', '1600x1600'],\r\n        quality: { jpeg: 90, webp: 85 }\r\n    },\r\n    gallery: {\r\n        purpose: 'Více úhlů pohledu na produkt',\r\n        requirements: 'Konzistentní kvalita, lazy loading',\r\n        sizes: ['800x800', '600x600'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    },\r\n    lifestyle: {\r\n        purpose: 'Produkt v použití/kontextu',\r\n        requirements: 'Optimalizováno pro emoce/kontext',\r\n        sizes: ['1200x800', '800x533'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    }\r\n};\r\n```\r\n\r\n### Strategie optimalizace podle kategorie produktu\r\n\r\nRůzné kategorie produktů mají specifické požadavky na obrázky:\r\n\r\n```python\r\ndef get_category_optimization_settings(product_category):\r\n    \"\"\"Získat nastavení optimalizace pro různé kategorie produktů\"\"\"\r\n    settings = {\r\n        'fashion': {\r\n            'priority': ['color_accuracy', 'texture_detail'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 90},\r\n            'critical_views': ['front', 'back', 'detail']\r\n        },\r\n        'electronics': {\r\n            'priority': ['detail_preservation', 'fast_loading'],\r\n            'format_preference': 'webp_or_avif',\r\n            'quality_range': {'min': 75, 'max': 85},\r\n            'critical_views': ['main', 'interfaces', 'size_comparison']\r\n        },\r\n        'home_decor': {\r\n            'priority': ['color_accuracy', 'lifestyle_context'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 88},\r\n            'critical_views': ['styled', 'closeup', 'dimensions']\r\n        },\r\n        'jewelry': {\r\n            'priority': ['maximum_detail', 'color_accuracy'],\r\n            'format_preference': 'png_for_detailed_webp_for_hero',\r\n            'quality_range': {'min': 85, 'max': 95},\r\n            'critical_views': ['macro', '360_spin', 'lifestyle']\r\n        },\r\n        'books': {\r\n            'priority': ['fast_loading', 'text_readability'],\r\n            'format_preference': 'webp_aggressive_compression',\r\n            'quality_range': {'min': 70, 'max': 80},\r\n            'critical_views': ['cover', 'back', 'spine']\r\n        }\r\n    }\r\n    return settings.get(product_category, settings['electronics'])\r\n```\r\n\r\n## Pokročilé zpracování obrázků produktů\r\n\r\n### Automatizovaný pipeline pro obrázky produktů\r\n\r\nKomplexní automatizovaný systém zpracování:\r\n\r\n```python\r\nimport os\r\nfrom PIL import Image, ImageEnhance, ImageFilter\r\nimport numpy as np\r\n\r\nclass EcommerceImageProcessor:\r\n    def __init__(self, config=None):\r\n        self.config = config or self.get_default_config()\r\n        self.supported_formats = ['jpeg', 'webp', 'avif', 'png']\r\n        \r\n    def get_default_config(self):\r\n        return {\r\n            'background_removal': True,\r\n            'auto_crop': True,\r\n            'color_enhancement': True,\r\n            'noise_reduction': True,\r\n            'watermark': False,\r\n            'quality_thresholds': {\r\n                'hero': 85,\r\n                'gallery': 80,\r\n                'thumbnail': 75,\r\n                'zoom': 90\r\n            }\r\n        }\r\n    \r\n    def process_product_image(self, input_path, output_dir, product_id):\r\n        \"\"\"Zpracovat jeden obrázek produktu do všech požadovaných variant\"\"\"\r\n        img = Image.open(input_path)\r\n        \r\n        # Základní předzpracování\r\n        processed_img = self.preprocess_image(img)\r\n        \r\n        # Generovat všechny požadované velikosti a formáty\r\n        variants = self.generate_image_variants(processed_img, product_id)\r\n        \r\n        # Uložit optimalizované verze\r\n        saved_files = self.save_variants(variants, output_dir)\r\n        \r\n        return saved_files\r\n    \r\n    def preprocess_image(self, img):\r\n        \"\"\"Aplikovat základní předzpracování na obrázek produktu\"\"\"\r\n        # Převést na RGB pokud je to nutné\r\n        if img.mode in ('RGBA', 'LA', 'P'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            if img.mode == 'RGBA':\r\n                background.paste(img, mask=img.split()[-1])\r\n            else:\r\n                background.paste(img)\r\n            img = background\r\n        \r\n        # Automatické oříznutí pro odstranění přebytečného bílého prostoru\r\n        if self.config['auto_crop']:\r\n            img = self.smart_crop(img)\r\n        \r\n        # Vylepšit kvalitu obrázku\r\n        if self.config['color_enhancement']:\r\n            img = self.enhance_product_image(img)\r\n        \r\n        # Redukovat šum\r\n        if self.config['noise_reduction']:\r\n            img = img.filter(ImageFilter.SMOOTH_MORE)\r\n        \r\n        return img\r\n    \r\n    def smart_crop(self, img):\r\n        \"\"\"Inteligentně oříznout obrázek produktu pro odstranění přebytečného pozadí\"\"\"\r\n        # Převést na numpy pole pro analýzu\r\n        img_array = np.array(img)\r\n        \r\n        # Najít ohraničující box ne-bílých pixelů\r\n        mask = np.any(img_array \u003C 240, axis=2)  # Není čistě bílá\r\n        coords = np.argwhere(mask)\r\n        \r\n        if len(coords) == 0:\r\n            return img  # Není potřeba oříznutí\r\n        \r\n        # Získat ohraničující box\r\n        y0, x0 = coords.min(axis=0)\r\n        y1, x1 = coords.max(axis=0)\r\n        \r\n        # Přidat odsazení\r\n        padding = 20\r\n        y0 = max(0, y0 - padding)\r\n        x0 = max(0, x0 - padding)\r\n        y1 = min(img.height, y1 + padding)\r\n        x1 = min(img.width, x1 + padding)\r\n        \r\n        return img.crop((x0, y0, x1, y1))\r\n    \r\n    def enhance_product_image(self, img):\r\n        \"\"\"Vylepšit obrázek produktu pro zobrazení v e-commerce\"\"\"\r\n        # Mírně zvýšit jas\r\n        brightness_enhancer = ImageEnhance.Brightness(img)\r\n        img = brightness_enhancer.enhance(1.05)\r\n        \r\n        # Zvýšit kontrast\r\n        contrast_enhancer = ImageEnhance.Contrast(img)\r\n        img = contrast_enhancer.enhance(1.1)\r\n        \r\n        # Zvýšit sytost barev\r\n        color_enhancer = ImageEnhance.Color(img)\r\n        img = color_enhancer.enhance(1.05)\r\n        \r\n        # Zvýšit ostrost\r\n        sharpness_enhancer = ImageEnhance.Sharpness(img)\r\n        img = sharpness_enhancer.enhance(1.1)\r\n        \r\n        return img\r\n    \r\n    def generate_image_variants(self, img, product_id):\r\n        \"\"\"Generovat všechny požadované varianty obrázku\"\"\"\r\n        variants = {}\r\n        \r\n        # Definovat standardní velikosti pro e-commerce\r\n        sizes = {\r\n            'hero': (1200, 1200),\r\n            'gallery': (800, 800),\r\n            'thumbnail': (300, 300),\r\n            'zoom': (2000, 2000),\r\n            'mobile_hero': (600, 600),\r\n            'mobile_thumb': (150, 150)\r\n        }\r\n        \r\n        for variant_name, size in sizes.items():\r\n            # Změnit velikost s vysokoqualitním převzorkováním\r\n            resized = img.resize(size, Image.Resampling.LANCZOS)\r\n            variants[variant_name] = resized\r\n        \r\n        return variants\r\n    \r\n    def save_variants(self, variants, output_dir):\r\n        \"\"\"Uložit všechny varianty v optimalizovaných formátech\"\"\"\r\n        saved_files = []\r\n        \r\n        for variant_name, img in variants.items():\r\n            base_path = os.path.join(output_dir, variant_name)\r\n            \r\n            # Uložit ve více formátech\r\n            for format_type in ['jpeg', 'webp']:\r\n                filename = f\"{base_path}.{format_type}\"\r\n                quality = self.get_quality_for_variant(variant_name, format_type)\r\n                \r\n                if format_type == 'jpeg':\r\n                    img.save(filename, 'JPEG', quality=quality, optimize=True, progressive=True)\r\n                elif format_type == 'webp':\r\n                    img.save(filename, 'WebP', quality=quality, optimize=True)\r\n                \r\n                saved_files.append(filename)\r\n        \r\n        return saved_files\r\n    \r\n    def get_quality_for_variant(self, variant_name, format_type):\r\n        \"\"\"Získat optimální nastavení kvality pro specifickou variantu a formát\"\"\"\r\n        base_quality = self.config['quality_thresholds'].get(variant_name, 80)\r\n        \r\n        # Upravit pro formát\r\n        if format_type == 'webp':\r\n            return base_quality - 5  # WebP může dosáhnout stejné kvality při nižším nastavení\r\n        elif format_type == 'avif':\r\n            return base_quality - 10  # AVIF je ještě efektivnější\r\n        \r\n        return base_quality\r\n\r\n# Příklad použití\r\nprocessor = EcommerceImageProcessor()\r\nprocessor.process_product_image('product_raw.jpg', 'output/', 'product_123')\r\n```\r\n\r\n## Optimalizace specifická pro platformy\r\n\r\n### Optimalizace pro Amazon Marketplace\r\n\r\nAmazon má specifické požadavky na obrázky a algoritmy:\r\n\r\n```python\r\nclass AmazonImageOptimizer:\r\n    def __init__(self):\r\n        self.requirements = {\r\n            'main_image': {\r\n                'min_size': (1000, 1000),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'background': 'pure_white',\r\n                'product_coverage': 85  # Minimální procento obrázku\r\n            },\r\n            'additional_images': {\r\n                'min_size': (500, 500),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'lifestyle_allowed': True\r\n            }\r\n        }\r\n    \r\n    def optimize_for_amazon(self, image_path, output_path, image_type='main'):\r\n        \"\"\"Optimalizovat obrázek specificky pro Amazon listing\"\"\"\r\n        img = Image.open(image_path)\r\n        \r\n        if image_type == 'main':\r\n            img = self.ensure_white_background(img)\r\n            img = self.ensure_minimum_size(img, (1000, 1000))\r\n        \r\n        # Amazon preferuje sRGB barevný prostor\r\n        if img.mode != 'RGB':\r\n            img = img.convert('RGB')\r\n        \r\n        # Optimalizovat velikost souboru při zachování kvality\r\n        quality = 90 if image_type == 'main' else 85\r\n        img.save(output_path, 'JPEG', quality=quality, optimize=True)\r\n        \r\n        return self.validate_amazon_requirements(output_path, image_type)\r\n    \r\n    def ensure_white_background(self, img):\r\n        \"\"\"Zajistit, že obrázek má čistě bílé pozadí\"\"\"\r\n        if img.mode == 'RGBA':\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            background.paste(img, mask=img.split()[-1])\r\n            return background\r\n        return img\r\n    \r\n    def ensure_minimum_size(self, img, min_size):\r\n        \"\"\"Zajistit, že obrázek splňuje minimální požadavky na velikost\"\"\"\r\n        if img.size[0] \u003C min_size[0] or img.size[1] \u003C min_size[1]:\r\n            img = img.resize(min_size, Image.Resampling.LANCZOS)\r\n        return img\r\n    \r\n    def validate_amazon_requirements(self, image_path, image_type):\r\n        \"\"\"Ověřit, že obrázek splňuje požadavky Amazonu\"\"\"\r\n        img = Image.open(image_path)\r\n        requirements = self.requirements[image_type]\r\n        \r\n        validation_results = {\r\n            'size_valid': (\r\n                img.size[0] >= requirements['min_size'][0] and \r\n                img.size[1] >= requirements['min_size'][1]\r\n            ),\r\n            'format_valid': image_path.upper().endswith(tuple(requirements['formats'])),\r\n            'file_size_valid': os.path.getsize(image_path) \u003C= 10 * 1024 * 1024  # Limit 10MB\r\n        }\r\n        \r\n        return all(validation_results.values()), validation_results\r\n```\r\n\r\n### Optimalizace pro Shopify obchod\r\n\r\nOptimalizace pro Shopify témata a výkon:\r\n\r\n```javascript\r\nclass ShopifyImageOptimizer {\r\n    constructor() {\r\n        this.themeRequirements = {\r\n            'product_card': { width: 600, height: 600, quality: 80 },\r\n            'product_detail': { width: 1200, height: 1200, quality: 85 },\r\n            'product_zoom': { width: 2048, height: 2048, quality: 90 },\r\n            'collection_featured': { width: 800, height: 600, quality: 80 }\r\n        };\r\n    }\r\n    \r\n    generateShopifyImageUrls(baseImageUrl, productHandle) {\r\n        const urls = {};\r\n        \r\n        Object.entries(this.themeRequirements).forEach(([variant, specs]) => {\r\n            // Formát URL pro transformaci obrázků Shopify\r\n            const transformedUrl = baseImageUrl.replace('.jpg', \r\n                `_${specs.width}x${specs.height}_crop_center.jpg`);\r\n            urls[variant] = transformedUrl;\r\n        });\r\n        \r\n        return urls;\r\n    }\r\n    \r\n    generateShopifyPictureElement(productData) {\r\n        const { images, title, handle } = productData;\r\n        \r\n        return `\r\n            \u003Cpicture>\r\n                \u003Csource media=\"(min-width: 768px)\" \r\n                        srcset=\"${this.generateShopifyImageUrls(images[0], handle).product_detail}\">\r\n                \u003Csource media=\"(max-width: 767px)\" \r\n                        srcset=\"${this.generateShopifyImageUrls(images[0], handle).product_card}\">\r\n                \u003Cimg src=\"${images[0]}\" alt=\"${title}\" loading=\"lazy\">\r\n            \u003C/picture>\r\n        `;\r\n    }\r\n}\r\n```\r\n\r\n## Měření výkonu a optimalizace\r\n\r\n### Metriky pro sledování úspěchu\r\n\r\nKlíčové ukazatele výkonu pro optimalizaci obrázků:\r\n\r\n```javascript\r\nclass EcommerceImageMetrics {\r\n    constructor() {\r\n        this.metrics = {\r\n            technical: {\r\n                'load_time': 'Doba načítání obrázku',\r\n                'file_size': 'Velikost souboru',\r\n                'compression_ratio': 'Poměr komprese',\r\n                'quality_score': 'Skóre kvality'\r\n            },\r\n            business: {\r\n                'conversion_rate': 'Konverzní poměr',\r\n                'bounce_rate': 'Míra opuštění',\r\n                'time_on_page': 'Čas strávený na stránce',\r\n                'cart_addition_rate': 'Míra přidání do košíku'\r\n            }\r\n        };\r\n    }\r\n    \r\n    measureImagePerformance(imageUrl, callback) {\r\n        const startTime = performance.now();\r\n        const img = new Image();\r\n        \r\n        img.onload = () => {\r\n            const loadTime = performance.now() - startTime;\r\n            const fileSize = this.getImageFileSize(imageUrl);\r\n            \r\n            callback({\r\n                loadTime: loadTime,\r\n                fileSize: fileSize,\r\n                dimensions: { width: img.width, height: img.height },\r\n                timestamp: new Date().toISOString()\r\n            });\r\n        };\r\n        \r\n        img.src = imageUrl;\r\n    }\r\n    \r\n    getImageFileSize(url) {\r\n        return fetch(url, { method: 'HEAD' })\r\n            .then(response => response.headers.get('content-length'))\r\n            .then(size => parseInt(size, 10));\r\n    }\r\n    \r\n    calculateCompressionRatio(originalSize, compressedSize) {\r\n        return ((originalSize - compressedSize) / originalSize * 100).toFixed(2);\r\n    }\r\n}\r\n```\r\n\r\n### A/B testování optimalizace obrázků\r\n\r\nSystematické testování různých přístupů k optimalizaci:\r\n\r\n```python\r\nclass ImageOptimizationABTest:\r\n    def __init__(self):\r\n        self.test_variants = {\r\n            'control': {\r\n                'format': 'jpeg',\r\n                'quality': 85,\r\n                'progressive': False,\r\n                'lazy_loading': False\r\n            },\r\n            'variant_a': {\r\n                'format': 'webp',\r\n                'quality': 80,\r\n                'progressive': True,\r\n                'lazy_loading': True\r\n            },\r\n            'variant_b': {\r\n                'format': 'avif',\r\n                'quality': 75,\r\n                'progressive': True,\r\n                'lazy_loading': True\r\n            }\r\n        }\r\n    \r\n    def setup_test(self, product_ids, test_duration_days=30):\r\n        \"\"\"Nastavit A/B test pro optimalizaci obrázků\"\"\"\r\n        test_config = {\r\n            'test_id': f\"image_opt_{int(time.time())}\",\r\n            'start_date': datetime.now(),\r\n            'end_date': datetime.now() + timedelta(days=test_duration_days),\r\n            'products': product_ids,\r\n            'variants': self.test_variants,\r\n            'metrics_to_track': [\r\n                'page_load_time',\r\n                'conversion_rate',\r\n                'bounce_rate',\r\n                'image_load_time'\r\n            ]\r\n        }\r\n        \r\n        return test_config\r\n    \r\n    def assign_variant(self, user_id, test_config):\r\n        \"\"\"Přiřadit variantu uživateli na základě hash\"\"\"\r\n        import hashlib\r\n        \r\n        hash_input = f\"{user_id}_{test_config['test_id']}\"\r\n        hash_value = int(hashlib.md5(hash_input.encode()).hexdigest(), 16)\r\n        variant_index = hash_value % len(self.test_variants)\r\n        \r\n        return list(self.test_variants.keys())[variant_index]\r\n    \r\n    def track_conversion(self, user_id, variant, conversion_type, value=None):\r\n        \"\"\"Sledovat konverzi pro analýzu testu\"\"\"\r\n        conversion_data = {\r\n            'user_id': user_id,\r\n            'variant': variant,\r\n            'conversion_type': conversion_type,\r\n            'value': value,\r\n            'timestamp': datetime.now().isoformat()\r\n        }\r\n        \r\n        # Uložit do databáze nebo analytického systému\r\n        return conversion_data\r\n```\r\n\r\n## Automatizace a škálování\r\n\r\n### Batch zpracování pro velké katalogy\r\n\r\nEfektivní zpracování tisíců produktových obrázků:\r\n\r\n```python\r\nimport concurrent.futures\r\nimport multiprocessing\r\nfrom pathlib import Path\r\n\r\nclass BatchImageProcessor:\r\n    def __init__(self, max_workers=None):\r\n        self.max_workers = max_workers or multiprocessing.cpu_count()\r\n        self.processor = EcommerceImageProcessor()\r\n    \r\n    def process_catalog(self, input_directory, output_directory, progress_callback=None):\r\n        \"\"\"Zpracovat celý katalog produktových obrázků\"\"\"\r\n        input_path = Path(input_directory)\r\n        output_path = Path(output_directory)\r\n        output_path.mkdir(parents=True, exist_ok=True)\r\n        \r\n        # Najít všechny obrázky\r\n        image_files = list(input_path.glob('**/*.{jpg,jpeg,png,webp}'))\r\n        total_files = len(image_files)\r\n        \r\n        processed_count = 0\r\n        failed_files = []\r\n        \r\n        with concurrent.futures.ThreadPoolExecutor(max_workers=self.max_workers) as executor:\r\n            # Odeslat všechny úlohy\r\n            future_to_file = {\r\n                executor.submit(self.process_single_image, img_file, output_path): img_file\r\n                for img_file in image_files\r\n            }\r\n            \r\n            # Zpracovat výsledky\r\n            for future in concurrent.futures.as_completed(future_to_file):\r\n                img_file = future_to_file[future]\r\n                try:\r\n                    result = future.result()\r\n                    processed_count += 1\r\n                    \r\n                    if progress_callback:\r\n                        progress_callback(processed_count, total_files, img_file.name)\r\n                        \r\n                except Exception as exc:\r\n                    failed_files.append((img_file, str(exc)))\r\n                    print(f'Soubor {img_file} vygeneroval výjimku: {exc}')\r\n        \r\n        return {\r\n            'total_files': total_files,\r\n            'processed_count': processed_count,\r\n            'failed_files': failed_files,\r\n            'success_rate': (processed_count / total_files) * 100 if total_files > 0 else 0\r\n        }\r\n    \r\n    def process_single_image(self, image_path, output_directory):\r\n        \"\"\"Zpracovat jeden obrázek s error handling\"\"\"\r\n        try:\r\n            product_id = image_path.stem\r\n            product_output_dir = output_directory / product_id\r\n            product_output_dir.mkdir(parents=True, exist_ok=True)\r\n            \r\n            return self.processor.process_product_image(\r\n                str(image_path), \r\n                str(product_output_dir), \r\n                product_id\r\n            )\r\n        except Exception as e:\r\n            raise Exception(f\"Chyba při zpracování {image_path}: {str(e)}\")\r\n\r\n# Příklad použití\r\ndef progress_callback(current, total, filename):\r\n    percentage = (current / total) * 100\r\n    print(f\"Zpracováno: {current}/{total} ({percentage:.1f}%) - {filename}\")\r\n\r\nbatch_processor = BatchImageProcessor(max_workers=8)\r\nresults = batch_processor.process_catalog(\r\n    'input_catalog/', \r\n    'output_catalog/', \r\n    progress_callback\r\n)\r\n\r\nprint(f\"Zpracování dokončeno s úspěšností {results['success_rate']:.1f}%\")\r\n```\r\n\r\n### Integrace s CDN a cloud službami\r\n\r\nAutomatické nahrávání a distribuce optimalizovaných obrázků:\r\n\r\n```python\r\nimport boto3\r\nfrom azure.storage.blob import BlobServiceClient\r\nimport cloudinary\r\nimport cloudinary.uploader\r\n\r\nclass CloudImageManager:\r\n    def __init__(self, provider='aws', config=None):\r\n        self.provider = provider\r\n        self.config = config or {}\r\n        self.setup_client()\r\n    \r\n    def setup_client(self):\r\n        \"\"\"Nastavit klienta podle poskytovatele\"\"\"\r\n        if self.provider == 'aws':\r\n            self.client = boto3.client(\r\n                's3',\r\n                aws_access_key_id=self.config.get('access_key'),\r\n                aws_secret_access_key=self.config.get('secret_key'),\r\n                region_name=self.config.get('region', 'us-east-1')\r\n            )\r\n        elif self.provider == 'azure':\r\n            self.client = BlobServiceClient(\r\n                account_url=self.config.get('account_url'),\r\n                credential=self.config.get('credential')\r\n            )\r\n        elif self.provider == 'cloudinary':\r\n            cloudinary.config(\r\n                cloud_name=self.config.get('cloud_name'),\r\n                api_key=self.config.get('api_key'),\r\n                api_secret=self.config.get('api_secret')\r\n            )\r\n    \r\n    def upload_optimized_images(self, local_directory, remote_path_prefix='products/'):\r\n        \"\"\"Nahrát optimalizované obrázky do cloudu\"\"\"\r\n        uploaded_files = []\r\n        \r\n        for root, dirs, files in os.walk(local_directory):\r\n            for file in files:\r\n                if file.lower().endswith(('.jpg', '.jpeg', '.png', '.webp')):\r\n                    local_path = os.path.join(root, file)\r\n                    remote_path = f\"{remote_path_prefix}{file}\"\r\n                    \r\n                    try:\r\n                        if self.provider == 'aws':\r\n                            self.upload_to_s3(local_path, remote_path)\r\n                        elif self.provider == 'azure':\r\n                            self.upload_to_azure(local_path, remote_path)\r\n                        elif self.provider == 'cloudinary':\r\n                            self.upload_to_cloudinary(local_path, remote_path)\r\n                        \r\n                        uploaded_files.append(remote_path)\r\n                        \r\n                    except Exception as e:\r\n                        print(f\"Chyba při nahrávání {file}: {str(e)}\")\r\n        \r\n        return uploaded_files\r\n    \r\n    def upload_to_s3(self, local_path, remote_path):\r\n        \"\"\"Nahrát soubor do Amazon S3\"\"\"\r\n        self.client.upload_file(\r\n            local_path, \r\n            self.config['bucket_name'], \r\n            remote_path,\r\n            ExtraArgs={\r\n                'ContentType': self.get_content_type(local_path),\r\n                'CacheControl': 'max-age=31536000'  # 1 rok cache\r\n            }\r\n        )\r\n    \r\n    def upload_to_azure(self, local_path, remote_path):\r\n        \"\"\"Nahrát soubor do Azure Blob Storage\"\"\"\r\n        blob_client = self.client.get_blob_client(\r\n            container=self.config['container_name'],\r\n            blob=remote_path\r\n        )\r\n        \r\n        with open(local_path, 'rb') as data:\r\n            blob_client.upload_blob(\r\n                data, \r\n                overwrite=True,\r\n                content_settings={\r\n                    'content_type': self.get_content_type(local_path),\r\n                    'cache_control': 'max-age=31536000'\r\n                }\r\n            )\r\n    \r\n    def upload_to_cloudinary(self, local_path, remote_path):\r\n        \"\"\"Nahrát soubor do Cloudinary\"\"\"\r\n        result = cloudinary.uploader.upload(\r\n            local_path,\r\n            public_id=remote_path.replace('.', '_'),\r\n            folder='ecommerce/products',\r\n            resource_type='image',\r\n            quality='auto',\r\n            fetch_format='auto'\r\n        )\r\n        return result\r\n    \r\n    def get_content_type(self, file_path):\r\n        \"\"\"Získat MIME typ souboru\"\"\"\r\n        extension = file_path.lower().split('.')[-1]\r\n        content_types = {\r\n            'jpg': 'image/jpeg',\r\n            'jpeg': 'image/jpeg',\r\n            'png': 'image/png',\r\n            'webp': 'image/webp',\r\n            'avif': 'image/avif'\r\n        }\r\n        return content_types.get(extension, 'application/octet-stream')\r\n```\r\n\r\n## Závěr\r\n\r\nOptimalizace obrázků produktů pro e-commerce je kritický faktor pro úspěch online obchodu. Správná implementace technik komprese, automatizace zpracování a měření výkonu může výrazně zlepšit konverzní poměry, snížit míru opuštění a zvýšit spokojenost zákazníků.\r\n\r\nKlíčové body k zapamatování:\r\n\r\n1. **Vyvážení kvality a výkonu**: Najděte optimální bod mezi vizuální kvalitou a rychlostí načítání\r\n2. **Automatizace je klíčová**: Implementujte automatizované pipeline pro škálování\r\n3. **Testování a měření**: Používejte A/B testování pro ověření dopadů optimalizace\r\n4. **Specifické požadavky platforem**: Přizpůsobte optimalizaci požadavkům konkrétních tržišť\r\n5. **Kontinuální zlepšování**: Pravidelně aktualizujte strategie na základě nových technologií a dat\r\n\r\nInvestice do profesionální optimalizace obrázků se rychle vrátí prostřednictvím zlepšených obchodních výsledků a lepší uživatelské zkušenosti.","# E-kereskedelmi termékképek tömörítése: Értékesítés-orientált optimalizálás\r\n\r\nAz e-kereskedelmi siker nagymértékben függ a termékképek minőségétől, tanulmányok szerint a fogyasztók 67%-a tartja \"nagyon fontosnak\" a képminőséget online vásárláskor. Azonban a nagy képfájlok jelentősen befolyásolhatják az oldal betöltési idejét, a konverziós arányokat és a mobil felhasználói élményt. Ez az átfogó útmutató fejlett technikákat mutat be az e-kereskedelmi termékképek optimalizálásához, miközben megőrzi az értékesítés ösztönzéséhez szükséges vizuális minőséget.\r\n\r\n## Miért fontos az e-kereskedelmi képoptimalizálás\r\n\r\n### Hatás a konverziós arányokra\r\n\r\nA termékképek optimalizálása közvetlenül befolyásolja az üzleti mutatókat:\r\n- **Konverziós arányok**: 1 másodperces késés az oldal betöltési idejében 7%-kal csökkenti a konverziókat\r\n- **Visszapattanási arányok**: A felhasználók 40%-a elhagyja azokat az oldalakat, amelyek 3 másodpercnél tovább töltenek\r\n- **Mobil kereskedelem**: Az e-kereskedelmi forgalom 73%-a mobil eszközökről származik\r\n- **Keresési rangsorolás**: A Google figyelembe veszi az oldal sebességét a keresési rangsorolásban\r\n- **Vásárlói elégedettség**: A jó minőségű képek növelik a vásárlási bizalmat\r\n\r\n### E-kereskedelmi specifikus követelmények\r\n\r\nA termékképek egyedi optimalizálási kihívásokkal rendelkeznek:\r\n- **Többféle terméknézet**: Főkép, miniatűrök, nagyítási nézetek, 360°-os forgatások\r\n- **Színpontosság**: Kritikus a divat, kozmetikumok és lakberendezési termékek esetében\r\n- **Részletmegőrzés**: A vásárlóknak látniuk kell a textúrát, anyagokat és kidolgozást\r\n- **Betöltési teljesítmény**: Egyensúly a minőség és sebesség között\r\n- **Eszközök közötti kompatibilitás**: Konzisztens élmény minden eszközön\r\n\r\n## E-kereskedelmi képtípusok megértése\r\n\r\n### Termékkép kategóriák\r\n\r\nA különböző képtípusok eltérő optimalizálási megközelítést igényelnek:\r\n\r\n```javascript\r\nconst ecommerceImageTypes = {\r\n    hero: {\r\n        purpose: 'Elsődleges termékbemutató',\r\n        requirements: 'Magas minőség, gyors betöltés',\r\n        sizes: ['1200x1200', '800x800', '600x600'],\r\n        quality: { jpeg: 85, webp: 80 }\r\n    },\r\n    thumbnail: {\r\n        purpose: 'Termékrács megjelenítések',\r\n        requirements: 'Kis fájlméret, felismerhető',\r\n        sizes: ['300x300', '200x200', '150x150'],\r\n        quality: { jpeg: 75, webp: 70 }\r\n    },\r\n    zoom: {\r\n        purpose: 'Részletes termékvizsgálat',\r\n        requirements: 'Maximális részletmegőrzés',\r\n        sizes: ['2000x2000', '1600x1600'],\r\n        quality: { jpeg: 90, webp: 85 }\r\n    },\r\n    gallery: {\r\n        purpose: 'Többféle termékszög',\r\n        requirements: 'Konzisztens minőség, lusta betöltés',\r\n        sizes: ['800x800', '600x600'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    },\r\n    lifestyle: {\r\n        purpose: 'Termék használatban/kontextusban',\r\n        requirements: 'Optimalizált érzelem/kontextus számára',\r\n        sizes: ['1200x800', '800x533'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    }\r\n};\r\n```\r\n\r\n### Optimalizálási stratégia termékkategóriák szerint\r\n\r\nA különböző termékkategóriák specifikus képkövetelményekkel rendelkeznek:\r\n\r\n```python\r\ndef get_category_optimization_settings(product_category):\r\n    \"\"\"Optimalizálási beállítások lekérése különböző termékkategóriákhoz\"\"\"\r\n    settings = {\r\n        'fashion': {\r\n            'priority': ['color_accuracy', 'texture_detail'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 90},\r\n            'critical_views': ['front', 'back', 'detail']\r\n        },\r\n        'electronics': {\r\n            'priority': ['detail_preservation', 'fast_loading'],\r\n            'format_preference': 'webp_or_avif',\r\n            'quality_range': {'min': 75, 'max': 85},\r\n            'critical_views': ['main', 'interfaces', 'size_comparison']\r\n        },\r\n        'home_decor': {\r\n            'priority': ['color_accuracy', 'lifestyle_context'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 88},\r\n            'critical_views': ['styled', 'closeup', 'dimensions']\r\n        },\r\n        'jewelry': {\r\n            'priority': ['maximum_detail', 'color_accuracy'],\r\n            'format_preference': 'png_for_detailed_webp_for_hero',\r\n            'quality_range': {'min': 85, 'max': 95},\r\n            'critical_views': ['macro', '360_spin', 'lifestyle']\r\n        },\r\n        'books': {\r\n            'priority': ['fast_loading', 'text_readability'],\r\n            'format_preference': 'webp_aggressive_compression',\r\n            'quality_range': {'min': 70, 'max': 80},\r\n            'critical_views': ['cover', 'back', 'spine']\r\n        }\r\n    }\r\n    return settings.get(product_category, settings['electronics'])\r\n```\r\n\r\n## Fejlett termékképfeldolgozás\r\n\r\n### Automatizált termékkép pipeline\r\n\r\nÁtfogó automatizált feldolgozási rendszer:\r\n\r\n```python\r\nimport os\r\nfrom PIL import Image, ImageEnhance, ImageFilter\r\nimport numpy as np\r\n\r\nclass EcommerceImageProcessor:\r\n    def __init__(self, config=None):\r\n        self.config = config or self.get_default_config()\r\n        self.supported_formats = ['jpeg', 'webp', 'avif', 'png']\r\n        \r\n    def get_default_config(self):\r\n        return {\r\n            'background_removal': True,\r\n            'auto_crop': True,\r\n            'color_enhancement': True,\r\n            'noise_reduction': True,\r\n            'watermark': False,\r\n            'quality_thresholds': {\r\n                'hero': 85,\r\n                'gallery': 80,\r\n                'thumbnail': 75,\r\n                'zoom': 90\r\n            }\r\n        }\r\n    \r\n    def process_product_image(self, input_path, output_dir, product_id):\r\n        \"\"\"Egyetlen termékkép feldolgozása az összes szükséges változatba\"\"\"\r\n        img = Image.open(input_path)\r\n        \r\n        # Alapvető előfeldolgozás\r\n        processed_img = self.preprocess_image(img)\r\n        \r\n        # Összes szükséges méret és formátum generálása\r\n        variants = self.generate_image_variants(processed_img, product_id)\r\n        \r\n        # Optimalizált verziók mentése\r\n        saved_files = self.save_variants(variants, output_dir)\r\n        \r\n        return saved_files\r\n    \r\n    def preprocess_image(self, img):\r\n        \"\"\"Alapvető előfeldolgozás alkalmazása termékképre\"\"\"\r\n        # Konvertálás RGB-re ha szükséges\r\n        if img.mode in ('RGBA', 'LA', 'P'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            if img.mode == 'RGBA':\r\n                background.paste(img, mask=img.split()[-1])\r\n            else:\r\n                background.paste(img)\r\n            img = background\r\n        \r\n        # Automatikus vágás a felesleges fehér terület eltávolításához\r\n        if self.config['auto_crop']:\r\n            img = self.smart_crop(img)\r\n        \r\n        # Képminőség javítása\r\n        if self.config['color_enhancement']:\r\n            img = self.enhance_product_image(img)\r\n        \r\n        # Zaj csökkentése\r\n        if self.config['noise_reduction']:\r\n            img = img.filter(ImageFilter.SMOOTH_MORE)\r\n        \r\n        return img\r\n    \r\n    def smart_crop(self, img):\r\n        \"\"\"Intelligens vágás termékképen a felesleges háttér eltávolításához\"\"\"\r\n        # Konvertálás numpy tömbbé elemzéshez\r\n        img_array = np.array(img)\r\n        \r\n        # Nem fehér pixelek határdobozának megkeresése\r\n        mask = np.any(img_array \u003C 240, axis=2)  # Nem tiszta fehér\r\n        coords = np.argwhere(mask)\r\n        \r\n        if len(coords) == 0:\r\n            return img  # Nincs szükség vágásra\r\n        \r\n        # Határdoboz lekérése\r\n        y0, x0 = coords.min(axis=0)\r\n        y1, x1 = coords.max(axis=0)\r\n        \r\n        # Padding hozzáadása\r\n        padding = 20\r\n        y0 = max(0, y0 - padding)\r\n        x0 = max(0, x0 - padding)\r\n        y1 = min(img.height, y1 + padding)\r\n        x1 = min(img.width, x1 + padding)\r\n        \r\n        return img.crop((x0, y0, x1, y1))\r\n    \r\n    def enhance_product_image(self, img):\r\n        \"\"\"Termékkép minőségének javítása\"\"\"\r\n        # Kontraszt javítása\r\n        enhancer = ImageEnhance.Contrast(img)\r\n        img = enhancer.enhance(1.1)\r\n        \r\n        # Színtelítettség finomhangolása\r\n        enhancer = ImageEnhance.Color(img)\r\n        img = enhancer.enhance(1.05)\r\n        \r\n        # Élesség javítása\r\n        enhancer = ImageEnhance.Sharpness(img)\r\n        img = enhancer.enhance(1.1)\r\n        \r\n        return img\r\n    \r\n    def generate_image_variants(self, img, product_id):\r\n        \"\"\"Képváltozatok generálása különböző méretekben és formátumokban\"\"\"\r\n        variants = {}\r\n        \r\n        # Szabványos méretek definiálása\r\n        sizes = {\r\n            'hero': [(1200, 1200), (800, 800), (600, 600)],\r\n            'thumbnail': [(300, 300), (200, 200), (150, 150)],\r\n            'zoom': [(2000, 2000), (1600, 1600)],\r\n            'gallery': [(800, 800), (600, 600)]\r\n        }\r\n        \r\n        for variant_type, size_list in sizes.items():\r\n            variants[variant_type] = {}\r\n            for size in size_list:\r\n                # Kép átméretezése megfelelő minőséggel\r\n                resized_img = self.resize_with_quality(img, size)\r\n                variants[variant_type][f\"{size[0]}x{size[1]}\"] = resized_img\r\n        \r\n        return variants\r\n    \r\n    def resize_with_quality(self, img, target_size):\r\n        \"\"\"Kép átméretezése magas minőséggel\"\"\"\r\n        # Arány megőrzése\r\n        img.thumbnail(target_size, Image.Resampling.LANCZOS)\r\n        \r\n        # Új kép létrehozása fehér háttérrel ha szükséges\r\n        if img.size != target_size:\r\n            new_img = Image.new('RGB', target_size, (255, 255, 255))\r\n            # Kép középre helyezése\r\n            paste_x = (target_size[0] - img.size[0]) // 2\r\n            paste_y = (target_size[1] - img.size[1]) // 2\r\n            new_img.paste(img, (paste_x, paste_y))\r\n            return new_img\r\n        \r\n        return img\r\n    \r\n    def save_variants(self, variants, output_dir):\r\n        \"\"\"Képváltozatok mentése optimalizált formátumokban\"\"\"\r\n        saved_files = []\r\n        \r\n        for variant_type, sizes in variants.items():\r\n            variant_dir = os.path.join(output_dir, variant_type)\r\n            os.makedirs(variant_dir, exist_ok=True)\r\n            \r\n            for size_name, img in sizes.items():\r\n                # JPEG mentése\r\n                jpeg_path = os.path.join(variant_dir, f\"{size_name}.jpg\")\r\n                quality = self.config['quality_thresholds'].get(variant_type, 80)\r\n                img.save(jpeg_path, 'JPEG', quality=quality, optimize=True)\r\n                saved_files.append(jpeg_path)\r\n                \r\n                # WebP mentése\r\n                webp_path = os.path.join(variant_dir, f\"{size_name}.webp\")\r\n                webp_quality = max(quality - 5, 70)  # WebP általában jobb tömörítés\r\n                img.save(webp_path, 'WebP', quality=webp_quality, optimize=True)\r\n                saved_files.append(webp_path)\r\n        \r\n        return saved_files\r\n```\r\n\r\n## Amazon Marketplace optimalizálás\r\n\r\n### Amazon képkövetelmények\r\n\r\nAz Amazon specifikus képoptimalizálási követelményei:\r\n\r\n```python\r\nclass AmazonImageOptimizer:\r\n    def __init__(self):\r\n        self.amazon_requirements = {\r\n            'main_image': {\r\n                'min_size': (1000, 1000),\r\n                'max_size': (10000, 10000),\r\n                'background': 'pure_white',\r\n                'format': ['JPEG', 'PNG', 'GIF'],\r\n                'quality_min': 85\r\n            },\r\n            'additional_images': {\r\n                'min_size': (500, 500),\r\n                'recommended_size': (1600, 1600),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'max_count': 8\r\n            },\r\n            'zoom_functionality': {\r\n                'min_size': (1001, 1001),\r\n                'recommended_size': (2000, 2000),\r\n                'enables_zoom': True\r\n            }\r\n        }\r\n    \r\n    def optimize_for_amazon(self, image_path, image_type='main'):\r\n        \"\"\"Kép optimalizálása Amazon követelményekhez\"\"\"\r\n        img = Image.open(image_path)\r\n        requirements = self.amazon_requirements[f\"{image_type}_image\"]\r\n        \r\n        # Méret ellenőrzése és módosítása\r\n        if img.size[0] \u003C requirements['min_size'][0] or img.size[1] \u003C requirements['min_size'][1]:\r\n            # Kép nagyítása ha túl kicsi\r\n            img = self.upscale_image(img, requirements['min_size'])\r\n        \r\n        # Háttér fehérítése főképnél\r\n        if image_type == 'main' and requirements.get('background') == 'pure_white':\r\n            img = self.ensure_white_background(img)\r\n        \r\n        # Optimalizált mentés\r\n        return self.save_amazon_optimized(img, image_path, image_type)\r\n    \r\n    def ensure_white_background(self, img):\r\n        \"\"\"Tiszta fehér háttér biztosítása\"\"\"\r\n        if img.mode in ('RGBA', 'LA'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            background.paste(img, mask=img.split()[-1])\r\n            return background\r\n        elif img.mode == 'P':\r\n            return img.convert('RGB')\r\n        return img\r\n    \r\n    def upscale_image(self, img, min_size):\r\n        \"\"\"Kép nagyítása minimum méretre\"\"\"\r\n        scale_factor = max(min_size[0] / img.size[0], min_size[1] / img.size[1])\r\n        new_size = (int(img.size[0] * scale_factor), int(img.size[1] * scale_factor))\r\n        return img.resize(new_size, Image.Resampling.LANCZOS)\r\n```\r\n\r\n## Teljesítménymérés és monitorozás\r\n\r\n### Képoptimalizálási metrikák\r\n\r\nKulcsfontosságú teljesítménymutatók nyomon követése:\r\n\r\n```python\r\nimport time\r\nimport requests\r\nfrom PIL import Image\r\nimport os\r\n\r\nclass ImagePerformanceMonitor:\r\n    def __init__(self):\r\n        self.metrics = {\r\n            'file_sizes': {},\r\n            'load_times': {},\r\n            'quality_scores': {},\r\n            'conversion_impact': {}\r\n        }\r\n    \r\n    def measure_optimization_impact(self, original_path, optimized_path):\r\n        \"\"\"Optimalizálás hatásának mérése\"\"\"\r\n        # Fájlméret összehasonlítás\r\n        original_size = os.path.getsize(original_path)\r\n        optimized_size = os.path.getsize(optimized_path)\r\n        size_reduction = ((original_size - optimized_size) / original_size) * 100\r\n        \r\n        # Képminőség értékelése\r\n        quality_score = self.calculate_quality_score(original_path, optimized_path)\r\n        \r\n        # Betöltési idő szimuláció\r\n        load_time_improvement = self.simulate_load_time_improvement(\r\n            original_size, optimized_size\r\n        )\r\n        \r\n        return {\r\n            'size_reduction_percent': size_reduction,\r\n            'quality_retention_percent': quality_score,\r\n            'load_time_improvement_ms': load_time_improvement,\r\n            'optimization_ratio': size_reduction / (100 - quality_score) if quality_score \u003C 100 else size_reduction\r\n        }\r\n    \r\n    def calculate_quality_score(self, original_path, optimized_path):\r\n        \"\"\"Képminőség pontszám számítása\"\"\"\r\n        try:\r\n            from skimage.metrics import structural_similarity as ssim\r\n            import numpy as np\r\n            \r\n            # Képek betöltése és konvertálása\r\n            original = np.array(Image.open(original_path).convert('RGB'))\r\n            optimized = np.array(Image.open(optimized_path).convert('RGB'))\r\n            \r\n            # SSIM számítása\r\n            ssim_score = ssim(original, optimized, multichannel=True, channel_axis=2)\r\n            return ssim_score * 100\r\n        except ImportError:\r\n            # Egyszerű méret alapú becslés ha nincs scikit-image\r\n            return 85.0  # Alapértelmezett érték\r\n    \r\n    def simulate_load_time_improvement(self, original_size, optimized_size):\r\n        \"\"\"Betöltési idő javulásának szimulációja\"\"\"\r\n        # Átlagos internetsebesség alapján (5 Mbps)\r\n        avg_speed_bytes_per_ms = 5 * 1024 * 1024 / 8 / 1000  # 5 Mbps to bytes/ms\r\n        \r\n        original_load_time = original_size / avg_speed_bytes_per_ms\r\n        optimized_load_time = optimized_size / avg_speed_bytes_per_ms\r\n        \r\n        return original_load_time - optimized_load_time\r\n    \r\n    def generate_performance_report(self, optimization_results):\r\n        \"\"\"Teljesítményjelentés generálása\"\"\"\r\n        report = {\r\n            'summary': {\r\n                'total_images_processed': len(optimization_results),\r\n                'average_size_reduction': sum(r['size_reduction_percent'] for r in optimization_results) / len(optimization_results),\r\n                'average_quality_retention': sum(r['quality_retention_percent'] for r in optimization_results) / len(optimization_results),\r\n                'total_load_time_saved_ms': sum(r['load_time_improvement_ms'] for r in optimization_results)\r\n            },\r\n            'recommendations': self.generate_recommendations(optimization_results)\r\n        }\r\n        return report\r\n    \r\n    def generate_recommendations(self, results):\r\n        \"\"\"Optimalizálási javaslatok generálása\"\"\"\r\n        recommendations = []\r\n        \r\n        avg_size_reduction = sum(r['size_reduction_percent'] for r in results) / len(results)\r\n        avg_quality = sum(r['quality_retention_percent'] for r in results) / len(results)\r\n        \r\n        if avg_size_reduction \u003C 30:\r\n            recommendations.append(\"Agresszívabb tömörítési beállítások alkalmazása\")\r\n        \r\n        if avg_quality \u003C 85:\r\n            recommendations.append(\"Minőségi beállítások finomhangolása a jobb vizuális eredményért\")\r\n        \r\n        if any(r['load_time_improvement_ms'] > 500 for r in results):\r\n            recommendations.append(\"Kritikus képek prioritás alapú optimalizálása\")\r\n        \r\n        return recommendations\r\n```\r\n\r\n## Kötegelt feldolgozás nagy katalógusokhoz\r\n\r\n### Párhuzamos képfeldolgozás\r\n\r\nNagy mennyiségű termékkép hatékony feldolgozása:\r\n\r\n```python\r\nimport concurrent.futures\r\nimport multiprocessing\r\nfrom pathlib import Path\r\nimport logging\r\n\r\nclass BatchImageProcessor:\r\n    def __init__(self, max_workers=None):\r\n        self.max_workers = max_workers or multiprocessing.cpu_count()\r\n        self.processed_count = 0\r\n        self.failed_count = 0\r\n        \r\n        # Logging beállítása\r\n        logging.basicConfig(level=logging.INFO)\r\n        self.logger = logging.getLogger(__name__)\r\n    \r\n    def process_catalog(self, input_directory, output_directory, product_categories=None):\r\n        \"\"\"Teljes termékkatalógus feldolgozása\"\"\"\r\n        input_path = Path(input_directory)\r\n        output_path = Path(output_directory)\r\n        output_path.mkdir(parents=True, exist_ok=True)\r\n        \r\n        # Képfájlok összegyűjtése\r\n        image_files = self.collect_image_files(input_path)\r\n        self.logger.info(f\"Összesen {len(image_files)} kép feldolgozásra vár\")\r\n        \r\n        # Párhuzamos feldolgozás\r\n        with concurrent.futures.ThreadPoolExecutor(max_workers=self.max_workers) as executor:\r\n            # Feladatok beküldése\r\n            future_to_file = {\r\n                executor.submit(\r\n                    self.process_single_product_image, \r\n                    img_file, \r\n                    output_path,\r\n                    product_categories.get(img_file.stem) if product_categories else None\r\n                ): img_file \r\n                for img_file in image_files\r\n            }\r\n            \r\n            # Eredmények feldolgozása\r\n            for future in concurrent.futures.as_completed(future_to_file):\r\n                img_file = future_to_file[future]\r\n                try:\r\n                    result = future.result()\r\n                    self.processed_count += 1\r\n                    if self.processed_count % 100 == 0:\r\n                        self.logger.info(f\"Feldolgozva: {self.processed_count}/{len(image_files)}\")\r\n                except Exception as exc:\r\n                    self.failed_count += 1\r\n                    self.logger.error(f\"Hiba {img_file} feldolgozásakor: {exc}\")\r\n        \r\n        # Összefoglaló jelentés\r\n        self.generate_batch_report(len(image_files))\r\n    \r\n    def collect_image_files(self, input_path):\r\n        \"\"\"Képfájlok összegyűjtése a bemeneti könyvtárból\"\"\"\r\n        supported_extensions = {'.jpg', '.jpeg', '.png', '.webp', '.tiff', '.bmp'}\r\n        image_files = []\r\n        \r\n        for ext in supported_extensions:\r\n            image_files.extend(input_path.glob(f\"**/*{ext}\"))\r\n            image_files.extend(input_path.glob(f\"**/*{ext.upper()}\"))\r\n        \r\n        return image_files\r\n    \r\n    def process_single_product_image(self, image_path, output_dir, category=None):\r\n        \"\"\"Egyetlen termékkép feldolgozása\"\"\"\r\n        try:\r\n            processor = EcommerceImageProcessor()\r\n            \r\n            # Kategória-specifikus beállítások alkalmazása\r\n            if category:\r\n                category_settings = get_category_optimization_settings(category)\r\n                processor.config.update(category_settings)\r\n            \r\n            # Kép feldolgozása\r\n            product_id = image_path.stem\r\n            result = processor.process_product_image(\r\n                str(image_path), \r\n                str(output_dir), \r\n                product_id\r\n            )\r\n            \r\n            return {\r\n                'status': 'success',\r\n                'input_file': str(image_path),\r\n                'output_files': result,\r\n                'product_id': product_id\r\n            }\r\n            \r\n        except Exception as e:\r\n            return {\r\n                'status': 'error',\r\n                'input_file': str(image_path),\r\n                'error': str(e)\r\n            }\r\n    \r\n    def generate_batch_report(self, total_files):\r\n        \"\"\"Kötegelt feldolgozás jelentésének generálása\"\"\"\r\n        success_rate = (self.processed_count / total_files) * 100\r\n        \r\n        report = f\"\"\"\r\n        Kötegelt képfeldolgozás jelentés\r\n        ================================\r\n        Összes fájl: {total_files}\r\n        Sikeresen feldolgozva: {self.processed_count}\r\n        Sikertelen: {self.failed_count}\r\n        Sikerességi arány: {success_rate:.2f}%\r\n        \r\n        Feldolgozási sebesség: {self.processed_count / self.max_workers:.2f} kép/worker\r\n        \"\"\"\r\n        \r\n        self.logger.info(report)\r\n        return report\r\n\r\n# Használati példa\r\ndef optimize_ecommerce_catalog():\r\n    \"\"\"E-kereskedelmi katalógus optimalizálása\"\"\"\r\n    # Termékkategóriák definiálása\r\n    product_categories = {\r\n        'shirt_001': 'fashion',\r\n        'laptop_002': 'electronics',\r\n        'sofa_003': 'home_decor',\r\n        'ring_004': 'jewelry'\r\n    }\r\n    \r\n    # Kötegelt feldolgozó inicializálása\r\n    batch_processor = BatchImageProcessor(max_workers=8)\r\n    \r\n    # Katalógus feldolgozása\r\n    batch_processor.process_catalog(\r\n        input_directory='./raw_product_images',\r\n        output_directory='./optimized_product_images',\r\n        product_categories=product_categories\r\n    )\r\n\r\nif __name__ == \"__main__\":\r\n    optimize_ecommerce_catalog()\r\n```\r\n\r\n## Automatizálás és integráció\r\n\r\n### E-kereskedelmi platform integráció\r\n\r\nAutomatikus képoptimalizálás e-kereskedelmi rendszerekhez:\r\n\r\n```python\r\nimport requests\r\nimport json\r\nfrom datetime import datetime\r\n\r\nclass EcommerceIntegration:\r\n    def __init__(self, platform_config):\r\n        self.platform = platform_config['platform']  # 'shopify', 'woocommerce', 'magento'\r\n        self.api_key = platform_config['api_key']\r\n        self.store_url = platform_config['store_url']\r\n        self.headers = self.setup_headers()\r\n    \r\n    def setup_headers(self):\r\n        \"\"\"API fejlécek beállítása platform szerint\"\"\"\r\n        if self.platform == 'shopify':\r\n            return {\r\n                'X-Shopify-Access-Token': self.api_key,\r\n                'Content-Type': 'application/json'\r\n            }\r\n        elif self.platform == 'woocommerce':\r\n            return {\r\n                'Authorization': f'Bearer {self.api_key}',\r\n                'Content-Type': 'application/json'\r\n            }\r\n        return {'Content-Type': 'application/json'}\r\n    \r\n    def get_products_needing_optimization(self):\r\n        \"\"\"Optimalizálásra szoruló termékek lekérése\"\"\"\r\n        if self.platform == 'shopify':\r\n            return self.get_shopify_products()\r\n        elif self.platform == 'woocommerce':\r\n            return self.get_woocommerce_products()\r\n        return []\r\n    \r\n    def get_shopify_products(self):\r\n        \"\"\"Shopify termékek lekérése\"\"\"\r\n        url = f\"{self.store_url}/admin/api/2023-01/products.json\"\r\n        response = requests.get(url, headers=self.headers)\r\n        \r\n        if response.status_code == 200:\r\n            products = response.json()['products']\r\n            return [\r\n                {\r\n                    'id': product['id'],\r\n                    'title': product['title'],\r\n                    'images': [img['src'] for img in product['images']]\r\n                }\r\n                for product in products\r\n            ]\r\n        return []\r\n    \r\n    def optimize_product_images(self, product_data):\r\n        \"\"\"Termékképek optimalizálása és feltöltése\"\"\"\r\n        optimized_images = []\r\n        \r\n        for image_url in product_data['images']:\r\n            try:\r\n                # Kép letöltése\r\n                response = requests.get(image_url)\r\n                if response.status_code == 200:\r\n                    # Ideiglenes fájl mentése\r\n                    temp_path = f\"temp_{product_data['id']}.jpg\"\r\n                    with open(temp_path, 'wb') as f:\r\n                        f.write(response.content)\r\n                    \r\n                    # Optimalizálás\r\n                    processor = EcommerceImageProcessor()\r\n                    optimized_files = processor.process_product_image(\r\n                        temp_path, \r\n                        f\"optimized_{product_data['id']}\", \r\n                        str(product_data['id'])\r\n                    )\r\n                    \r\n                    # Optimalizált képek feltöltése\r\n                    uploaded_urls = self.upload_optimized_images(\r\n                        optimized_files, \r\n                        product_data['id']\r\n                    )\r\n                    optimized_images.extend(uploaded_urls)\r\n                    \r\n                    # Ideiglenes fájl törlése\r\n                    os.remove(temp_path)\r\n                    \r\n            except Exception as e:\r\n                print(f\"Hiba a kép optimalizálásakor: {e}\")\r\n        \r\n        return optimized_images\r\n    \r\n    def upload_optimized_images(self, image_files, product_id):\r\n        \"\"\"Optimalizált képek feltöltése a platformra\"\"\"\r\n        uploaded_urls = []\r\n        \r\n        for image_file in image_files:\r\n            if self.platform == 'shopify':\r\n                url = self.upload_to_shopify(image_file, product_id)\r\n            elif self.platform == 'woocommerce':\r\n                url = self.upload_to_woocommerce(image_file, product_id)\r\n            \r\n            if url:\r\n                uploaded_urls.append(url)\r\n        \r\n        return uploaded_urls\r\n    \r\n    def schedule_optimization(self, schedule_config):\r\n        \"\"\"Optimalizálás ütemezése\"\"\"\r\n        import schedule\r\n        import time\r\n        \r\n        def run_optimization():\r\n            products = self.get_products_needing_optimization()\r\n            for product in products:\r\n                self.optimize_product_images(product)\r\n                time.sleep(1)  # Rate limiting\r\n        \r\n        # Ütemezés beállítása\r\n        if schedule_config['frequency'] == 'daily':\r\n            schedule.every().day.at(schedule_config['time']).do(run_optimization)\r\n        elif schedule_config['frequency'] == 'weekly':\r\n            schedule.every().week.do(run_optimization)\r\n        \r\n        # Ütemező futtatása\r\n        while True:\r\n            schedule.run_pending()\r\n            time.sleep(60)\r\n```\r\n\r\n## Következtetés\r\n\r\nAz e-kereskedelmi termékképek optimalizálása kritikus fontosságú az online értékesítés sikeréhez. A megfelelő tömörítési technikák alkalmazásával jelentősen javíthatjuk az oldal teljesítményét anélkül, hogy feláldoznánk a képminőséget.\r\n\r\n### Kulcsfontosságú megállapítások\r\n\r\n1. **Kategória-specifikus optimalizálás**: Minden termékkategória egyedi képkövetelményekkel rendelkezik\r\n2. **Automatizálás fontossága**: Nagy katalógusok esetén elengedhetetlen a kötegelt feldolgozás\r\n3. **Teljesítménymérés**: Rendszeres monitorozás szükséges az optimális eredményekhez\r\n4. **Platform integráció**: Zökkenőmentes munkafolyamat az e-kereskedelmi rendszerekkel\r\n5. **Minőség vs. sebesség**: Megfelelő egyensúly megtalálása az üzleti célokhoz\r\n\r\n### Implementációs javaslatok\r\n\r\n- Kezdje a legkritikusabb termékképekkel (főképek, bestseller termékek)\r\n- Tesztelje az optimalizálási beállításokat kis mintán\r\n- Mérje a konverziós arányokra gyakorolt hatást\r\n- Automatizálja a folyamatot a konzisztencia érdekében\r\n- Rendszeresen frissítse az optimalizálási stratégiákat\r\n\r\nA megfelelően implementált képoptimalizálási stratégia jelentős javulást eredményezhet az oldal sebességében, felhasználói élményben és végső soron az értékesítési eredményekben.","# การบีบอัดภาพสินค้าอีคอมเมิร์ซ: การปรับแต่งเพื่อเพิ่มยอดขาย\r\n\r\nความสำเร็จในอีคอมเมิร์ซขึ้นอยู่กับคุณภาพของภาพสินค้าเป็นอย่างมาก: งานวิจัยพบว่า 67% ของผู้บริโภคมองว่าคุณภาพของภาพเป็น \"สิ่งสำคัญมาก\" ในการตัดสินใจซื้อออนไลน์ อย่างไรก็ตาม ไฟล์ภาพขนาดใหญ่สามารถส่งผลกระทบต่อเวลาในการโหลดหน้าเว็บ อัตราการแปลง และประสบการณ์บนมือถืออย่างมีนัยสำคัญ คู่มือฉบับสมบูรณ์นี้จะครอบคลุมแนวทางปฏิบัติขั้นสูงในการปรับแต่งภาพสินค้าอีคอมเมิร์ซโดยยังคงรักษาคุณภาพภาพที่จำเป็นต่อการเพิ่มยอดขาย\r\n\r\n## ทำไมการปรับแต่งภาพสำหรับอีคอมเมิร์ซจึงสำคัญ\r\n\r\n### ผลกระทบต่อ Conversion\r\n\r\nการปรับแต่งภาพสินค้ามีผลโดยตรงต่อผลลัพธ์ทางธุรกิจ:\r\n- **Conversion**: ความล่าช้าในการโหลดหน้าเว็บ 1 วินาที ลดอัตราการแปลงลง 7%\r\n- **Bounce Rate**: 40% ของผู้ใช้จะออกจากเว็บไซต์ที่โหลดเกิน 3 วินาที\r\n- **Mobile Commerce**: 73% ของทราฟฟิกอีคอมเมิร์ซมาจากอุปกรณ์มือถือ\r\n- **Search Ranking**: Google นำความเร็วในการโหลดหน้าเว็บมาพิจารณาในการจัดอันดับ\r\n- **ความพึงพอใจของลูกค้า**: ภาพคุณภาพสูงช่วยเพิ่มความมั่นใจในการซื้อ\r\n\r\n### ข้อกำหนดเฉพาะของอีคอมเมิร์ซ\r\n\r\nภาพสินค้ามีความท้าทายในการปรับแต่งที่ไม่เหมือนใคร:\r\n- **มุมมองสินค้าหลายมุม**: ภาพหลัก, ภาพย่อ, ซูม, มุมมอง 360°\r\n- **ความแม่นยำของสี**: สำคัญสำหรับแฟชั่น เครื่องสำอาง และของแต่งบ้าน\r\n- **การรักษารายละเอียด**: ลูกค้าต้องการเห็นพื้นผิว วัสดุ และคุณภาพการผลิต\r\n- **ประสิทธิภาพการโหลด**: สมดุลระหว่างคุณภาพกับความเร็ว\r\n- **ประสบการณ์ข้ามแพลตฟอร์ม**: ประสบการณ์ที่สอดคล้องกันในทุกอุปกรณ์\r\n\r\n## ประเภทของภาพสำหรับอีคอมเมิร์ซ\r\n\r\n### หมวดหมู่ของภาพสินค้า\r\n\r\nภาพแต่ละประเภทต้องการแนวทางการปรับแต่งที่แตกต่างกัน:\r\n\r\n```javascript\r\nconst ecommerceImageTypes = {\r\n    hero: {\r\n        purpose: 'การนำเสนอสินค้าหลัก',\r\n        requirements: 'คุณภาพสูง โหลดเร็ว',\r\n        sizes: ['1200x1200', '800x800', '600x600'],\r\n        quality: { jpeg: 85, webp: 80 }\r\n    },\r\n    thumbnail: {\r\n        purpose: 'แกลเลอรีสินค้า',\r\n        requirements: 'ขนาดไฟล์เล็ก จำแนกได้',\r\n        sizes: ['300x300', '200x200', '150x150'],\r\n        quality: { jpeg: 75, webp: 70 }\r\n    },\r\n    zoom: {\r\n        purpose: 'ดูรายละเอียดสินค้า',\r\n        requirements: 'รักษารายละเอียดสูงสุด',\r\n        sizes: ['2000x2000', '1600x1600'],\r\n        quality: { jpeg: 90, webp: 85 }\r\n    },\r\n    gallery: {\r\n        purpose: 'มุมมองสินค้าหลายมุม',\r\n        requirements: 'คุณภาพคงที่ โหลดแบบ Lazy',\r\n        sizes: ['800x800', '600x600'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    },\r\n    lifestyle: {\r\n        purpose: 'สินค้าในบริบท/การใช้งาน',\r\n        requirements: 'ปรับแต่งเพื่ออารมณ์/บริบท',\r\n        sizes: ['1200x800', '800x533'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    }\r\n};\r\n```\r\n\r\n### กลยุทธ์การปรับแต่งตามหมวดหมู่สินค้า\r\n\r\nแต่ละหมวดหมู่สินค้ามีข้อกำหนดเฉพาะสำหรับภาพ:\r\n\r\n```python\r\ndef get_category_optimization_settings(product_category):\r\n    \"\"\"ดึงการตั้งค่าการปรับแต่งสำหรับแต่ละหมวดหมู่สินค้า\"\"\"\r\n    settings = {\r\n        'fashion': {\r\n            'priority': ['ความแม่นยำของสี', 'รายละเอียดพื้นผิว'],\r\n            'format_preference': 'webp_พร้อม_fallback_jpeg',\r\n            'quality_range': {'min': 80, 'max': 90},\r\n            'critical_views': ['ด้านหน้า', 'ด้านหลัง', 'รายละเอียด']\r\n        },\r\n        'electronics': {\r\n            'priority': ['การรักษารายละเอียด', 'โหลดเร็ว'],\r\n            'format_preference': 'webp_หรือ_avif',\r\n            'quality_range': {'min': 75, 'max': 85},\r\n            'critical_views': ['หลัก', 'พอร์ต', 'เปรียบเทียบขนาด']\r\n        },\r\n        'home_decor': {\r\n            'priority': ['ความแม่นยำของสี', 'บริบทการใช้งาน'],\r\n            'format_preference': 'webp_พร้อม_fallback_jpeg',\r\n            'quality_range': {'min': 80, 'max': 88},\r\n            'critical_views': ['ตกแต่งภายใน', 'ซูม', 'ขนาด']\r\n        },\r\n        'jewelry': {\r\n            'priority': ['รายละเอียดสูงสุด', 'ความแม่นยำของสี'],\r\n            'format_preference': 'png_สำหรับรายละเอียด_webp_สำหรับ_hero',\r\n            'quality_range': {'min': 85, 'max': 95},\r\n            'critical_views': ['มาโคร', '360_องศา', 'lifestyle']\r\n        },\r\n        'books': {\r\n            'priority': ['โหลดเร็ว', 'ความชัดเจนของตัวอักษร'],\r\n            'format_preference': 'webp_บีบอัดสูง',\r\n            'quality_range': {'min': 70, 'max': 80},\r\n            'critical_views': ['ปก', 'ปกหลัง', 'สันหนังสือ']\r\n        }\r\n    }\r\n    return settings.get(product_category, settings['electronics'])\r\n```\r\n\r\n## การประมวลผลภาพสินค้าขั้นสูง\r\n\r\n### Pipeline การประมวลผลภาพอัตโนมัติ\r\n\r\nระบบประมวลผลภาพอัตโนมัติแบบครบวงจร:\r\n\r\n```python\r\nimport os\r\nfrom PIL import Image, ImageEnhance, ImageFilter\r\nimport numpy as np\r\n\r\nclass EcommerceImageProcessor:\r\n    def __init__(self, config=None):\r\n        self.config = config or self.get_default_config()\r\n        self.supported_formats = ['jpeg', 'webp', 'avif', 'png']\r\n        \r\n    def get_default_config(self):\r\n        return {\r\n            'background_removal': True,\r\n            'auto_crop': True,\r\n            'color_enhancement': True,\r\n            'noise_reduction': True,\r\n            'watermark': False,\r\n            'quality_thresholds': {\r\n                'hero': 85,\r\n                'gallery': 80,\r\n                'thumbnail': 75,\r\n                'zoom': 90\r\n            }\r\n        }\r\n    \r\n    def process_product_image(self, input_path, output_dir, product_id):\r\n        \"\"\"ประมวลผลภาพสินค้า 1 ภาพให้ได้ทุกเวอร์ชันที่ต้องการ\"\"\"\r\n        img = Image.open(input_path)\r\n        \r\n        # การประมวลผลเบื้องต้น\r\n        processed_img = self.preprocess_image(img)\r\n        \r\n        # สร้างทุกขนาดและฟอร์แมตที่ต้องการ\r\n        variants = self.generate_image_variants(processed_img, product_id)\r\n        \r\n        # บันทึกเวอร์ชันที่ปรับแต่งแล้ว\r\n        saved_files = self.save_variants(variants, output_dir)\r\n        \r\n        return saved_files\r\n    \r\n    def preprocess_image(self, img):\r\n        \"\"\"การประมวลผลเบื้องต้นของภาพสินค้า\"\"\"\r\n        # แปลงเป็น RGB หากจำเป็น\r\n        if img.mode in ('RGBA', 'LA', 'P'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            if img.mode == 'RGBA':\r\n                background.paste(img, mask=img.split()[-1])\r\n            else:\r\n                background.paste(img)\r\n            img = background\r\n        \r\n        # ครอปอัตโนมัติเพื่อลบพื้นหลังส่วนเกิน\r\n        if self.config['auto_crop']:\r\n            img = self.smart_crop(img)\r\n        \r\n        # ปรับปรุงคุณภาพภาพ\r\n        if self.config['color_enhancement']:\r\n            img = self.enhance_product_image(img)\r\n        \r\n        # ลดนอยส์\r\n        if self.config['noise_reduction']:\r\n            img = img.filter(ImageFilter.SMOOTH_MORE)\r\n        \r\n        return img\r\n    \r\n    def smart_crop(self, img):\r\n        \"\"\"ครอปอัจฉริยะเพื่อลบพื้นหลังส่วนเกิน\"\"\"\r\n        # แปลงเป็น numpy array เพื่อวิเคราะห์\r\n        img_array = np.array(img)\r\n        \r\n        # หา bounding box ของพิกเซลที่ไม่ใช่สีขาว\r\n        mask = np.any(img_array \u003C 240, axis=2)  # ไม่ใช่ขาวล้วน\r\n        coords = np.argwhere(mask)\r\n        \r\n        if len(coords) == 0:\r\n            return img  # ไม่ต้องครอป\r\n        \r\n        # หา bounding box\r\n        y0, x0 = coords.min(axis=0)\r\n        y1, x1 = coords.max(axis=0)\r\n        \r\n        # เพิ่ม padding\r\n        padding = 20\r\n        y0 = max(0, y0 - padding)\r\n        x0 = max(0, x0 - padding)\r\n        y1 = min(img.height, y1 + padding)\r\n        x1 = min(img.width, x1 + padding)\r\n        \r\n        return img.crop((x0, y0, x1, y1))\r\n    \r\n    def enhance_product_image(self, img):\r\n        \"\"\"ปรับปรุงภาพสินค้าให้เหมาะกับอีคอมเมิร์ซ\"\"\"\r\n        # เพิ่มความสว่างเล็กน้อย\r\n        brightness_enhancer = ImageEnhance.Brightness(img)\r\n        img = brightness_enhancer.enhance(1.05)\r\n        \r\n        # เพิ่มคอนทราสต์\r\n        contrast_enhancer = ImageEnhance.Contrast(img)\r\n        img = contrast_enhancer.enhance(1.1)\r\n        \r\n        # เพิ่มความอิ่มตัวของสี\r\n        color_enhancer = ImageEnhance.Color(img)\r\n        img = color_enhancer.enhance(1.05)\r\n        \r\n        # เพิ่มความคมชัด\r\n        sharpness_enhancer = ImageEnhance.Sharpness(img)\r\n        img = sharpness_enhancer.enhance(1.1)\r\n        \r\n        return img\r\n    \r\n    def generate_image_variants(self, img, product_id):\r\n        \"\"\"สร้างทุกเวอร์ชันของภาพที่ต้องการ\"\"\"\r\n        variants = {}\r\n        \r\n        # ขนาดมาตรฐานสำหรับอีคอมเมิร์ซ\r\n        sizes = {\r\n            'hero': (1200, 1200),\r\n            'gallery': (800, 800),\r\n            'thumbnail': (300, 300),\r\n            'zoom': (2000, 2000),\r\n            'mobile_hero': (600, 600),\r\n            'mobile_thumb': (150, 150)\r\n        }\r\n        \r\n        for variant_name, size in sizes.items():\r\n            # ปรับขนาดด้วย resampling คุณภาพสูง\r\n            resized = img.resize(size, Image.Resampling.LANCZOS)\r\n            variants[variant_name] = resized\r\n        \r\n        return variants\r\n    \r\n    def save_variants(self, variants, output_dir):\r\n        \"\"\"บันทึกทุกเวอร์ชันในฟอร์แมตที่ปรับแต่งแล้ว\"\"\"\r\n        saved_files = []\r\n        \r\n        for variant_name, img in variants.items():\r\n            base_path = os.path.join(output_dir, variant_name)\r\n            \r\n            # บันทึกหลายฟอร์แมต\r\n            for format_type in ['jpeg', 'webp']:\r\n                filename = f\"{base_path}.{format_type}\"\r\n                quality = self.get_quality_for_variant(variant_name, format_type)\r\n                \r\n                if format_type == 'jpeg':\r\n                    img.save(filename, 'JPEG', quality=quality, optimize=True, progressive=True)\r\n                elif format_type == 'webp':\r\n                    img.save(filename, 'WebP', quality=quality, optimize=True)\r\n                \r\n                saved_files.append(filename)\r\n        \r\n        return saved_files\r\n    \r\n    def get_quality_for_variant(self, variant_name, format_type):\r\n        \"\"\"ดึงคุณภาพที่เหมาะสมสำหรับแต่ละเวอร์ชันและฟอร์แมต\"\"\"\r\n        base_quality = self.config['quality_thresholds'].get(variant_name, 80)\r\n        \r\n        # ปรับตามฟอร์แมต\r\n        if format_type == 'webp':\r\n            return base_quality - 5  # WebP ให้คุณภาพเท่ากันที่ค่าต่ำกว่า\r\n        elif format_type == 'avif':\r\n            return base_quality - 10  # AVIF ยิ่งประหยัดกว่า\r\n        \r\n        return base_quality\r\n\r\n# ตัวอย่างการใช้งาน\r\nprocessor = EcommerceImageProcessor()\r\nprocessor.process_product_image('product_raw.jpg', 'output/', 'product_123')\r\n```\r\n\r\n### การลบและมาตรฐานพื้นหลัง\r\n\r\nการจัดการพื้นหลังอัตโนมัติเพื่อความสม่ำเสมอของภาพสินค้า:\r\n\r\n```python\r\ndef remove_product_background(image_path, output_path):\r\n    \"\"\"ลบพื้นหลังภาพสินค้าด้วย edge detection\"\"\"\r\n    import cv2\r\n    import numpy as np\r\n    \r\n    # อ่านภาพ\r\n    img = cv2.imread(image_path)\r\n    original = img.copy()\r\n    \r\n    # แปลงเป็น grayscale\r\n    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\r\n    \r\n    # Gaussian blur ลดนอยส์\r\n    blurred = cv2.GaussianBlur(gray, (5, 5), 0)\r\n    \r\n    # ตรวจจับขอบ\r\n    edges = cv2.Canny(blurred, 50, 150)\r\n    \r\n    # หา contour\r\n    contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\r\n    \r\n    if contours:\r\n        # หา contour ที่ใหญ่ที่สุด (น่าจะเป็นสินค้า)\r\n        largest_contour = max(contours, key=cv2.contourArea)\r\n        \r\n        # สร้าง mask\r\n        mask = np.zeros(gray.shape, np.uint8)\r\n        cv2.fillPoly(mask, [largest_contour], 255)\r\n        \r\n        # ใช้ mask กับภาพต้นฉบับ\r\n        result = cv2.bitwise_and(original, original, mask=mask)\r\n        \r\n        # เปลี่ยนพื้นหลังเป็นขาว\r\n        result[mask == 0] = [255, 255, 255]\r\n        \r\n        cv2.imwrite(output_path, result)\r\n        return True\r\n    \r\n    return False\r\n\r\ndef standardize_product_backgrounds(input_dir, output_dir, background_color=(255, 255, 255)):\r\n    \"\"\"ปรับพื้นหลังสินค้าทั้งหมดให้เป็นสีเดียวกัน\"\"\"\r\n    for filename in os.listdir(input_dir):\r\n        if filename.lower().endswith(('.jpg', '.jpeg', '.png')):\r\n            input_path = os.path.join(input_dir, filename)\r\n            output_path = os.path.join(output_dir, filename)\r\n            \r\n            # พยายามลบพื้นหลังอัตโนมัติ\r\n            if not remove_product_background(input_path, output_path):\r\n                # ทางเลือก: พื้นหลังขาวล้วน\r\n                img = Image.open(input_path)\r\n                if img.mode == 'RGBA':\r\n                    background = Image.new('RGB', img.size, background_color)\r\n                    background.paste(img, mask=img.split()[-1])\r\n                    background.save(output_path, 'JPEG', quality=85)\r\n                else:\r\n                    img.save(output_path)\r\n```\r\n\r\n## การปรับแต่งสำหรับแพลตฟอร์ม\r\n\r\n### การปรับแต่งสำหรับ Amazon Marketplace\r\n\r\nAmazon มีข้อกำหนดเฉพาะสำหรับภาพและใช้อัลกอริทึมของตัวเอง:\r\n\r\n```python\r\nclass AmazonImageOptimizer:\r\n    def __init__(self):\r\n        self.requirements = {\r\n            'main_image': {\r\n                'min_size': (1000, 1000),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'background': 'pure_white',\r\n                'product_coverage': 85  # เปอร์เซ็นต์ขั้นต่ำของภาพ\r\n            },\r\n            'additional_images': {\r\n                'min_size': (500, 500),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'lifestyle_allowed': True\r\n            }\r\n        }\r\n    \r\n    def optimize_for_amazon(self, image_path, output_path, image_type='main'):\r\n        \"\"\"ปรับแต่งภาพสำหรับการลงขายบน Amazon โดยเฉพาะ\"\"\"\r\n        img = Image.open(image_path)\r\n        \r\n        if image_type == 'main':\r\n            img = self.ensure_white_background(img)\r\n            img = self.ensure_minimum_size(img, (1000, 1000))\r\n        \r\n        # Amazon ต้องการ sRGB\r\n        if img.mode != 'RGB':\r\n            img = img.convert('RGB')\r\n        \r\n        # ปรับขนาดไฟล์โดยคงคุณภาพ\r\n        quality = 90 if image_type == 'main' else 85\r\n        img.save(output_path, 'JPEG', quality=quality, optimize=True)\r\n        \r\n        return self.validate_amazon_requirements(output_path, image_type)\r\n    \r\n    def ensure_white_background(self, img):\r\n        \"\"\"ตรวจสอบให้แน่ใจว่าพื้นหลังเป็นขาวล้วน\"\"\"\r\n        if img.mode == 'RGBA':\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            background.paste(img, mask=img.split()[-1])\r\n            return background\r\n        return img\r\n    \r\n    def ensure_minimum_size(self, img, min_size):\r\n        \"\"\"ตรวจสอบให้แน่ใจว่าขนาดภาพถึงขั้นต่ำ\"\"\"\r\n        if img.size[0] \u003C min_size[0] or img.size[1] \u003C min_size[1]:\r\n            img = img.resize(min_size, Image.Resampling.LANCZOS)\r\n        return img\r\n    \r\n    def validate_amazon_requirements(self, image_path, image_type):\r\n        \"\"\"ตรวจสอบว่าภาพตรงตามข้อกำหนดของ Amazon\"\"\"\r\n        img = Image.open(image_path)\r\n        requirements = self.requirements[image_type]\r\n        \r\n        validation_results = {\r\n            'size_valid': (\r\n                img.size[0] >= requirements['min_size'][0] and \r\n                img.size[1] >= requirements['min_size'][1]\r\n            ),\r\n            'format_valid': image_path.upper().endswith(tuple(requirements['formats'])),\r\n            'file_size_valid': os.path.getsize(image_path) \u003C= 10 * 1024 * 1024  # จำกัด 10MB\r\n        }\r\n        \r\n        return all(validation_results.values()), validation_results\r\n```\r\n\r\n### การปรับแต่งสำหรับร้านค้า Shopify\r\n\r\nการปรับแต่งสำหรับธีมและประสิทธิภาพของ Shopify:\r\n\r\n```javascript\r\nclass ShopifyImageOptimizer {\r\n    constructor() {\r\n        this.themeRequirements = {\r\n            'product_card': { width: 600, height: 600, quality: 80 },\r\n            'product_detail': { width: 1200, height: 1200, quality: 85 },\r\n            'product_zoom': { width: 2048, height: 2048, quality: 90 },\r\n            'collection_featured': { width: 800, height: 600, quality: 80 }\r\n        };\r\n    }\r\n    \r\n    generateShopifyImageUrls(baseImageUrl, productHandle) {\r\n        const urls = {};\r\n        \r\n        Object.entries(this.themeRequirements).forEach(([variant, specs]) => {\r\n            // สร้าง URL สำหรับแปลงภาพของ Shopify\r\n            const transformedUrl = baseImageUrl.replace('.jpg', \r\n                `_${specs.width}x${specs.height}_crop_center.jpg`);\r\n            urls[variant] = transformedUrl;\r\n        });\r\n        \r\n        return urls;\r\n    }\r\n    \r\n    generateShopifyPictureElement(productData) {\r\n        const { images, title, handle } = productData;\r\n        const mainImage = images[0];\r\n        \r\n        return `\r\n            \u003Cpicture>\r\n                \u003Csource media=\"(min-width: 1200px)\" \r\n                        srcset=\"${mainImage}_1200x1200.webp 1x, ${mainImage}_2400x2400.webp 2x\"\r\n                        type=\"image/webp\">\r\n                \u003Csource media=\"(min-width: 768px)\" \r\n                        srcset=\"${mainImage}_800x800.webp 1x, ${mainImage}_1600x1600.webp 2x\"\r\n                        type=\"image/webp\">\r\n                \u003Csource media=\"(max-width: 767px)\" \r\n                        srcset=\"${mainImage}_600x600.webp 1x, ${mainImage}_1200x1200.webp 2x\"\r\n                        type=\"image/webp\">\r\n                \u003Cimg src=\"${mainImage}_800x800.jpg\"\r\n                     srcset=\"${mainImage}_400x400.jpg 400w,\r\n                             ${mainImage}_600x600.jpg 600w,\r\n                             ${mainImage}_800x800.jpg 800w,\r\n                             ${mainImage}_1200x1200.jpg 1200w\"\r\n                     sizes=\"(max-width: 767px) 100vw, (max-width: 1023px) 50vw, 33vw\"\r\n                     alt=\"${title}\"\r\n                     loading=\"lazy\"\r\n                     data-product-handle=\"${handle}\">\r\n            \u003C/picture>\r\n        `;\r\n    }\r\n}\r\n```\r\n\r\n## กลยุทธ์การโหลดภาพขั้นสูงสำหรับอีคอมเมิร์ซ\r\n\r\n### การโหลดภาพสินค้าแบบอัจฉริยะ\r\n\r\nโหลดภาพอย่างชาญฉลาดตามพฤติกรรมผู้ใช้และความสามารถของอุปกรณ์:\r\n\r\n```javascript\r\nclass EcommerceImageLoader {\r\n    constructor() {\r\n        this.userBehavior = this.trackUserBehavior();\r\n        this.deviceCapabilities = this.analyzeDevice();\r\n        this.loadingStrategies = this.initializeStrategies();\r\n    }\r\n    \r\n    trackUserBehavior() {\r\n        return {\r\n            isReturningCustomer: localStorage.getItem('visited') === 'true',\r\n            viewingHistory: JSON.parse(localStorage.getItem('viewedProducts') || '[]'),\r\n            averageSessionTime: parseInt(localStorage.getItem('avgSessionTime') || '0'),\r\n            purchaseHistory: JSON.parse(localStorage.getItem('purchases') || '[]')\r\n        };\r\n    }\r\n    \r\n    analyzeDevice() {\r\n        const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;\r\n        \r\n        return {\r\n            connectionSpeed: connection ? connection.effectiveType : '4g',\r\n            deviceMemory: navigator.deviceMemory || 4,\r\n            isLowEndDevice: navigator.deviceMemory \u003C 2,\r\n            isMobile: window.innerWidth \u003C= 768,\r\n            isSlowConnection: connection && (connection.effectiveType === 'slow-2g' || connection.effectiveType === '2g')\r\n        };\r\n    }\r\n    \r\n    initializeStrategies() {\r\n        return {\r\n            eager: this.eagerLoadingStrategy.bind(this),\r\n            progressive: this.progressiveLoadingStrategy.bind(this),\r\n            lazy: this.lazyLoadingStrategy.bind(this),\r\n            adaptive: this.adaptiveLoadingStrategy.bind(this)\r\n        };\r\n    }\r\n    \r\n    selectOptimalStrategy(productData, context) {\r\n        const { deviceCapabilities, userBehavior } = this;\r\n        \r\n        // ลูกค้าประจำที่มีการเชื่อมต่อดี\r\n        if (userBehavior.isReturningCustomer && \r\n            userBehavior.purchaseHistory.length > 0 && \r\n            !deviceCapabilities.isSlowConnection) {\r\n            return 'eager';\r\n        }\r\n        \r\n        // อุปกรณ์สเปกต่ำหรือเน็ตช้า\r\n        if (deviceCapabilities.isLowEndDevice || deviceCapabilities.isSlowConnection) {\r\n            return 'lazy';\r\n        }\r\n        \r\n        // มือถือที่เชื่อมต่อดี\r\n        if (deviceCapabilities.isMobile && !deviceCapabilities.isSlowConnection) {\r\n            return 'progressive';\r\n        }\r\n        \r\n        // ค่าเริ่มต้น: กลยุทธ์แบบ adaptive\r\n        return 'adaptive';\r\n    }\r\n    \r\n    eagerLoadingStrategy(productImages) {\r\n        // โหลดภาพทั้งหมดทันทีเพื่อประสบการณ์ระดับพรีเมียม\r\n        productImages.forEach(img => {\r\n            const imageLoader = new Image();\r\n            imageLoader.src = img.dataset.src;\r\n            \r\n            if (img.dataset.srcset) {\r\n                imageLoader.srcset = img.dataset.srcset;\r\n            }\r\n            \r\n            imageLoader.onload = () => {\r\n                img.src = imageLoader.src;\r\n                if (img.dataset.srcset) {\r\n                    img.srcset = imageLoader.srcset;\r\n                }\r\n                img.classList.add('loaded');\r\n            };\r\n        });\r\n    }\r\n    \r\n    progressiveLoadingStrategy(productImages) {\r\n        // โหลดภาพคุณภาพต่ำก่อน แล้วตามด้วยคุณภาพสูง\r\n        productImages.forEach(img => {\r\n            // โหลด placeholder คุณภาพต่ำ\r\n            const lowQualitySrc = img.dataset.lowSrc || img.dataset.src.replace('_q85', '_q40');\r\n            const highQualitySrc = img.dataset.src;\r\n            \r\n            img.src = lowQualitySrc;\r\n            img.classList.add('loading');\r\n            \r\n            // โหลดเวอร์ชันคุณภาพสูง\r\n            const highQualityLoader = new Image();\r\n            highQualityLoader.onload = () => {\r\n                img.src = highQualitySrc;\r\n                img.classList.remove('loading');\r\n                img.classList.add('loaded');\r\n            };\r\n            highQualityLoader.src = highQualitySrc;\r\n        });\r\n    }\r\n    \r\n    lazyLoadingStrategy(productImages) {\r\n        // ใช้ Intersection Observer เพื่อโหลดแบบ Lazy\r\n        const observer = new IntersectionObserver((entries) => {\r\n            entries.forEach(entry => {\r\n                if (entry.isIntersecting) {\r\n                    this.loadImage(entry.target);\r\n                    observer.unobserve(entry.target);\r\n                }\r\n            });\r\n        }, { rootMargin: '100px' });\r\n        \r\n        productImages.forEach(img => observer.observe(img));\r\n    }\r\n    \r\n    adaptiveLoadingStrategy(productImages) {\r\n        // ปรับตามการ scroll และ interaction\r\n        let scrollTimeout;\r\n        let isScrolling = false;\r\n        \r\n        window.addEventListener('scroll', () => {\r\n            if (!isScrolling) {\r\n                isScrolling = true;\r\n                // โหลดภาพที่มองเห็นทันทีเมื่อ scroll\r\n                this.loadVisibleImages(productImages);\r\n            }\r\n            \r\n            clearTimeout(scrollTimeout);\r\n            scrollTimeout = setTimeout(() => {\r\n                isScrolling = false;\r\n            }, 150);\r\n        });\r\n        \r\n        // โหลดภาพสำคัญที่อยู่เหนือ fold ทันที\r\n        this.loadCriticalImages(productImages);\r\n        \r\n        // โหลดภาพที่เหลือแบบ Lazy\r\n        this.lazyLoadingStrategy(productImages.filter(img => !img.dataset.critical));\r\n    }\r\n    \r\n    loadCriticalImages(productImages) {\r\n        const criticalImages = productImages.filter(img => \r\n            img.dataset.critical === 'true' || \r\n            img.getBoundingClientRect().top \u003C window.innerHeight\r\n        );\r\n        \r\n        criticalImages.forEach(img => this.loadImage(img));\r\n    }\r\n    \r\n    loadVisibleImages(productImages) {\r\n        const visibleImages = productImages.filter(img => {\r\n            const rect = img.getBoundingClientRect();\r\n            return rect.top \u003C window.innerHeight && rect.bottom > 0;\r\n        });\r\n        \r\n        visibleImages.forEach(img => this.loadImage(img));\r\n    }\r\n    \r\n    loadImage(img) {\r\n        if (img.dataset.loaded) return;\r\n        \r\n        const imageLoader = new Image();\r\n        imageLoader.onload = () => {\r\n            img.src = imageLoader.src;\r\n            if (img.dataset.srcset) {\r\n                img.srcset = imageLoader.srcset;\r\n            }\r\n            img.classList.add('loaded');\r\n            img.dataset.loaded = 'true';\r\n        };\r\n        \r\n        imageLoader.src = img.dataset.src;\r\n    }\r\n}\r\n\r\n// การใช้งานสำหรับหน้าสินค้า\r\n// document.addEventListener('DOMContentLoaded', () => {\r\n//     const imageLoader = new EcommerceImageLoader();\r\n//     const productImages = document.querySelectorAll('.product-image[data-src]');\r\n//     \r\n//     if (productImages.length > 0) {\r\n//         const strategy = imageLoader.selectOptimalStrategy();\r\n//         imageLoader.loadingStrategies[strategy](productImages);\r\n//     }\r\n// });\r\n```\r\n\r\n## การปรับแต่ง zoom และ 360° view\r\n\r\n### การทำ zoom อย่างมีประสิทธิภาพ\r\n\r\nฟังก์ชัน zoom ที่ปรับแต่งสำหรับหน้ารายละเอียดสินค้า:\r\n\r\n```javascript\r\nclass ProductImageZoom {\r\n    constructor(options = {}) {\r\n        this.container = options.container;\r\n        this.zoomLevel = options.zoomLevel || 2;\r\n        this.loadingStrategy = options.loadingStrategy || 'on-demand';\r\n        this.highResImages = new Map();\r\n        \r\n        this.initializeZoom();\r\n    }\r\n    \r\n    initializeZoom() {\r\n        const zoomImages = this.container.querySelectorAll('.zoomable-image');\r\n        \r\n        zoomImages.forEach(img => {\r\n            img.addEventListener('mouseenter', this.handleMouseEnter.bind(this));\r\n            img.addEventListener('mouseleave', this.handleMouseLeave.bind(this));\r\n            img.addEventListener('mousemove', this.handleMouseMove.bind(this));\r\n        });\r\n    }\r\n    \r\n    async handleMouseEnter(event) {\r\n        const img = event.target;\r\n        const highResUrl = img.dataset.zoomSrc;\r\n        \r\n        if (!highResUrl) return;\r\n        \r\n        // โหลดภาพความละเอียดสูงเมื่อจำเป็น\r\n        if (!this.highResImages.has(highResUrl)) {\r\n            this.loadHighResImage(highResUrl);\r\n        }\r\n        \r\n        this.showZoomOverlay(img);\r\n    }\r\n    \r\n    loadHighResImage(url) {\r\n        return new Promise((resolve, reject) => {\r\n            const img = new Image();\r\n            img.onload = () => {\r\n                this.highResImages.set(url, img);\r\n                resolve(img);\r\n            };\r\n            img.onerror = reject;\r\n            img.src = url;\r\n        });\r\n    }\r\n    \r\n    showZoomOverlay(img) {\r\n        // สร้าง overlay สำหรับ zoom หากยังไม่มี\r\n        let overlay = img.parentNode.querySelector('.zoom-overlay');\r\n        if (!overlay) {\r\n            overlay = document.createElement('div');\r\n            overlay.className = 'zoom-overlay';\r\n            overlay.style.cssText = `\r\n                position: absolute;\r\n                top: 0;\r\n                left: 100%;\r\n                width: 300px;\r\n                height: 300px;\r\n                border: 1px solid #ddd;\r\n                background: white;\r\n                overflow: hidden;\r\n                z-index: 1000;\r\n                display: none;\r\n            `;\r\n            img.parentNode.appendChild(overlay);\r\n        }\r\n        \r\n        overlay.style.display = 'block';\r\n    }\r\n    \r\n    handleMouseMove(event) {\r\n        const img = event.target;\r\n        const overlay = img.parentNode.querySelector('.zoom-overlay');\r\n        const highResUrl = img.dataset.zoomSrc;\r\n        \r\n        if (!overlay || !this.highResImages.has(highResUrl)) return;\r\n        \r\n        const rect = img.getBoundingClientRect();\r\n        const x = (event.clientX - rect.left) / rect.width;\r\n        const y = (event.clientY - rect.top) / rect.height;\r\n        \r\n        const highResImg = this.highResImages.get(highResUrl);\r\n        \r\n        // อัปเดต overlay zoom\r\n        overlay.style.backgroundImage = `url(${highResUrl})`;\r\n        overlay.style.backgroundSize = `${highResImg.width}px ${highResImg.height}px`;\r\n        overlay.style.backgroundPosition = `-${x * (highResImg.width - 300)}px -${y * (highResImg.height - 300)}px`;\r\n    }\r\n    \r\n    handleMouseLeave(event) {\r\n        const img = event.target;\r\n        const overlay = img.parentNode.querySelector('.zoom-overlay');\r\n        \r\n        if (overlay) {\r\n            overlay.style.display = 'none';\r\n        }\r\n    }\r\n}\r\n\r\n// การปรับแต่ง 360° view ของสินค้า\r\nclass Product360View {\r\n    constructor(container, options = {}) {\r\n        this.container = container;\r\n        this.frameCount = options.frameCount || 36;\r\n        this.autoPlay = options.autoPlay || false;\r\n        this.frames = [];\r\n        this.currentFrame = 0;\r\n        this.isLoading = false;\r\n        \r\n        this.initialize();\r\n    }\r\n    \r\n    async initialize() {\r\n        await this.loadFrames();\r\n        this.setupControls();\r\n        this.setupInteraction();\r\n    }\r\n    \r\n    async loadFrames() {\r\n        this.isLoading = true;\r\n        const baseUrl = this.container.dataset.baseUrl;\r\n        \r\n        // โหลด frame แบบ progressive\r\n        const loadPromises = [];\r\n        \r\n        for (let i = 1; i \u003C= this.frameCount; i++) {\r\n            const frameUrl = `${baseUrl}/frame_${i.toString().padStart(3, '0')}.jpg`;\r\n            loadPromises.push(this.loadFrame(frameUrl, i - 1));\r\n        }\r\n        \r\n        // โหลด frame แรกๆ ทันที ที่เหลือโหลดเบื้องหลัง\r\n        await Promise.all(loadPromises.slice(0, 8));\r\n        \r\n        // ที่เหลือโหลดเบื้องหลัง\r\n        Promise.all(loadPromises.slice(8));\r\n        \r\n        this.isLoading = false;\r\n        this.displayFrame(0);\r\n    }\r\n    \r\n    loadFrame(url, index) {\r\n        return new Promise((resolve) => {\r\n            const img = new Image();\r\n            img.onload = () => {\r\n                this.frames[index] = img;\r\n                resolve();\r\n            };\r\n            img.onerror = () => {\r\n                // placeholder สำหรับโหลดไม่สำเร็จ\r\n                this.frames[index] = null;\r\n                resolve();\r\n            };\r\n            img.src = url;\r\n        });\r\n    }\r\n    \r\n    displayFrame(frameIndex) {\r\n        if (!this.frames[frameIndex]) return;\r\n        \r\n        const img = this.container.querySelector('.view-360-image') || \r\n                   this.createImageElement();\r\n        \r\n        img.src = this.frames[frameIndex].src;\r\n        this.currentFrame = frameIndex;\r\n    }\r\n    \r\n    createImageElement() {\r\n        const img = document.createElement('img');\r\n        img.className = 'view-360-image';\r\n        img.style.cssText = 'width: 100%; height: auto; display: block;';\r\n        this.container.appendChild(img);\r\n        return img;\r\n    }\r\n    \r\n    setupInteraction() {\r\n        let isDragging = false;\r\n        let startX = 0;\r\n        let startFrame = 0;\r\n        \r\n        this.container.addEventListener('mousedown', (e) => {\r\n            isDragging = true;\r\n            startX = e.clientX;\r\n            startFrame = this.currentFrame;\r\n            e.preventDefault();\r\n        });\r\n        \r\n        document.addEventListener('mousemove', (e) => {\r\n            if (!isDragging) return;\r\n            \r\n            const deltaX = e.clientX - startX;\r\n            const sensitivity = 2; // พิกเซลต่อเฟรม\r\n            const frameChange = Math.floor(deltaX / sensitivity);\r\n            \r\n            let newFrame = (startFrame + frameChange) % this.frameCount;\r\n            if (newFrame \u003C 0) newFrame += this.frameCount;\r\n            \r\n            this.displayFrame(newFrame);\r\n        });\r\n        \r\n        document.addEventListener('mouseup', () => {\r\n            isDragging = false;\r\n        });\r\n    }\r\n}\r\n```\r\n\r\n## การติดตามประสิทธิภาพและการวิเคราะห์\r\n\r\n### การติดตามประสิทธิภาพของภาพสำหรับอีคอมเมิร์ซ\r\n\r\nการติดตามประสิทธิภาพของภาพสำหรับอีคอมเมิร์ซแบบครบวงจร:\r\n\r\n```javascript\r\nclass EcommerceImageAnalytics {\r\n    constructor() {\r\n        this.metrics = {\r\n            imageLoadTimes: [],\r\n            conversionTracking: new Map(),\r\n            userInteractions: [],\r\n            performanceImpact: []\r\n        };\r\n        \r\n        this.startMonitoring();\r\n    }\r\n    \r\n    startMonitoring() {\r\n        // ติดตามประสิทธิภาพการโหลดภาพ\r\n        new PerformanceObserver((list) => {\r\n            const entries = list.getEntries();\r\n            entries.forEach(entry => {\r\n                if (this.isProductImage(entry.name)) {\r\n                    this.trackImagePerformance(entry);\r\n                }\r\n            });\r\n        }).observe({ entryTypes: ['resource'] });\r\n        \r\n        // ติดตาม interaction ของผู้ใช้กับภาพ\r\n        this.trackImageInteractions();\r\n        \r\n        // ติดตามความสัมพันธ์กับ conversion\r\n        this.trackConversionCorrelation();\r\n    }\r\n    \r\n    isProductImage(url) {\r\n        return url.includes('/products/') || \r\n               url.includes('product-images') ||\r\n               url.match(/\\/(hero|gallery|thumbnail|zoom)\\//);\r\n    }\r\n    \r\n    trackImagePerformance(entry) {\r\n        const imageData = {\r\n            url: entry.name,\r\n            loadTime: entry.responseEnd - entry.requestStart,\r\n            fileSize: entry.transferSize,\r\n            renderTime: entry.responseEnd,\r\n            imageType: this.categorizeImage(entry.name),\r\n            timestamp: Date.now()\r\n        };\r\n        \r\n        this.metrics.imageLoadTimes.push(imageData);\r\n        \r\n        // ส่งไป analytics ถ้าโหลดช้าเกินไป\r\n        if (imageData.loadTime > 2000) {\r\n            this.reportSlowImage(imageData);\r\n        }\r\n    }\r\n    \r\n    categorizeImage(url) {\r\n        if (url.includes('hero')) return 'hero';\r\n        if (url.includes('thumbnail')) return 'thumbnail';\r\n        if (url.includes('gallery')) return 'gallery';\r\n        if (url.includes('zoom')) return 'zoom';\r\n        return 'other';\r\n    }\r\n    \r\n    trackImageInteractions() {\r\n        // ติดตามการใช้ zoom\r\n        document.addEventListener('mouseenter', (e) => {\r\n            if (e.target.classList.contains('zoomable-image')) {\r\n                this.recordInteraction('zoom_hover', e.target);\r\n            }\r\n        });\r\n        \r\n        // ติดตามการคลิกแกลเลอรี\r\n        document.addEventListener('click', (e) => {\r\n            if (e.target.classList.contains('gallery-thumbnail')) {\r\n                this.recordInteraction('gallery_click', e.target);\r\n            }\r\n        });\r\n        \r\n        // ติดตาม interaction กับ 360° view\r\n        document.addEventListener('mousedown', (e) => {\r\n            if (e.target.closest('.view-360')) {\r\n                this.recordInteraction('360_interact', e.target);\r\n            }\r\n        });\r\n    }\r\n    \r\n    recordInteraction(type, element) {\r\n        const interaction = {\r\n            type: type,\r\n            productId: element.dataset.productId || this.extractProductId(element),\r\n            timestamp: Date.now(),\r\n            elementSrc: element.src || element.dataset.src,\r\n            loadTime: this.getImageLoadTime(element.src)\r\n        };\r\n        \r\n        this.metrics.userInteractions.push(interaction);\r\n    }\r\n    \r\n    trackConversionCorrelation() {\r\n        // ติดตามการเพิ่มลงตะกร้าหลัง interaction กับภาพ\r\n        document.addEventListener('click', (e) => {\r\n            if (e.target.matches('.add-to-cart, .buy-now')) {\r\n                const productId = this.extractProductId(e.target);\r\n                this.correlateWithImageInteractions(productId);\r\n            }\r\n        });\r\n    }\r\n    \r\n    correlateWithImageInteractions(productId) {\r\n        const recentInteractions = this.metrics.userInteractions\r\n            .filter(interaction => \r\n                interaction.productId === productId &&\r\n                Date.now() - interaction.timestamp \u003C 300000 // 5 นาทีล่าสุด\r\n            );\r\n        \r\n        if (recentInteractions.length > 0) {\r\n            this.metrics.conversionTracking.set(productId, {\r\n                interactions: recentInteractions,\r\n                conversionTime: Date.now()\r\n            });\r\n        }\r\n    }\r\n    \r\n    generatePerformanceReport() {\r\n        const avgLoadTime = this.calculateAverageLoadTime();\r\n        const slowImages = this.identifySlowImages();\r\n        const interactionCorrelation = this.analyzeInteractionCorrelation();\r\n        \r\n        return {\r\n            averageImageLoadTime: avgLoadTime,\r\n            slowestImages: slowImages,\r\n            interactionToConversionRate: interactionCorrelation,\r\n            recommendations: this.generateRecommendations(avgLoadTime, slowImages)\r\n        };\r\n    }\r\n    \r\n    calculateAverageLoadTime() {\r\n        const loadTimes = this.metrics.imageLoadTimes.map(img => img.loadTime);\r\n        return loadTimes.reduce((sum, time) => sum + time, 0) / loadTimes.length;\r\n    }\r\n    \r\n    identifySlowImages() {\r\n        return this.metrics.imageLoadTimes\r\n            .filter(img => img.loadTime > 2000)\r\n            .sort((a, b) => b.loadTime - a.loadTime)\r\n            .slice(0, 10);\r\n    }\r\n    \r\n    analyzeInteractionCorrelation() {\r\n        const totalInteractions = this.metrics.userInteractions.length;\r\n        const conversionsWithInteractions = this.metrics.conversionTracking.size;\r\n        \r\n        return totalInteractions > 0 ? \r\n            (conversionsWithInteractions / totalInteractions) * 100 : 0;\r\n    }\r\n    \r\n    generateRecommendations(avgLoadTime, slowImages) {\r\n        const recommendations = [];\r\n        \r\n        if (avgLoadTime > 1500) {\r\n            recommendations.push('พิจารณาบีบอัดภาพให้มากขึ้น');\r\n            recommendations.push('ใช้ฟอร์แมต WebP เพื่อการบีบอัดที่ดีกว่า');\r\n        }\r\n        \r\n        if (slowImages.length > 0) {\r\n            recommendations.push('ปรับแต่งภาพสินค้าที่โหลดช้าที่สุด');\r\n            recommendations.push('พิจารณา lazy load สำหรับภาพแกลเลอรี');\r\n        }\r\n        \r\n        const heroImages = slowImages.filter(img => img.imageType === 'hero');\r\n        if (heroImages.length > 0) {\r\n            recommendations.push('ให้ความสำคัญกับการปรับแต่งภาพหลักเพื่อสร้างความประทับใจแรก');\r\n        }\r\n        \r\n        return recommendations;\r\n    }\r\n    \r\n    extractProductId(element) {\r\n        // ลองวิธีต่างๆ ในการดึง productId\r\n        return element.dataset.productId ||\r\n               element.closest('[data-product-id]')?.dataset.productId ||\r\n               window.location.pathname.match(/\\/products\\/([^\\/]+)/)?.[1] ||\r\n               'unknown';\r\n    }\r\n    \r\n    getImageLoadTime(src) {\r\n        const imageMetric = this.metrics.imageLoadTimes.find(img => img.url.includes(src));\r\n        return imageMetric ? imageMetric.loadTime : null;\r\n    }\r\n    \r\n    reportSlowImage(imageData) {\r\n        // ส่งไป analytics\r\n        if (typeof gtag !== 'undefined') {\r\n            gtag('event', 'slow_image_load', {\r\n                'url': imageData.url,\r\n                'load_time': imageData.loadTime,\r\n                'file_size': imageData.fileSize,\r\n                'image_type': imageData.imageType\r\n            });\r\n        }\r\n    }\r\n}\r\n\r\n// เริ่มต้น analytics\r\nconst imageAnalytics = new EcommerceImageAnalytics();\r\n\r\n// สร้างรายงานเป็นระยะ\r\nsetInterval(() => {\r\n    const report = imageAnalytics.generatePerformanceReport();\r\n    console.log('รายงานประสิทธิภาพภาพสำหรับอีคอมเมิร์ซ:', report);\r\n}, 300000); // ทุก 5 นาที\r\n```\r\n\r\n## สรุป\r\n\r\nการปรับแต่งภาพสินค้าอีคอมเมิร์ซเป็นปัจจัยสำคัญต่อความสำเร็จของร้านค้าออนไลน์ มีผลโดยตรงต่อ conversion, ประสบการณ์ผู้ใช้ และอันดับการค้นหา กุญแจสำคัญคือการหาสมดุลที่เหมาะสมระหว่างคุณภาพภาพกับประสิทธิภาพ โดยคำนึงถึงลักษณะเฉพาะของแต่ละหมวดหมู่สินค้าและแพลตฟอร์ม\r\n\r\nการปรับแต่งภาพสำหรับอีคอมเมิร์ซที่ประสบความสำเร็จต้องการ:\r\n\r\n1. **แนวทางเฉพาะตามหมวดหมู่**: สินค้าแต่ละประเภทต้องการกลยุทธ์การปรับแต่งที่ต่างกัน\r\n2. **สอดคล้องกับแพลตฟอร์ม**: เข้าใจและปฏิบัติตามข้อกำหนดของ marketplace\r\n3. **ติดตามประสิทธิภาพ**: ตรวจสอบประสิทธิภาพของภาพและพฤติกรรมผู้ใช้อย่างต่อเนื่อง\r\n4. **กลยุทธ์การโหลดขั้นสูง**: โหลดภาพอย่างชาญฉลาดตามบริบทและความสามารถของอุปกรณ์\r\n5. **รักษาคุณภาพ**: คงความน่าสนใจทางสายตาแม้จะลดขนาดไฟล์\r\n\r\nเมื่ออีคอมเมิร์ซพัฒนาไปพร้อมเทคโนโลยีใหม่ เช่น AR, อัลกอริทึมการบีบอัดที่มีประสิทธิภาพมากขึ้น และประสบการณ์มือถือที่ดีขึ้น วิธีการปรับแต่งสมัยใหม่และการเน้น conversion จะยังคงเป็นกุญแจสำคัญในการแข่งขัน\r\n\r\nอนาคตของการปรับแต่งภาพสำหรับอีคอมเมิร์ซจะอยู่ที่ระบบ AI ที่สามารถปรับแต่งภาพโดยอัตโนมัติตามพฤติกรรมผู้ใช้ ความสามารถของอุปกรณ์ และรูปแบบ conversion โดยยังคงคุณภาพภาพที่จำเป็นต่อการเพิ่มยอดขายและความพึงพอใจของลูกค้า\r\n","# Nén Ảnh Sản Phẩm Thương Mại Điện Tử: Tối Ưu Hóa Để Tăng Doanh Số\r\n\r\nThành công trong thương mại điện tử phụ thuộc nhiều vào chất lượng hình ảnh sản phẩm, với các nghiên cứu cho thấy 67% người tiêu dùng coi chất lượng hình ảnh là \"rất quan trọng\" khi mua hàng trực tuyến. Tuy nhiên, các tệp hình ảnh lớn có thể ảnh hưởng đáng kể đến thời gian tải trang, tỷ lệ chuyển đổi và trải nghiệm người dùng di động. Hướng dẫn toàn diện này trình bày các kỹ thuật nâng cao để tối ưu hóa hình ảnh sản phẩm thương mại điện tử trong khi vẫn duy trì chất lượng hình ảnh cần thiết để thúc đẩy doanh số.\r\n\r\n## Tại Sao Tối Ưu Hóa Ảnh Thương Mại Điện Tử Lại Quan Trọng\r\n\r\n### Ảnh Hưởng Đến Tỷ Lệ Chuyển Đổi\r\n\r\nTối ưu hóa hình ảnh sản phẩm ảnh hưởng trực tiếp đến các chỉ số kinh doanh:\r\n- **Tỷ lệ chuyển đổi**: Chậm 1 giây khi tải trang làm giảm 7% chuyển đổi\r\n- **Tỷ lệ thoát**: 40% người dùng rời bỏ trang nếu mất hơn 3 giây để tải\r\n- **Thương mại di động**: 73% lưu lượng thương mại điện tử đến từ thiết bị di động\r\n- **Xếp hạng tìm kiếm**: Google tính tốc độ trang vào xếp hạng tìm kiếm\r\n- **Sự hài lòng của khách hàng**: Hình ảnh chất lượng cao tăng sự tự tin khi mua hàng\r\n\r\n### Yêu Cầu Đặc Thù Cho Ảnh Thương Mại Điện Tử\r\n\r\nHình ảnh sản phẩm có những thách thức tối ưu hóa riêng:\r\n- **Nhiều góc nhìn sản phẩm**: Ảnh chính, ảnh thu nhỏ, ảnh zoom, xoay 360°\r\n- **Độ chính xác màu sắc**: Quan trọng với thời trang, mỹ phẩm, trang trí nhà cửa\r\n- **Bảo toàn chi tiết**: Khách hàng cần thấy rõ kết cấu, chất liệu, độ tinh xảo\r\n- **Hiệu suất tải**: Cân bằng giữa chất lượng và tốc độ\r\n- **Tương thích đa thiết bị**: Trải nghiệm nhất quán trên mọi thiết bị\r\n\r\n## Tìm Hiểu Các Loại Ảnh Thương Mại Điện Tử\r\n\r\n### Danh Mục Ảnh Sản Phẩm\r\n\r\nCác loại ảnh khác nhau cần cách tối ưu hóa khác nhau:\r\n\r\n```javascript\r\nconst ecommerceImageTypes = {\r\n    hero: {\r\n        purpose: 'Trưng bày sản phẩm chính',\r\n        requirements: 'Chất lượng cao, tải nhanh',\r\n        sizes: ['1200x1200', '800x800', '600x600'],\r\n        quality: { jpeg: 85, webp: 80 }\r\n    },\r\n    thumbnail: {\r\n        purpose: 'Hiển thị lưới sản phẩm',\r\n        requirements: 'Kích thước tệp nhỏ, dễ nhận biết',\r\n        sizes: ['300x300', '200x200', '150x150'],\r\n        quality: { jpeg: 75, webp: 70 }\r\n    },\r\n    zoom: {\r\n        purpose: 'Xem chi tiết sản phẩm',\r\n        requirements: 'Bảo toàn chi tiết tối đa',\r\n        sizes: ['2000x2000', '1600x1600'],\r\n        quality: { jpeg: 90, webp: 85 }\r\n    },\r\n    gallery: {\r\n        purpose: 'Nhiều góc chụp sản phẩm',\r\n        requirements: 'Chất lượng đồng nhất, tải lười',\r\n        sizes: ['800x800', '600x600'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    },\r\n    lifestyle: {\r\n        purpose: 'Sản phẩm trong bối cảnh sử dụng',\r\n        requirements: 'Tối ưu hóa cho cảm xúc/bối cảnh',\r\n        sizes: ['1200x800', '800x533'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    }\r\n};\r\n```\r\n\r\n### Chiến Lược Tối Ưu Theo Danh Mục Sản Phẩm\r\n\r\nCác danh mục sản phẩm khác nhau có yêu cầu hình ảnh riêng:\r\n\r\n```python\r\ndef get_category_optimization_settings(product_category):\r\n    \"\"\"Lấy cài đặt tối ưu hóa cho từng danh mục sản phẩm\"\"\"\r\n    settings = {\r\n        'fashion': {\r\n            'priority': ['color_accuracy', 'texture_detail'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 90},\r\n            'critical_views': ['front', 'back', 'detail']\r\n        },\r\n        'electronics': {\r\n            'priority': ['detail_preservation', 'fast_loading'],\r\n            'format_preference': 'webp_or_avif',\r\n            'quality_range': {'min': 75, 'max': 85},\r\n            'critical_views': ['main', 'interfaces', 'size_comparison']\r\n        },\r\n        'home_decor': {\r\n            'priority': ['color_accuracy', 'lifestyle_context'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 88},\r\n            'critical_views': ['styled', 'closeup', 'dimensions']\r\n        },\r\n        'jewelry': {\r\n            'priority': ['maximum_detail', 'color_accuracy'],\r\n            'format_preference': 'png_for_detailed_webp_for_hero',\r\n            'quality_range': {'min': 85, 'max': 95},\r\n            'critical_views': ['macro', '360_spin', 'lifestyle']\r\n        },\r\n        'books': {\r\n            'priority': ['fast_loading', 'text_readability'],\r\n            'format_preference': 'webp_aggressive_compression',\r\n            'quality_range': {'min': 70, 'max': 80},\r\n            'critical_views': ['cover', 'back', 'spine']\r\n        }\r\n    }\r\n    return settings.get(product_category, settings['electronics'])\r\n```\r\n\r\n## Xử Lý Ảnh Sản Phẩm Nâng Cao\r\n\r\n### Quy Trình Tự Động Hóa Xử Lý Ảnh Sản Phẩm\r\n\r\nHệ thống xử lý tự động toàn diện:\r\n\r\n```python\r\nimport os\r\nfrom PIL import Image, ImageEnhance, ImageFilter\r\nimport numpy as np\r\n\r\nclass EcommerceImageProcessor:\r\n    def __init__(self, config=None):\r\n        self.config = config or self.get_default_config()\r\n        self.supported_formats = ['jpeg', 'webp', 'avif', 'png']\r\n        \r\n    def get_default_config(self):\r\n        return {\r\n            'background_removal': True,\r\n            'auto_crop': True,\r\n            'color_enhancement': True,\r\n            'noise_reduction': True,\r\n            'watermark': False,\r\n            'quality_thresholds': {\r\n                'hero': 85,\r\n                'gallery': 80,\r\n                'thumbnail': 75,\r\n                'zoom': 90\r\n            }\r\n        }\r\n    \r\n    def process_product_image(self, input_path, output_dir, product_id):\r\n        \"\"\"Xử lý một ảnh sản phẩm thành tất cả các biến thể cần thiết\"\"\"\r\n        img = Image.open(input_path)\r\n        \r\n        # Tiền xử lý cơ bản\r\n        processed_img = self.preprocess_image(img)\r\n        \r\n        # Tạo tất cả kích thước và định dạng cần thiết\r\n        variants = self.generate_image_variants(processed_img, product_id)\r\n        \r\n        # Lưu các phiên bản tối ưu\r\n        saved_files = self.save_variants(variants, output_dir)\r\n        \r\n        return saved_files\r\n    \r\n    def preprocess_image(self, img):\r\n        \"\"\"Áp dụng tiền xử lý cơ bản cho ảnh sản phẩm\"\"\"\r\n        # Chuyển sang RGB nếu cần thiết\r\n        if img.mode in ('RGBA', 'LA', 'P'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            if img.mode == 'RGBA':\r\n                background.paste(img, mask=img.split()[-1])\r\n            else:\r\n                background.paste(img)\r\n            img = background\r\n        \r\n        # Tự động cắt để loại bỏ khoảng trắng thừa\r\n        if self.config['auto_crop']:\r\n            img = self.smart_crop(img)\r\n        \r\n        # Nâng cao chất lượng ảnh\r\n        if self.config['color_enhancement']:\r\n            img = self.enhance_product_image(img)\r\n        \r\n        # Giảm nhiễu\r\n        if self.config['noise_reduction']:\r\n            img = img.filter(ImageFilter.SMOOTH_MORE)\r\n        \r\n        return img\r\n    \r\n    def smart_crop(self, img):\r\n        \"\"\"Cắt thông minh để loại bỏ nền thừa\"\"\"\r\n        # Chuyển sang mảng numpy để phân tích\r\n        img_array = np.array(img)\r\n        \r\n        # Tìm bounding box của các pixel không phải màu trắng\r\n        mask = np.any(img_array \u003C 240, axis=2)  # Không phải trắng tinh\r\n        coords = np.argwhere(mask)\r\n        \r\n        if len(coords) == 0:\r\n            return img  # Không cần cắt\r\n        \r\n        # Lấy bounding box\r\n        y0, x0 = coords.min(axis=0)\r\n        y1, x1 = coords.max(axis=0)\r\n        \r\n        # Thêm padding\r\n        padding = 20\r\n        y0 = max(0, y0 - padding)\r\n        x0 = max(0, x0 - padding)\r\n        y1 = min(img.height, y1 + padding)\r\n        x1 = min(img.width, x1 + padding)\r\n        \r\n        return img.crop((x0, y0, x1, y1))\r\n    \r\n    def enhance_product_image(self, img):\r\n        \"\"\"Nâng cao ảnh sản phẩm cho hiển thị thương mại điện tử\"\"\"\r\n        # Tăng nhẹ độ sáng\r\n        brightness_enhancer = ImageEnhance.Brightness(img)\r\n        img = brightness_enhancer.enhance(1.05)\r\n        \r\n        # Tăng độ tương phản\r\n        contrast_enhancer = ImageEnhance.Contrast(img)\r\n        img = contrast_enhancer.enhance(1.1)\r\n        \r\n        # Tăng độ bão hòa màu\r\n        color_enhancer = ImageEnhance.Color(img)\r\n        img = color_enhancer.enhance(1.05)\r\n        \r\n        # Tăng độ sắc nét\r\n        sharpness_enhancer = ImageEnhance.Sharpness(img)\r\n        img = sharpness_enhancer.enhance(1.1)\r\n        \r\n        return img\r\n    \r\n    def generate_image_variants(self, img, product_id):\r\n        \"\"\"Tạo tất cả các biến thể ảnh cần thiết\"\"\"\r\n        variants = {}\r\n        \r\n        # Định nghĩa các kích thước tiêu chuẩn cho thương mại điện tử\r\n        sizes = {\r\n            'hero': (1200, 1200),\r\n            'gallery': (800, 800),\r\n            'thumbnail': (300, 300),\r\n            'zoom': (2000, 2000),\r\n            'mobile_hero': (600, 600),\r\n            'mobile_thumb': (150, 150)\r\n        }\r\n        \r\n        for variant_name, size in sizes.items():\r\n            # Thay đổi kích thước với nội suy chất lượng cao\r\n            resized = img.resize(size, Image.Resampling.LANCZOS)\r\n            variants[variant_name] = resized\r\n        \r\n        return variants\r\n    \r\n    def save_variants(self, variants, output_dir):\r\n        \"\"\"Lưu tất cả các biến thể ở định dạng tối ưu\"\"\"\r\n        saved_files = []\r\n        \r\n        for variant_name, img in variants.items():\r\n            base_path = os.path.join(output_dir, variant_name)\r\n            img.save(f\"{base_path}.{self.config['format_preference']}\", optimize=True, quality=self.config['quality_thresholds'][variant_name])\r\n            saved_files.append(f\"{base_path}.{self.config['format_preference']}\")\r\n        \r\n        return saved_files\r\n","# Kompresi Gambar Produk E-commerce: Optimasi yang Didorong Penjualan\r\n\r\nKesuksesan e-commerce sangat bergantung pada kualitas gambar produk, dengan studi menunjukkan bahwa 67% konsumen menganggap kualitas gambar \"sangat penting\" saat melakukan pembelian online. Namun, file gambar yang besar dapat secara signifikan mempengaruhi waktu muat halaman, tingkat konversi, dan pengalaman pengguna mobile. Panduan komprehensif ini mencakup teknik-teknik canggih untuk mengoptimalkan gambar produk e-commerce sambil mempertahankan kualitas visual yang diperlukan untuk mendorong penjualan.\r\n\r\n## Mengapa Optimasi Gambar E-commerce Penting\r\n\r\n### Dampak pada Tingkat Konversi\r\n\r\nOptimasi gambar produk secara langsung mempengaruhi metrik bisnis:\r\n- **Tingkat konversi**: Keterlambatan 1 detik dalam waktu muat halaman mengurangi konversi sebesar 7%\r\n- **Tingkat bounce**: 40% pengguna meninggalkan situs yang membutuhkan lebih dari 3 detik untuk dimuat\r\n- **Mobile commerce**: 73% lalu lintas e-commerce berasal dari perangkat mobile\r\n- **Peringkat pencarian**: Google mempertimbangkan kecepatan halaman dalam peringkat pencarian\r\n- **Kepuasan pelanggan**: Gambar berkualitas tinggi meningkatkan kepercayaan pembelian\r\n\r\n### Persyaratan Khusus E-commerce\r\n\r\nGambar produk memiliki tantangan optimasi yang unik:\r\n- **Beberapa tampilan produk**: Gambar utama, thumbnail, tampilan zoom, rotasi 360°\r\n- **Akurasi warna**: Kritis untuk fashion, kosmetik, dan dekorasi rumah\r\n- **Preservasi detail**: Pelanggan perlu melihat tekstur, bahan, dan keahlian\r\n- **Performa loading**: Keseimbangan antara kualitas dan kecepatan\r\n- **Kompatibilitas lintas perangkat**: Pengalaman konsisten di semua perangkat\r\n\r\n## Memahami Jenis Gambar E-commerce\r\n\r\n### Kategori Gambar Produk\r\n\r\nJenis gambar yang berbeda memerlukan pendekatan optimasi yang berbeda:\r\n\r\n```javascript\r\nconst ecommerceImageTypes = {\r\n    hero: {\r\n        purpose: 'Showcase produk utama',\r\n        requirements: 'Kualitas tinggi, loading cepat',\r\n        sizes: ['1200x1200', '800x800', '600x600'],\r\n        quality: { jpeg: 85, webp: 80 }\r\n    },\r\n    thumbnail: {\r\n        purpose: 'Tampilan grid produk',\r\n        requirements: 'Ukuran file kecil, dapat dikenali',\r\n        sizes: ['300x300', '200x200', '150x150'],\r\n        quality: { jpeg: 75, webp: 70 }\r\n    },\r\n    zoom: {\r\n        purpose: 'Inspeksi produk detail',\r\n        requirements: 'Preservasi detail maksimum',\r\n        sizes: ['2000x2000', '1600x1600'],\r\n        quality: { jpeg: 90, webp: 85 }\r\n    },\r\n    gallery: {\r\n        purpose: 'Beberapa sudut produk',\r\n        requirements: 'Kualitas konsisten, lazy loading',\r\n        sizes: ['800x800', '600x600'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    },\r\n    lifestyle: {\r\n        purpose: 'Produk dalam penggunaan/konteks',\r\n        requirements: 'Dioptimalkan untuk emosi/konteks',\r\n        sizes: ['1200x800', '800x533'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    }\r\n};\r\n```\r\n\r\n### Strategi Optimasi berdasarkan Kategori Produk\r\n\r\nKategori produk yang berbeda memiliki persyaratan gambar yang spesifik:\r\n\r\n```python\r\ndef get_category_optimization_settings(product_category):\r\n    \"\"\"Dapatkan pengaturan optimasi untuk kategori produk yang berbeda\"\"\"\r\n    settings = {\r\n        'fashion': {\r\n            'priority': ['color_accuracy', 'texture_detail'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 90},\r\n            'critical_views': ['front', 'back', 'detail']\r\n        },\r\n        'electronics': {\r\n            'priority': ['detail_preservation', 'fast_loading'],\r\n            'format_preference': 'webp_or_avif',\r\n            'quality_range': {'min': 75, 'max': 85},\r\n            'critical_views': ['main', 'interfaces', 'size_comparison']\r\n        },\r\n        'home_decor': {\r\n            'priority': ['color_accuracy', 'lifestyle_context'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 88},\r\n            'critical_views': ['styled', 'closeup', 'dimensions']\r\n        },\r\n        'jewelry': {\r\n            'priority': ['maximum_detail', 'color_accuracy'],\r\n            'format_preference': 'png_for_detailed_webp_for_hero',\r\n            'quality_range': {'min': 85, 'max': 95},\r\n            'critical_views': ['macro', '360_spin', 'lifestyle']\r\n        },\r\n        'books': {\r\n            'priority': ['fast_loading', 'text_readability'],\r\n            'format_preference': 'webp_aggressive_compression',\r\n            'quality_range': {'min': 70, 'max': 80},\r\n            'critical_views': ['cover', 'back', 'spine']\r\n        }\r\n    }\r\n    return settings.get(product_category, settings['electronics'])\r\n```\r\n\r\n## Pemrosesan Gambar Produk Lanjutan\r\n\r\n### Pipeline Gambar Produk Otomatis\r\n\r\nSistem pemrosesan otomatis yang komprehensif:\r\n\r\n```python\r\nimport os\r\nfrom PIL import Image, ImageEnhance, ImageFilter\r\nimport numpy as np\r\n\r\nclass EcommerceImageProcessor:\r\n    def __init__(self, config=None):\r\n        self.config = config or self.get_default_config()\r\n        self.supported_formats = ['jpeg', 'webp', 'avif', 'png']\r\n        \r\n    def get_default_config(self):\r\n        return {\r\n            'background_removal': True,\r\n            'auto_crop': True,\r\n            'color_enhancement': True,\r\n            'noise_reduction': True,\r\n            'watermark': False,\r\n            'quality_thresholds': {\r\n                'hero': 85,\r\n                'gallery': 80,\r\n                'thumbnail': 75,\r\n                'zoom': 90\r\n            }\r\n        }\r\n    \r\n    def process_product_image(self, input_path, output_dir, product_id):\r\n        \"\"\"Proses satu gambar produk menjadi semua varian yang diperlukan\"\"\"\r\n        img = Image.open(input_path)\r\n        \r\n        # Preprocessing dasar\r\n        processed_img = self.preprocess_image(img)\r\n        \r\n        # Generate semua ukuran dan format yang diperlukan\r\n        variants = self.generate_image_variants(processed_img, product_id)\r\n        \r\n        # Simpan versi yang dioptimalkan\r\n        saved_files = self.save_variants(variants, output_dir)\r\n        \r\n        return saved_files\r\n    \r\n    def preprocess_image(self, img):\r\n        \"\"\"Terapkan preprocessing dasar pada gambar produk\"\"\"\r\n        # Konversi ke RGB jika perlu\r\n        if img.mode in ('RGBA', 'LA', 'P'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            if img.mode == 'RGBA':\r\n                background.paste(img, mask=img.split()[-1])\r\n            else:\r\n                background.paste(img)\r\n            img = background\r\n        \r\n        # Auto-crop untuk menghilangkan whitespace berlebih\r\n        if self.config['auto_crop']:\r\n            img = self.smart_crop(img)\r\n        \r\n        # Tingkatkan kualitas gambar\r\n        if self.config['color_enhancement']:\r\n            img = self.enhance_product_image(img)\r\n        \r\n        # Kurangi noise\r\n        if self.config['noise_reduction']:\r\n            img = img.filter(ImageFilter.SMOOTH_MORE)\r\n        \r\n        return img\r\n    \r\n    def smart_crop(self, img):\r\n        \"\"\"Crop gambar produk secara cerdas untuk menghilangkan background berlebih\"\"\"\r\n        # Konversi ke numpy array untuk analisis\r\n        img_array = np.array(img)\r\n        \r\n        # Temukan bounding box dari piksel non-putih\r\n        mask = np.any(img_array \u003C 240, axis=2)  # Bukan putih murni\r\n        coords = np.argwhere(mask)\r\n        \r\n        if len(coords) == 0:\r\n            return img  # Tidak perlu cropping\r\n        \r\n        # Dapatkan bounding box\r\n        y0, x0 = coords.min(axis=0)\r\n        y1, x1 = coords.max(axis=0)\r\n        \r\n        # Tambahkan padding\r\n        padding = 20\r\n        y0 = max(0, y0 - padding)\r\n        x0 = max(0, x0 - padding)\r\n        y1 = min(img.height, y1 + padding)\r\n        x1 = min(img.width, x1 + padding)\r\n        \r\n        return img.crop((x0, y0, x1, y1))\r\n    \r\n    def enhance_product_image(self, img):\r\n        \"\"\"Tingkatkan kualitas gambar produk\"\"\"\r\n        # Tingkatkan kontras\r\n        enhancer = ImageEnhance.Contrast(img)\r\n        img = enhancer.enhance(1.1)\r\n        \r\n        # Fine-tune saturasi warna\r\n        enhancer = ImageEnhance.Color(img)\r\n        img = enhancer.enhance(1.05)\r\n        \r\n        # Tingkatkan ketajaman\r\n        enhancer = ImageEnhance.Sharpness(img)\r\n        img = enhancer.enhance(1.1)\r\n        \r\n        return img\r\n    \r\n    def generate_image_variants(self, img, product_id):\r\n        \"\"\"Generate varian gambar dalam berbagai ukuran dan format\"\"\"\r\n        variants = {}\r\n        \r\n        # Definisikan ukuran standar\r\n        sizes = {\r\n            'hero': [(1200, 1200), (800, 800), (600, 600)],\r\n            'thumbnail': [(300, 300), (200, 200), (150, 150)],\r\n            'zoom': [(2000, 2000), (1600, 1600)],\r\n            'gallery': [(800, 800), (600, 600)]\r\n        }\r\n        \r\n        for variant_type, size_list in sizes.items():\r\n            variants[variant_type] = {}\r\n            for size in size_list:\r\n                # Resize gambar dengan kualitas yang tepat\r\n                resized_img = self.resize_with_quality(img, size)\r\n                variants[variant_type][f\"{size[0]}x{size[1]}\"] = resized_img\r\n        \r\n        return variants\r\n    \r\n    def resize_with_quality(self, img, target_size):\r\n        \"\"\"Resize gambar dengan kualitas tinggi\"\"\"\r\n        # Pertahankan aspect ratio\r\n        img.thumbnail(target_size, Image.Resampling.LANCZOS)\r\n        \r\n        # Buat gambar baru dengan background putih jika perlu\r\n        if img.size != target_size:\r\n            new_img = Image.new('RGB', target_size, (255, 255, 255))\r\n            # Center gambar\r\n            paste_x = (target_size[0] - img.size[0]) // 2\r\n            paste_y = (target_size[1] - img.size[1]) // 2\r\n            new_img.paste(img, (paste_x, paste_y))\r\n            return new_img\r\n        \r\n        return img\r\n    \r\n    def save_variants(self, variants, output_dir):\r\n        \"\"\"Simpan varian gambar dalam format yang dioptimalkan\"\"\"\r\n        saved_files = []\r\n        \r\n        for variant_type, sizes in variants.items():\r\n            variant_dir = os.path.join(output_dir, variant_type)\r\n            os.makedirs(variant_dir, exist_ok=True)\r\n            \r\n            for size_name, img in sizes.items():\r\n                # Simpan JPEG\r\n                jpeg_path = os.path.join(variant_dir, f\"{size_name}.jpg\")\r\n                quality = self.config['quality_thresholds'].get(variant_type, 80)\r\n                img.save(jpeg_path, 'JPEG', quality=quality, optimize=True)\r\n                saved_files.append(jpeg_path)\r\n                \r\n                # Simpan WebP\r\n                webp_path = os.path.join(variant_dir, f\"{size_name}.webp\")\r\n                webp_quality = max(quality - 5, 70)  # WebP biasanya kompresi lebih baik\r\n                img.save(webp_path, 'WebP', quality=webp_quality, optimize=True)\r\n                saved_files.append(webp_path)\r\n        \r\n        return saved_files\r\n```\r\n\r\n## Optimasi Amazon Marketplace\r\n\r\n### Persyaratan Gambar Amazon\r\n\r\nPersyaratan optimasi gambar khusus Amazon:\r\n\r\n```python\r\nclass AmazonImageOptimizer:\r\n    def __init__(self):\r\n        self.amazon_requirements = {\r\n            'main_image': {\r\n                'min_size': (1000, 1000),\r\n                'max_size': (10000, 10000),\r\n                'background': 'pure_white',\r\n                'format': ['JPEG', 'PNG', 'GIF'],\r\n                'quality_min': 85\r\n            },\r\n            'additional_images': {\r\n                'min_size': (500, 500),\r\n                'recommended_size': (1600, 1600),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'max_count': 8\r\n            },\r\n            'zoom_functionality': {\r\n                'min_size': (1001, 1001),\r\n                'recommended_size': (2000, 2000),\r\n                'enables_zoom': True\r\n            }\r\n        }\r\n    \r\n    def optimize_for_amazon(self, image_path, image_type='main'):\r\n        \"\"\"Optimalkan gambar untuk persyaratan Amazon\"\"\"\r\n        img = Image.open(image_path)\r\n        requirements = self.amazon_requirements[f\"{image_type}_image\"]\r\n        \r\n        # Periksa dan modifikasi ukuran\r\n        if img.size[0] \u003C requirements['min_size'][0] or img.size[1] \u003C requirements['min_size'][1]:\r\n            # Perbesar gambar jika terlalu kecil\r\n            img = self.upscale_image(img, requirements['min_size'])\r\n        \r\n        # Pastikan background putih untuk gambar utama\r\n        if image_type == 'main' and requirements.get('background') == 'pure_white':\r\n            img = self.ensure_white_background(img)\r\n        \r\n        # Simpan dengan optimasi\r\n        return self.save_amazon_optimized(img, image_path, image_type)\r\n    \r\n    def ensure_white_background(self, img):\r\n        \"\"\"Pastikan background putih murni\"\"\"\r\n        if img.mode in ('RGBA', 'LA'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            background.paste(img, mask=img.split()[-1])\r\n            return background\r\n        elif img.mode == 'P':\r\n            return img.convert('RGB')\r\n        return img\r\n    \r\n    def upscale_image(self, img, min_size):\r\n        \"\"\"Perbesar gambar ke ukuran minimum\"\"\"\r\n        scale_factor = max(min_size[0] / img.size[0], min_size[1] / img.size[1])\r\n        new_size = (int(img.size[0] * scale_factor), int(img.size[1] * scale_factor))\r\n        return img.resize(new_size, Image.Resampling.LANCZOS)\r\n```\r\n\r\n## Pengukuran dan Monitoring Performa\r\n\r\n### Metrik Optimasi Gambar\r\n\r\nMelacak indikator kinerja utama:\r\n\r\n```python\r\nimport time\r\nimport requests\r\nfrom PIL import Image\r\nimport os\r\n\r\nclass ImagePerformanceMonitor:\r\n    def __init__(self):\r\n        self.metrics = {\r\n            'file_sizes': {},\r\n            'load_times': {},\r\n            'quality_scores': {},\r\n            'conversion_impact': {}\r\n        }\r\n    \r\n    def measure_optimization_impact(self, original_path, optimized_path):\r\n        \"\"\"Ukur dampak optimasi\"\"\"\r\n        # Perbandingan ukuran file\r\n        original_size = os.path.getsize(original_path)\r\n        optimized_size = os.path.getsize(optimized_path)\r\n        size_reduction = ((original_size - optimized_size) / original_size) * 100\r\n        \r\n        # Evaluasi kualitas gambar\r\n        quality_score = self.calculate_quality_score(original_path, optimized_path)\r\n        \r\n        # Simulasi peningkatan waktu loading\r\n        load_time_improvement = self.simulate_load_time_improvement(\r\n            original_size, optimized_size\r\n        )\r\n        \r\n        return {\r\n            'size_reduction_percent': size_reduction,\r\n            'quality_retention_percent': quality_score,\r\n            'load_time_improvement_ms': load_time_improvement,\r\n            'optimization_ratio': size_reduction / (100 - quality_score) if quality_score \u003C 100 else size_reduction\r\n        }\r\n    \r\n    def calculate_quality_score(self, original_path, optimized_path):\r\n        \"\"\"Hitung skor kualitas gambar\"\"\"\r\n        try:\r\n            from skimage.metrics import structural_similarity as ssim\r\n            import numpy as np\r\n            \r\n            # Muat dan konversi gambar\r\n            original = np.array(Image.open(original_path).convert('RGB'))\r\n            optimized = np.array(Image.open(optimized_path).convert('RGB'))\r\n            \r\n            # Hitung SSIM\r\n            ssim_score = ssim(original, optimized, multichannel=True, channel_axis=2)\r\n            return ssim_score * 100\r\n        except ImportError:\r\n            # Estimasi sederhana berdasarkan ukuran jika tidak ada scikit-image\r\n            return 85.0  # Nilai default\r\n    \r\n    def simulate_load_time_improvement(self, original_size, optimized_size):\r\n        \"\"\"Simulasi peningkatan waktu loading\"\"\"\r\n        # Berdasarkan kecepatan internet rata-rata (5 Mbps)\r\n        avg_speed_bytes_per_ms = 5 * 1024 * 1024 / 8 / 1000  # 5 Mbps ke bytes/ms\r\n        \r\n        original_load_time = original_size / avg_speed_bytes_per_ms\r\n        optimized_load_time = optimized_size / avg_speed_bytes_per_ms\r\n        \r\n        return original_load_time - optimized_load_time\r\n    \r\n    def generate_performance_report(self, optimization_results):\r\n        \"\"\"Generate laporan performa\"\"\"\r\n        report = {\r\n            'summary': {\r\n                'total_images_processed': len(optimization_results),\r\n                'average_size_reduction': sum(r['size_reduction_percent'] for r in optimization_results) / len(optimization_results),\r\n                'average_quality_retention': sum(r['quality_retention_percent'] for r in optimization_results) / len(optimization_results),\r\n                'total_load_time_saved_ms': sum(r['load_time_improvement_ms'] for r in optimization_results)\r\n            },\r\n            'recommendations': self.generate_recommendations(optimization_results)\r\n        }\r\n        return report\r\n    \r\n    def generate_recommendations(self, results):\r\n        \"\"\"Generate rekomendasi optimasi\"\"\"\r\n        recommendations = []\r\n        \r\n        avg_size_reduction = sum(r['size_reduction_percent'] for r in results) / len(results)\r\n        avg_quality = sum(r['quality_retention_percent'] for r in results) / len(results)\r\n        \r\n        if avg_size_reduction \u003C 30:\r\n            recommendations.append(\"Terapkan pengaturan kompresi yang lebih agresif\")\r\n        \r\n        if avg_quality \u003C 85:\r\n            recommendations.append(\"Fine-tune pengaturan kualitas untuk hasil visual yang lebih baik\")\r\n        \r\n        if any(r['load_time_improvement_ms'] > 500 for r in results):\r\n            recommendations.append(\"Prioritaskan optimasi gambar kritis\")\r\n        \r\n        return recommendations\r\n```\r\n\r\n## Pemrosesan Batch untuk Katalog Besar\r\n\r\n### Pemrosesan Gambar Paralel\r\n\r\nPemrosesan efisien untuk volume gambar produk yang besar:\r\n\r\n```python\r\nimport concurrent.futures\r\nimport multiprocessing\r\nfrom pathlib import Path\r\nimport logging\r\n\r\nclass BatchImageProcessor:\r\n    def __init__(self, max_workers=None):\r\n        self.max_workers = max_workers or multiprocessing.cpu_count()\r\n        self.processed_count = 0\r\n        self.failed_count = 0\r\n        \r\n        # Setup logging\r\n        logging.basicConfig(level=logging.INFO)\r\n        self.logger = logging.getLogger(__name__)\r\n    \r\n    def process_catalog(self, input_directory, output_directory, product_categories=None):\r\n        \"\"\"Proses seluruh katalog produk\"\"\"\r\n        input_path = Path(input_directory)\r\n        output_path = Path(output_directory)\r\n        output_path.mkdir(parents=True, exist_ok=True)\r\n        \r\n        # Kumpulkan file gambar\r\n        image_files = self.collect_image_files(input_path)\r\n        self.logger.info(f\"Total {len(image_files)} gambar menunggu pemrosesan\")\r\n        \r\n        # Pemrosesan paralel\r\n        with concurrent.futures.ThreadPoolExecutor(max_workers=self.max_workers) as executor:\r\n            # Submit tasks\r\n            future_to_file = {\r\n                executor.submit(\r\n                    self.process_single_product_image, \r\n                    img_file, \r\n                    output_path,\r\n                    product_categories.get(img_file.stem) if product_categories else None\r\n                ): img_file \r\n                for img_file in image_files\r\n            }\r\n            \r\n            # Proses hasil\r\n            for future in concurrent.futures.as_completed(future_to_file):\r\n                img_file = future_to_file[future]\r\n                try:\r\n                    result = future.result()\r\n                    self.processed_count += 1\r\n                    if self.processed_count % 100 == 0:\r\n                        self.logger.info(f\"Diproses: {self.processed_count}/{len(image_files)}\")\r\n                except Exception as exc:\r\n                    self.failed_count += 1\r\n                    self.logger.error(f\"Error memproses {img_file}: {exc}\")\r\n        \r\n        # Generate laporan ringkasan\r\n        self.generate_batch_report(len(image_files))\r\n    \r\n    def collect_image_files(self, input_path):\r\n        \"\"\"Kumpulkan file gambar dari direktori input\"\"\"\r\n        supported_extensions = {'.jpg', '.jpeg', '.png', '.webp', '.tiff', '.bmp'}\r\n        image_files = []\r\n        \r\n        for ext in supported_extensions:\r\n            image_files.extend(input_path.glob(f\"**/*{ext}\"))\r\n            image_files.extend(input_path.glob(f\"**/*{ext.upper()}\"))\r\n        \r\n        return image_files\r\n    \r\n    def process_single_product_image(self, image_path, output_dir, category=None):\r\n        \"\"\"Proses satu gambar produk\"\"\"\r\n        try:\r\n            processor = EcommerceImageProcessor()\r\n            \r\n            # Terapkan pengaturan khusus kategori\r\n            if category:\r\n                category_settings = get_category_optimization_settings(category)\r\n                processor.config.update(category_settings)\r\n            \r\n            # Proses gambar\r\n            product_id = image_path.stem\r\n            result = processor.process_product_image(\r\n                str(image_path), \r\n                str(output_dir), \r\n                product_id\r\n            )\r\n            \r\n            return {\r\n                'status': 'success',\r\n                'input_file': str(image_path),\r\n                'output_files': result,\r\n                'product_id': product_id\r\n            }\r\n            \r\n        except Exception as e:\r\n            return {\r\n                'status': 'error',\r\n                'input_file': str(image_path),\r\n                'error': str(e)\r\n            }\r\n    \r\n    def generate_batch_report(self, total_files):\r\n        \"\"\"Generate laporan pemrosesan batch\"\"\"\r\n        success_rate = (self.processed_count / total_files) * 100\r\n        \r\n        report = f\"\"\"\r\n        Laporan Pemrosesan Gambar Batch\r\n        ===============================\r\n        Total file: {total_files}\r\n        Berhasil diproses: {self.processed_count}\r\n        Gagal: {self.failed_count}\r\n        Tingkat keberhasilan: {success_rate:.2f}%\r\n        \r\n        Kecepatan pemrosesan: {self.processed_count / self.max_workers:.2f} gambar/worker\r\n        \"\"\"\r\n        \r\n        self.logger.info(report)\r\n        return report\r\n\r\n# Contoh penggunaan\r\ndef optimize_ecommerce_catalog():\r\n    \"\"\"Optimalkan katalog e-commerce\"\"\"\r\n    # Definisikan kategori produk\r\n    product_categories = {\r\n        'shirt_001': 'fashion',\r\n        'laptop_002': 'electronics',\r\n        'sofa_003': 'home_decor',\r\n        'ring_004': 'jewelry'\r\n    }\r\n    \r\n    # Inisialisasi batch processor\r\n    batch_processor = BatchImageProcessor(max_workers=8)\r\n    \r\n    # Proses katalog\r\n    batch_processor.process_catalog(\r\n        input_directory='./raw_product_images',\r\n        output_directory='./optimized_product_images',\r\n        product_categories=product_categories\r\n    )\r\n\r\nif __name__ == \"__main__\":\r\n    optimize_ecommerce_catalog()\r\n```\r\n\r\n## Otomatisasi dan Integrasi\r\n\r\n### Integrasi Platform E-commerce\r\n\r\nOptimasi gambar otomatis untuk sistem e-commerce:\r\n\r\n```python\r\nimport requests\r\nimport json\r\nfrom datetime import datetime\r\n\r\nclass EcommerceIntegration:\r\n    def __init__(self, platform_config):\r\n        self.platform = platform_config['platform']  # 'shopify', 'woocommerce', 'magento'\r\n        self.api_key = platform_config['api_key']\r\n        self.store_url = platform_config['store_url']\r\n        self.headers = self.setup_headers()\r\n    \r\n    def setup_headers(self):\r\n        \"\"\"Setup API headers berdasarkan platform\"\"\"\r\n        if self.platform == 'shopify':\r\n            return {\r\n                'X-Shopify-Access-Token': self.api_key,\r\n                'Content-Type': 'application/json'\r\n            }\r\n        elif self.platform == 'woocommerce':\r\n            return {\r\n                'Authorization': f'Bearer {self.api_key}',\r\n                'Content-Type': 'application/json'\r\n            }\r\n        return {'Content-Type': 'application/json'}\r\n    \r\n    def get_products_needing_optimization(self):\r\n        \"\"\"Dapatkan produk yang memerlukan optimasi\"\"\"\r\n        if self.platform == 'shopify':\r\n            return self.get_shopify_products()\r\n        elif self.platform == 'woocommerce':\r\n            return self.get_woocommerce_products()\r\n        return []\r\n    \r\n    def get_shopify_products(self):\r\n        \"\"\"Dapatkan produk Shopify\"\"\"\r\n        url = f\"{self.store_url}/admin/api/2023-01/products.json\"\r\n        response = requests.get(url, headers=self.headers)\r\n        \r\n        if response.status_code == 200:\r\n            products = response.json()['products']\r\n            return [\r\n                {\r\n                    'id': product['id'],\r\n                    'title': product['title'],\r\n                    'images': [img['src'] for img in product['images']]\r\n                }\r\n                for product in products\r\n            ]\r\n        return []\r\n    \r\n    def optimize_product_images(self, product_data):\r\n        \"\"\"Optimalkan dan upload gambar produk\"\"\"\r\n        optimized_images = []\r\n        \r\n        for image_url in product_data['images']:\r\n            try:\r\n                # Download gambar\r\n                response = requests.get(image_url)\r\n                if response.status_code == 200:\r\n                    # Simpan file sementara\r\n                    temp_path = f\"temp_{product_data['id']}.jpg\"\r\n                    with open(temp_path, 'wb') as f:\r\n                        f.write(response.content)\r\n                    \r\n                    # Optimalkan\r\n                    processor = EcommerceImageProcessor()\r\n                    optimized_files = processor.process_product_image(\r\n                        temp_path, \r\n                        f\"optimized_{product_data['id']}\", \r\n                        str(product_data['id'])\r\n                    )\r\n                    \r\n                    # Upload gambar yang dioptimalkan\r\n                    uploaded_urls = self.upload_optimized_images(\r\n                        optimized_files, \r\n                        product_data['id']\r\n                    )\r\n                    optimized_images.extend(uploaded_urls)\r\n                    \r\n                    # Hapus file sementara\r\n                    os.remove(temp_path)\r\n                    \r\n            except Exception as e:\r\n                print(f\"Error mengoptimalkan gambar: {e}\")\r\n        \r\n        return optimized_images\r\n    \r\n    def upload_optimized_images(self, image_files, product_id):\r\n        \"\"\"Upload gambar yang dioptimalkan ke platform\"\"\"\r\n        uploaded_urls = []\r\n        \r\n        for image_file in image_files:\r\n            if self.platform == 'shopify':\r\n                url = self.upload_to_shopify(image_file, product_id)\r\n            elif self.platform == 'woocommerce':\r\n                url = self.upload_to_woocommerce(image_file, product_id)\r\n            \r\n            if url:\r\n                uploaded_urls.append(url)\r\n        \r\n        return uploaded_urls\r\n    \r\n    def schedule_optimization(self, schedule_config):\r\n        \"\"\"Jadwalkan optimasi\"\"\"\r\n        import schedule\r\n        import time\r\n        \r\n        def run_optimization():\r\n            products = self.get_products_needing_optimization()\r\n            for product in products:\r\n                self.optimize_product_images(product)\r\n                time.sleep(1)  # Rate limiting\r\n        \r\n        # Setup jadwal\r\n        if schedule_config['frequency'] == 'daily':\r\n            schedule.every().day.at(schedule_config['time']).do(run_optimization)\r\n        elif schedule_config['frequency'] == 'weekly':\r\n            schedule.every().week.do(run_optimization)\r\n        \r\n        # Jalankan scheduler\r\n        while True:\r\n            schedule.run_pending()\r\n            time.sleep(60)\r\n```\r\n\r\n## Kesimpulan\r\n\r\nOptimasi gambar produk e-commerce sangat penting untuk kesuksesan penjualan online. Dengan menerapkan teknik kompresi yang tepat, kita dapat secara signifikan meningkatkan performa situs tanpa mengorbankan kualitas gambar.\r\n\r\n### Temuan Kunci\r\n\r\n1. **Optimasi khusus kategori**: Setiap kategori produk memiliki persyaratan gambar yang unik\r\n2. **Pentingnya otomatisasi**: Pemrosesan batch sangat penting untuk katalog besar\r\n3. **Pengukuran performa**: Monitoring reguler diperlukan untuk hasil optimal\r\n4. **Integrasi platform**: Workflow yang mulus dengan sistem e-commerce\r\n5. **Kualitas vs kecepatan**: Menemukan keseimbangan yang tepat untuk tujuan bisnis\r\n\r\n### Rekomendasi Implementasi\r\n\r\n- Mulai dengan gambar produk paling kritis (gambar utama, produk bestseller)\r\n- Uji pengaturan optimasi pada sampel kecil\r\n- Ukur dampak pada tingkat konversi\r\n- Otomatisasi proses untuk konsistensi\r\n- Perbarui strategi optimasi secara berkala\r\n\r\nStrategi optimasi gambar yang diimplementasikan dengan benar dapat menghasilkan peningkatan signifikan dalam kecepatan situs, pengalaman pengguna, dan pada akhirnya hasil penjualan.","# E-ticaret Ürün Görsellerinin Sıkıştırılması: Satış Odaklı Optimizasyon\r\n\r\nE-ticarette başarı büyük ölçüde ürün görsellerinin kalitesine bağlıdır: Araştırmalar, tüketicilerin %67'sinin çevrimiçi alışverişte görsel kalitesini \"çok önemli\" bulduğunu gösteriyor. Ancak büyük görsel dosyaları, sayfa yükleme süresi, dönüşüm oranı ve mobil deneyim üzerinde ciddi etkilere yol açabilir. Bu kapsamlı rehber, satışları artırmak için gerekli görsel kaliteyi koruyarak e-ticaret ürün görsellerinin optimize edilmesine yönelik ileri düzey uygulamaları kapsar.\r\n\r\n## E-ticaret Görsel Optimizasyonu Neden Önemli?\r\n\r\n### Dönüşüme Etkisi\r\n\r\nÜrün görsellerinin optimizasyonu doğrudan iş sonuçlarını etkiler:\r\n- **Dönüşüm**: Sayfa yüklemesinde 1 saniyelik gecikme dönüşüm oranını %7 azaltır\r\n- **Hemen Çıkma Oranı**: Kullanıcıların %40'ı 3 saniyeden uzun sürede yüklenen siteleri terk eder\r\n- **Mobil Ticaret**: E-ticaret trafiğinin %73'ü mobil cihazlardan gelir\r\n- **Arama Sıralaması**: Google, sıralamada sayfa hızını dikkate alır\r\n- **Müşteri Memnuniyeti**: Yüksek kaliteli görseller satın alma güvenini artırır\r\n\r\n### E-ticarete Özgü Gereksinimler\r\n\r\nÜrün görsellerinin kendine has optimizasyon zorlukları vardır:\r\n- **Çoklu ürün açıları**: ana görsel, küçük resimler, yakınlaştırma, 360° görünüm\r\n- **Renk doğruluğu**: moda, kozmetik ve ev ürünlerinde kritik\r\n- **Detay koruma**: Müşteriler doku, malzeme ve işçilik görmek ister\r\n- **Yükleme performansı**: kalite ile hız arasında denge\r\n- **Çapraz platform deneyimi**: tüm cihazlarda tutarlı deneyim\r\n\r\n## E-ticaret İçin Görsel Türleri\r\n\r\n### Ürün Görseli Kategorileri\r\n\r\nFarklı görsel türleri farklı optimizasyon yaklaşımları gerektirir:\r\n\r\n```javascript\r\nconst ecommerceImageTypes = {\r\n    hero: {\r\n        purpose: 'Ürünün ana sunumu',\r\n        requirements: 'Yüksek kalite, hızlı yükleme',\r\n        sizes: ['1200x1200', '800x800', '600x600'],\r\n        quality: { jpeg: 85, webp: 80 }\r\n    },\r\n    thumbnail: {\r\n        purpose: 'Ürün galerisi',\r\n        requirements: 'Küçük dosya boyutu, tanınabilirlik',\r\n        sizes: ['300x300', '200x200', '150x150'],\r\n        quality: { jpeg: 75, webp: 70 }\r\n    },\r\n    zoom: {\r\n        purpose: 'Detaylı ürün görünümü',\r\n        requirements: 'Maksimum detay koruma',\r\n        sizes: ['2000x2000', '1600x1600'],\r\n        quality: { jpeg: 90, webp: 85 }\r\n    },\r\n    gallery: {\r\n        purpose: 'Çoklu ürün açıları',\r\n        requirements: 'Sabit kalite, gecikmeli yükleme',\r\n        sizes: ['800x800', '600x600'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    },\r\n    lifestyle: {\r\n        purpose: 'Kullanımda/bağlamda ürün',\r\n        requirements: 'Duygu/bağlam için optimize',\r\n        sizes: ['1200x800', '800x533'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    }\r\n};\r\n```\r\n\r\n### Ürün Kategorisine Göre Optimizasyon Stratejisi\r\n\r\nFarklı ürün kategorilerinin görseller için farklı gereksinimleri vardır:\r\n\r\n```python\r\ndef get_category_optimization_settings(product_category):\r\n    \"\"\"Farklı ürün kategorileri için optimizasyon ayarlarını getir\"\"\"\r\n    settings = {\r\n        'fashion': {\r\n            'priority': ['renk_doğruluğu', 'doku_detayı'],\r\n            'format_preference': 'webp_fallback_jpeg',\r\n            'quality_range': {'min': 80, 'max': 90},\r\n            'critical_views': ['ön', 'arka', 'detay']\r\n        },\r\n        'electronics': {\r\n            'priority': ['detay_koruma', 'hızlı_yükleme'],\r\n            'format_preference': 'webp_veya_avif',\r\n            'quality_range': {'min': 75, 'max': 85},\r\n            'critical_views': ['ana', 'bağlantılar', 'boyut_karşılaştırma']\r\n        },\r\n        'home_decor': {\r\n            'priority': ['renk_doğruluğu', 'kullanım_bağlamı'],\r\n            'format_preference': 'webp_fallback_jpeg',\r\n            'quality_range': {'min': 80, 'max': 88},\r\n            'critical_views': ['iç_mekan', 'yakın_plan', 'ölçüler']\r\n        },\r\n        'jewelry': {\r\n            'priority': ['maksimum_detay', 'renk_doğruluğu'],\r\n            'format_preference': 'png_detaylar_için_webp_hero_için',\r\n            'quality_range': {'min': 85, 'max': 95},\r\n            'critical_views': ['makro', '360_görünüm', 'lifestyle']\r\n        },\r\n        'books': {\r\n            'priority': ['hızlı_yükleme', 'metin_okunabilirliği'],\r\n            'format_preference': 'webp_agresif_sıkıştırma',\r\n            'quality_range': {'min': 70, 'max': 80},\r\n            'critical_views': ['kapak', 'arka', 'sırt']\r\n        }\r\n    }\r\n    return settings.get(product_category, settings['electronics'])\r\n```\r\n\r\n## Gelişmiş Ürün Görseli İşleme\r\n\r\n### Otomatik Görsel İşleme Pipeline'ı\r\n\r\nKapsamlı otomatik görsel işleme sistemi:\r\n\r\n```python\r\nimport os\r\nfrom PIL import Image, ImageEnhance, ImageFilter\r\nimport numpy as np\r\n\r\nclass EcommerceImageProcessor:\r\n    def __init__(self, config=None):\r\n        self.config = config or self.get_default_config()\r\n        self.supported_formats = ['jpeg', 'webp', 'avif', 'png']\r\n        \r\n    def get_default_config(self):\r\n        return {\r\n            'background_removal': True,\r\n            'auto_crop': True,\r\n            'color_enhancement': True,\r\n            'noise_reduction': True,\r\n            'watermark': False,\r\n            'quality_thresholds': {\r\n                'hero': 85,\r\n                'gallery': 80,\r\n                'thumbnail': 75,\r\n                'zoom': 90\r\n            }\r\n        }\r\n    \r\n    def process_product_image(self, input_path, output_dir, product_id):\r\n        \"\"\"Bir ürün görselini tüm gerekli varyantlara işle\"\"\"\r\n        img = Image.open(input_path)\r\n        \r\n        # Temel ön işleme\r\n        processed_img = self.preprocess_image(img)\r\n        \r\n        # Tüm gerekli boyut ve formatları oluştur\r\n        variants = self.generate_image_variants(processed_img, product_id)\r\n        \r\n        # Optimize edilmiş sürümleri kaydet\r\n        saved_files = self.save_variants(variants, output_dir)\r\n        \r\n        return saved_files\r\n    \r\n    def preprocess_image(self, img):\r\n        \"\"\"Ürün görselinin temel ön işlemesi\"\"\"\r\n        # Gerekirse RGB'ye dönüştür\r\n        if img.mode in ('RGBA', 'LA', 'P'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            if img.mode == 'RGBA':\r\n                background.paste(img, mask=img.split()[-1])\r\n            else:\r\n                background.paste(img)\r\n            img = background\r\n        \r\n        # Fazla arka planı kaldırmak için otomatik kırpma\r\n        if self.config['auto_crop']:\r\n            img = self.smart_crop(img)\r\n        \r\n        # Görsel kalitesini artır\r\n        if self.config['color_enhancement']:\r\n            img = self.enhance_product_image(img)\r\n        \r\n        # Gürültüyü azalt\r\n        if self.config['noise_reduction']:\r\n            img = img.filter(ImageFilter.SMOOTH_MORE)\r\n        \r\n        return img\r\n    \r\n    def smart_crop(self, img):\r\n        \"\"\"Fazla arka planı kaldırmak için akıllı kırpma\"\"\"\r\n        # Analiz için numpy array'e dönüştür\r\n        img_array = np.array(img)\r\n        \r\n        # Beyaz olmayan piksellerin bounding box'unu bul\r\n        mask = np.any(img_array \u003C 240, axis=2)  # Tam beyaz değil\r\n        coords = np.argwhere(mask)\r\n        \r\n        if len(coords) == 0:\r\n            return img  # Kırpma gerekmez\r\n        \r\n        # Bounding box'u al\r\n        y0, x0 = coords.min(axis=0)\r\n        y1, x1 = coords.max(axis=0)\r\n        \r\n        # Kenar boşluğu ekle\r\n        padding = 20\r\n        y0 = max(0, y0 - padding)\r\n        x0 = max(0, x0 - padding)\r\n        y1 = min(img.height, y1 + padding)\r\n        x1 = min(img.width, x1 + padding)\r\n        \r\n        return img.crop((x0, y0, x1, y1))\r\n    \r\n    def enhance_product_image(self, img):\r\n        \"\"\"E-ticaret için ürün görselini iyileştir\"\"\"\r\n        # Hafif parlaklık artırımı\r\n        brightness_enhancer = ImageEnhance.Brightness(img)\r\n        img = brightness_enhancer.enhance(1.05)\r\n        \r\n        # Kontrast artırımı\r\n        contrast_enhancer = ImageEnhance.Contrast(img)\r\n        img = contrast_enhancer.enhance(1.1)\r\n        \r\n        # Renk doygunluğu artırımı\r\n        color_enhancer = ImageEnhance.Color(img)\r\n        img = color_enhancer.enhance(1.05)\r\n        \r\n        # Keskinlik artırımı\r\n        sharpness_enhancer = ImageEnhance.Sharpness(img)\r\n        img = sharpness_enhancer.enhance(1.1)\r\n        \r\n        return img\r\n    \r\n    def generate_image_variants(self, img, product_id):\r\n        \"\"\"Tüm gerekli görsel varyantlarını oluştur\"\"\"\r\n        variants = {}\r\n        \r\n        # E-ticaret için standart boyutlar\r\n        sizes = {\r\n            'hero': (1200, 1200),\r\n            'gallery': (800, 800),\r\n            'thumbnail': (300, 300),\r\n            'zoom': (2000, 2000),\r\n            'mobile_hero': (600, 600),\r\n            'mobile_thumb': (150, 150)\r\n        }\r\n        \r\n        for variant_name, size in sizes.items():\r\n            # Yüksek kaliteli yeniden örnekleme ile yeniden boyutlandır\r\n            resized = img.resize(size, Image.Resampling.LANCZOS)\r\n            variants[variant_name] = resized\r\n        \r\n        return variants\r\n    \r\n    def save_variants(self, variants, output_dir):\r\n        \"\"\"Tüm varyantları optimize formatlarda kaydet\"\"\"\r\n        saved_files = []\r\n        \r\n        for variant_name, img in variants.items():\r\n            base_path = os.path.join(output_dir, variant_name)\r\n            \r\n            # Birden fazla formatta kaydet\r\n            for format_type in ['jpeg', 'webp']:\r\n                filename = f\"{base_path}.{format_type}\"\r\n                quality = self.get_quality_for_variant(variant_name, format_type)\r\n                \r\n                if format_type == 'jpeg':\r\n                    img.save(filename, 'JPEG', quality=quality, optimize=True, progressive=True)\r\n                elif format_type == 'webp':\r\n                    img.save(filename, 'WebP', quality=quality, optimize=True)\r\n                \r\n                saved_files.append(filename)\r\n        \r\n        return saved_files\r\n    \r\n    def get_quality_for_variant(self, variant_name, format_type):\r\n        \"\"\"Varyant ve format için optimum kaliteyi getir\"\"\"\r\n        base_quality = self.config['quality_thresholds'].get(variant_name, 80)\r\n        \r\n        # Formata göre ayarla\r\n        if format_type == 'webp':\r\n            return base_quality - 5  # WebP aynı kaliteyi daha düşük değerde verir\r\n        elif format_type == 'avif':\r\n            return base_quality - 10  # AVIF daha da verimli\r\n        \r\n        return base_quality\r\n\r\n# Kullanım örneği\r\nprocessor = EcommerceImageProcessor()\r\nprocessor.process_product_image('product_raw.jpg', 'output/', 'product_123')\r\n```\r\n\r\n### Arka Planı Kaldırma ve Standartlaştırma\r\n\r\nÜrün görsellerinde tutarlılık için otomatik arka plan işleme:\r\n\r\n```python\r\ndef remove_product_background(image_path, output_path):\r\n    \"\"\"Kenar algılama ile ürün görselinin arka planını kaldır\"\"\"\r\n    import cv2\r\n    import numpy as np\r\n    \r\n    # Görseli oku\r\n    img = cv2.imread(image_path)\r\n    original = img.copy()\r\n    \r\n    # Gri tonlamaya çevir\r\n    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\r\n    \r\n    # Gürültüyü azaltmak için Gauss bulanıklığı\r\n    blurred = cv2.GaussianBlur(gray, (5, 5), 0)\r\n    \r\n    # Kenar algılama\r\n    edges = cv2.Canny(blurred, 50, 150)\r\n    \r\n    # Kontur bul\r\n    contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\r\n    \r\n    if contours:\r\n        # En büyük konturu bul (muhtemelen ürün)\r\n        largest_contour = max(contours, key=cv2.contourArea)\r\n        \r\n        # Maske oluştur\r\n        mask = np.zeros(gray.shape, np.uint8)\r\n        cv2.fillPoly(mask, [largest_contour], 255)\r\n        \r\n        # Maskeyi orijinal görsele uygula\r\n        result = cv2.bitwise_and(original, original, mask=mask)\r\n        \r\n        # Arka planı beyaz yap\r\n        result[mask == 0] = [255, 255, 255]\r\n        \r\n        cv2.imwrite(output_path, result)\r\n        return True\r\n    \r\n    return False\r\n\r\ndef standardize_product_backgrounds(input_dir, output_dir, background_color=(255, 255, 255)):\r\n    \"\"\"Tüm ürün arka planlarını tek renge standartlaştır\"\"\"\r\n    for filename in os.listdir(input_dir):\r\n        if filename.lower().endswith(('.jpg', '.jpeg', '.png')):\r\n            input_path = os.path.join(input_dir, filename)\r\n            output_path = os.path.join(output_dir, filename)\r\n            \r\n            # Otomatik arka plan kaldırmayı dene\r\n            if not remove_product_background(input_path, output_path):\r\n                # Alternatif: sadece beyaz arka plan\r\n                img = Image.open(input_path)\r\n                if img.mode == 'RGBA':\r\n                    background = Image.new('RGB', img.size, background_color)\r\n                    background.paste(img, mask=img.split()[-1])\r\n                    background.save(output_path, 'JPEG', quality=85)\r\n                else:\r\n                    img.save(output_path)\r\n```\r\n\r\n## Platforma Özel Optimizasyon\r\n\r\n### Amazon Marketplace için Optimizasyon\r\n\r\nAmazon'un özel görsel gereksinimleri ve kendi algoritmaları vardır:\r\n\r\n```python\r\nclass AmazonImageOptimizer:\r\n    def __init__(self):\r\n        self.requirements = {\r\n            'main_image': {\r\n                'min_size': (1000, 1000),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'background': 'pure_white',\r\n                'product_coverage': 85  # Görselin minimum yüzdesi\r\n            },\r\n            'additional_images': {\r\n                'min_size': (500, 500),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'lifestyle_allowed': True\r\n            }\r\n        }\r\n    \r\n    def optimize_for_amazon(self, image_path, output_path, image_type='main'):\r\n        \"\"\"Amazon listesi için görseli özel olarak optimize et\"\"\"\r\n        img = Image.open(image_path)\r\n        \r\n        if image_type == 'main':\r\n            img = self.ensure_white_background(img)\r\n            img = self.ensure_minimum_size(img, (1000, 1000))\r\n        \r\n        # Amazon sRGB renk uzayını ister\r\n        if img.mode != 'RGB':\r\n            img = img.convert('RGB')\r\n        \r\n        # Kaliteyi koruyarak dosya boyutunu optimize et\r\n        quality = 90 if image_type == 'main' else 85\r\n        img.save(output_path, 'JPEG', quality=quality, optimize=True)\r\n        \r\n        return self.validate_amazon_requirements(output_path, image_type)\r\n    \r\n    def ensure_white_background(self, img):\r\n        \"\"\"Görselin tamamen beyaz arka plana sahip olduğundan emin ol\"\"\"\r\n        if img.mode == 'RGBA':\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            background.paste(img, mask=img.split()[-1])\r\n            return background\r\n        return img\r\n    \r\n    def ensure_minimum_size(self, img, min_size):\r\n        \"\"\"Görselin minimum boyutları karşıladığından emin ol\"\"\"\r\n        if img.size[0] \u003C min_size[0] or img.size[1] \u003C min_size[1]:\r\n            img = img.resize(min_size, Image.Resampling.LANCZOS)\r\n        return img\r\n    \r\n    def validate_amazon_requirements(self, image_path, image_type):\r\n        \"\"\"Görselin Amazon gereksinimlerini karşıladığını doğrula\"\"\"\r\n        img = Image.open(image_path)\r\n        requirements = self.requirements[image_type]\r\n        \r\n        validation_results = {\r\n            'size_valid': (\r\n                img.size[0] >= requirements['min_size'][0] and \r\n                img.size[1] >= requirements['min_size'][1]\r\n            ),\r\n            'format_valid': image_path.upper().endswith(tuple(requirements['formats'])),\r\n            'file_size_valid': os.path.getsize(image_path) \u003C= 10 * 1024 * 1024  # 10MB sınırı\r\n        }\r\n        \r\n        return all(validation_results.values()), validation_results\r\n```\r\n\r\n### Shopify Mağazaları için Optimizasyon\r\n\r\nShopify temaları ve performansı için optimizasyon:\r\n\r\n```javascript\r\nclass ShopifyImageOptimizer {\r\n    constructor() {\r\n        this.themeRequirements = {\r\n            'product_card': { width: 600, height: 600, quality: 80 },\r\n            'product_detail': { width: 1200, height: 1200, quality: 85 },\r\n            'product_zoom': { width: 2048, height: 2048, quality: 90 },\r\n            'collection_featured': { width: 800, height: 600, quality: 80 }\r\n        };\r\n    }\r\n    \r\n    generateShopifyImageUrls(baseImageUrl, productHandle) {\r\n        const urls = {};\r\n        \r\n        Object.entries(this.themeRequirements).forEach(([variant, specs]) => {\r\n            // Shopify görsel dönüşümü için URL oluştur\r\n            const transformedUrl = baseImageUrl.replace('.jpg', \r\n                `_${specs.width}x${specs.height}_crop_center.jpg`);\r\n            urls[variant] = transformedUrl;\r\n        });\r\n        \r\n        return urls;\r\n    }\r\n    \r\n    generateShopifyPictureElement(productData) {\r\n        const { images, title, handle } = productData;\r\n        const mainImage = images[0];\r\n        \r\n        return `\r\n            \u003Cpicture>\r\n                \u003Csource media=\"(min-width: 1200px)\" \r\n                        srcset=\"${mainImage}_1200x1200.webp 1x, ${mainImage}_2400x2400.webp 2x\"\r\n                        type=\"image/webp\">\r\n                \u003Csource media=\"(min-width: 768px)\" \r\n                        srcset=\"${mainImage}_800x800.webp 1x, ${mainImage}_1600x1600.webp 2x\"\r\n                        type=\"image/webp\">\r\n                \u003Csource media=\"(max-width: 767px)\" \r\n                        srcset=\"${mainImage}_600x600.webp 1x, ${mainImage}_1200x1200.webp 2x\"\r\n                        type=\"image/webp\">\r\n                \u003Cimg src=\"${mainImage}_800x800.jpg\"\r\n                     srcset=\"${mainImage}_400x400.jpg 400w,\r\n                             ${mainImage}_600x600.jpg 600w,\r\n                             ${mainImage}_800x800.jpg 800w,\r\n                             ${mainImage}_1200x1200.jpg 1200w\"\r\n                     sizes=\"(max-width: 767px) 100vw, (max-width: 1023px) 50vw, 33vw\"\r\n                     alt=\"${title}\"\r\n                     loading=\"lazy\"\r\n                     data-product-handle=\"${handle}\">\r\n            \u003C/picture>\r\n        `;\r\n    }\r\n}\r\n```\r\n\r\n## E-ticaret İçin Gelişmiş Yükleme Stratejileri\r\n\r\n### Akıllı Ürün Görseli Yükleme\r\n\r\nKullanıcı davranışı ve cihaz yeteneklerine göre akıllı yükleme:\r\n\r\n```javascript\r\nclass EcommerceImageLoader {\r\n    constructor() {\r\n        this.userBehavior = this.trackUserBehavior();\r\n        this.deviceCapabilities = this.analyzeDevice();\r\n        this.loadingStrategies = this.initializeStrategies();\r\n    }\r\n    \r\n    trackUserBehavior() {\r\n        return {\r\n            isReturningCustomer: localStorage.getItem('visited') === 'true',\r\n            viewingHistory: JSON.parse(localStorage.getItem('viewedProducts') || '[]'),\r\n            averageSessionTime: parseInt(localStorage.getItem('avgSessionTime') || '0'),\r\n            purchaseHistory: JSON.parse(localStorage.getItem('purchases') || '[]')\r\n        };\r\n    }\r\n    \r\n    analyzeDevice() {\r\n        const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;\r\n        \r\n        return {\r\n            connectionSpeed: connection ? connection.effectiveType : '4g',\r\n            deviceMemory: navigator.deviceMemory || 4,\r\n            isLowEndDevice: navigator.deviceMemory \u003C 2,\r\n            isMobile: window.innerWidth \u003C= 768,\r\n            isSlowConnection: connection && (connection.effectiveType === 'slow-2g' || connection.effectiveType === '2g')\r\n        };\r\n    }\r\n    \r\n    initializeStrategies() {\r\n        return {\r\n            eager: this.eagerLoadingStrategy.bind(this),\r\n            progressive: this.progressiveLoadingStrategy.bind(this),\r\n            lazy: this.lazyLoadingStrategy.bind(this),\r\n            adaptive: this.adaptiveLoadingStrategy.bind(this)\r\n        };\r\n    }\r\n    \r\n    selectOptimalStrategy(productData, context) {\r\n        const { deviceCapabilities, userBehavior } = this;\r\n        \r\n        // İyi bağlantılı sadık müşteriler\r\n        if (userBehavior.isReturningCustomer && \r\n            userBehavior.purchaseHistory.length > 0 && \r\n            !deviceCapabilities.isSlowConnection) {\r\n            return 'eager';\r\n        }\r\n        \r\n        // Düşük özellikli cihazlar veya yavaş bağlantı\r\n        if (deviceCapabilities.isLowEndDevice || deviceCapabilities.isSlowConnection) {\r\n            return 'lazy';\r\n        }\r\n        \r\n        // İyi bağlantılı mobil cihazlar\r\n        if (deviceCapabilities.isMobile && !deviceCapabilities.isSlowConnection) {\r\n            return 'progressive';\r\n        }\r\n        \r\n        // Varsayılan: adaptif strateji\r\n        return 'adaptive';\r\n    }\r\n    \r\n    eagerLoadingStrategy(productImages) {\r\n        // Tüm görselleri hemen yükle (premium deneyim)\r\n        productImages.forEach(img => {\r\n            const imageLoader = new Image();\r\n            imageLoader.src = img.dataset.src;\r\n            \r\n            if (img.dataset.srcset) {\r\n                imageLoader.srcset = img.dataset.srcset;\r\n            }\r\n            \r\n            imageLoader.onload = () => {\r\n                img.src = imageLoader.src;\r\n                if (img.dataset.srcset) {\r\n                    img.srcset = imageLoader.srcset;\r\n                }\r\n                img.classList.add('loaded');\r\n            };\r\n        });\r\n    }\r\n    \r\n    progressiveLoadingStrategy(productImages) {\r\n        // Önce düşük kaliteli, sonra yüksek kaliteli yükle\r\n        productImages.forEach(img => {\r\n            // Düşük kaliteli placeholder yükle\r\n            const lowQualitySrc = img.dataset.lowSrc || img.dataset.src.replace('_q85', '_q40');\r\n            const highQualitySrc = img.dataset.src;\r\n            \r\n            img.src = lowQualitySrc;\r\n            img.classList.add('loading');\r\n            \r\n            // Yüksek kaliteli sürümü yükle\r\n            const highQualityLoader = new Image();\r\n            highQualityLoader.onload = () => {\r\n                img.src = highQualitySrc;\r\n                img.classList.remove('loading');\r\n                img.classList.add('loaded');\r\n            };\r\n            highQualityLoader.src = highQualitySrc;\r\n        });\r\n    }\r\n    \r\n    lazyLoadingStrategy(productImages) {\r\n        // Lazy yükleme için Intersection Observer kullan\r\n        const observer = new IntersectionObserver((entries) => {\r\n            entries.forEach(entry => {\r\n                if (entry.isIntersecting) {\r\n                    this.loadImage(entry.target);\r\n                    observer.unobserve(entry.target);\r\n                }\r\n            });\r\n        }, { rootMargin: '100px' });\r\n        \r\n        productImages.forEach(img => observer.observe(img));\r\n    }\r\n    \r\n    adaptiveLoadingStrategy(productImages) {\r\n        // Kullanıcı etkileşimi ve kaydırmaya göre uyum sağla\r\n        let scrollTimeout;\r\n        let isScrolling = false;\r\n        \r\n        window.addEventListener('scroll', () => {\r\n            if (!isScrolling) {\r\n                isScrolling = true;\r\n                // Kaydırma başladığında görünen görselleri hemen yükle\r\n                this.loadVisibleImages(productImages);\r\n            }\r\n            \r\n            clearTimeout(scrollTimeout);\r\n            scrollTimeout = setTimeout(() => {\r\n                isScrolling = false;\r\n            }, 150);\r\n        });\r\n        \r\n        // Fold üzerindeki kritik görselleri hemen yükle\r\n        this.loadCriticalImages(productImages);\r\n        \r\n        // Kalan görselleri lazy yükle\r\n        this.lazyLoadingStrategy(productImages.filter(img => !img.dataset.critical));\r\n    }\r\n    \r\n    loadCriticalImages(productImages) {\r\n        const criticalImages = productImages.filter(img => \r\n            img.dataset.critical === 'true' || \r\n            img.getBoundingClientRect().top \u003C window.innerHeight\r\n        );\r\n        \r\n        criticalImages.forEach(img => this.loadImage(img));\r\n    }\r\n    \r\n    loadVisibleImages(productImages) {\r\n        const visibleImages = productImages.filter(img => {\r\n            const rect = img.getBoundingClientRect();\r\n            return rect.top \u003C window.innerHeight && rect.bottom > 0;\r\n        });\r\n        \r\n        visibleImages.forEach(img => this.loadImage(img));\r\n    }\r\n    \r\n    loadImage(img) {\r\n        if (img.dataset.loaded) return;\r\n        \r\n        const imageLoader = new Image();\r\n        imageLoader.onload = () => {\r\n            img.src = imageLoader.src;\r\n            if (img.dataset.srcset) {\r\n                img.srcset = imageLoader.srcset;\r\n            }\r\n            img.classList.add('loaded');\r\n            img.dataset.loaded = 'true';\r\n        };\r\n        \r\n        imageLoader.src = img.dataset.src;\r\n    }\r\n}\r\n\r\n// Ürün sayfaları için başlatma\r\n// document.addEventListener('DOMContentLoaded', () => {\r\n//     const imageLoader = new EcommerceImageLoader();\r\n//     const productImages = document.querySelectorAll('.product-image[data-src]');\r\n//     \r\n//     if (productImages.length > 0) {\r\n//         const strategy = imageLoader.selectOptimalStrategy();\r\n//         imageLoader.loadingStrategies[strategy](productImages);\r\n//     }\r\n// });\r\n```\r\n\r\n## Yakınlaştırma ve 360° Görünüm Optimizasyonu\r\n\r\n### Etkili Yakınlaştırma Uygulaması\r\n\r\nÜrün detay sayfaları için optimize edilmiş yakınlaştırma fonksiyonu:\r\n\r\n```javascript\r\nclass ProductImageZoom {\r\n    constructor(options = {}) {\r\n        this.container = options.container;\r\n        this.zoomLevel = options.zoomLevel || 2;\r\n        this.loadingStrategy = options.loadingStrategy || 'on-demand';\r\n        this.highResImages = new Map();\r\n        \r\n        this.initializeZoom();\r\n    }\r\n    \r\n    initializeZoom() {\r\n        const zoomImages = this.container.querySelectorAll('.zoomable-image');\r\n        \r\n        zoomImages.forEach(img => {\r\n            img.addEventListener('mouseenter', this.handleMouseEnter.bind(this));\r\n            img.addEventListener('mouseleave', this.handleMouseLeave.bind(this));\r\n            img.addEventListener('mousemove', this.handleMouseMove.bind(this));\r\n        });\r\n    }\r\n    \r\n    async handleMouseEnter(event) {\r\n        const img = event.target;\r\n        const highResUrl = img.dataset.zoomSrc;\r\n        \r\n        if (!highResUrl) return;\r\n        \r\n        // Yüksek çözünürlüklü görseli gerektiğinde yükle\r\n        if (!this.highResImages.has(highResUrl)) {\r\n            this.loadHighResImage(highResUrl);\r\n        }\r\n        \r\n        this.showZoomOverlay(img);\r\n    }\r\n    \r\n    loadHighResImage(url) {\r\n        return new Promise((resolve, reject) => {\r\n            const img = new Image();\r\n            img.onload = () => {\r\n                this.highResImages.set(url, img);\r\n                resolve(img);\r\n            };\r\n            img.onerror = reject;\r\n            img.src = url;\r\n        });\r\n    }\r\n    \r\n    showZoomOverlay(img) {\r\n        // Zoom için overlay oluştur (yoksa)\r\n        let overlay = img.parentNode.querySelector('.zoom-overlay');\r\n        if (!overlay) {\r\n            overlay = document.createElement('div');\r\n            overlay.className = 'zoom-overlay';\r\n            overlay.style.cssText = `\r\n                position: absolute;\r\n                top: 0;\r\n                left: 100%;\r\n                width: 300px;\r\n                height: 300px;\r\n                border: 1px solid #ddd;\r\n                background: white;\r\n                overflow: hidden;\r\n                z-index: 1000;\r\n                display: none;\r\n            `;\r\n            img.parentNode.appendChild(overlay);\r\n        }\r\n        \r\n        overlay.style.display = 'block';\r\n    }\r\n    \r\n    handleMouseMove(event) {\r\n        const img = event.target;\r\n        const overlay = img.parentNode.querySelector('.zoom-overlay');\r\n        const highResUrl = img.dataset.zoomSrc;\r\n        \r\n        if (!overlay || !this.highResImages.has(highResUrl)) return;\r\n        \r\n        const rect = img.getBoundingClientRect();\r\n        const x = (event.clientX - rect.left) / rect.width;\r\n        const y = (event.clientY - rect.top) / rect.height;\r\n        \r\n        const highResImg = this.highResImages.get(highResUrl);\r\n        \r\n        // Zoom overlay'i güncelle\r\n        overlay.style.backgroundImage = `url(${highResUrl})`;\r\n        overlay.style.backgroundSize = `${highResImg.width}px ${highResImg.height}px`;\r\n        overlay.style.backgroundPosition = `-${x * (highResImg.width - 300)}px -${y * (highResImg.height - 300)}px`;\r\n    }\r\n    \r\n    handleMouseLeave(event) {\r\n        const img = event.target;\r\n        const overlay = img.parentNode.querySelector('.zoom-overlay');\r\n        \r\n        if (overlay) {\r\n            overlay.style.display = 'none';\r\n        }\r\n    }\r\n}\r\n\r\n// Ürün için 360° görünüm optimizasyonu\r\nclass Product360View {\r\n    constructor(container, options = {}) {\r\n        this.container = container;\r\n        this.frameCount = options.frameCount || 36;\r\n        this.autoPlay = options.autoPlay || false;\r\n        this.frames = [];\r\n        this.currentFrame = 0;\r\n        this.isLoading = false;\r\n        \r\n        this.initialize();\r\n    }\r\n    \r\n    async initialize() {\r\n        await this.loadFrames();\r\n        this.setupControls();\r\n        this.setupInteraction();\r\n    }\r\n    \r\n    async loadFrames() {\r\n        this.isLoading = true;\r\n        const baseUrl = this.container.dataset.baseUrl;\r\n        \r\n        // Progressive frame yükleme\r\n        const loadPromises = [];\r\n        \r\n        for (let i = 1; i \u003C= this.frameCount; i++) {\r\n            const frameUrl = `${baseUrl}/frame_${i.toString().padStart(3, '0')}.jpg`;\r\n            loadPromises.push(this.loadFrame(frameUrl, i - 1));\r\n        }\r\n        \r\n        // İlk birkaç frame hemen, kalanlar arka planda yüklenir\r\n        await Promise.all(loadPromises.slice(0, 8));\r\n        \r\n        // Kalanlar arka planda yüklenir\r\n        Promise.all(loadPromises.slice(8));\r\n        \r\n        this.isLoading = false;\r\n        this.displayFrame(0);\r\n    }\r\n    \r\n    loadFrame(url, index) {\r\n        return new Promise((resolve) => {\r\n            const img = new Image();\r\n            img.onload = () => {\r\n                this.frames[index] = img;\r\n                resolve();\r\n            };\r\n            img.onerror = () => {\r\n                // Başarısız yükleme için placeholder\r\n                this.frames[index] = null;\r\n                resolve();\r\n            };\r\n            img.src = url;\r\n        });\r\n    }\r\n    \r\n    displayFrame(frameIndex) {\r\n        if (!this.frames[frameIndex]) return;\r\n        \r\n        const img = this.container.querySelector('.view-360-image') || \r\n                   this.createImageElement();\r\n        \r\n        img.src = this.frames[frameIndex].src;\r\n        this.currentFrame = frameIndex;\r\n    }\r\n    \r\n    createImageElement() {\r\n        const img = document.createElement('img');\r\n        img.className = 'view-360-image';\r\n        img.style.cssText = 'width: 100%; height: auto; display: block;';\r\n        this.container.appendChild(img);\r\n        return img;\r\n    }\r\n    \r\n    setupInteraction() {\r\n        let isDragging = false;\r\n        let startX = 0;\r\n        let startFrame = 0;\r\n        \r\n        this.container.addEventListener('mousedown', (e) => {\r\n            isDragging = true;\r\n            startX = e.clientX;\r\n            startFrame = this.currentFrame;\r\n            e.preventDefault();\r\n        });\r\n        \r\n        document.addEventListener('mousemove', (e) => {\r\n            if (!isDragging) return;\r\n            \r\n            const deltaX = e.clientX - startX;\r\n            const sensitivity = 2; // Frame başına piksel\r\n            const frameChange = Math.floor(deltaX / sensitivity);\r\n            \r\n            let newFrame = (startFrame + frameChange) % this.frameCount;\r\n            if (newFrame \u003C 0) newFrame += this.frameCount;\r\n            \r\n            this.displayFrame(newFrame);\r\n        });\r\n        \r\n        document.addEventListener('mouseup', () => {\r\n            isDragging = false;\r\n        });\r\n    }\r\n}\r\n```\r\n\r\n## Performans Takibi ve Analitik\r\n\r\n### E-ticaret Görsel Performansını İzleme\r\n\r\nE-ticaret için kapsamlı görsel performans takibi:\r\n\r\n```javascript\r\nclass EcommerceImageAnalytics {\r\n    constructor() {\r\n        this.metrics = {\r\n            imageLoadTimes: [],\r\n            conversionTracking: new Map(),\r\n            userInteractions: [],\r\n            performanceImpact: []\r\n        };\r\n        \r\n        this.startMonitoring();\r\n    }\r\n    \r\n    startMonitoring() {\r\n        // Görsel yükleme performansını izle\r\n        new PerformanceObserver((list) => {\r\n            const entries = list.getEntries();\r\n            entries.forEach(entry => {\r\n                if (this.isProductImage(entry.name)) {\r\n                    this.trackImagePerformance(entry);\r\n                }\r\n            });\r\n        }).observe({ entryTypes: ['resource'] });\r\n        \r\n        // Kullanıcı etkileşimlerini takip et\r\n        this.trackImageInteractions();\r\n        \r\n        // Dönüşümle korelasyonu takip et\r\n        this.trackConversionCorrelation();\r\n    }\r\n    \r\n    isProductImage(url) {\r\n        return url.includes('/products/') || \r\n               url.includes('product-images') ||\r\n               url.match(/\\/(hero|gallery|thumbnail|zoom)\\//);\r\n    }\r\n    \r\n    trackImagePerformance(entry) {\r\n        const imageData = {\r\n            url: entry.name,\r\n            loadTime: entry.responseEnd - entry.requestStart,\r\n            fileSize: entry.transferSize,\r\n            renderTime: entry.responseEnd,\r\n            imageType: this.categorizeImage(entry.name),\r\n            timestamp: Date.now()\r\n        };\r\n        \r\n        this.metrics.imageLoadTimes.push(imageData);\r\n        \r\n        // Yavaş yüklenen görseli analitik servisine gönder\r\n        if (imageData.loadTime > 2000) {\r\n            this.reportSlowImage(imageData);\r\n        }\r\n    }\r\n    \r\n    categorizeImage(url) {\r\n        if (url.includes('hero')) return 'hero';\r\n        if (url.includes('thumbnail')) return 'thumbnail';\r\n        if (url.includes('gallery')) return 'gallery';\r\n        if (url.includes('zoom')) return 'zoom';\r\n        return 'other';\r\n    }\r\n    \r\n    trackImageInteractions() {\r\n        // Zoom kullanımını takip et\r\n        document.addEventListener('mouseenter', (e) => {\r\n            if (e.target.classList.contains('zoomable-image')) {\r\n                this.recordInteraction('zoom_hover', e.target);\r\n            }\r\n        });\r\n        \r\n        // Galeri tıklamalarını takip et\r\n        document.addEventListener('click', (e) => {\r\n            if (e.target.classList.contains('gallery-thumbnail')) {\r\n                this.recordInteraction('gallery_click', e.target);\r\n            }\r\n        });\r\n        \r\n        // 360° görünüm etkileşimlerini takip et\r\n        document.addEventListener('mousedown', (e) => {\r\n            if (e.target.closest('.view-360')) {\r\n                this.recordInteraction('360_interact', e.target);\r\n            }\r\n        });\r\n    }\r\n    \r\n    recordInteraction(type, element) {\r\n        const interaction = {\r\n            type: type,\r\n            productId: element.dataset.productId || this.extractProductId(element),\r\n            timestamp: Date.now(),\r\n            elementSrc: element.src || element.dataset.src,\r\n            loadTime: this.getImageLoadTime(element.src)\r\n        };\r\n        \r\n        this.metrics.userInteractions.push(interaction);\r\n    }\r\n    \r\n    trackConversionCorrelation() {\r\n        // Görsel etkileşimi sonrası sepete eklemeyi takip et\r\n        document.addEventListener('click', (e) => {\r\n            if (e.target.matches('.add-to-cart, .buy-now')) {\r\n                const productId = this.extractProductId(e.target);\r\n                this.correlateWithImageInteractions(productId);\r\n            }\r\n        });\r\n    }\r\n    \r\n    correlateWithImageInteractions(productId) {\r\n        const recentInteractions = this.metrics.userInteractions\r\n            .filter(interaction => \r\n                interaction.productId === productId &&\r\n                Date.now() - interaction.timestamp \u003C 300000 // Son 5 dakika\r\n            );\r\n        \r\n        if (recentInteractions.length > 0) {\r\n            this.metrics.conversionTracking.set(productId, {\r\n                interactions: recentInteractions,\r\n                conversionTime: Date.now()\r\n            });\r\n        }\r\n    }\r\n    \r\n    generatePerformanceReport() {\r\n        const avgLoadTime = this.calculateAverageLoadTime();\r\n        const slowImages = this.identifySlowImages();\r\n        const interactionCorrelation = this.analyzeInteractionCorrelation();\r\n        \r\n        return {\r\n            averageImageLoadTime: avgLoadTime,\r\n            slowestImages: slowImages,\r\n            interactionToConversionRate: interactionCorrelation,\r\n            recommendations: this.generateRecommendations(avgLoadTime, slowImages)\r\n        };\r\n    }\r\n    \r\n    calculateAverageLoadTime() {\r\n        const loadTimes = this.metrics.imageLoadTimes.map(img => img.loadTime);\r\n        return loadTimes.reduce((sum, time) => sum + time, 0) / loadTimes.length;\r\n    }\r\n    \r\n    identifySlowImages() {\r\n        return this.metrics.imageLoadTimes\r\n            .filter(img => img.loadTime > 2000)\r\n            .sort((a, b) => b.loadTime - a.loadTime)\r\n            .slice(0, 10);\r\n    }\r\n    \r\n    analyzeInteractionCorrelation() {\r\n        const totalInteractions = this.metrics.userInteractions.length;\r\n        const conversionsWithInteractions = this.metrics.conversionTracking.size;\r\n        \r\n        return totalInteractions > 0 ? \r\n            (conversionsWithInteractions / totalInteractions) * 100 : 0;\r\n    }\r\n    \r\n    generateRecommendations(avgLoadTime, slowImages) {\r\n        const recommendations = [];\r\n        \r\n        if (avgLoadTime > 1500) {\r\n            recommendations.push('Daha agresif görsel sıkıştırmayı düşünün');\r\n            recommendations.push('Daha iyi sıkıştırma için WebP formatını kullanın');\r\n        }\r\n        \r\n        if (slowImages.length > 0) {\r\n            recommendations.push('En yavaş yüklenen ürün görsellerini optimize edin');\r\n            recommendations.push('Galeri görselleri için lazy loading uygulayın');\r\n        }\r\n        \r\n        const heroImages = slowImages.filter(img => img.imageType === 'hero');\r\n        if (heroImages.length > 0) {\r\n            recommendations.push('İlk izlenim için ana görselin optimizasyonuna öncelik verin');\r\n        }\r\n        \r\n        return recommendations;\r\n    }\r\n    \r\n    extractProductId(element) {\r\n        // Ürün ID'sini almak için farklı yöntemler deneyin\r\n        return element.dataset.productId ||\r\n               element.closest('[data-product-id]')?.dataset.productId ||\r\n               window.location.pathname.match(/\\/products\\/([^\\/]+)/)?.[1] ||\r\n               'unknown';\r\n    }\r\n    \r\n    getImageLoadTime(src) {\r\n        const imageMetric = this.metrics.imageLoadTimes.find(img => img.url.includes(src));\r\n        return imageMetric ? imageMetric.loadTime : null;\r\n    }\r\n    \r\n    reportSlowImage(imageData) {\r\n        // Analitik servisine gönder\r\n        if (typeof gtag !== 'undefined') {\r\n            gtag('event', 'slow_image_load', {\r\n                'url': imageData.url,\r\n                'load_time': imageData.loadTime,\r\n                'file_size': imageData.fileSize,\r\n                'image_type': imageData.imageType\r\n            });\r\n        }\r\n    }\r\n}\r\n\r\n// Analitik başlatma\r\nconst imageAnalytics = new EcommerceImageAnalytics();\r\n\r\n// Periyodik rapor oluşturma\r\nsetInterval(() => {\r\n    const report = imageAnalytics.generatePerformanceReport();\r\n    console.log('E-ticaret görsel performans raporu:', report);\r\n}, 300000); // Her 5 dakikada bir\r\n```\r\n\r\n## Sonuç\r\n\r\nE-ticaret ürün görsellerinin optimizasyonu, çevrimiçi perakende başarısında kritik bir faktördür ve doğrudan dönüşüm, kullanıcı deneyimi ve arama sıralamasını etkiler. Anahtar, farklı ürün kategorileri ve platformların özelliklerini dikkate alarak görsel kalitesi ile performans arasında optimum dengeyi bulmaktır.\r\n\r\nBaşarılı e-ticaret görsel optimizasyonu şunları gerektirir:\r\n\r\n1. **Kategoriye özel yaklaşımlar**: Farklı ürün türleri farklı optimizasyon stratejileri gerektirir\r\n2. **Platform uyumluluğu**: Pazar yeri gereksinimlerini anlama ve uygulama\r\n3. **Performans takibi**: Görsel performansı ve kullanıcı davranışını sürekli izleme\r\n4. **Gelişmiş yükleme stratejileri**: Kullanıcı ve cihaz bağlamına göre akıllı yükleme\r\n5. **Kaliteyi koruma**: Dosya boyutunu optimize ederken görsel çekiciliği sürdürme\r\n\r\nE-ticaret, AR ürün görselleştirme, daha verimli sıkıştırma algoritmaları ve gelişmiş mobil deneyim gibi yeni teknolojilerle geliştikçe, modern optimizasyon yöntemleri ve dönüşüm odaklılık rekabet avantajı için anahtar olmaya devam edecektir.\r\n\r\nE-ticaret görsel optimizasyonunun geleceği, görsel kaliteyi koruyarak kullanıcı davranışı, cihaz yetenekleri ve dönüşüm kalıplarına göre otomatik olarak optimize edebilen, satışları ve müşteri memnuniyetini artıran yapay zeka tabanlı sistemlerde yatmaktadır.\r\n","# Komprimering av produktbilder för e-handel: optimering för försäljning\r\n\r\nFramgång inom e-handel är starkt beroende av kvaliteten på produktbilder: studier visar att 67 % av konsumenterna anser att bildkvalitet är \"mycket viktigt\" vid onlineköp. Stora bildfiler kan dock avsevärt påverka sidladdningstider, konverteringar och mobilupplevelse. Denna detaljerade guide täcker avancerade metoder för att optimera produktbilder för e-handel samtidigt som den visuella kvaliteten som krävs för att öka försäljningen bibehålls.\r\n\r\n## Varför bildoptimering för e-handel är viktigt\r\n\r\n### Påverkan på konvertering\r\n\r\nOptimering av produktbilder påverkar direkt affärsresultat:\r\n- **Konvertering**: 1 sekunds fördröjning i sidladdning minskar konverteringen med 7 %\r\n- **Avvisningsfrekvens**: 40 % av användarna lämnar webbplatser som tar mer än 3 sekunder att ladda\r\n- **Mobilhandel**: 73 % av e-handelstrafiken kommer från mobila enheter\r\n- **Sökrankning**: Google tar hänsyn till sidladdningshastighet vid rankning\r\n- **Kundnöjdhet**: högkvalitativa bilder ökar förtroendet för köp\r\n\r\n### Specifika krav för e-handel\r\n\r\nProduktbilder har unika optimeringsutmaningar:\r\n- **Flera produktvyer**: huvudbild, miniatyrer, zoom, 360°-vy\r\n- **Färgåtergivning**: avgörande för mode, kosmetika och heminredning\r\n- **Detaljbevarande**: kunder vill se textur, material och hantverk\r\n- **Laddningsprestanda**: balans mellan kvalitet och hastighet\r\n- **Plattformsoberoende**: enhetlig upplevelse på alla enheter\r\n\r\n## Typer av bilder för e-handel\r\n\r\n### Kategorier av produktbilder\r\n\r\nOlika bildtyper kräver olika optimeringsstrategier:\r\n\r\n```javascript\r\nconst ecommerceImageTypes = {\r\n    hero: {\r\n        purpose: 'Huvudvisning av produkten',\r\n        requirements: 'Hög kvalitet, snabb laddning',\r\n        sizes: ['1200x1200', '800x800', '600x600'],\r\n        quality: { jpeg: 85, webp: 80 }\r\n    },\r\n    thumbnail: {\r\n        purpose: 'Produktgalleri',\r\n        requirements: 'Liten filstorlek, igenkänning',\r\n        sizes: ['300x300', '200x200', '150x150'],\r\n        quality: { jpeg: 75, webp: 70 }\r\n    },\r\n    zoom: {\r\n        purpose: 'Detaljerad produktvy',\r\n        requirements: 'Maximalt detaljbevarande',\r\n        sizes: ['2000x2000', '1600x1600'],\r\n        quality: { jpeg: 90, webp: 85 }\r\n    },\r\n    gallery: {\r\n        purpose: 'Flera produktvyer',\r\n        requirements: 'Stabil kvalitet, fördröjd laddning',\r\n        sizes: ['800x800', '600x600'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    },\r\n    lifestyle: {\r\n        purpose: 'Produkten i användning/sammanhang',\r\n        requirements: 'Optimering för känsla/sammanhang',\r\n        sizes: ['1200x800', '800x533'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    }\r\n};\r\n```\r\n\r\n### Optimeringsstrategi per produktkategori\r\n\r\nOlika produktkategorier har sina egna bildkrav:\r\n\r\n```python\r\ndef get_category_optimization_settings(product_category):\r\n    \"\"\"Hämta optimeringsinställningar för olika produktkategorier\"\"\"\r\n    settings = {\r\n        'fashion': {\r\n            'priority': ['färgåtergivning', 'texturdetaljer'],\r\n            'format_preference': 'webp_med_fallback_jpeg',\r\n            'quality_range': {'min': 80, 'max': 90},\r\n            'critical_views': ['framifrån', 'bakifrån', 'detaljer']\r\n        },\r\n        'electronics': {\r\n            'priority': ['detaljbevarande', 'snabb_laddning'],\r\n            'format_preference': 'webp_eller_avif',\r\n            'quality_range': {'min': 75, 'max': 85},\r\n            'critical_views': ['huvud', 'anslutningar', 'storleksjämförelse']\r\n        },\r\n        'home_decor': {\r\n            'priority': ['färgåtergivning', 'användningssammanhang'],\r\n            'format_preference': 'webp_med_fallback_jpeg',\r\n            'quality_range': {'min': 80, 'max': 88},\r\n            'critical_views': ['interiör', 'närbild', 'mått']\r\n        },\r\n        'jewelry': {\r\n            'priority': ['maximal_detalj', 'färgåtergivning'],\r\n            'format_preference': 'png_för_detaljer_webp_för_hero',\r\n            'quality_range': {'min': 85, 'max': 95},\r\n            'critical_views': ['makro', '360_vy', 'lifestyle']\r\n        },\r\n        'books': {\r\n            'priority': ['snabb_laddning', 'textläsbarhet'],\r\n            'format_preference': 'webp_aggressiv_komprimering',\r\n            'quality_range': {'min': 70, 'max': 80},\r\n            'critical_views': ['omslag', 'baksida', 'rygg']\r\n        }\r\n    }\r\n    return settings.get(product_category, settings['electronics'])\r\n```\r\n\r\n## Avancerad bildbehandling för produkter\r\n\r\n### Automatiserad pipeline för bildbehandling\r\n\r\nEtt komplett system för automatiserad bildbehandling:\r\n\r\n```python\r\nimport os\r\nfrom PIL import Image, ImageEnhance, ImageFilter\r\nimport numpy as np\r\n\r\nclass EcommerceImageProcessor:\r\n    def __init__(self, config=None):\r\n        self.config = config or self.get_default_config()\r\n        self.supported_formats = ['jpeg', 'webp', 'avif', 'png']\r\n        \r\n    def get_default_config(self):\r\n        return {\r\n            'background_removal': True,\r\n            'auto_crop': True,\r\n            'color_enhancement': True,\r\n            'noise_reduction': True,\r\n            'watermark': False,\r\n            'quality_thresholds': {\r\n                'hero': 85,\r\n                'gallery': 80,\r\n                'thumbnail': 75,\r\n                'zoom': 90\r\n            }\r\n        }\r\n    \r\n    def process_product_image(self, input_path, output_dir, product_id):\r\n        \"\"\"Bearbeta en produktbild till alla nödvändiga varianter\"\"\"\r\n        img = Image.open(input_path)\r\n        \r\n        # Grundläggande förbehandling\r\n        processed_img = self.preprocess_image(img)\r\n        \r\n        # Generera alla nödvändiga storlekar och format\r\n        variants = self.generate_image_variants(processed_img, product_id)\r\n        \r\n        # Spara optimerade versioner\r\n        saved_files = self.save_variants(variants, output_dir)\r\n        \r\n        return saved_files\r\n    \r\n    def preprocess_image(self, img):\r\n        \"\"\"Grundläggande förbehandling av produktbild\"\"\"\r\n        # Konvertera till RGB vid behov\r\n        if img.mode in ('RGBA', 'LA', 'P'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            if img.mode == 'RGBA':\r\n                background.paste(img, mask=img.split()[-1])\r\n            else:\r\n                background.paste(img)\r\n            img = background\r\n        \r\n        # Automatisk beskärning för att ta bort överflödig bakgrund\r\n        if self.config['auto_crop']:\r\n            img = self.smart_crop(img)\r\n        \r\n        # Förbättra bildkvaliteten\r\n        if self.config['color_enhancement']:\r\n            img = self.enhance_product_image(img)\r\n        \r\n        # Minska brus\r\n        if self.config['noise_reduction']:\r\n            img = img.filter(ImageFilter.SMOOTH_MORE)\r\n        \r\n        return img\r\n    \r\n    def smart_crop(self, img):\r\n        \"\"\"Smart beskärning för att ta bort överflödig bakgrund\"\"\"\r\n        # Konvertera till numpy-array för analys\r\n        img_array = np.array(img)\r\n        \r\n        # Hitta begränsningsrektangel för icke-vita pixlar\r\n        mask = np.any(img_array \u003C 240, axis=2)  # Inte helt vit\r\n        coords = np.argwhere(mask)\r\n        \r\n        if len(coords) == 0:\r\n            return img  # Ingen beskärning behövs\r\n        \r\n        # Hämta begränsningsrektangel\r\n        y0, x0 = coords.min(axis=0)\r\n        y1, x1 = coords.max(axis=0)\r\n        \r\n        # Lägg till marginal\r\n        padding = 20\r\n        y0 = max(0, y0 - padding)\r\n        x0 = max(0, x0 - padding)\r\n        y1 = min(img.height, y1 + padding)\r\n        x1 = min(img.width, x1 + padding)\r\n        \r\n        return img.crop((x0, y0, x1, y1))\r\n    \r\n    def enhance_product_image(self, img):\r\n        \"\"\"Förbättra produktbild för e-handel\"\"\"\r\n        # Lätt ökning av ljusstyrka\r\n        brightness_enhancer = ImageEnhance.Brightness(img)\r\n        img = brightness_enhancer.enhance(1.05)\r\n        \r\n        # Öka kontrasten\r\n        contrast_enhancer = ImageEnhance.Contrast(img)\r\n        img = contrast_enhancer.enhance(1.1)\r\n        \r\n        # Öka färgmättnaden\r\n        color_enhancer = ImageEnhance.Color(img)\r\n        img = color_enhancer.enhance(1.05)\r\n        \r\n        # Öka skärpan\r\n        sharpness_enhancer = ImageEnhance.Sharpness(img)\r\n        img = sharpness_enhancer.enhance(1.1)\r\n        \r\n        return img\r\n    \r\n    def generate_image_variants(self, img, product_id):\r\n        \"\"\"Generera alla nödvändiga bildvarianter\"\"\"\r\n        variants = {}\r\n        \r\n        # Standardstorlekar för e-handel\r\n        sizes = {\r\n            'hero': (1200, 1200),\r\n            'gallery': (800, 800),\r\n            'thumbnail': (300, 300),\r\n            'zoom': (2000, 2000),\r\n            'mobile_hero': (600, 600),\r\n            'mobile_thumb': (150, 150)\r\n        }\r\n        \r\n        for variant_name, size in sizes.items():\r\n            # Ändra storlek med högkvalitativ omprovning\r\n            resized = img.resize(size, Image.Resampling.LANCZOS)\r\n            variants[variant_name] = resized\r\n        \r\n        return variants\r\n    \r\n    def save_variants(self, variants, output_dir):\r\n        \"\"\"Spara alla varianter i optimerade format\"\"\"\r\n        saved_files = []\r\n        \r\n        for variant_name, img in variants.items():\r\n            base_path = os.path.join(output_dir, variant_name)\r\n            \r\n            # Spara i flera format\r\n            for format_type in ['jpeg', 'webp']:\r\n                filename = f\"{base_path}.{format_type}\"\r\n                quality = self.get_quality_for_variant(variant_name, format_type)\r\n                \r\n                if format_type == 'jpeg':\r\n                    img.save(filename, 'JPEG', quality=quality, optimize=True, progressive=True)\r\n                elif format_type == 'webp':\r\n                    img.save(filename, 'WebP', quality=quality, optimize=True)\r\n                \r\n                saved_files.append(filename)\r\n        \r\n        return saved_files\r\n    \r\n    def get_quality_for_variant(self, variant_name, format_type):\r\n        \"\"\"Hämta optimal kvalitet för variant och format\"\"\"\r\n        base_quality = self.config['quality_thresholds'].get(variant_name, 80)\r\n        \r\n        # Justering för format\r\n        if format_type == 'webp':\r\n            return base_quality - 5  # WebP ger samma kvalitet vid lägre värde\r\n        elif format_type == 'avif':\r\n            return base_quality - 10  # AVIF är ännu effektivare\r\n        \r\n        return base_quality\r\n\r\n# Exempel på användning\r\nprocessor = EcommerceImageProcessor()\r\nprocessor.process_product_image('product_raw.jpg', 'output/', 'product_123')\r\n```\r\n\r\n### Borttagning och standardisering av bakgrund\r\n\r\nAutomatiserad bakgrundshantering för enhetlig produktvisning:\r\n\r\n```python\r\ndef remove_product_background(image_path, output_path):\r\n    \"\"\"Ta bort bakgrund från produktbild med kantdetektering\"\"\"\r\n    import cv2\r\n    import numpy as np\r\n    \r\n    # Läs in bilden\r\n    img = cv2.imread(image_path)\r\n    original = img.copy()\r\n    \r\n    # Konvertera till gråskala\r\n    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\r\n    \r\n    # Gaussisk suddighet för att minska brus\r\n    blurred = cv2.GaussianBlur(gray, (5, 5), 0)\r\n    \r\n    # Kantdetektering\r\n    edges = cv2.Canny(blurred, 50, 150)\r\n    \r\n    # Hitta konturer\r\n    contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\r\n    \r\n    if contours:\r\n        # Hitta den största konturen (förmodligen produkten)\r\n        largest_contour = max(contours, key=cv2.contourArea)\r\n        \r\n        # Skapa mask\r\n        mask = np.zeros(gray.shape, np.uint8)\r\n        cv2.fillPoly(mask, [largest_contour], 255)\r\n        \r\n        # Applicera masken på originalbilden\r\n        result = cv2.bitwise_and(original, original, mask=mask)\r\n        \r\n        # Byt ut bakgrunden mot vit\r\n        result[mask == 0] = [255, 255, 255]\r\n        \r\n        cv2.imwrite(output_path, result)\r\n        return True\r\n    \r\n    return False\r\n\r\ndef standardize_product_backgrounds(input_dir, output_dir, background_color=(255, 255, 255)):\r\n    \"\"\"Standardisera alla produktbakgrunder till en enhetlig färg\"\"\"\r\n    for filename in os.listdir(input_dir):\r\n        if filename.lower().endswith(('.jpg', '.jpeg', '.png')):\r\n            input_path = os.path.join(input_dir, filename)\r\n            output_path = os.path.join(output_dir, filename)\r\n            \r\n            # Försök ta bort bakgrunden automatiskt\r\n            if not remove_product_background(input_path, output_path):\r\n                # Alternativ: bara vit bakgrund\r\n                img = Image.open(input_path)\r\n                if img.mode == 'RGBA':\r\n                    background = Image.new('RGB', img.size, background_color)\r\n                    background.paste(img, mask=img.split()[-1])\r\n                    background.save(output_path, 'JPEG', quality=85)\r\n                else:\r\n                    img.save(output_path)\r\n```\r\n\r\n## Optimering för plattform\r\n\r\n### Optimering för Amazon Marketplace\r\n\r\nAmazon har särskilda bildkrav och använder egna algoritmer:\r\n\r\n```python\r\nclass AmazonImageOptimizer:\r\n    def __init__(self):\r\n        self.requirements = {\r\n            'main_image': {\r\n                'min_size': (1000, 1000),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'background': 'pure_white',\r\n                'product_coverage': 85  # Minsta procent av bilden\r\n            },\r\n            'additional_images': {\r\n                'min_size': (500, 500),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'lifestyle_allowed': True\r\n            }\r\n        }\r\n    \r\n    def optimize_for_amazon(self, image_path, output_path, image_type='main'):\r\n        \"\"\"Optimera bild specifikt för Amazon-listning\"\"\"\r\n        img = Image.open(image_path)\r\n        \r\n        if image_type == 'main':\r\n            img = self.ensure_white_background(img)\r\n            img = self.ensure_minimum_size(img, (1000, 1000))\r\n        \r\n        # Amazon föredrar färgrymden sRGB\r\n        if img.mode != 'RGB':\r\n            img = img.convert('RGB')\r\n        \r\n        # Optimera filstorlek med bibehållen kvalitet\r\n        quality = 90 if image_type == 'main' else 85\r\n        img.save(output_path, 'JPEG', quality=quality, optimize=True)\r\n        \r\n        return self.validate_amazon_requirements(output_path, image_type)\r\n    \r\n    def ensure_white_background(self, img):\r\n        \"\"\"Säkerställ att bilden har helt vit bakgrund\"\"\"\r\n        if img.mode == 'RGBA':\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            background.paste(img, mask=img.split()[-1])\r\n            return background\r\n        return img\r\n    \r\n    def ensure_minimum_size(self, img, min_size):\r\n        \"\"\"Säkerställ att bilden uppfyller minimistorlek\"\"\"\r\n        if img.size[0] \u003C min_size[0] or img.size[1] \u003C min_size[1]:\r\n            img = img.resize(min_size, Image.Resampling.LANCZOS)\r\n        return img\r\n    \r\n    def validate_amazon_requirements(self, image_path, image_type):\r\n        \"\"\"Validera att bilden uppfyller Amazons krav\"\"\"\r\n        img = Image.open(image_path)\r\n        requirements = self.requirements[image_type]\r\n        \r\n        validation_results = {\r\n            'size_valid': (\r\n                img.size[0] >= requirements['min_size'][0] and \r\n                img.size[1] >= requirements['min_size'][1]\r\n            ),\r\n            'format_valid': image_path.upper().endswith(tuple(requirements['formats'])),\r\n            'file_size_valid': os.path.getsize(image_path) \u003C= 10 * 1024 * 1024  # Gräns 10 MB\r\n        }\r\n        \r\n        return all(validation_results.values()), validation_results\r\n```\r\n\r\n### Optimering för Shopify-butiker\r\n\r\nOptimering för Shopify-teman och prestanda:\r\n\r\n```javascript\r\nclass ShopifyImageOptimizer {\r\n    constructor() {\r\n        this.themeRequirements = {\r\n            'product_card': { width: 600, height: 600, quality: 80 },\r\n            'product_detail': { width: 1200, height: 1200, quality: 85 },\r\n            'product_zoom': { width: 2048, height: 2048, quality: 90 },\r\n            'collection_featured': { width: 800, height: 600, quality: 80 }\r\n        };\r\n    }\r\n    \r\n    generateShopifyImageUrls(baseImageUrl, productHandle) {\r\n        const urls = {};\r\n        \r\n        Object.entries(this.themeRequirements).forEach(([variant, specs]) => {\r\n            // Skapa URL för Shopifys bildtransformation\r\n            const transformedUrl = baseImageUrl.replace('.jpg', \r\n                `_${specs.width}x${specs.height}_crop_center.jpg`);\r\n            urls[variant] = transformedUrl;\r\n        });\r\n        \r\n        return urls;\r\n    }\r\n    \r\n    generateShopifyPictureElement(productData) {\r\n        const { images, title, handle } = productData;\r\n        const mainImage = images[0];\r\n        \r\n        return `\r\n            \u003Cpicture>\r\n                \u003Csource media=\"(min-width: 1200px)\" \r\n                        srcset=\"${mainImage}_1200x1200.webp 1x, ${mainImage}_2400x2400.webp 2x\"\r\n                        type=\"image/webp\">\r\n                \u003Csource media=\"(min-width: 768px)\" \r\n                        srcset=\"${mainImage}_800x800.webp 1x, ${mainImage}_1600x1600.webp 2x\"\r\n                        type=\"image/webp\">\r\n                \u003Csource media=\"(max-width: 767px)\" \r\n                        srcset=\"${mainImage}_600x600.webp 1x, ${mainImage}_1200x1200.webp 2x\"\r\n                        type=\"image/webp\">\r\n                \u003Cimg src=\"${mainImage}_800x800.jpg\"\r\n                     srcset=\"${mainImage}_400x400.jpg 400w,\r\n                             ${mainImage}_600x600.jpg 600w,\r\n                             ${mainImage}_800x800.jpg 800w,\r\n                             ${mainImage}_1200x1200.jpg 1200w\"\r\n                     sizes=\"(max-width: 767px) 100vw, (max-width: 1023px) 50vw, 33vw\"\r\n                     alt=\"${title}\"\r\n                     loading=\"lazy\"\r\n                     data-product-handle=\"${handle}\">\r\n            \u003C/picture>\r\n        `;\r\n    }\r\n}\r\n```\r\n\r\n## Avancerade laddningsstrategier för e-handel\r\n\r\n### Smart laddning av produktbilder\r\n\r\nSmart laddning baserat på användarbeteende och enhetskapacitet:\r\n\r\n```javascript\r\nclass EcommerceImageLoader {\r\n    constructor() {\r\n        this.userBehavior = this.trackUserBehavior();\r\n        this.deviceCapabilities = this.analyzeDevice();\r\n        this.loadingStrategies = this.initializeStrategies();\r\n    }\r\n    \r\n    trackUserBehavior() {\r\n        return {\r\n            isReturningCustomer: localStorage.getItem('visited') === 'true',\r\n            viewingHistory: JSON.parse(localStorage.getItem('viewedProducts') || '[]'),\r\n            averageSessionTime: parseInt(localStorage.getItem('avgSessionTime') || '0'),\r\n            purchaseHistory: JSON.parse(localStorage.getItem('purchases') || '[]')\r\n        };\r\n    }\r\n    \r\n    analyzeDevice() {\r\n        const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;\r\n        \r\n        return {\r\n            connectionSpeed: connection ? connection.effectiveType : '4g',\r\n            deviceMemory: navigator.deviceMemory || 4,\r\n            isLowEndDevice: navigator.deviceMemory \u003C 2,\r\n            isMobile: window.innerWidth \u003C= 768,\r\n            isSlowConnection: connection && (connection.effectiveType === 'slow-2g' || connection.effectiveType === '2g')\r\n        };\r\n    }\r\n    \r\n    initializeStrategies() {\r\n        return {\r\n            eager: this.eagerLoadingStrategy.bind(this),\r\n            progressive: this.progressiveLoadingStrategy.bind(this),\r\n            lazy: this.lazyLoadingStrategy.bind(this),\r\n            adaptive: this.adaptiveLoadingStrategy.bind(this)\r\n        };\r\n    }\r\n    \r\n    selectOptimalStrategy(productData, context) {\r\n        const { deviceCapabilities, userBehavior } = this;\r\n        \r\n        // Återkommande kunder med bra uppkoppling\r\n        if (userBehavior.isReturningCustomer && \r\n            userBehavior.purchaseHistory.length > 0 && \r\n            !deviceCapabilities.isSlowConnection) {\r\n            return 'eager';\r\n        }\r\n        \r\n        // Svaga enheter eller långsam uppkoppling\r\n        if (deviceCapabilities.isLowEndDevice || deviceCapabilities.isSlowConnection) {\r\n            return 'lazy';\r\n        }\r\n        \r\n        // Mobila enheter med bra uppkoppling\r\n        if (deviceCapabilities.isMobile && !deviceCapabilities.isSlowConnection) {\r\n            return 'progressive';\r\n        }\r\n        \r\n        // Standard: adaptiv strategi\r\n        return 'adaptive';\r\n    }\r\n    \r\n    eagerLoadingStrategy(productImages) {\r\n        // Ladda alla bilder direkt för premiumupplevelse\r\n        productImages.forEach(img => {\r\n            const imageLoader = new Image();\r\n            imageLoader.src = img.dataset.src;\r\n            \r\n            if (img.dataset.srcset) {\r\n                imageLoader.srcset = img.dataset.srcset;\r\n            }\r\n            \r\n            imageLoader.onload = () => {\r\n                img.src = imageLoader.src;\r\n                if (img.dataset.srcset) {\r\n                    img.srcset = imageLoader.srcset;\r\n                }\r\n                img.classList.add('loaded');\r\n            };\r\n        });\r\n    }\r\n    \r\n    progressiveLoadingStrategy(productImages) {\r\n        // Ladda lågupplöst först, sedan högupplöst\r\n        productImages.forEach(img => {\r\n            // Ladda lågkvalitativ placeholder\r\n            const lowQualitySrc = img.dataset.lowSrc || img.dataset.src.replace('_q85', '_q40');\r\n            const highQualitySrc = img.dataset.src;\r\n            \r\n            img.src = lowQualitySrc;\r\n            img.classList.add('loading');\r\n            \r\n            // Ladda högkvalitativ version\r\n            const highQualityLoader = new Image();\r\n            highQualityLoader.onload = () => {\r\n                img.src = highQualitySrc;\r\n                img.classList.remove('loading');\r\n                img.classList.add('loaded');\r\n            };\r\n            highQualityLoader.src = highQualitySrc;\r\n        });\r\n    }\r\n    \r\n    lazyLoadingStrategy(productImages) {\r\n        // Använd Intersection Observer för fördröjd laddning\r\n        const observer = new IntersectionObserver((entries) => {\r\n            entries.forEach(entry => {\r\n                if (entry.isIntersecting) {\r\n                    this.loadImage(entry.target);\r\n                    observer.unobserve(entry.target);\r\n                }\r\n            });\r\n        }, { rootMargin: '100px' });\r\n        \r\n        productImages.forEach(img => observer.observe(img));\r\n    }\r\n    \r\n    adaptiveLoadingStrategy(productImages) {\r\n        // Anpassa baserat på användarinteraktion och scroll\r\n        let scrollTimeout;\r\n        let isScrolling = false;\r\n        \r\n        window.addEventListener('scroll', () => {\r\n            if (!isScrolling) {\r\n                isScrolling = true;\r\n                // Ladda synliga bilder direkt vid scrollstart\r\n                this.loadVisibleImages(productImages);\r\n            }\r\n            \r\n            clearTimeout(scrollTimeout);\r\n            scrollTimeout = setTimeout(() => {\r\n                isScrolling = false;\r\n            }, 150);\r\n        });\r\n        \r\n        // Ladda kritiska bilder ovanför fold direkt\r\n        this.loadCriticalImages(productImages);\r\n        \r\n        // Fördröjd laddning av övriga bilder\r\n        this.lazyLoadingStrategy(productImages.filter(img => !img.dataset.critical));\r\n    }\r\n    \r\n    loadCriticalImages(productImages) {\r\n        const criticalImages = productImages.filter(img => \r\n            img.dataset.critical === 'true' || \r\n            img.getBoundingClientRect().top \u003C window.innerHeight\r\n        );\r\n        \r\n        criticalImages.forEach(img => this.loadImage(img));\r\n    }\r\n    \r\n    loadVisibleImages(productImages) {\r\n        const visibleImages = productImages.filter(img => {\r\n            const rect = img.getBoundingClientRect();\r\n            return rect.top \u003C window.innerHeight && rect.bottom > 0;\r\n        });\r\n        \r\n        visibleImages.forEach(img => this.loadImage(img));\r\n    }\r\n    \r\n    loadImage(img) {\r\n        if (img.dataset.loaded) return;\r\n        \r\n        const imageLoader = new Image();\r\n        imageLoader.onload = () => {\r\n            img.src = imageLoader.src;\r\n            if (img.dataset.srcset) {\r\n                img.srcset = imageLoader.srcset;\r\n            }\r\n            img.classList.add('loaded');\r\n            img.dataset.loaded = 'true';\r\n        };\r\n        \r\n        imageLoader.src = img.dataset.src;\r\n    }\r\n}\r\n\r\n// Initiering för produktsidor\r\n// document.addEventListener('DOMContentLoaded', () => {\r\n//     const imageLoader = new EcommerceImageLoader();\r\n//     const productImages = document.querySelectorAll('.product-image[data-src]');\r\n//     \r\n//     if (productImages.length > 0) {\r\n//         const strategy = imageLoader.selectOptimalStrategy();\r\n//         imageLoader.loadingStrategies[strategy](productImages);\r\n//     }\r\n// });\r\n```\r\n\r\n## Optimering av zoom och 360°-vy\r\n\r\n### Effektiv implementation av zoom\r\n\r\nOptimerad zoomfunktion för produktsidor:\r\n\r\n```javascript\r\nclass ProductImageZoom {\r\n    constructor(options = {}) {\r\n        this.container = options.container;\r\n        this.zoomLevel = options.zoomLevel || 2;\r\n        this.loadingStrategy = options.loadingStrategy || 'on-demand';\r\n        this.highResImages = new Map();\r\n        \r\n        this.initializeZoom();\r\n    }\r\n    \r\n    initializeZoom() {\r\n        const zoomImages = this.container.querySelectorAll('.zoomable-image');\r\n        \r\n        zoomImages.forEach(img => {\r\n            img.addEventListener('mouseenter', this.handleMouseEnter.bind(this));\r\n            img.addEventListener('mouseleave', this.handleMouseLeave.bind(this));\r\n            img.addEventListener('mousemove', this.handleMouseMove.bind(this));\r\n        });\r\n    }\r\n    \r\n    async handleMouseEnter(event) {\r\n        const img = event.target;\r\n        const highResUrl = img.dataset.zoomSrc;\r\n        \r\n        if (!highResUrl) return;\r\n        \r\n        // Ladda högupplöst bild vid behov\r\n        if (!this.highResImages.has(highResUrl)) {\r\n            this.loadHighResImage(highResUrl);\r\n        }\r\n        \r\n        this.showZoomOverlay(img);\r\n    }\r\n    \r\n    loadHighResImage(url) {\r\n        return new Promise((resolve, reject) => {\r\n            const img = new Image();\r\n            img.onload = () => {\r\n                this.highResImages.set(url, img);\r\n                resolve(img);\r\n            };\r\n            img.onerror = reject;\r\n            img.src = url;\r\n        });\r\n    }\r\n    \r\n    showZoomOverlay(img) {\r\n        // Skapa overlay för zoom om det inte finns\r\n        let overlay = img.parentNode.querySelector('.zoom-overlay');\r\n        if (!overlay) {\r\n            overlay = document.createElement('div');\r\n            overlay.className = 'zoom-overlay';\r\n            overlay.style.cssText = `\r\n                position: absolute;\r\n                top: 0;\r\n                left: 100%;\r\n                width: 300px;\r\n                height: 300px;\r\n                border: 1px solid #ddd;\r\n                background: white;\r\n                overflow: hidden;\r\n                z-index: 1000;\r\n                display: none;\r\n            `;\r\n            img.parentNode.appendChild(overlay);\r\n        }\r\n        \r\n        overlay.style.display = 'block';\r\n    }\r\n    \r\n    handleMouseMove(event) {\r\n        const img = event.target;\r\n        const overlay = img.parentNode.querySelector('.zoom-overlay');\r\n        const highResUrl = img.dataset.zoomSrc;\r\n        \r\n        if (!overlay || !this.highResImages.has(highResUrl)) return;\r\n        \r\n        const rect = img.getBoundingClientRect();\r\n        const x = (event.clientX - rect.left) / rect.width;\r\n        const y = (event.clientY - rect.top) / rect.height;\r\n        \r\n        const highResImg = this.highResImages.get(highResUrl);\r\n        \r\n        // Uppdatera zoom-overlay\r\n        overlay.style.backgroundImage = `url(${highResUrl})`;\r\n        overlay.style.backgroundSize = `${highResImg.width}px ${highResImg.height}px`;\r\n        overlay.style.backgroundPosition = `-${x * (highResImg.width - 300)}px -${y * (highResImg.height - 300)}px`;\r\n    }\r\n    \r\n    handleMouseLeave(event) {\r\n        const img = event.target;\r\n        const overlay = img.parentNode.querySelector('.zoom-overlay');\r\n        \r\n        if (overlay) {\r\n            overlay.style.display = 'none';\r\n        }\r\n    }\r\n}\r\n\r\n// Optimering av 360°-vy för produkter\r\nclass Product360View {\r\n    constructor(container, options = {}) {\r\n        this.container = container;\r\n        this.frameCount = options.frameCount || 36;\r\n        this.autoPlay = options.autoPlay || false;\r\n        this.frames = [];\r\n        this.currentFrame = 0;\r\n        this.isLoading = false;\r\n        \r\n        this.initialize();\r\n    }\r\n    \r\n    async initialize() {\r\n        await this.loadFrames();\r\n        this.setupControls();\r\n        this.setupInteraction();\r\n    }\r\n    \r\n    async loadFrames() {\r\n        this.isLoading = true;\r\n        const baseUrl = this.container.dataset.baseUrl;\r\n        \r\n        // Progressiv inläsning av ramar\r\n        const loadPromises = [];\r\n        \r\n        for (let i = 1; i \u003C= this.frameCount; i++) {\r\n            const frameUrl = `${baseUrl}/frame_${i.toString().padStart(3, '0')}.jpg`;\r\n            loadPromises.push(this.loadFrame(frameUrl, i - 1));\r\n        }\r\n        \r\n        // De första ramarna laddas direkt, resten i bakgrunden\r\n        await Promise.all(loadPromises.slice(0, 8));\r\n        \r\n        // Resterande ramar laddas i bakgrunden\r\n        Promise.all(loadPromises.slice(8));\r\n        \r\n        this.isLoading = false;\r\n        this.displayFrame(0);\r\n    }\r\n    \r\n    loadFrame(url, index) {\r\n        return new Promise((resolve) => {\r\n            const img = new Image();\r\n            img.onload = () => {\r\n                this.frames[index] = img;\r\n                resolve();\r\n            };\r\n            img.onerror = () => {\r\n                // Platshållare för misslyckad inläsning\r\n                this.frames[index] = null;\r\n                resolve();\r\n            };\r\n            img.src = url;\r\n        });\r\n    }\r\n    \r\n    displayFrame(frameIndex) {\r\n        if (!this.frames[frameIndex]) return;\r\n        \r\n        const img = this.container.querySelector('.view-360-image') || \r\n                   this.createImageElement();\r\n        \r\n        img.src = this.frames[frameIndex].src;\r\n        this.currentFrame = frameIndex;\r\n    }\r\n    \r\n    createImageElement() {\r\n        const img = document.createElement('img');\r\n        img.className = 'view-360-image';\r\n        img.style.cssText = 'width: 100%; height: auto; display: block;';\r\n        this.container.appendChild(img);\r\n        return img;\r\n    }\r\n    \r\n    setupInteraction() {\r\n        let isDragging = false;\r\n        let startX = 0;\r\n        let startFrame = 0;\r\n        \r\n        this.container.addEventListener('mousedown', (e) => {\r\n            isDragging = true;\r\n            startX = e.clientX;\r\n            startFrame = this.currentFrame;\r\n            e.preventDefault();\r\n        });\r\n        \r\n        document.addEventListener('mousemove', (e) => {\r\n            if (!isDragging) return;\r\n            \r\n            const deltaX = e.clientX - startX;\r\n            const sensitivity = 2; // Pixlar per ram\r\n            const frameChange = Math.floor(deltaX / sensitivity);\r\n            \r\n            let newFrame = (startFrame + frameChange) % this.frameCount;\r\n            if (newFrame \u003C 0) newFrame += this.frameCount;\r\n            \r\n            this.displayFrame(newFrame);\r\n        });\r\n        \r\n        document.addEventListener('mouseup', () => {\r\n            isDragging = false;\r\n        });\r\n    }\r\n}\r\n```\r\n\r\n## Övervakning av prestanda och analys\r\n\r\n### Spåra bildprestanda för e-handel\r\n\r\nOmfattande övervakning av bildprestanda för e-handel:\r\n\r\n```javascript\r\nclass EcommerceImageAnalytics {\r\n    constructor() {\r\n        this.metrics = {\r\n            imageLoadTimes: [],\r\n            conversionTracking: new Map(),\r\n            userInteractions: [],\r\n            performanceImpact: []\r\n        };\r\n        \r\n        this.startMonitoring();\r\n    }\r\n    \r\n    startMonitoring() {\r\n        // Övervaka bildladdningsprestanda\r\n        new PerformanceObserver((list) => {\r\n            const entries = list.getEntries();\r\n            entries.forEach(entry => {\r\n                if (this.isProductImage(entry.name)) {\r\n                    this.trackImagePerformance(entry);\r\n                }\r\n            });\r\n        }).observe({ entryTypes: ['resource'] });\r\n        \r\n        // Spåra användarinteraktioner med bilder\r\n        this.trackImageInteractions();\r\n        \r\n        // Spåra korrelation med konverteringar\r\n        this.trackConversionCorrelation();\r\n    }\r\n    \r\n    isProductImage(url) {\r\n        return url.includes('/products/') || \r\n               url.includes('product-images') ||\r\n               url.match(/\\/(hero|gallery|thumbnail|zoom)\\//);\r\n    }\r\n    \r\n    trackImagePerformance(entry) {\r\n        const imageData = {\r\n            url: entry.name,\r\n            loadTime: entry.responseEnd - entry.requestStart,\r\n            fileSize: entry.transferSize,\r\n            renderTime: entry.responseEnd,\r\n            imageType: this.categorizeImage(entry.name),\r\n            timestamp: Date.now()\r\n        };\r\n        \r\n        this.metrics.imageLoadTimes.push(imageData);\r\n        \r\n        // Skicka till analys om laddningstiden är för lång\r\n        if (imageData.loadTime > 2000) {\r\n            this.reportSlowImage(imageData);\r\n        }\r\n    }\r\n    \r\n    categorizeImage(url) {\r\n        if (url.includes('hero')) return 'hero';\r\n        if (url.includes('thumbnail')) return 'thumbnail';\r\n        if (url.includes('gallery')) return 'gallery';\r\n        if (url.includes('zoom')) return 'zoom';\r\n        return 'other';\r\n    }\r\n    \r\n    trackImageInteractions() {\r\n        // Spåra zoomanvändning\r\n        document.addEventListener('mouseenter', (e) => {\r\n            if (e.target.classList.contains('zoomable-image')) {\r\n                this.recordInteraction('zoom_hover', e.target);\r\n            }\r\n        });\r\n        \r\n        // Spåra galleriinteraktioner\r\n        document.addEventListener('click', (e) => {\r\n            if (e.target.classList.contains('gallery-thumbnail')) {\r\n                this.recordInteraction('gallery_click', e.target);\r\n            }\r\n        });\r\n        \r\n        // Spåra 360°-interaktioner\r\n        document.addEventListener('mousedown', (e) => {\r\n            if (e.target.closest('.view-360')) {\r\n                this.recordInteraction('360_interact', e.target);\r\n            }\r\n        });\r\n    }\r\n    \r\n    recordInteraction(type, element) {\r\n        const interaction = {\r\n            type: type,\r\n            productId: element.dataset.productId || this.extractProductId(element),\r\n            timestamp: Date.now(),\r\n            elementSrc: element.src || element.dataset.src,\r\n            loadTime: this.getImageLoadTime(element.src)\r\n        };\r\n        \r\n        this.metrics.userInteractions.push(interaction);\r\n    }\r\n    \r\n    trackConversionCorrelation() {\r\n        // Spåra tillägg till kundvagn efter bildinteraktion\r\n        document.addEventListener('click', (e) => {\r\n            if (e.target.matches('.add-to-cart, .buy-now')) {\r\n                const productId = this.extractProductId(e.target);\r\n                this.correlateWithImageInteractions(productId);\r\n            }\r\n        });\r\n    }\r\n    \r\n    correlateWithImageInteractions(productId) {\r\n        const recentInteractions = this.metrics.userInteractions\r\n            .filter(interaction => \r\n                interaction.productId === productId &&\r\n                Date.now() - interaction.timestamp \u003C 300000 // Senaste 5 minuterna\r\n            );\r\n        \r\n        if (recentInteractions.length > 0) {\r\n            this.metrics.conversionTracking.set(productId, {\r\n                interactions: recentInteractions,\r\n                conversionTime: Date.now()\r\n            });\r\n        }\r\n    }\r\n    \r\n    generatePerformanceReport() {\r\n        const avgLoadTime = this.calculateAverageLoadTime();\r\n        const slowImages = this.identifySlowImages();\r\n        const interactionCorrelation = this.analyzeInteractionCorrelation();\r\n        \r\n        return {\r\n            averageImageLoadTime: avgLoadTime,\r\n            slowestImages: slowImages,\r\n            interactionToConversionRate: interactionCorrelation,\r\n            recommendations: this.generateRecommendations(avgLoadTime, slowImages)\r\n        };\r\n    }\r\n    \r\n    calculateAverageLoadTime() {\r\n        const loadTimes = this.metrics.imageLoadTimes.map(img => img.loadTime);\r\n        return loadTimes.reduce((sum, time) => sum + time, 0) / loadTimes.length;\r\n    }\r\n    \r\n    identifySlowImages() {\r\n        return this.metrics.imageLoadTimes\r\n            .filter(img => img.loadTime > 2000)\r\n            .sort((a, b) => b.loadTime - a.loadTime)\r\n            .slice(0, 10);\r\n    }\r\n    \r\n    analyzeInteractionCorrelation() {\r\n        const totalInteractions = this.metrics.userInteractions.length;\r\n        const conversionsWithInteractions = this.metrics.conversionTracking.size;\r\n        \r\n        return totalInteractions > 0 ? \r\n            (conversionsWithInteractions / totalInteractions) * 100 : 0;\r\n    }\r\n    \r\n    generateRecommendations(avgLoadTime, slowImages) {\r\n        const recommendations = [];\r\n        \r\n        if (avgLoadTime > 1500) {\r\n            recommendations.push('Överväg mer aggressiv bildkomprimering');\r\n            recommendations.push('Inför WebP-format för bättre komprimering');\r\n        }\r\n        \r\n        if (slowImages.length > 0) {\r\n            recommendations.push('Optimera de långsammaste produktbilderna');\r\n            recommendations.push('Överväg fördröjd laddning för galleribilder');\r\n        }\r\n        \r\n        const heroImages = slowImages.filter(img => img.imageType === 'hero');\r\n        if (heroImages.length > 0) {\r\n            recommendations.push('Prioritera optimering av huvudbilden för bästa första intryck');\r\n        }\r\n        \r\n        return recommendations;\r\n    }\r\n    \r\n    extractProductId(element) {\r\n        // Prova olika metoder för att hämta produkt-ID\r\n        return element.dataset.productId ||\r\n               element.closest('[data-product-id]')?.dataset.productId ||\r\n               window.location.pathname.match(/\\/products\\/([^\\/]+)/)?.[1] ||\r\n               'unknown';\r\n    }\r\n    \r\n    getImageLoadTime(src) {\r\n        const imageMetric = this.metrics.imageLoadTimes.find(img => img.url.includes(src));\r\n        return imageMetric ? imageMetric.loadTime : null;\r\n    }\r\n    \r\n    reportSlowImage(imageData) {\r\n        // Skicka till analysverktyg\r\n        if (typeof gtag !== 'undefined') {\r\n            gtag('event', 'slow_image_load', {\r\n                'url': imageData.url,\r\n                'load_time': imageData.loadTime,\r\n                'file_size': imageData.fileSize,\r\n                'image_type': imageData.imageType\r\n            });\r\n        }\r\n    }\r\n}\r\n\r\n// Initiera analys\r\nconst imageAnalytics = new EcommerceImageAnalytics();\r\n\r\n// Generera rapport periodiskt\r\nsetInterval(() => {\r\n    const report = imageAnalytics.generatePerformanceReport();\r\n    console.log('Prestandarapport för e-handelsbilder:', report);\r\n}, 300000); // Var 5:e minut\r\n```\r\n\r\n## Slutsats\r\n\r\nOptimering av produktbilder för e-handel är en avgörande framgångsfaktor för onlinehandel och påverkar direkt konvertering, användarupplevelse och sökrankning. Nyckeln är att hitta rätt balans mellan bildkvalitet och prestanda, med hänsyn till olika produktkategorier och plattformar.\r\n\r\nFramgångsrik bildoptimering för e-handel kräver:\r\n\r\n1. **Kategori-specifika metoder**: Olika produkttyper kräver olika optimeringsstrategier\r\n2. **Plattformsanpassning**: Förståelse och efterlevnad av marknadsplatskrav\r\n3. **Prestandaövervakning**: Kontinuerlig övervakning av bildprestanda och användarbeteende\r\n4. **Avancerade laddningsstrategier**: Smart laddning baserat på användarkontext och enhetskapacitet\r\n5. **Kvalitetsbevarande**: Bibehållen visuell attraktionskraft vid filoptimering\r\n\r\nI takt med att e-handeln utvecklas med ny teknik som AR-produktvisualisering, effektivare komprimeringsalgoritmer och förbättrad mobilupplevelse, kommer moderna optimeringsmetoder och konverteringsfokus att förbli avgörande för konkurrensfördelar.\r\n\r\nFramtiden för bildoptimering inom e-handel ligger i AI-baserade system som automatiskt kan optimera bilder baserat på användarbeteende, enhetskapacitet och konverteringsmönster, samtidigt som den nödvändiga visuella kvaliteten bibehålls för att öka försäljning och kundnöjdhet.\r\n","# E-commerce produktbillede komprimering: Salgsrettet optimering\r\n\r\nE-commerce succes afhænger i høj grad af produktbilledernes kvalitet, hvor undersøgelser viser, at 67% af forbrugerne anser billedkvalitet som \"meget vigtig\" ved online indkøb. Store billedfiler kan dog betydeligt påvirke sideindlæsningstider, konverteringsrater og mobilbrugeroplevelsen. Denne omfattende guide dækker avancerede teknikker til optimering af e-commerce produktbilleder, mens den visuelle kvalitet, der er nødvendig for at drive salg, bevares.\r\n\r\n## Hvorfor e-commerce billedoptimering betyder noget\r\n\r\n### Indvirkning på konverteringsrater\r\n\r\nProduktbilledoptimering påvirker direkte forretningsmetrikker:\r\n- **Konverteringsrater**: 1 sekunds forsinkelse i sideindlæsningstid reducerer konverteringer med 7%\r\n- **Bounce rates**: 40% af brugerne forlader sites, der tager mere end 3 sekunder at indlæse\r\n- **Mobil handel**: 73% af e-commerce trafik kommer fra mobile enheder\r\n- **Søgerangeringer**: Google faktorer sidehastighed ind i søgerangeringer\r\n- **Kundetilfredshed**: Billeder af høj kvalitet øger købstilliden\r\n\r\n### E-commerce specifikke krav\r\n\r\nProduktbilleder har unikke optimeringsudfordringer:\r\n- **Flere produktvisninger**: Hovedbillede, thumbnails, zoom-visninger, 360° rotationer\r\n- **Farvenøjagtighed**: Kritisk for mode, kosmetik og boligindretning\r\n- **Detaljebevaring**: Kunder skal kunne se tekstur, materialer og håndværk\r\n- **Indlæsningsydelse**: Balance mellem kvalitet og hastighed\r\n- **Tværenhedskompatibilitet**: Konsistent oplevelse på tværs af enheder\r\n\r\n## Forståelse af e-commerce billedtyper\r\n\r\n### Produktbilledkategorier\r\n\r\nForskellige billedtyper kræver forskellige optimeringstilgange:\r\n\r\n```javascript\r\nconst ecommerceImageTypes = {\r\n    hero: {\r\n        purpose: 'Primær produktpræsentation',\r\n        requirements: 'Høj kvalitet, hurtig indlæsning',\r\n        sizes: ['1200x1200', '800x800', '600x600'],\r\n        quality: { jpeg: 85, webp: 80 }\r\n    },\r\n    thumbnail: {\r\n        purpose: 'Produktgitter displays',\r\n        requirements: 'Lille filstørrelse, genkendelig',\r\n        sizes: ['300x300', '200x200', '150x150'],\r\n        quality: { jpeg: 75, webp: 70 }\r\n    },\r\n    zoom: {\r\n        purpose: 'Detaljeret produktinspektion',\r\n        requirements: 'Maksimal detaljebevaring',\r\n        sizes: ['2000x2000', '1600x1600'],\r\n        quality: { jpeg: 90, webp: 85 }\r\n    },\r\n    gallery: {\r\n        purpose: 'Flere produktvinkler',\r\n        requirements: 'Konsistent kvalitet, lazy loading',\r\n        sizes: ['800x800', '600x600'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    },\r\n    lifestyle: {\r\n        purpose: 'Produkt i brug/kontekst',\r\n        requirements: 'Optimeret til følelse/kontekst',\r\n        sizes: ['1200x800', '800x533'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    }\r\n};\r\n```\r\n\r\n### Optimeringsstrategi efter produktkategori\r\n\r\nForskellige produktkategorier har specifikke billedkrav:\r\n\r\n```python\r\ndef get_category_optimization_settings(product_category):\r\n    \"\"\"Få optimeringsindstillinger for forskellige produktkategorier\"\"\"\r\n    settings = {\r\n        'fashion': {\r\n            'priority': ['color_accuracy', 'texture_detail'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 90},\r\n            'critical_views': ['front', 'back', 'detail']\r\n        },\r\n        'electronics': {\r\n            'priority': ['detail_preservation', 'fast_loading'],\r\n            'format_preference': 'webp_or_avif',\r\n            'quality_range': {'min': 75, 'max': 85},\r\n            'critical_views': ['main', 'interfaces', 'size_comparison']\r\n        },\r\n        'home_decor': {\r\n            'priority': ['color_accuracy', 'lifestyle_context'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 88},\r\n            'critical_views': ['styled', 'closeup', 'dimensions']\r\n        },\r\n        'jewelry': {\r\n            'priority': ['maximum_detail', 'color_accuracy'],\r\n            'format_preference': 'png_for_detailed_webp_for_hero',\r\n            'quality_range': {'min': 85, 'max': 95},\r\n            'critical_views': ['macro', '360_spin', 'lifestyle']\r\n        },\r\n        'books': {\r\n            'priority': ['fast_loading', 'text_readability'],\r\n            'format_preference': 'webp_aggressive_compression',\r\n            'quality_range': {'min': 70, 'max': 80},\r\n            'critical_views': ['cover', 'back', 'spine']\r\n        }\r\n    }\r\n    return settings.get(product_category, settings['electronics'])\r\n```\r\n\r\n## Avanceret produktbilledbehandling\r\n\r\n### Automatiseret produktbillede pipeline\r\n\r\nOmfattende automatiseret behandlingssystem:\r\n\r\n```python\r\nimport os\r\nfrom PIL import Image, ImageEnhance, ImageFilter\r\nimport numpy as np\r\n\r\nclass EcommerceImageProcessor:\r\n    def __init__(self, config=None):\r\n        self.config = config or self.get_default_config()\r\n        self.supported_formats = ['jpeg', 'webp', 'avif', 'png']\r\n        \r\n    def get_default_config(self):\r\n        return {\r\n            'background_removal': True,\r\n            'auto_crop': True,\r\n            'color_enhancement': True,\r\n            'noise_reduction': True,\r\n            'watermark': False,\r\n            'quality_thresholds': {\r\n                'hero': 85,\r\n                'gallery': 80,\r\n                'thumbnail': 75,\r\n                'zoom': 90\r\n            }\r\n        }\r\n    \r\n    def process_product_image(self, input_path, output_dir, product_id):\r\n        \"\"\"Behandl et enkelt produktbillede til alle nødvendige varianter\"\"\"\r\n        img = Image.open(input_path)\r\n        \r\n        # Grundlæggende forbehandling\r\n        processed_img = self.preprocess_image(img)\r\n        \r\n        # Generer alle nødvendige størrelser og formater\r\n        variants = self.generate_image_variants(processed_img, product_id)\r\n        \r\n        # Gem optimerede versioner\r\n        saved_files = self.save_variants(variants, output_dir)\r\n        \r\n        return saved_files\r\n    \r\n    def preprocess_image(self, img):\r\n        \"\"\"Anvend grundlæggende forbehandling på produktbillede\"\"\"\r\n        # Konverter til RGB hvis nødvendigt\r\n        if img.mode in ('RGBA', 'LA', 'P'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            if img.mode == 'RGBA':\r\n                background.paste(img, mask=img.split()[-1])\r\n            else:\r\n                background.paste(img)\r\n            img = background\r\n        \r\n        # Auto-beskær for at fjerne overskydende whitespace\r\n        if self.config['auto_crop']:\r\n            img = self.smart_crop(img)\r\n        \r\n        # Forbedre billedkvalitet\r\n        if self.config['color_enhancement']:\r\n            img = self.enhance_product_image(img)\r\n        \r\n        # Reducer støj\r\n        if self.config['noise_reduction']:\r\n            img = img.filter(ImageFilter.SMOOTH_MORE)\r\n        \r\n        return img\r\n    \r\n    def smart_crop(self, img):\r\n        \"\"\"Intelligent beskæring af produktbillede for at fjerne overskydende baggrund\"\"\"\r\n        # Konverter til numpy array til analyse\r\n        img_array = np.array(img)\r\n        \r\n        # Find bounding box af ikke-hvide pixels\r\n        mask = np.any(img_array \u003C 240, axis=2)  # Ikke rent hvid\r\n        coords = np.argwhere(mask)\r\n        \r\n        if len(coords) == 0:\r\n            return img  # Ingen beskæring nødvendig\r\n        \r\n        # Få bounding box\r\n        y0, x0 = coords.min(axis=0)\r\n        y1, x1 = coords.max(axis=0)\r\n        \r\n        # Tilføj padding\r\n        padding = 20\r\n        y0 = max(0, y0 - padding)\r\n        x0 = max(0, x0 - padding)\r\n        y1 = min(img.height, y1 + padding)\r\n        x1 = min(img.width, x1 + padding)\r\n        \r\n        return img.crop((x0, y0, x1, y1))\r\n    \r\n    def enhance_product_image(self, img):\r\n        \"\"\"Forbedre produktbillede til e-commerce visning\"\"\"\r\n        # Forbedre lysstyrke lidt\r\n        brightness_enhancer = ImageEnhance.Brightness(img)\r\n        img = brightness_enhancer.enhance(1.05)\r\n        \r\n        # Forbedre kontrast\r\n        contrast_enhancer = ImageEnhance.Contrast(img)\r\n        img = contrast_enhancer.enhance(1.1)\r\n        \r\n        # Forbedre farvemætning\r\n        color_enhancer = ImageEnhance.Color(img)\r\n        img = color_enhancer.enhance(1.05)\r\n        \r\n        # Forbedre skarphed\r\n        sharpness_enhancer = ImageEnhance.Sharpness(img)\r\n        img = sharpness_enhancer.enhance(1.1)\r\n        \r\n        return img\r\n```\r\n\r\n## Platformspecifik optimering\r\n\r\n### Amazon Marketplace optimering\r\n\r\nAmazon har specifikke billedkrav og algoritmer:\r\n\r\n```python\r\nclass AmazonImageOptimizer:\r\n    def __init__(self):\r\n        self.requirements = {\r\n            'main_image': {\r\n                'min_size': (1000, 1000),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'background': 'pure_white',\r\n                'product_coverage': 85  # Minimum procent af billede\r\n            },\r\n            'additional_images': {\r\n                'min_size': (500, 500),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'lifestyle_allowed': True\r\n            }\r\n        }\r\n    \r\n    def optimize_for_amazon(self, image_path, output_path, image_type='main'):\r\n        \"\"\"Optimer billede specifikt til Amazon listing\"\"\"\r\n        img = Image.open(image_path)\r\n        \r\n        if image_type == 'main':\r\n            img = self.ensure_white_background(img)\r\n            img = self.ensure_minimum_size(img, (1000, 1000))\r\n        \r\n        # Amazon foretrækker sRGB farverum\r\n        if img.mode != 'RGB':\r\n            img = img.convert('RGB')\r\n        \r\n        # Optimer filstørrelse mens kvalitet bevares\r\n        quality = 90 if image_type == 'main' else 85\r\n        img.save(output_path, 'JPEG', quality=quality, optimize=True)\r\n        \r\n        return self.validate_amazon_requirements(output_path, image_type)\r\n```\r\n\r\n## Ydeevnemåling og optimering\r\n\r\n### Metrikker til sporing af succes\r\n\r\nNøgle performance indikatorer for billedoptimering:\r\n\r\n```javascript\r\nclass EcommerceImageMetrics {\r\n    constructor() {\r\n        this.metrics = {\r\n            technical: {\r\n                'load_time': 'Billedindlæsningstid',\r\n                'file_size': 'Filstørrelse',\r\n                'compression_ratio': 'Komprimeringsforhold',\r\n                'quality_score': 'Kvalitetsscore'\r\n            },\r\n            business: {\r\n                'conversion_rate': 'Konverteringsrate',\r\n                'bounce_rate': 'Bounce rate',\r\n                'time_on_page': 'Tid på side',\r\n                'cart_addition_rate': 'Kurv tilføjelsesrate'\r\n            }\r\n        };\r\n    }\r\n    \r\n    measureImagePerformance(imageUrl, callback) {\r\n        const startTime = performance.now();\r\n        const img = new Image();\r\n        \r\n        img.onload = () => {\r\n            const loadTime = performance.now() - startTime;\r\n            const fileSize = this.getImageFileSize(imageUrl);\r\n            \r\n            callback({\r\n                loadTime: loadTime,\r\n                fileSize: fileSize,\r\n                dimensions: { width: img.width, height: img.height },\r\n                timestamp: new Date().toISOString()\r\n            });\r\n        };\r\n        \r\n        img.src = imageUrl;\r\n    }\r\n}\r\n```\r\n\r\n## Automatisering og skalering\r\n\r\n### Batch behandling for store kataloger\r\n\r\nEffektiv behandling af tusindvis af produktbilleder:\r\n\r\n```python\r\nimport concurrent.futures\r\nimport multiprocessing\r\nfrom pathlib import Path\r\n\r\nclass BatchImageProcessor:\r\n    def __init__(self, max_workers=None):\r\n        self.max_workers = max_workers or multiprocessing.cpu_count()\r\n        self.processor = EcommerceImageProcessor()\r\n    \r\n    def process_catalog(self, input_directory, output_directory, progress_callback=None):\r\n        \"\"\"Behandl hele katalog af produktbilleder\"\"\"\r\n        input_path = Path(input_directory)\r\n        output_path = Path(output_directory)\r\n        output_path.mkdir(parents=True, exist_ok=True)\r\n        \r\n        # Find alle billeder\r\n        image_files = list(input_path.glob('**/*.{jpg,jpeg,png,webp}'))\r\n        total_files = len(image_files)\r\n        \r\n        processed_count = 0\r\n        failed_files = []\r\n        \r\n        with concurrent.futures.ThreadPoolExecutor(max_workers=self.max_workers) as executor:\r\n            # Send alle opgaver\r\n            future_to_file = {\r\n                executor.submit(self.process_single_image, img_file, output_path): img_file\r\n                for img_file in image_files\r\n            }\r\n            \r\n            # Behandl resultater\r\n            for future in concurrent.futures.as_completed(future_to_file):\r\n                img_file = future_to_file[future]\r\n                try:\r\n                    result = future.result()\r\n                    processed_count += 1\r\n                    \r\n                    if progress_callback:\r\n                        progress_callback(processed_count, total_files, img_file.name)\r\n                        \r\n                except Exception as exc:\r\n                    failed_files.append((img_file, str(exc)))\r\n                    print(f'Fil {img_file} genererede undtagelse: {exc}')\r\n        \r\n        return {\r\n            'total_files': total_files,\r\n            'processed_count': processed_count,\r\n            'failed_files': failed_files,\r\n            'success_rate': (processed_count / total_files) * 100 if total_files > 0 else 0\r\n        }\r\n```\r\n\r\n## Konklusion\r\n\r\nProduktbilledoptimering for e-commerce er en kritisk faktor for online butikssucces. Korrekt implementering af kompressionsteknikker, automatisering af behandling og ydeevnemåling kan betydeligt forbedre konverteringsrater, reducere bounce rates og øge kundetilfredshed.\r\n\r\nNøglepunkter at huske:\r\n\r\n1. **Balance kvalitet og ydeevne**: Find det optimale punkt mellem visuel kvalitet og indlæsningshastighed\r\n2. **Automatisering er nøglen**: Implementer automatiserede pipelines til skalering\r\n3. **Test og mål**: Brug A/B testing til at verificere optimeringsimpact\r\n4. **Platformspecifikke krav**: Tilpas optimering til specifikke markedspladsers krav\r\n5. **Kontinuerlig forbedring**: Opdater regelmæssigt strategier baseret på nye teknologier og data\r\n\r\nInvestering i professionel billedoptimering vil hurtigt betale sig tilbage gennem forbedrede forretningsresultater og bedre brugeroplevelse.\r\n","# Verkkokaupan tuotekuvien pakkaus: Myyntiin suuntautunut optimointi\r\n\r\nVerkkokaupan menestys riippuu suuresti tuotekuvien laadusta, ja tutkimukset osoittavat, että 67% kuluttajista pitää kuvan laatua \"erittäin tärkeänä\" verkko-ostoksissa. Suuret kuvatiedostot voivat kuitenkin vaikuttaa merkittävästi sivujen latausaikoihin, konversioasteisiin ja mobiililaitteiden käyttökokemukseen. Tämä kattava opas käsittelee edistyneitä tekniikoita verkkokaupan tuotekuvien optimointiin säilyttäen samalla visuaalisen laadun, joka tarvitaan myynnin edistämiseen.\r\n\r\n## Miksi verkkokaupan kuvien optimointi on tärkeää\r\n\r\n### Vaikutus konversioasteisiin\r\n\r\nTuotekuvien optimointi vaikuttaa suoraan liiketoiminnan mittareihin:\r\n- **Konversioasteet**: 1 sekunnin viive sivun latausajassa vähentää konversioita 7%\r\n- **Poistumisasteet**: 40% käyttäjistä poistuu sivustoilta, joiden lataaminen kestää yli 3 sekuntia\r\n- **Mobiilikauppa**: 73% verkkokaupan liikenteestä tulee mobiililaitteista\r\n- **Hakukonesijoitukset**: Google ottaa sivun nopeuden huomioon hakusijoituksissa\r\n- **Asiakastyytyväisyys**: Korkealaatuiset kuvat lisäävät ostovarmuutta\r\n\r\n### Verkkokaupan erityisvaatimukset\r\n\r\nTuotekuvilla on ainutlaatuisia optimointihaasteita:\r\n- **Useita tuotenäkymiä**: Pääkuva, pikkukuvat, zoomausnäkymät, 360° pyöritykset\r\n- **Värien tarkkuus**: Kriittistä muodille, kosmetiikalle ja sisustukselle\r\n- **Yksityiskohtien säilyttäminen**: Asiakkaiden täytyy nähdä tekstuuri, materiaalit ja käsityö\r\n- **Lataussuorituskyky**: Tasapaino laadun ja nopeuden välillä\r\n- **Laitteiden välinen yhteensopivuus**: Johdonmukainen kokemus kaikilla laitteilla\r\n\r\n## Verkkokaupan kuvatyyppien ymmärtäminen\r\n\r\n### Tuotekuvien kategoriat\r\n\r\nErilaiset kuvatyypit vaativat erilaisia optimointilähestymistapoja:\r\n\r\n```javascript\r\nconst ecommerceImageTypes = {\r\n    hero: {\r\n        purpose: 'Ensisijainen tuotteen esittely',\r\n        requirements: 'Korkea laatu, nopea lataus',\r\n        sizes: ['1200x1200', '800x800', '600x600'],\r\n        quality: { jpeg: 85, webp: 80 }\r\n    },\r\n    thumbnail: {\r\n        purpose: 'Tuoteruudukkonäkymät',\r\n        requirements: 'Pieni tiedostokoko, tunnistettava',\r\n        sizes: ['300x300', '200x200', '150x150'],\r\n        quality: { jpeg: 75, webp: 70 }\r\n    },\r\n    zoom: {\r\n        purpose: 'Yksityiskohtainen tuotetarkastelu',\r\n        requirements: 'Maksimaalinen yksityiskohtien säilyttäminen',\r\n        sizes: ['2000x2000', '1600x1600'],\r\n        quality: { jpeg: 90, webp: 85 }\r\n    },\r\n    gallery: {\r\n        purpose: 'Useita tuotekulmia',\r\n        requirements: 'Johdonmukainen laatu, lazy loading',\r\n        sizes: ['800x800', '600x600'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    },\r\n    lifestyle: {\r\n        purpose: 'Tuote käytössä/kontekstissa',\r\n        requirements: 'Optimoitu tunnelmalle/kontekstille',\r\n        sizes: ['1200x800', '800x533'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    }\r\n};\r\n```\r\n\r\n### Optimointistrategia tuotekategorian mukaan\r\n\r\nEri tuotekategorioilla on erityiset kuvavaatimukset:\r\n\r\n```python\r\ndef get_category_optimization_settings(product_category):\r\n    \"\"\"Hae optimointiasetukset eri tuotekategorioille\"\"\"\r\n    settings = {\r\n        'fashion': {\r\n            'priority': ['color_accuracy', 'texture_detail'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 90},\r\n            'critical_views': ['front', 'back', 'detail']\r\n        },\r\n        'electronics': {\r\n            'priority': ['detail_preservation', 'fast_loading'],\r\n            'format_preference': 'webp_or_avif',\r\n            'quality_range': {'min': 75, 'max': 85},\r\n            'critical_views': ['main', 'interfaces', 'size_comparison']\r\n        },\r\n        'home_decor': {\r\n            'priority': ['color_accuracy', 'lifestyle_context'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 88},\r\n            'critical_views': ['styled', 'closeup', 'dimensions']\r\n        },\r\n        'jewelry': {\r\n            'priority': ['maximum_detail', 'color_accuracy'],\r\n            'format_preference': 'png_for_detailed_webp_for_hero',\r\n            'quality_range': {'min': 85, 'max': 95},\r\n            'critical_views': ['macro', '360_spin', 'lifestyle']\r\n        },\r\n        'books': {\r\n            'priority': ['fast_loading', 'text_readability'],\r\n            'format_preference': 'webp_aggressive_compression',\r\n            'quality_range': {'min': 70, 'max': 80},\r\n            'critical_views': ['cover', 'back', 'spine']\r\n        }\r\n    }\r\n    return settings.get(product_category, settings['electronics'])\r\n```\r\n\r\n## Edistynyt tuotekuvien käsittely\r\n\r\n### Automaattinen tuotekuvien käsittelylinja\r\n\r\nKattava automaattinen käsittelyjärjestelmä:\r\n\r\n```python\r\nimport os\r\nfrom PIL import Image, ImageEnhance, ImageFilter\r\nimport numpy as np\r\n\r\nclass EcommerceImageProcessor:\r\n    def __init__(self, config=None):\r\n        self.config = config or self.get_default_config()\r\n        self.supported_formats = ['jpeg', 'webp', 'avif', 'png']\r\n        \r\n    def get_default_config(self):\r\n        return {\r\n            'background_removal': True,\r\n            'auto_crop': True,\r\n            'color_enhancement': True,\r\n            'noise_reduction': True,\r\n            'watermark': False,\r\n            'quality_thresholds': {\r\n                'hero': 85,\r\n                'gallery': 80,\r\n                'thumbnail': 75,\r\n                'zoom': 90\r\n            }\r\n        }\r\n    \r\n    def process_product_image(self, input_path, output_dir, product_id):\r\n        \"\"\"Käsittele yksittäinen tuotekuva kaikkiin vaadittuihin variantteihin\"\"\"\r\n        img = Image.open(input_path)\r\n        \r\n        # Peruskäsittely\r\n        processed_img = self.preprocess_image(img)\r\n        \r\n        # Luo kaikki vaaditut koot ja formaatit\r\n        variants = self.generate_image_variants(processed_img, product_id)\r\n        \r\n        # Tallenna optimoidut versiot\r\n        saved_files = self.save_variants(variants, output_dir)\r\n        \r\n        return saved_files\r\n    \r\n    def preprocess_image(self, img):\r\n        \"\"\"Sovella peruskäsittely tuotekuvaan\"\"\"\r\n        # Muunna RGB:ksi tarvittaessa\r\n        if img.mode in ('RGBA', 'LA', 'P'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            if img.mode == 'RGBA':\r\n                background.paste(img, mask=img.split()[-1])\r\n            else:\r\n                background.paste(img)\r\n            img = background\r\n        \r\n        # Automaattinen rajaus ylimääräisen valkoisen tilan poistamiseksi\r\n        if self.config['auto_crop']:\r\n            img = self.smart_crop(img)\r\n        \r\n        # Paranna kuvan laatua\r\n        if self.config['color_enhancement']:\r\n            img = self.enhance_product_image(img)\r\n        \r\n        # Vähennä kohinaa\r\n        if self.config['noise_reduction']:\r\n            img = img.filter(ImageFilter.SMOOTH_MORE)\r\n        \r\n        return img\r\n    \r\n    def smart_crop(self, img):\r\n        \"\"\"Älykäs tuotekuvan rajaus ylimääräisen taustan poistamiseksi\"\"\"\r\n        # Muunna numpy-taulukoksi analysointia varten\r\n        img_array = np.array(img)\r\n        \r\n        # Etsi ei-valkoisten pikselien rajauslaatikko\r\n        mask = np.any(img_array \u003C 240, axis=2)  # Ei puhtaan valkoinen\r\n        coords = np.argwhere(mask)\r\n        \r\n        if len(coords) == 0:\r\n            return img  # Ei rajausta tarvita\r\n        \r\n        # Hae rajauslaatikko\r\n        y0, x0 = coords.min(axis=0)\r\n        y1, x1 = coords.max(axis=0)\r\n        \r\n        # Lisää täyte\r\n        padding = 20\r\n        y0 = max(0, y0 - padding)\r\n        x0 = max(0, x0 - padding)\r\n        y1 = min(img.height, y1 + padding)\r\n        x1 = min(img.width, x1 + padding)\r\n        \r\n        return img.crop((x0, y0, x1, y1))\r\n```\r\n\r\n## Alustakohtainen optimointi\r\n\r\n### Amazon Marketplace -optimointi\r\n\r\nAmazonilla on erityiset kuvavaatimukset ja algoritmit:\r\n\r\n```python\r\nclass AmazonImageOptimizer:\r\n    def __init__(self):\r\n        self.requirements = {\r\n            'main_image': {\r\n                'min_size': (1000, 1000),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'background': 'pure_white',\r\n                'product_coverage': 85  # Vähimmäisprosentti kuvasta\r\n            },\r\n            'additional_images': {\r\n                'min_size': (500, 500),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'lifestyle_allowed': True\r\n            }\r\n        }\r\n    \r\n    def optimize_for_amazon(self, image_path, output_path, image_type='main'):\r\n        \"\"\"Optimoi kuva erityisesti Amazon-listausta varten\"\"\"\r\n        img = Image.open(image_path)\r\n        \r\n        if image_type == 'main':\r\n            img = self.ensure_white_background(img)\r\n            img = self.ensure_minimum_size(img, (1000, 1000))\r\n        \r\n        # Amazon suosii sRGB-väriavaruutta\r\n        if img.mode != 'RGB':\r\n            img = img.convert('RGB')\r\n        \r\n        # Optimoi tiedostokoko säilyttäen laatu\r\n        quality = 90 if image_type == 'main' else 85\r\n        img.save(output_path, 'JPEG', quality=quality, optimize=True)\r\n        \r\n        return self.validate_amazon_requirements(output_path, image_type)\r\n```\r\n\r\n## Suorituskyvyn mittaus ja optimointi\r\n\r\n### Menestyksen seurannan mittarit\r\n\r\nKeskeiset suorituskykyindikaattorit kuvien optimointiin:\r\n\r\n```javascript\r\nclass EcommerceImageMetrics {\r\n    constructor() {\r\n        this.metrics = {\r\n            technical: {\r\n                'load_time': 'Kuvan latausaika',\r\n                'file_size': 'Tiedostokoko',\r\n                'compression_ratio': 'Pakkaussuhde',\r\n                'quality_score': 'Laatupisteet'\r\n            },\r\n            business: {\r\n                'conversion_rate': 'Konversioaste',\r\n                'bounce_rate': 'Poistumisaste',\r\n                'time_on_page': 'Aika sivulla',\r\n                'cart_addition_rate': 'Ostoskoriin lisäysaste'\r\n            }\r\n        };\r\n    }\r\n    \r\n    measureImagePerformance(imageUrl, callback) {\r\n        const startTime = performance.now();\r\n        const img = new Image();\r\n        \r\n        img.onload = () => {\r\n            const loadTime = performance.now() - startTime;\r\n            const fileSize = this.getImageFileSize(imageUrl);\r\n            \r\n            callback({\r\n                loadTime: loadTime,\r\n                fileSize: fileSize,\r\n                dimensions: { width: img.width, height: img.height },\r\n                timestamp: new Date().toISOString()\r\n            });\r\n        };\r\n        \r\n        img.src = imageUrl;\r\n    }\r\n}\r\n```\r\n\r\n## Automaatio ja skaalaus\r\n\r\n### Eräkäsittely suurille luetteloille\r\n\r\nTehokas tuhansien tuotekuvien käsittely:\r\n\r\n```python\r\nimport concurrent.futures\r\nimport multiprocessing\r\nfrom pathlib import Path\r\n\r\nclass BatchImageProcessor:\r\n    def __init__(self, max_workers=None):\r\n        self.max_workers = max_workers or multiprocessing.cpu_count()\r\n        self.processor = EcommerceImageProcessor()\r\n    \r\n    def process_catalog(self, input_directory, output_directory, progress_callback=None):\r\n        \"\"\"Käsittele koko tuotekuvien luettelo\"\"\"\r\n        input_path = Path(input_directory)\r\n        output_path = Path(output_directory)\r\n        output_path.mkdir(parents=True, exist_ok=True)\r\n        \r\n        # Etsi kaikki kuvat\r\n        image_files = list(input_path.glob('**/*.{jpg,jpeg,png,webp}'))\r\n        total_files = len(image_files)\r\n        \r\n        processed_count = 0\r\n        failed_files = []\r\n        \r\n        with concurrent.futures.ThreadPoolExecutor(max_workers=self.max_workers) as executor:\r\n            # Lähetä kaikki tehtävät\r\n            future_to_file = {\r\n                executor.submit(self.process_single_image, img_file, output_path): img_file\r\n                for img_file in image_files\r\n            }\r\n            \r\n            # Käsittele tulokset\r\n            for future in concurrent.futures.as_completed(future_to_file):\r\n                img_file = future_to_file[future]\r\n                try:\r\n                    result = future.result()\r\n                    processed_count += 1\r\n                    \r\n                    if progress_callback:\r\n                        progress_callback(processed_count, total_files, img_file.name)\r\n                        \r\n                except Exception as exc:\r\n                    failed_files.append((img_file, str(exc)))\r\n                    print(f'Tiedosto {img_file} aiheutti poikkeuksen: {exc}')\r\n        \r\n        return {\r\n            'total_files': total_files,\r\n            'processed_count': processed_count,\r\n            'failed_files': failed_files,\r\n            'success_rate': (processed_count / total_files) * 100 if total_files > 0 else 0\r\n        }\r\n```\r\n\r\n## Johtopäätös\r\n\r\nVerkkokaupan tuotekuvien optimointi on kriittinen tekijä verkkokaupan menestykselle. Pakkaustekniikoiden, käsittelyn automaation ja suorituskyvyn mittauksen oikea toteutus voi parantaa merkittävästi konversioasteita, vähentää poistumisasteita ja lisätä asiakastyytyväisyyttä.\r\n\r\nKeskeiset muistettavat asiat:\r\n\r\n1. **Tasapainota laatu ja suorituskyky**: Löydä optimaalinen piste visuaalisen laadun ja latausnopeuden välillä\r\n2. **Automaatio on avain**: Toteuta automaattiset käsittelylinjat skaalausta varten\r\n3. **Testaa ja mittaa**: Käytä A/B-testausta optimoinnin vaikutusten varmistamiseen\r\n4. **Alustakohtaiset vaatimukset**: Mukauta optimointi tiettyjen markkinapaikkojen vaatimuksiin\r\n5. **Jatkuva parantaminen**: Päivitä strategioita säännöllisesti uusien teknologioiden ja tietojen perusteella\r\n\r\nInvestointi ammattimaiseen kuvien optimointiin maksaa itsensä nopeasti takaisin parantuneina liiketoimintatuloksina ja parempana käyttökokemuksena.\r\n","# Compresia imaginilor de produse pentru comerț electronic: Optimizare orientată spre vânzări\r\n\r\nSuccesul în e-commerce depinde în mare măsură de calitatea imaginilor produselor, studiile arătând că 67% dintre consumatori consideră calitatea imaginii \"foarte importantă\" atunci când fac achiziții online. Totuși, fișierele mari de imagine pot afecta semnificativ timpii de încărcare a paginii, ratele de conversie și experiența utilizatorilor de pe mobil. Acest ghid cuprinzător acoperă tehnici avansate pentru optimizarea imaginilor de produse e-commerce, menținând calitatea vizuală necesară pentru a stimula vânzările.\r\n\r\n## De ce contează optimizarea imaginilor pentru e-commerce\r\n\r\n### Impactul asupra ratelor de conversie\r\n\r\nOptimizarea imaginilor de produs afectează direct indicatorii de business:\r\n- **Rate de conversie**: O întârziere de 1 secundă la încărcarea paginii reduce conversiile cu 7%\r\n- **Rate de abandon**: 40% dintre utilizatori părăsesc site-urile care se încarcă în peste 3 secunde\r\n- **Comerț mobil**: 73% din traficul e-commerce provine de pe dispozitive mobile\r\n- **Clasare în căutări**: Google ia în considerare viteza paginii în algoritmul de ranking\r\n- **Satisfacția clientului**: Imaginile de înaltă calitate sporesc încrederea în achiziție\r\n\r\n### Cerințe specifice e-commerce\r\n\r\nImaginile de produs au provocări unice de optimizare:\r\n- **Vizualizări multiple ale produsului**: Imagine principală, miniaturi, zoom, rotații 360°\r\n- **Acuratețea culorilor**: Esențială pentru modă, cosmetice și decorațiuni\r\n- **Păstrarea detaliilor**: Clienții trebuie să vadă textura, materialele și execuția\r\n- **Performanța la încărcare**: Echilibru între calitate și viteză\r\n- **Compatibilitate cross-device**: Experiență consistentă pe toate dispozitivele\r\n\r\n## Înțelegerea tipurilor de imagini pentru e-commerce\r\n\r\n### Categorii de imagini de produs\r\n\r\nDiferite tipuri de imagini necesită abordări diferite de optimizare:\r\n\r\n```javascript\r\nconst ecommerceImageTypes = {\r\n    hero: {\r\n        purpose: 'Prezentarea principală a produsului',\r\n        requirements: 'Calitate înaltă, încărcare rapidă',\r\n        sizes: ['1200x1200', '800x800', '600x600'],\r\n        quality: { jpeg: 85, webp: 80 }\r\n    },\r\n    thumbnail: {\r\n        purpose: 'Afișare în grilă de produse',\r\n        requirements: 'Dimensiune mică a fișierului, recognoscibilă',\r\n        sizes: ['300x300', '200x200', '150x150'],\r\n        quality: { jpeg: 75, webp: 70 }\r\n    },\r\n    zoom: {\r\n        purpose: 'Inspecție detaliată a produsului',\r\n        requirements: 'Păstrarea maximă a detaliilor',\r\n        sizes: ['2000x2000', '1600x1600'],\r\n        quality: { jpeg: 90, webp: 85 }\r\n    },\r\n    gallery: {\r\n        purpose: 'Unghiuri multiple ale produsului',\r\n        requirements: 'Calitate consistentă, încărcare întârziată (lazy loading)',\r\n        sizes: ['800x800', '600x600'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    },\r\n    lifestyle: {\r\n        purpose: 'Produsul în utilizare/context',\r\n        requirements: 'Optimizat pentru emoție/context',\r\n        sizes: ['1200x800', '800x533'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    }\r\n};\r\n```\r\n\r\n### Strategie de optimizare pe categorie de produs\r\n\r\nDiferite categorii de produse au cerințe specifice pentru imagini:\r\n\r\n```python\r\ndef get_category_optimization_settings(product_category):\r\n    \"\"\"Obține setările de optimizare pentru diferite categorii de produse\"\"\"\r\n    settings = {\r\n        'fashion': {\r\n            'priority': ['acuratețea_culorilor', 'detaliu_textură'],\r\n            'format_preference': 'webp_cu_rezervă_jpeg',\r\n            'quality_range': {'min': 80, 'max': 90},\r\n            'critical_views': ['față', 'spate', 'detaliu']\r\n        },\r\n        'electronics': {\r\n            'priority': ['păstrarea_detaliilor', 'încărcare_rapidă'],\r\n            'format_preference': 'webp_sau_avif',\r\n            'quality_range': {'min': 75, 'max': 85},\r\n            'critical_views': ['principală', 'interfețe', 'comparație_dimensiune']\r\n        },\r\n        'home_decor': {\r\n            'priority': ['acuratețea_culorilor', 'context_lifestyle'],\r\n            'format_preference': 'webp_cu_rezervă_jpeg',\r\n            'quality_range': {'min': 80, 'max': 88},\r\n            'critical_views': ['stilizat', 'closeup', 'dimensiuni']\r\n        },\r\n        'jewelry': {\r\n            'priority': ['detaliu_maxim', 'acuratețea_culorilor'],\r\n            'format_preference': 'png_pentru_detaliu_webp_pentru_hero',\r\n            'quality_range': {'min': 85, 'max': 95},\r\n            'critical_views': ['macro', '360_rotire', 'lifestyle']\r\n        },\r\n        'books': {\r\n            'priority': ['încărcare_rapidă', 'lizibilitate_text'],\r\n            'format_preference': 'webp_compresie_agresivă',\r\n            'quality_range': {'min': 70, 'max': 80},\r\n            'critical_views': ['copertă', 'spate', 'cotor']\r\n        }\r\n    }\r\n    return settings.get(product_category, settings['electronics'])\r\n```\r\n\r\n## Procesare avansată a imaginilor de produs\r\n\r\n### Flux automatizat de procesare a imaginilor de produs\r\n\r\nSistem cuprinzător de procesare automată:\r\n\r\n```python\r\nimport os\r\nfrom PIL import Image, ImageEnhance, ImageFilter\r\nimport numpy as np\r\n\r\nclass EcommerceImageProcessor:\r\n    def __init__(self, config=None):\r\n        self.config = config or self.get_default_config()\r\n        self.supported_formats = ['jpeg', 'webp', 'avif', 'png']\r\n        \r\n    def get_default_config(self):\r\n        return {\r\n            'background_removal': True,\r\n            'auto_crop': True,\r\n            'color_enhancement': True,\r\n            'noise_reduction': True,\r\n            'watermark': False,\r\n            'quality_thresholds': {\r\n                'hero': 85,\r\n                'gallery': 80,\r\n                'thumbnail': 75,\r\n                'zoom': 90\r\n            }\r\n        }\r\n    \r\n    def process_product_image(self, input_path, output_dir, product_id):\r\n        \"\"\"Procesează o singură imagine de produs în toate variantele necesare\"\"\"\r\n        img = Image.open(input_path)\r\n        \r\n        # Preprocesare de bază\r\n        processed_img = self.preprocess_image(img)\r\n        \r\n        # Generează toate dimensiunile și formatele necesare\r\n        variants = self.generate_image_variants(processed_img, product_id)\r\n        \r\n        # Salvează versiunile optimizate\r\n        saved_files = self.save_variants(variants, output_dir)\r\n        \r\n        return saved_files\r\n    \r\n    def preprocess_image(self, img):\r\n        \"\"\"Aplică preprocesare de bază imaginii de produs\"\"\"\r\n        # Conversie la RGB dacă este necesar\r\n        if img.mode in ('RGBA', 'LA', 'P'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            if img.mode == 'RGBA':\r\n                background.paste(img, mask=img.split()[-1])\r\n            else:\r\n                background.paste(img)\r\n            img = background\r\n        \r\n        # Decupare automată pentru a elimina spațiul alb\r\n        if self.config['auto_crop']:\r\n            img = self.smart_crop(img)\r\n        \r\n        # Îmbunătățirea calității imaginii\r\n        if self.config['color_enhancement']:\r\n            img = self.enhance_product_image(img)\r\n        \r\n        # Reducerea zgomotului\r\n        if self.config['noise_reduction']:\r\n            img = img.filter(ImageFilter.SMOOTH_MORE)\r\n        \r\n        return img\r\n    \r\n    def smart_crop(self, img):\r\n        \"\"\"Decupare inteligentă pentru a elimina fundalul în exces\"\"\"\r\n        # Conversie la array numpy pentru analiză\r\n        img_array = np.array(img)\r\n        \r\n        # Găsește bounding box-ul pixelilor non-albi\r\n        mask = np.any(img_array \u003C 240, axis=2)  # Nu este alb pur\r\n        coords = np.argwhere(mask)\r\n        \r\n        if len(coords) == 0:\r\n            return img  # Nu este necesară decuparea\r\n        \r\n        # Obține bounding box-ul\r\n        y0, x0 = coords.min(axis=0)\r\n        y1, x1 = coords.max(axis=0)\r\n        \r\n        # Adaugă padding\r\n        padding = 20\r\n        y0 = max(0, y0 - padding)\r\n        x0 = max(0, x0 - padding)\r\n        y1 = min(img.height, y1 + padding)\r\n        x1 = min(img.width, x1 + padding)\r\n        \r\n        return img.crop((x0, y0, x1, y1))\r\n    \r\n    def enhance_product_image(self, img):\r\n        \"\"\"Îmbunătățește imaginea produsului pentru afișare e-commerce\"\"\"\r\n        # Crește ușor luminozitatea\r\n        brightness_enhancer = ImageEnhance.Brightness(img)\r\n        img = brightness_enhancer.enhance(1.05)\r\n        \r\n        # Crește contrastul\r\n        contrast_enhancer = ImageEnhance.Contrast(img)\r\n        img = contrast_enhancer.enhance(1.1)\r\n        \r\n        # Crește saturația culorii\r\n        color_enhancer = ImageEnhance.Color(img)\r\n        img = color_enhancer.enhance(1.05)\r\n        \r\n        # Crește claritatea\r\n        sharpness_enhancer = ImageEnhance.Sharpness(img)\r\n        img = sharpness_enhancer.enhance(1.1)\r\n        \r\n        return img\r\n    \r\n    def generate_image_variants(self, img, product_id):\r\n        \"\"\"Generează toate variantele de imagine necesare\"\"\"\r\n        variants = {}\r\n        \r\n        # Definește dimensiuni standard pentru e-commerce\r\n        sizes = {\r\n            'hero': (1200, 1200),\r\n            'gallery': (800, 800),\r\n            'thumbnail': (300, 300),\r\n            'zoom': (2000, 2000),\r\n            'mobile_hero': (600, 600),\r\n            'mobile_thumb': (150, 150)\r\n        }\r\n        \r\n        for variant_name, size in sizes.items():\r\n            # Redimensionare cu resampling de înaltă calitate\r\n            resized = img.resize(size, Image.Resampling.LANCZOS)\r\n            variants[variant_name] = resized\r\n        \r\n        return variants\r\n    \r\n    def save_variants(self, variants, output_dir):\r\n        \"\"\"Salvează toate variantele în formate optimizate\"\"\"\r\n        saved_files = []\r\n        \r\n        for variant_name, img in variants.items():\r\n            base_path = os.path.join(output_dir, variant_name)\r\n            \r\n            # Salvează în mai multe formate\r\n            for format_type in ['jpeg', 'webp']:\r\n                filename = f\"{base_path}.{format_type}\"\r\n                quality = self.get_quality_for_variant(variant_name, format_type)\r\n                \r\n                if format_type == 'jpeg':\r\n                    img.save(filename, 'JPEG', quality=quality, optimize=True, progressive=True)\r\n                elif format_type == 'webp':\r\n                    img.save(filename, 'WebP', quality=quality, optimize=True)\r\n                \r\n                saved_files.append(filename)\r\n        \r\n        return saved_files\r\n    \r\n    def get_quality_for_variant(self, variant_name, format_type):\r\n        \"\"\"Obține setarea optimă de calitate pentru variantă și format\"\"\"\r\n        base_quality = self.config['quality_thresholds'].get(variant_name, 80)\r\n        \r\n        # Ajustează pentru format\r\n        if format_type == 'webp':\r\n            return base_quality - 5  # WebP poate atinge aceeași calitate la o setare mai mică\r\n        elif format_type == 'avif':\r\n            return base_quality - 10  # AVIF este și mai eficient\r\n        \r\n        return base_quality\r\n\r\n# Exemplu de utilizare\r\nprocessor = EcommerceImageProcessor()\r\nprocessor.process_product_image('product_raw.jpg', 'output/', 'product_123')\r\n```\r\n\r\n### Eliminarea și standardizarea fundalului\r\n\r\nProcesare automată a fundalului pentru afișare consistentă a produsului:\r\n\r\n```python\r\ndef remove_product_background(image_path, output_path):\r\n    \"\"\"Elimină fundalul imaginii de produs folosind detecția marginilor\"\"\"\r\n    import cv2\r\n    import numpy as np\r\n    \r\n    # Citește imaginea\r\n    img = cv2.imread(image_path)\r\n    original = img.copy()\r\n    \r\n    # Conversie la gri\r\n    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\r\n    \r\n    # Aplică GaussianBlur pentru reducerea zgomotului\r\n    blurred = cv2.GaussianBlur(gray, (5, 5), 0)\r\n    \r\n    # Detecție margini\r\n    edges = cv2.Canny(blurred, 50, 150)\r\n    \r\n    # Găsește contururi\r\n    contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\r\n    \r\n    if contours:\r\n        # Găsește cel mai mare contur (presupus a fi produsul)\r\n        largest_contour = max(contours, key=cv2.contourArea)\r\n        \r\n        # Creează mască\r\n        mask = np.zeros(gray.shape, np.uint8)\r\n        cv2.fillPoly(mask, [largest_contour], 255)\r\n        \r\n        # Aplică masca pe imaginea originală\r\n        result = cv2.bitwise_and(original, original, mask=mask)\r\n        \r\n        # Transformă fundalul în alb\r\n        result[mask == 0] = [255, 255, 255]\r\n        \r\n        cv2.imwrite(output_path, result)\r\n        return True\r\n    \r\n    return False\r\n\r\ndef standardize_product_backgrounds(input_dir, output_dir, background_color=(255, 255, 255)):\r\n    \"\"\"Standardizează toate fundalurile produselor la o culoare consistentă\"\"\"\r\n    for filename in os.listdir(input_dir):\r\n        if filename.lower().endswith(('.jpg', '.jpeg', '.png')):\r\n            input_path = os.path.join(input_dir, filename)\r\n            output_path = os.path.join(output_dir, filename)\r\n            \r\n            # Încearcă eliminarea automată a fundalului\r\n            if not remove_product_background(input_path, output_path):\r\n                # Alternativă: fundal alb simplu\r\n                img = Image.open(input_path)\r\n                if img.mode == 'RGBA':\r\n                    background = Image.new('RGB', img.size, background_color)\r\n                    background.paste(img, mask=img.split()[-1])\r\n                    background.save(output_path, 'JPEG', quality=85)\r\n                else:\r\n                    img.save(output_path)\r\n```\r\n\r\n## Optimizare specifică platformei\r\n\r\n### Optimizare pentru marketplace-ul Amazon\r\n\r\nAmazon are cerințe și algoritmi specifici pentru imagini:\r\n\r\n```python\r\nclass AmazonImageOptimizer:\r\n    def __init__(self):\r\n        self.requirements = {\r\n            'main_image': {\r\n                'min_size': (1000, 1000),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'background': 'pure_white',\r\n                'product_coverage': 85  # Procentaj minim din imagine\r\n            },\r\n            'additional_images': {\r\n                'min_size': (500, 500),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'lifestyle_allowed': True\r\n            }\r\n        }\r\n    \r\n    def optimize_for_amazon(self, image_path, output_path, image_type='main'):\r\n        \"\"\"Optimizează imaginea special pentru listarea pe Amazon\"\"\"\r\n        img = Image.open(image_path)\r\n        \r\n        if image_type == 'main':\r\n            img = self.ensure_white_background(img)\r\n            img = self.ensure_minimum_size(img, (1000, 1000))\r\n        \r\n        # Amazon preferă spațiul de culoare sRGB\r\n        if img.mode != 'RGB':\r\n            img = img.convert('RGB')\r\n        \r\n        # Optimizează dimensiunea fișierului menținând calitatea\r\n        quality = 90 if image_type == 'main' else 85\r\n        img.save(output_path, 'JPEG', quality=quality, optimize=True)\r\n        \r\n        return self.validate_amazon_requirements(output_path, image_type)\r\n    \r\n    def ensure_white_background(self, img):\r\n        \"\"\"Asigură-te că imaginea are fundal alb pur\"\"\"\r\n        if img.mode == 'RGBA':\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            background.paste(img, mask=img.split()[-1])\r\n            return background\r\n        return img\r\n    \r\n    def ensure_minimum_size(self, img, min_size):\r\n        \"\"\"Asigură-te că imaginea respectă dimensiunea minimă\"\"\"\r\n        if img.size[0] \u003C min_size[0] or img.size[1] \u003C min_size[1]:\r\n            img = img.resize(min_size, Image.Resampling.LANCZOS)\r\n        return img\r\n    \r\n    def validate_amazon_requirements(self, image_path, image_type):\r\n        \"\"\"Validează dacă imaginea respectă cerințele Amazon\"\"\"\r\n        img = Image.open(image_path)\r\n        requirements = self.requirements[image_type]\r\n        \r\n        validation_results = {\r\n            'size_valid': (\r\n                img.size[0] >= requirements['min_size'][0] and \r\n                img.size[1] >= requirements['min_size'][1]\r\n            ),\r\n            'format_valid': image_path.upper().endswith(tuple(requirements['formats'])),\r\n            'file_size_valid': os.path.getsize(image_path) \u003C= 10 * 1024 * 1024  # Limită 10MB\r\n        }\r\n        \r\n        return all(validation_results.values()), validation_results\r\n```\r\n\r\n### Optimizare pentru magazinele Shopify\r\n\r\nOptimizare pentru teme și performanță Shopify:\r\n\r\n```javascript\r\nclass ShopifyImageOptimizer {\r\n    constructor() {\r\n        this.themeRequirements = {\r\n            'product_card': { width: 600, height: 600, quality: 80 },\r\n            'product_detail': { width: 1200, height: 1200, quality: 85 },\r\n            'product_zoom': { width: 2048, height: 2048, quality: 90 },\r\n            'collection_featured': { width: 800, height: 600, quality: 80 }\r\n        };\r\n    }\r\n    \r\n    generateShopifyImageUrls(baseImageUrl, productHandle) {\r\n        const urls = {};\r\n        \r\n        Object.entries(this.themeRequirements).forEach(([variant, specs]) => {\r\n            // Format URL de transformare imagine Shopify\r\n            const transformedUrl = baseImageUrl.replace('.jpg', \r\n                `_${specs.width}x${specs.height}_crop_center.jpg`);\r\n            urls[variant] = transformedUrl;\r\n        });\r\n        \r\n        return urls;\r\n    }\r\n    \r\n    generateShopifyPictureElement(productData) {\r\n        const { images, title, handle } = productData;\r\n        const mainImage = images[0];\r\n        \r\n        return `\r\n            \u003Cpicture>\r\n                \u003Csource media=\"(min-width: 1200px)\" \r\n                        srcset=\"${mainImage}_1200x1200.webp 1x, ${mainImage}_2400x2400.webp 2x\"\r\n                        type=\"image/webp\">\r\n                \u003Csource media=\"(min-width: 768px)\" \r\n                        srcset=\"${mainImage}_800x800.webp 1x, ${mainImage}_1600x1600.webp 2x\"\r\n                        type=\"image/webp\">\r\n                \u003Csource media=\"(max-width: 767px)\" \r\n                        srcset=\"${mainImage}_600x600.webp 1x, ${mainImage}_1200x1200.webp 2x\"\r\n                        type=\"image/webp\">\r\n                \u003Cimg src=\"${mainImage}_800x800.jpg\"\r\n                     srcset=\"${mainImage}_400x400.jpg 400w,\r\n                             ${mainImage}_600x600.jpg 600w,\r\n                             ${mainImage}_800x800.jpg 800w,\r\n                             ${mainImage}_1200x1200.jpg 1200w\"\r\n                     sizes=\"(max-width: 767px) 100vw, (max-width: 1023px) 50vw, 33vw\"\r\n                     alt=\"${title}\"\r\n                     loading=\"lazy\"\r\n                     data-product-handle=\"${handle}\">\r\n            \u003C/picture>\r\n        `;\r\n    }\r\n}\r\n```\r\n\r\n## Strategii avansate de încărcare pentru e-commerce\r\n\r\n### Încărcare inteligentă a imaginilor de produs\r\n\r\nÎncărcare inteligentă bazată pe comportamentul utilizatorului și capabilitățile dispozitivului:\r\n\r\n```javascript\r\nclass EcommerceImageLoader {\r\n    constructor() {\r\n        this.userBehavior = this.trackUserBehavior();\r\n        this.deviceCapabilities = this.analyzeDevice();\r\n        this.loadingStrategies = this.initializeStrategies();\r\n    }\r\n    \r\n    trackUserBehavior() {\r\n        return {\r\n            isReturningCustomer: localStorage.getItem('visited') === 'true',\r\n            viewingHistory: JSON.parse(localStorage.getItem('viewedProducts') || '[]'),\r\n            averageSessionTime: parseInt(localStorage.getItem('avgSessionTime') || '0'),\r\n            purchaseHistory: JSON.parse(localStorage.getItem('purchases') || '[]')\r\n        };\r\n    }\r\n    \r\n    analyzeDevice() {\r\n        const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;\r\n        \r\n        return {\r\n            connectionSpeed: connection ? connection.effectiveType : '4g',\r\n            deviceMemory: navigator.deviceMemory || 4,\r\n            isLowEndDevice: navigator.deviceMemory \u003C 2,\r\n            isMobile: window.innerWidth \u003C= 768,\r\n            isSlowConnection: connection && (connection.effectiveType === 'slow-2g' || connection.effectiveType === '2g')\r\n        };\r\n    }\r\n    \r\n    initializeStrategies() {\r\n        return {\r\n            eager: this.eagerLoadingStrategy.bind(this),\r\n            progressive: this.progressiveLoadingStrategy.bind(this),\r\n            lazy: this.lazyLoadingStrategy.bind(this),\r\n            adaptive: this.adaptiveLoadingStrategy.bind(this)\r\n        };\r\n    }\r\n    \r\n    selectOptimalStrategy(productData, context) {\r\n        const { deviceCapabilities, userBehavior } = this;\r\n        \r\n        // Clienți fideli cu conexiuni bune\r\n        if (userBehavior.isReturningCustomer && \r\n            userBehavior.purchaseHistory.length > 0 && \r\n            !deviceCapabilities.isSlowConnection) {\r\n            return 'eager';\r\n        }\r\n        \r\n        // Dispozitive low-end sau conexiuni lente\r\n        if (deviceCapabilities.isLowEndDevice || deviceCapabilities.isSlowConnection) {\r\n            return 'lazy';\r\n        }\r\n        \r\n        // Dispozitive mobile cu conexiuni bune\r\n        if (deviceCapabilities.isMobile && !deviceCapabilities.isSlowConnection) {\r\n            return 'progressive';\r\n        }\r\n        \r\n        // Implicit: strategie adaptivă\r\n        return 'adaptive';\r\n    }\r\n    \r\n    eagerLoadingStrategy(productImages) {\r\n        // Încarcă toate imaginile produsului imediat pentru experiență premium\r\n        productImages.forEach(img => {\r\n            const imageLoader = new Image();\r\n            imageLoader.src = img.dataset.src;\r\n            \r\n            if (img.dataset.srcset) {\r\n                imageLoader.srcset = img.dataset.srcset;\r\n            }\r\n            \r\n            imageLoader.onload = () => {\r\n                img.src = imageLoader.src;\r\n                if (img.dataset.srcset) {\r\n                    img.srcset = imageLoader.srcset;\r\n                }\r\n                img.classList.add('loaded');\r\n            };\r\n        });\r\n    }\r\n    \r\n    progressiveLoadingStrategy(productImages) {\r\n        // Încarcă mai întâi calitate scăzută, apoi calitate înaltă\r\n        productImages.forEach(img => {\r\n            // Placeholder de calitate scăzută\r\n            const lowQualitySrc = img.dataset.lowSrc || img.dataset.src.replace('_q85', '_q40');\r\n            const highQualitySrc = img.dataset.src;\r\n            \r\n            img.src = lowQualitySrc;\r\n            img.classList.add('loading');\r\n            \r\n            // Încarcă versiunea de calitate înaltă\r\n            const highQualityLoader = new Image();\r\n            highQualityLoader.onload = () => {\r\n                img.src = highQualitySrc;\r\n                img.classList.remove('loading');\r\n                img.classList.add('loaded');\r\n            };\r\n            highQualityLoader.src = highQualitySrc;\r\n        });\r\n    }\r\n    \r\n    lazyLoadingStrategy(productImages) {\r\n        // Folosește Intersection Observer pentru încărcare întârziată\r\n        const observer = new IntersectionObserver((entries) => {\r\n            entries.forEach(entry => {\r\n                if (entry.isIntersecting) {\r\n                    this.loadImage(entry.target);\r\n                    observer.unobserve(entry.target);\r\n                }\r\n            });\r\n        }, { rootMargin: '100px' });\r\n        \r\n        productImages.forEach(img => observer.observe(img));\r\n    }\r\n    \r\n    adaptiveLoadingStrategy(productImages) {\r\n        // Adaptează pe baza interacțiunii utilizatorului și a comportamentului de scroll\r\n        let scrollTimeout;\r\n        let isScrolling = false;\r\n        \r\n        window.addEventListener('scroll', () => {\r\n            if (!isScrolling) {\r\n                isScrolling = true;\r\n                // Încarcă imaginile vizibile imediat la începutul scroll-ului\r\n                this.loadVisibleImages(productImages);\r\n            }\r\n            \r\n            clearTimeout(scrollTimeout);\r\n            scrollTimeout = setTimeout(() => {\r\n                isScrolling = false;\r\n            }, 150);\r\n        });\r\n        \r\n        // Încarcă imaginile critice deasupra fold-ului imediat\r\n        this.loadCriticalImages(productImages);\r\n        \r\n        // Lazy load pentru imaginile rămase\r\n        this.lazyLoadingStrategy(productImages.filter(img => !img.dataset.critical));\r\n    }\r\n    \r\n    loadCriticalImages(productImages) {\r\n        const criticalImages = productImages.filter(img => \r\n            img.dataset.critical === 'true' || \r\n            img.getBoundingClientRect().top \u003C window.innerHeight\r\n        );\r\n        \r\n        criticalImages.forEach(img => this.loadImage(img));\r\n    }\r\n    \r\n    loadVisibleImages(productImages) {\r\n        const visibleImages = productImages.filter(img => {\r\n            const rect = img.getBoundingClientRect();\r\n            return rect.top \u003C window.innerHeight && rect.bottom > 0;\r\n        });\r\n        \r\n        visibleImages.forEach(img => this.loadImage(img));\r\n    }\r\n    \r\n    loadImage(img) {\r\n        if (img.dataset.loaded) return;\r\n        \r\n        const imageLoader = new Image();\r\n        imageLoader.onload = () => {\r\n            img.src = imageLoader.src;\r\n            if (img.dataset.srcset) {\r\n                img.srcset = img.dataset.srcset;\r\n            }\r\n            img.classList.add('loaded');\r\n            img.dataset.loaded = 'true';\r\n        };\r\n        \r\n        imageLoader.src = img.dataset.src;\r\n    }\r\n}\r\n\r\n// Inițializează pentru paginile de produs\r\n// document.addEventListener('DOMContentLoaded', () => {\r\n//     const imageLoader = new EcommerceImageLoader();\r\n//     const productImages = document.querySelectorAll('.product-image[data-src]');\r\n//     \r\n//     if (productImages.length > 0) {\r\n//         const strategy = imageLoader.selectOptimalStrategy();\r\n//         imageLoader.loadingStrategies[strategy](productImages);\r\n//     }\r\n// });\r\n```\r\n\r\n## Optimizare zoom imagine și vizualizare 360°\r\n\r\n### Implementare eficientă a zoom-ului\r\n\r\nFuncționalitate de zoom optimizată pentru paginile de detalii ale produsului:\r\n\r\n```javascript\r\nclass ProductImageZoom {\r\n    constructor(options = {}) {\r\n        this.container = options.container;\r\n        this.zoomLevel = options.zoomLevel || 2;\r\n        this.loadingStrategy = options.loadingStrategy || 'on-demand';\r\n        this.highResImages = new Map();\r\n        \r\n        this.initializeZoom();\r\n    }\r\n    \r\n    initializeZoom() {\r\n        const zoomImages = this.container.querySelectorAll('.zoomable-image');\r\n        \r\n        zoomImages.forEach(img => {\r\n            img.addEventListener('mouseenter', this.handleMouseEnter.bind(this));\r\n            img.addEventListener('mouseleave', this.handleMouseLeave.bind(this));\r\n            img.addEventListener('mousemove', this.handleMouseMove.bind(this));\r\n        });\r\n    }\r\n    \r\n    async handleMouseEnter(event) {\r\n        const img = event.target;\r\n        const highResUrl = img.dataset.zoomSrc;\r\n        \r\n        if (!highResUrl) return;\r\n        \r\n        // Încarcă imaginea de înaltă rezoluție la cerere\r\n        if (!this.highResImages.has(highResUrl)) {\r\n            this.loadHighResImage(highResUrl);\r\n        }\r\n        \r\n        this.showZoomOverlay(img);\r\n    }\r\n    \r\n    loadHighResImage(url) {\r\n        return new Promise((resolve, reject) => {\r\n            const img = new Image();\r\n            img.onload = () => {\r\n                this.highResImages.set(url, img);\r\n                resolve(img);\r\n            };\r\n            img.onerror = reject;\r\n            img.src = url;\r\n        });\r\n    }\r\n    \r\n    showZoomOverlay(img) {\r\n        // Creează overlay de zoom dacă nu există\r\n        let overlay = img.parentNode.querySelector('.zoom-overlay');\r\n        if (!overlay) {\r\n            overlay = document.createElement('div');\r\n            overlay.className = 'zoom-overlay';\r\n            overlay.style.cssText = `\r\n                position: absolute;\r\n                top: 0;\r\n                left: 100%;\r\n                width: 300px;\r\n                height: 300px;\r\n                border: 1px solid #ddd;\r\n                background: white;\r\n                overflow: hidden;\r\n                z-index: 1000;\r\n                display: none;\r\n            `;\r\n            img.parentNode.appendChild(overlay);\r\n        }\r\n        \r\n        overlay.style.display = 'block';\r\n    }\r\n    \r\n    handleMouseMove(event) {\r\n        const img = event.target;\r\n        const overlay = img.parentNode.querySelector('.zoom-overlay');\r\n        const highResUrl = img.dataset.zoomSrc;\r\n        \r\n        if (!overlay || !this.highResImages.has(highResUrl)) return;\r\n        \r\n        const rect = img.getBoundingClientRect();\r\n        const x = (event.clientX - rect.left) / rect.width;\r\n        const y = (event.clientY - rect.top) / rect.height;\r\n        \r\n        const highResImg = this.highResImages.get(highResUrl);\r\n        \r\n        // Actualizează overlay-ul de zoom\r\n        overlay.style.backgroundImage = `url(${highResUrl})`;\r\n        overlay.style.backgroundSize = `${highResImg.width}px ${highResImg.height}px`;\r\n        overlay.style.backgroundPosition = `-${x * (highResImg.width - 300)}px -${y * (highResImg.height - 300)}px`;\r\n    }\r\n    \r\n    handleMouseLeave(event) {\r\n        const img = event.target;\r\n        const overlay = img.parentNode.querySelector('.zoom-overlay');\r\n        \r\n        if (overlay) {\r\n            overlay.style.display = 'none';\r\n        }\r\n    }\r\n}\r\n\r\n// Optimizare vizualizare 360° produs\r\nclass Product360View {\r\n    constructor(container, options = {}) {\r\n        this.container = container;\r\n        this.frameCount = options.frameCount || 36;\r\n        this.autoPlay = options.autoPlay || false;\r\n        this.frames = [];\r\n        this.currentFrame = 0;\r\n        this.isLoading = false;\r\n        \r\n        this.initialize();\r\n    }\r\n    \r\n    async initialize() {\r\n        await this.loadFrames();\r\n        this.setupControls();\r\n        this.setupInteraction();\r\n    }\r\n    \r\n    async loadFrames() {\r\n        this.isLoading = true;\r\n        const baseUrl = this.container.dataset.baseUrl;\r\n        \r\n        // Încarcă cadrele progresiv\r\n        const loadPromises = [];\r\n        \r\n        for (let i = 1; i \u003C= this.frameCount; i++) {\r\n            const frameUrl = `${baseUrl}/frame_${i.toString().padStart(3, '0')}.jpg`;\r\n            loadPromises.push(this.loadFrame(frameUrl, i - 1));\r\n        }\r\n        \r\n        // Încarcă primele cadre imediat, restul progresiv\r\n        await Promise.all(loadPromises.slice(0, 8));\r\n        \r\n        // Încarcă cadrele rămase în background\r\n        Promise.all(loadPromises.slice(8));\r\n        \r\n        this.isLoading = false;\r\n        this.displayFrame(0);\r\n    }\r\n    \r\n    loadFrame(url, index) {\r\n        return new Promise((resolve) => {\r\n            const img = new Image();\r\n            img.onload = () => {\r\n                this.frames[index] = img;\r\n                resolve();\r\n            };\r\n            img.onerror = () => {\r\n                // Creează placeholder pentru cadrele care nu se încarcă\r\n                this.frames[index] = null;\r\n                resolve();\r\n            };\r\n            img.src = url;\r\n        });\r\n    }\r\n    \r\n    displayFrame(frameIndex) {\r\n        if (!this.frames[frameIndex]) return;\r\n        \r\n        const img = this.container.querySelector('.view-360-image') || \r\n                   this.createImageElement();\r\n        \r\n        img.src = this.frames[frameIndex].src;\r\n        this.currentFrame = frameIndex;\r\n    }\r\n    \r\n    createImageElement() {\r\n        const img = document.createElement('img');\r\n        img.className = 'view-360-image';\r\n        img.style.cssText = 'width: 100%; height: auto; display: block;';\r\n        this.container.appendChild(img);\r\n        return img;\r\n    }\r\n    \r\n    setupInteraction() {\r\n        let isDragging = false;\r\n        let startX = 0;\r\n        let startFrame = 0;\r\n        \r\n        this.container.addEventListener('mousedown', (e) => {\r\n            isDragging = true;\r\n            startX = e.clientX;\r\n            startFrame = this.currentFrame;\r\n            e.preventDefault();\r\n        });\r\n        \r\n        document.addEventListener('mousemove', (e) => {\r\n            if (!isDragging) return;\r\n            \r\n            const deltaX = e.clientX - startX;\r\n            const sensitivity = 2; // Pixeli per cadru\r\n            const frameChange = Math.floor(deltaX / sensitivity);\r\n            \r\n            let newFrame = (startFrame + frameChange) % this.frameCount;\r\n            if (newFrame \u003C 0) newFrame += this.frameCount;\r\n            \r\n            this.displayFrame(newFrame);\r\n        });\r\n        \r\n        document.addEventListener('mouseup', () => {\r\n            isDragging = false;\r\n        });\r\n    }\r\n}\r\n```\r\n\r\n## Monitorizare performanță și analytics\r\n\r\n### Monitorizarea performanței imaginilor pentru e-commerce\r\n\r\nMonitorizare cuprinzătoare a performanței imaginilor pentru e-commerce:\r\n\r\n```javascript\r\nclass EcommerceImageAnalytics {\r\n    constructor() {\r\n        this.metrics = {\r\n            imageLoadTimes: [],\r\n            conversionTracking: new Map(),\r\n            userInteractions: [],\r\n            performanceImpact: []\r\n        };\r\n        \r\n        this.startMonitoring();\r\n    }\r\n    \r\n    startMonitoring() {\r\n        // Monitorizează performanța încărcării imaginilor\r\n        new PerformanceObserver((list) => {\r\n            const entries = list.getEntries();\r\n            entries.forEach(entry => {\r\n                if (this.isProductImage(entry.name)) {\r\n                    this.trackImagePerformance(entry);\r\n                }\r\n            });\r\n        }).observe({ entryTypes: ['resource'] });\r\n        \r\n        // Monitorizează interacțiunile utilizatorului cu imaginile\r\n        this.trackImageInteractions();\r\n        \r\n        // Monitorizează corelația cu conversiile\r\n        this.trackConversionCorrelation();\r\n    }\r\n    \r\n    isProductImage(url) {\r\n        return url.includes('/products/') || \r\n               url.includes('product-images') ||\r\n               url.match(/\\/(hero|gallery|thumbnail|zoom)\\//);\r\n    }\r\n    \r\n    trackImagePerformance(entry) {\r\n        const imageData = {\r\n            url: entry.name,\r\n            loadTime: entry.responseEnd - entry.requestStart,\r\n            fileSize: entry.transferSize,\r\n            renderTime: entry.responseEnd,\r\n            imageType: this.categorizeImage(entry.name),\r\n            timestamp: Date.now()\r\n        };\r\n        \r\n        this.metrics.imageLoadTimes.push(imageData);\r\n        \r\n        // Trimite la analytics dacă timpul de încărcare este problematic\r\n        if (imageData.loadTime > 2000) {\r\n            this.reportSlowImage(imageData);\r\n        }\r\n    }\r\n    \r\n    categorizeImage(url) {\r\n        if (url.includes('hero')) return 'hero';\r\n        if (url.includes('thumbnail')) return 'thumbnail';\r\n        if (url.includes('gallery')) return 'gallery';\r\n        if (url.includes('zoom')) return 'zoom';\r\n        return 'other';\r\n    }\r\n    \r\n    trackImageInteractions() {\r\n        // Monitorizează utilizarea zoom-ului pe imagine\r\n        document.addEventListener('mouseenter', (e) => {\r\n            if (e.target.classList.contains('zoomable-image')) {\r\n                this.recordInteraction('zoom_hover', e.target);\r\n            }\r\n        });\r\n        \r\n        // Monitorizează navigarea în galeria de imagini\r\n        document.addEventListener('click', (e) => {\r\n            if (e.target.classList.contains('gallery-thumbnail')) {\r\n                this.recordInteraction('gallery_click', e.target);\r\n            }\r\n        });\r\n        \r\n        // Monitorizează interacțiunile cu vizualizarea 360°\r\n        document.addEventListener('mousedown', (e) => {\r\n            if (e.target.closest('.view-360')) {\r\n                this.recordInteraction('360_interact', e.target);\r\n            }\r\n        });\r\n    }\r\n    \r\n    recordInteraction(type, element) {\r\n        const interaction = {\r\n            type: type,\r\n            productId: element.dataset.productId || this.extractProductId(element),\r\n            timestamp: Date.now(),\r\n            elementSrc: element.src || element.dataset.src,\r\n            loadTime: this.getImageLoadTime(element.src)\r\n        };\r\n        \r\n        this.metrics.userInteractions.push(interaction);\r\n    }\r\n    \r\n    trackConversionCorrelation() {\r\n        // Monitorizează când utilizatorii adaugă în coș după interacțiuni cu imagini\r\n        document.addEventListener('click', (e) => {\r\n            if (e.target.matches('.add-to-cart, .buy-now')) {\r\n                const productId = this.extractProductId(e.target);\r\n                this.correlateWithImageInteractions(productId);\r\n            }\r\n        });\r\n    }\r\n    \r\n    correlateWithImageInteractions(productId) {\r\n        const recentInteractions = this.metrics.userInteractions\r\n            .filter(interaction => \r\n                interaction.productId === productId &&\r\n                Date.now() - interaction.timestamp \u003C 300000 // Ultimele 5 minute\r\n            );\r\n        \r\n        if (recentInteractions.length > 0) {\r\n            this.metrics.conversionTracking.set(productId, {\r\n                interactions: recentInteractions,\r\n                conversionTime: Date.now()\r\n            });\r\n        }\r\n    }\r\n    \r\n    generatePerformanceReport() {\r\n        const avgLoadTime = this.calculateAverageLoadTime();\r\n        const slowImages = this.identifySlowImages();\r\n        const interactionCorrelation = this.analyzeInteractionCorrelation();\r\n        \r\n        return {\r\n            averageImageLoadTime: avgLoadTime,\r\n            slowestImages: slowImages,\r\n            interactionToConversionRate: interactionCorrelation,\r\n            recommendations: this.generateRecommendations(avgLoadTime, slowImages)\r\n        };\r\n    }\r\n    \r\n    calculateAverageLoadTime() {\r\n        const loadTimes = this.metrics.imageLoadTimes.map(img => img.loadTime);\r\n        return loadTimes.reduce((sum, time) => sum + time, 0) / loadTimes.length;\r\n    }\r\n    \r\n    identifySlowImages() {\r\n        return this.metrics.imageLoadTimes\r\n            .filter(img => img.loadTime > 2000)\r\n            .sort((a, b) => b.loadTime - a.loadTime)\r\n            .slice(0, 10);\r\n    }\r\n    \r\n    analyzeInteractionCorrelation() {\r\n        const totalInteractions = this.metrics.userInteractions.length;\r\n        const conversionsWithInteractions = this.metrics.conversionTracking.size;\r\n        \r\n        return totalInteractions > 0 ? \r\n            (conversionsWithInteractions / totalInteractions) * 100 : 0;\r\n    }\r\n    \r\n    generateRecommendations(avgLoadTime, slowImages) {\r\n        const recommendations = [];\r\n        \r\n        if (avgLoadTime > 1500) {\r\n            recommendations.push('Ia în considerare o compresie mai agresivă a imaginilor');\r\n            recommendations.push('Implementează formatul WebP pentru o compresie mai bună');\r\n        }\r\n        \r\n        if (slowImages.length > 0) {\r\n            recommendations.push('Optimizează imaginile de produs cu încărcare lentă');\r\n            recommendations.push('Ia în considerare încărcarea întârziată pentru imaginile din galerie');\r\n        }\r\n        \r\n        const heroImages = slowImages.filter(img => img.imageType === 'hero');\r\n        if (heroImages.length > 0) {\r\n            recommendations.push('Prioritizează optimizarea imaginii principale pentru o primă impresie mai rapidă');\r\n        }\r\n        \r\n        return recommendations;\r\n    }\r\n    \r\n    extractProductId(element) {\r\n        // Încearcă diverse metode pentru a extrage ID-ul produsului\r\n        return element.dataset.productId ||\r\n               element.closest('[data-product-id]')?.dataset.productId ||\r\n               window.location.pathname.match(/\\/products\\/([^\\/]+)/)?.[1] ||\r\n               'unknown';\r\n    }\r\n    \r\n    getImageLoadTime(src) {\r\n        const imageMetric = this.metrics.imageLoadTimes.find(img => img.url.includes(src));\r\n        return imageMetric ? imageMetric.loadTime : null;\r\n    }\r\n    \r\n    reportSlowImage(imageData) {\r\n        // Trimite la serviciul de analytics\r\n        if (typeof gtag !== 'undefined') {\r\n            gtag('event', 'slow_image_load', {\r\n                'url': imageData.url,\r\n                'load_time': imageData.loadTime,\r\n                'file_size': imageData.fileSize,\r\n                'image_type': imageData.imageType\r\n            });\r\n        }\r\n    }\r\n}\r\n\r\n// Inițializează analytics\r\nconst imageAnalytics = new EcommerceImageAnalytics();\r\n\r\n// Generează raport periodic\r\nsetInterval(() => {\r\n    const report = imageAnalytics.generatePerformanceReport();\r\n    console.log('Raport de performanță a imaginilor pentru e-commerce:', report);\r\n}, 300000); // La fiecare 5 minute\r\n```\r\n\r\n## Concluzie\r\n\r\nOptimizarea imaginilor de produse pentru e-commerce este un factor critic pentru succesul în retailul online, având impact direct asupra ratelor de conversie, experienței utilizatorului și poziționării în căutări. Cheia este găsirea echilibrului optim între calitatea imaginii și performanță, ținând cont de cerințele specifice ale diferitelor categorii de produse și platforme.\r\n\r\nSuccesul în optimizarea imaginilor pentru e-commerce necesită:\r\n\r\n1. **Abordări specifice pe categorie**: Diferite tipuri de produse necesită strategii de optimizare diferite\r\n2. **Conformitate cu platforma**: Înțelegerea și respectarea cerințelor marketplace-urilor\r\n3. **Monitorizare performanță**: Urmărirea continuă a performanței imaginilor și a comportamentului utilizatorului\r\n4. **Strategii avansate de încărcare**: Încărcare inteligentă bazată pe contextul utilizatorului și capabilitățile dispozitivului\r\n5. **Păstrarea calității**: Menținerea atractivității vizuale în timp ce se optimizează dimensiunea fișierelor\r\n\r\nPe măsură ce e-commerce-ul evoluează cu noi tehnologii precum vizualizarea produselor în AR, algoritmi de compresie mai buni și experiențe mobile îmbunătățite, menținerea la zi cu tehnicile de optimizare și concentrarea pe rezultate orientate spre conversie vor rămâne esențiale pentru avantajul competitiv.\r\n\r\nViitorul optimizării imaginilor pentru e-commerce constă în sisteme bazate pe inteligență artificială care pot optimiza automat imaginile pe baza comportamentului utilizatorului, capabilităților dispozitivului și tiparelor de conversie, menținând calitatea vizuală necesară pentru a stimula vânzările și satisfacția clienților.\r\n","# Συμπίεση Εικόνων Προϊόντων E-commerce: Βελτιστοποίηση Προσανατολισμένη στις Πωλήσεις\r\n\r\nΗ επιτυχία του e-commerce εξαρτάται σε μεγάλο βαθμό από την ποιότητα των εικόνων προϊόντων, με μελέτες να δείχνουν ότι το 67% των καταναλωτών θεωρεί την ποιότητα εικόνας \"πολύ σημαντική\" κατά τις διαδικτυακές αγορές. Ωστόσο, τα μεγάλα αρχεία εικόνων μπορούν να επηρεάσουν σημαντικά τους χρόνους φόρτωσης σελίδων, τα ποσοστά μετατροπής και την εμπειρία χρήστη σε κινητές συσκευές. Αυτός ο περιεκτικός οδηγός καλύπτει προηγμένες τεχνικές για τη βελτιστοποίηση εικόνων προϊόντων e-commerce διατηρώντας την οπτική ποιότητα που απαιτείται για την προώθηση των πωλήσεων.\r\n\r\n## Γιατί Έχει Σημασία η Βελτιστοποίηση Εικόνων E-commerce\r\n\r\n### Επίδραση στα Ποσοστά Μετατροπής\r\n\r\nΗ βελτιστοποίηση εικόνων προϊόντων επηρεάζει άμεσα τις επιχειρηματικές μετρήσεις:\r\n- **Ποσοστά μετατροπής**: 1 δευτερόλεπτο καθυστέρηση στο χρόνο φόρτωσης σελίδας μειώνει τις μετατροπές κατά 7%\r\n- **Ποσοστά εγκατάλειψης**: 40% των χρηστών εγκαταλείπουν ιστότοπους που χρειάζονται περισσότερα από 3 δευτερόλεπτα για φόρτωση\r\n- **Κινητό εμπόριο**: 73% της κίνησης e-commerce προέρχεται από κινητές συσκευές\r\n- **Κατατάξεις αναζήτησης**: Η Google λαμβάνει υπόψη την ταχύτητα σελίδας στις κατατάξεις αναζήτησης\r\n- **Ικανοποίηση πελατών**: Οι εικόνες υψηλής ποιότητας αυξάνουν την εμπιστοσύνη αγοράς\r\n\r\n### Ειδικές Απαιτήσεις E-commerce\r\n\r\nΟι εικόνες προϊόντων έχουν μοναδικές προκλήσεις βελτιστοποίησης:\r\n- **Πολλαπλές προβολές προϊόντων**: Κύρια εικόνα, μικρογραφίες, προβολές zoom, περιστροφές 360°\r\n- **Ακρίβεια χρωμάτων**: Κρίσιμη για μόδα, καλλυντικά και διακόσμηση σπιτιού\r\n- **Διατήρηση λεπτομερειών**: Οι πελάτες πρέπει να βλέπουν υφή, υλικά και χειροτεχνία\r\n- **Απόδοση φόρτωσης**: Ισορροπία μεταξύ ποιότητας και ταχύτητας\r\n- **Συμβατότητα μεταξύ συσκευών**: Συνεπής εμπειρία σε όλες τις συσκευές\r\n\r\n## Κατανόηση Τύπων Εικόνων E-commerce\r\n\r\n### Κατηγορίες Εικόνων Προϊόντων\r\n\r\nΔιαφορετικοί τύποι εικόνων απαιτούν διαφορετικές προσεγγίσεις βελτιστοποίησης:\r\n\r\n```javascript\r\nconst ecommerceImageTypes = {\r\n    hero: {\r\n        purpose: 'Κύρια παρουσίαση προϊόντος',\r\n        requirements: 'Υψηλή ποιότητα, γρήγορη φόρτωση',\r\n        sizes: ['1200x1200', '800x800', '600x600'],\r\n        quality: { jpeg: 85, webp: 80 }\r\n    },\r\n    thumbnail: {\r\n        purpose: 'Εμφανίσεις πλέγματος προϊόντων',\r\n        requirements: 'Μικρό μέγεθος αρχείου, αναγνωρίσιμο',\r\n        sizes: ['300x300', '200x200', '150x150'],\r\n        quality: { jpeg: 75, webp: 70 }\r\n    },\r\n    zoom: {\r\n        purpose: 'Λεπτομερής επιθεώρηση προϊόντος',\r\n        requirements: 'Μέγιστη διατήρηση λεπτομερειών',\r\n        sizes: ['2000x2000', '1600x1600'],\r\n        quality: { jpeg: 90, webp: 85 }\r\n    },\r\n    gallery: {\r\n        purpose: 'Πολλαπλές γωνίες προϊόντος',\r\n        requirements: 'Συνεπής ποιότητα, lazy loading',\r\n        sizes: ['800x800', '600x600'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    },\r\n    lifestyle: {\r\n        purpose: 'Προϊόν σε χρήση/πλαίσιο',\r\n        requirements: 'Βελτιστοποιημένο για συναίσθημα/πλαίσιο',\r\n        sizes: ['1200x800', '800x533'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    }\r\n};\r\n```\r\n\r\n### Στρατηγική Βελτιστοποίησης ανά Κατηγορία Προϊόντος\r\n\r\nΔιαφορετικές κατηγορίες προϊόντων έχουν συγκεκριμένες απαιτήσεις εικόνας:\r\n\r\n```python\r\ndef get_category_optimization_settings(product_category):\r\n    \"\"\"Λήψη ρυθμίσεων βελτιστοποίησης για διαφορετικές κατηγορίες προϊόντων\"\"\"\r\n    settings = {\r\n        'fashion': {\r\n            'priority': ['color_accuracy', 'texture_detail'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 90},\r\n            'critical_views': ['front', 'back', 'detail']\r\n        },\r\n        'electronics': {\r\n            'priority': ['detail_preservation', 'fast_loading'],\r\n            'format_preference': 'webp_or_avif',\r\n            'quality_range': {'min': 75, 'max': 85},\r\n            'critical_views': ['main', 'interfaces', 'size_comparison']\r\n        },\r\n        'home_decor': {\r\n            'priority': ['color_accuracy', 'lifestyle_context'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 88},\r\n            'critical_views': ['styled', 'closeup', 'dimensions']\r\n        },\r\n        'jewelry': {\r\n            'priority': ['maximum_detail', 'color_accuracy'],\r\n            'format_preference': 'png_for_detailed_webp_for_hero',\r\n            'quality_range': {'min': 85, 'max': 95},\r\n            'critical_views': ['macro', '360_spin', 'lifestyle']\r\n        },\r\n        'books': {\r\n            'priority': ['fast_loading', 'text_readability'],\r\n            'format_preference': 'webp_aggressive_compression',\r\n            'quality_range': {'min': 70, 'max': 80},\r\n            'critical_views': ['cover', 'back', 'spine']\r\n        }\r\n    }\r\n    return settings.get(product_category, settings['electronics'])\r\n```\r\n\r\n## Προηγμένη Επεξεργασία Εικόνων Προϊόντων\r\n\r\n### Αυτοματοποιημένη Pipeline Εικόνων Προϊόντων\r\n\r\nΠεριεκτικό αυτοματοποιημένο σύστημα επεξεργασίας:\r\n\r\n```python\r\nimport os\r\nfrom PIL import Image, ImageEnhance, ImageFilter\r\nimport numpy as np\r\n\r\nclass EcommerceImageProcessor:\r\n    def __init__(self, config=None):\r\n        self.config = config or self.get_default_config()\r\n        self.supported_formats = ['jpeg', 'webp', 'avif', 'png']\r\n        \r\n    def get_default_config(self):\r\n        return {\r\n            'background_removal': True,\r\n            'auto_crop': True,\r\n            'color_enhancement': True,\r\n            'noise_reduction': True,\r\n            'watermark': False,\r\n            'quality_thresholds': {\r\n                'hero': 85,\r\n                'gallery': 80,\r\n                'thumbnail': 75,\r\n                'zoom': 90\r\n            }\r\n        }\r\n    \r\n    def process_product_image(self, input_path, output_dir, product_id):\r\n        \"\"\"Επεξεργασία μιας εικόνας προϊόντος σε όλες τις απαιτούμενες παραλλαγές\"\"\"\r\n        img = Image.open(input_path)\r\n        \r\n        # Βασική προεπεξεργασία\r\n        processed_img = self.preprocess_image(img)\r\n        \r\n        # Δημιουργία όλων των απαιτούμενων μεγεθών και μορφών\r\n        variants = self.generate_image_variants(processed_img, product_id)\r\n        \r\n        # Αποθήκευση βελτιστοποιημένων εκδόσεων\r\n        saved_files = self.save_variants(variants, output_dir)\r\n        \r\n        return saved_files\r\n    \r\n    def preprocess_image(self, img):\r\n        \"\"\"Εφαρμογή βασικής προεπεξεργασίας σε εικόνα προϊόντος\"\"\"\r\n        # Μετατροπή σε RGB εάν είναι απαραίτητο\r\n        if img.mode in ('RGBA', 'LA', 'P'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            if img.mode == 'RGBA':\r\n                background.paste(img, mask=img.split()[-1])\r\n            else:\r\n                background.paste(img)\r\n            img = background\r\n        \r\n        # Αυτόματη περικοπή για αφαίρεση περιττού λευκού χώρου\r\n        if self.config['auto_crop']:\r\n            img = self.smart_crop(img)\r\n        \r\n        # Βελτίωση ποιότητας εικόνας\r\n        if self.config['color_enhancement']:\r\n            img = self.enhance_product_image(img)\r\n        \r\n        # Μείωση θορύβου\r\n        if self.config['noise_reduction']:\r\n            img = img.filter(ImageFilter.SMOOTH_MORE)\r\n        \r\n        return img\r\n    \r\n    def smart_crop(self, img):\r\n        \"\"\"Έξυπνη περικοπή εικόνας προϊόντος για αφαίρεση περιττού φόντου\"\"\"\r\n        # Μετατροπή σε numpy array για ανάλυση\r\n        img_array = np.array(img)\r\n        \r\n        # Εύρεση bounding box μη-λευκών pixels\r\n        mask = np.any(img_array \u003C 240, axis=2)  # Όχι καθαρά λευκό\r\n        coords = np.argwhere(mask)\r\n        \r\n        if len(coords) == 0:\r\n            return img  # Δεν χρειάζεται περικοπή\r\n        \r\n        # Λήψη bounding box\r\n        y0, x0 = coords.min(axis=0)\r\n        y1, x1 = coords.max(axis=0)\r\n        \r\n        # Προσθήκη padding\r\n        padding = 20\r\n        y0 = max(0, y0 - padding)\r\n        x0 = max(0, x0 - padding)\r\n        y1 = min(img.height, y1 + padding)\r\n        x1 = min(img.width, x1 + padding)\r\n        \r\n        return img.crop((x0, y0, x1, y1))\r\n```\r\n\r\n## Βελτιστοποίηση Ειδική για Πλατφόρμα\r\n\r\n### Βελτιστοποίηση Amazon Marketplace\r\n\r\nΗ Amazon έχει συγκεκριμένες απαιτήσεις εικόνων και αλγορίθμους:\r\n\r\n```python\r\nclass AmazonImageOptimizer:\r\n    def __init__(self):\r\n        self.requirements = {\r\n            'main_image': {\r\n                'min_size': (1000, 1000),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'background': 'pure_white',\r\n                'product_coverage': 85  # Ελάχιστο ποσοστό εικόνας\r\n            },\r\n            'additional_images': {\r\n                'min_size': (500, 500),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'lifestyle_allowed': True\r\n            }\r\n        }\r\n    \r\n    def optimize_for_amazon(self, image_path, output_path, image_type='main'):\r\n        \"\"\"Βελτιστοποίηση εικόνας ειδικά για Amazon listing\"\"\"\r\n        img = Image.open(image_path)\r\n        \r\n        if image_type == 'main':\r\n            img = self.ensure_white_background(img)\r\n            img = self.ensure_minimum_size(img, (1000, 1000))\r\n        \r\n        # Η Amazon προτιμά sRGB χρωματικό χώρο\r\n        if img.mode != 'RGB':\r\n            img = img.convert('RGB')\r\n        \r\n        # Βελτιστοποίηση μεγέθους αρχείου διατηρώντας την ποιότητα\r\n        quality = 90 if image_type == 'main' else 85\r\n        img.save(output_path, 'JPEG', quality=quality, optimize=True)\r\n        \r\n        return self.validate_amazon_requirements(output_path, image_type)\r\n```\r\n\r\n## Μέτρηση Απόδοσης και Βελτιστοποίηση\r\n\r\n### Μετρήσεις για Παρακολούθηση Επιτυχίας\r\n\r\nΒασικοί δείκτες απόδοσης για βελτιστοποίηση εικόνων:\r\n\r\n```javascript\r\nclass EcommerceImageMetrics {\r\n    constructor() {\r\n        this.metrics = {\r\n            technical: {\r\n                'load_time': 'Χρόνος φόρτωσης εικόνας',\r\n                'file_size': 'Μέγεθος αρχείου',\r\n                'compression_ratio': 'Αναλογία συμπίεσης',\r\n                'quality_score': 'Βαθμολογία ποιότητας'\r\n            },\r\n            business: {\r\n                'conversion_rate': 'Ποσοστό μετατροπής',\r\n                'bounce_rate': 'Ποσοστό εγκατάλειψης',\r\n                'time_on_page': 'Χρόνος στη σελίδα',\r\n                'cart_addition_rate': 'Ποσοστό προσθήκης στο καλάθι'\r\n            }\r\n        };\r\n    }\r\n    \r\n    measureImagePerformance(imageUrl, callback) {\r\n        const startTime = performance.now();\r\n        const img = new Image();\r\n        \r\n        img.onload = () => {\r\n            const loadTime = performance.now() - startTime;\r\n            const fileSize = this.getImageFileSize(imageUrl);\r\n            \r\n            callback({\r\n                loadTime: loadTime,\r\n                fileSize: fileSize,\r\n                dimensions: { width: img.width, height: img.height },\r\n                timestamp: new Date().toISOString()\r\n            });\r\n        };\r\n        \r\n        img.src = imageUrl;\r\n    }\r\n}\r\n```\r\n\r\n## Αυτοματοποίηση και Κλιμάκωση\r\n\r\n### Batch Επεξεργασία για Μεγάλους Καταλόγους\r\n\r\nΑποδοτική επεξεργασία χιλιάδων εικόνων προϊόντων:\r\n\r\n```python\r\nimport concurrent.futures\r\nimport multiprocessing\r\nfrom pathlib import Path\r\n\r\nclass BatchImageProcessor:\r\n    def __init__(self, max_workers=None):\r\n        self.max_workers = max_workers or multiprocessing.cpu_count()\r\n        self.processor = EcommerceImageProcessor()\r\n    \r\n    def process_catalog(self, input_directory, output_directory, progress_callback=None):\r\n        \"\"\"Επεξεργασία ολόκληρου καταλόγου εικόνων προϊόντων\"\"\"\r\n        input_path = Path(input_directory)\r\n        output_path = Path(output_directory)\r\n        output_path.mkdir(parents=True, exist_ok=True)\r\n        \r\n        # Εύρεση όλων των εικόνων\r\n        image_files = list(input_path.glob('**/*.{jpg,jpeg,png,webp}'))\r\n        total_files = len(image_files)\r\n        \r\n        processed_count = 0\r\n        failed_files = []\r\n        \r\n        with concurrent.futures.ThreadPoolExecutor(max_workers=self.max_workers) as executor:\r\n            # Υποβολή όλων των εργασιών\r\n            future_to_file = {\r\n                executor.submit(self.process_single_image, img_file, output_path): img_file\r\n                for img_file in image_files\r\n            }\r\n            \r\n            # Επεξεργασία αποτελεσμάτων\r\n            for future in concurrent.futures.as_completed(future_to_file):\r\n                img_file = future_to_file[future]\r\n                try:\r\n                    result = future.result()\r\n                    processed_count += 1\r\n                    \r\n                    if progress_callback:\r\n                        progress_callback(processed_count, total_files, img_file.name)\r\n                        \r\n                except Exception as exc:\r\n                    failed_files.append((img_file, str(exc)))\r\n                    print(f'Αρχείο {img_file} δημιούργησε εξαίρεση: {exc}')\r\n        \r\n        return {\r\n            'total_files': total_files,\r\n            'processed_count': processed_count,\r\n            'failed_files': failed_files,\r\n            'success_rate': (processed_count / total_files) * 100 if total_files > 0 else 0\r\n        }\r\n```\r\n\r\n## Συμπέρασμα\r\n\r\nΗ βελτιστοποίηση εικόνων προϊόντων για e-commerce είναι κρίσιμος παράγοντας για την επιτυχία του διαδικτυακού καταστήματος. Η σωστή υλοποίηση τεχνικών συμπίεσης, αυτοματοποίησης επεξεργασίας και μέτρησης απόδοσης μπορεί να βελτιώσει σημαντικά τα ποσοστά μετατροπής, να μειώσει τα ποσοστά εγκατάλειψης και να αυξήσει την ικανοποίηση των πελατών.\r\n\r\nΒασικά σημεία προς απομνημόνευση:\r\n\r\n1. **Ισορροπία ποιότητας και απόδοσης**: Εύρεση του βέλτιστου σημείου μεταξύ οπτικής ποιότητας και ταχύτητας φόρτωσης\r\n2. **Η αυτοματοποίηση είναι κλειδί**: Υλοποίηση αυτοματοποιημένων pipelines για κλιμάκωση\r\n3. **Δοκιμή και μέτρηση**: Χρήση A/B testing για επαλήθευση επιπτώσεων βελτιστοποίησης\r\n4. **Ειδικές απαιτήσεις πλατφόρμας**: Προσαρμογή βελτιστοποίησης σε συγκεκριμένες απαιτήσεις marketplace\r\n5. **Συνεχής βελτίωση**: Τακτική ενημέρωση στρατηγικών βάσει νέων τεχνολογιών και δεδομένων\r\n\r\nΗ επένδυση σε επαγγελματική βελτιστοποίηση εικόνων θα αποπληρωθεί γρήγορα μέσω βελτιωμένων επιχειρηματικών αποτελεσμάτων και καλύτερης εμπειρίας χρήστη.\r\n","# Stiskanje slik izdelkov za e-trgovino: optimizacija za prodajo\r\n\r\nUspeh v e-trgovini je močno odvisen od kakovosti slik izdelkov: raziskave kažejo, da 67 % potrošnikov meni, da je kakovost slik \"zelo pomembna\" pri spletnem nakupovanju. Vendar pa lahko velike datoteke slik bistveno vplivajo na čas nalaganja strani, konverzije in izkušnjo na mobilnih napravah. Ta podroben vodnik zajema napredne prakse optimizacije slik izdelkov za e-trgovino ob ohranjanju vizualne kakovosti, ki je potrebna za povečanje prodaje.\r\n\r\n## Zakaj je optimizacija slik za e-trgovino pomembna\r\n\r\n### Vpliv na konverzijo\r\n\r\nOptimizacija slik izdelkov neposredno vpliva na poslovne rezultate:\r\n- **Konverzija**: 1 sekunda zamude pri nalaganju strani zmanjša konverzijo za 7 %\r\n- **Stopnja zapustitve**: 40 % uporabnikov zapusti spletna mesta, ki se nalagajo več kot 3 sekunde\r\n- **Mobilna trgovina**: 73 % prometa v e-trgovini prihaja iz mobilnih naprav\r\n- **Uvrstitev v iskalnikih**: Google upošteva hitrost nalaganja strani pri razvrščanju\r\n- **Zadovoljstvo strank**: kakovostne slike povečajo zaupanje v nakup\r\n\r\n### Posebne zahteve e-trgovine\r\n\r\nSlike izdelkov imajo edinstvene izzive optimizacije:\r\n- **Več zornih kotov izdelka**: glavna slika, sličice, zoom, 360° pogled\r\n- **Natančnost barv**: ključno za modo, kozmetiko in izdelke za dom\r\n- **Ohranjanje podrobnosti**: kupci želijo videti teksturo, materiale in kakovost izdelave\r\n- **Učinkovitost nalaganja**: ravnovesje med kakovostjo in hitrostjo\r\n- **Večplatformska izkušnja**: enotna izkušnja na vseh napravah\r\n\r\n## Vrste slik za e-trgovino\r\n\r\n### Kategorije slik izdelkov\r\n\r\nRazlične vrste slik zahtevajo različne pristope k optimizaciji:\r\n\r\n```javascript\r\nconst ecommerceImageTypes = {\r\n    hero: {\r\n        purpose: 'Glavna predstavitev izdelka',\r\n        requirements: 'Visoka kakovost, hitro nalaganje',\r\n        sizes: ['1200x1200', '800x800', '600x600'],\r\n        quality: { jpeg: 85, webp: 80 }\r\n    },\r\n    thumbnail: {\r\n        purpose: 'Mreža izdelkov',\r\n        requirements: 'Majhna velikost datoteke, prepoznavnost',\r\n        sizes: ['300x300', '200x200', '150x150'],\r\n        quality: { jpeg: 75, webp: 70 }\r\n    },\r\n    zoom: {\r\n        purpose: 'Podroben ogled izdelka',\r\n        requirements: 'Maksimalno ohranjanje podrobnosti',\r\n        sizes: ['2000x2000', '1600x1600'],\r\n        quality: { jpeg: 90, webp: 85 }\r\n    },\r\n    gallery: {\r\n        purpose: 'Več zornih kotov izdelka',\r\n        requirements: 'Stabilna kakovost, odloženo nalaganje',\r\n        sizes: ['800x800', '600x600'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    },\r\n    lifestyle: {\r\n        purpose: 'Izdelek v uporabi/kontekstu',\r\n        requirements: 'Optimizacija za čustva/kontekst',\r\n        sizes: ['1200x800', '800x533'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    }\r\n};\r\n```\r\n\r\n### Optimizacijska strategija po kategorijah izdelkov\r\n\r\nRazlične kategorije izdelkov imajo svoje zahteve za slike:\r\n\r\n```python\r\ndef get_category_optimization_settings(product_category):\r\n    \"\"\"Pridobi nastavitve optimizacije za različne kategorije izdelkov\"\"\"\r\n    settings = {\r\n        'fashion': {\r\n            'priority': ['natančnost_barv', 'detajli_teksture'],\r\n            'format_preference': 'webp_z_rezervo_jpeg',\r\n            'quality_range': {'min': 80, 'max': 90},\r\n            'critical_views': ['spredaj', 'zadaj', 'detajli']\r\n        },\r\n        'electronics': {\r\n            'priority': ['ohranjanje_podrobnosti', 'hitro_nalaganje'],\r\n            'format_preference': 'webp_ali_avif',\r\n            'quality_range': {'min': 75, 'max': 85},\r\n            'critical_views': ['glavna', 'vmesniki', 'primerjava_velikosti']\r\n        },\r\n        'home_decor': {\r\n            'priority': ['natančnost_barv', 'kontekst_uporabe'],\r\n            'format_preference': 'webp_z_rezervo_jpeg',\r\n            'quality_range': {'min': 80, 'max': 88},\r\n            'critical_views': ['interier', 'povečava', 'dimenzije']\r\n        },\r\n        'jewelry': {\r\n            'priority': ['maksimalni_detajli', 'natančnost_barv'],\r\n            'format_preference': 'png_za_detajle_webp_za_hero',\r\n            'quality_range': {'min': 85, 'max': 95},\r\n            'critical_views': ['makro', '360_pogled', 'lifestyle']\r\n        },\r\n        'books': {\r\n            'priority': ['hitro_nalaganje', 'berljivost_besedila'],\r\n            'format_preference': 'webp_agresivno_stiskanje',\r\n            'quality_range': {'min': 70, 'max': 80},\r\n            'critical_views': ['naslovnica', 'zadnja_stran', 'hrbtišče']\r\n        }\r\n    }\r\n    return settings.get(product_category, settings['electronics'])\r\n```\r\n\r\n## Napredna obdelava slik izdelkov\r\n\r\n### Avtomatiziran pipeline za obdelavo slik\r\n\r\nCelovit sistem za avtomatizirano obdelavo:\r\n\r\n```python\r\nimport os\r\nfrom PIL import Image, ImageEnhance, ImageFilter\r\nimport numpy as np\r\n\r\nclass EcommerceImageProcessor:\r\n    def __init__(self, config=None):\r\n        self.config = config or self.get_default_config()\r\n        self.supported_formats = ['jpeg', 'webp', 'avif', 'png']\r\n        \r\n    def get_default_config(self):\r\n        return {\r\n            'background_removal': True,\r\n            'auto_crop': True,\r\n            'color_enhancement': True,\r\n            'noise_reduction': True,\r\n            'watermark': False,\r\n            'quality_thresholds': {\r\n                'hero': 85,\r\n                'gallery': 80,\r\n                'thumbnail': 75,\r\n                'zoom': 90\r\n            }\r\n        }\r\n    \r\n    def process_product_image(self, input_path, output_dir, product_id):\r\n        \"\"\"Obdelaj eno sliko izdelka v vse potrebne različice\"\"\"\r\n        img = Image.open(input_path)\r\n        \r\n        # Osnovna predobdelava\r\n        processed_img = self.preprocess_image(img)\r\n        \r\n        # Generiranje vseh potrebnih velikosti in formatov\r\n        variants = self.generate_image_variants(processed_img, product_id)\r\n        \r\n        # Shranjevanje optimiziranih različic\r\n        saved_files = self.save_variants(variants, output_dir)\r\n        \r\n        return saved_files\r\n    \r\n    def preprocess_image(self, img):\r\n        \"\"\"Osnovna predobdelava slike izdelka\"\"\"\r\n        # Pretvorba v RGB po potrebi\r\n        if img.mode in ('RGBA', 'LA', 'P'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            if img.mode == 'RGBA':\r\n                background.paste(img, mask=img.split()[-1])\r\n            else:\r\n                background.paste(img)\r\n            img = background\r\n        \r\n        # Samodejno obrezovanje za odstranitev odvečnega ozadja\r\n        if self.config['auto_crop']:\r\n            img = self.smart_crop(img)\r\n        \r\n        # Izboljšanje kakovosti slike\r\n        if self.config['color_enhancement']:\r\n            img = self.enhance_product_image(img)\r\n        \r\n        # Zmanjšanje šuma\r\n        if self.config['noise_reduction']:\r\n            img = img.filter(ImageFilter.SMOOTH_MORE)\r\n        \r\n        return img\r\n    \r\n    def smart_crop(self, img):\r\n        \"\"\"Pametno obrezovanje za odstranitev odvečnega ozadja\"\"\"\r\n        # Pretvorba v numpy array za analizo\r\n        img_array = np.array(img)\r\n        \r\n        # Iskanje omejevalnega pravokotnika ne-belih pikslov\r\n        mask = np.any(img_array \u003C 240, axis=2)  # Ni popolnoma belo\r\n        coords = np.argwhere(mask)\r\n        \r\n        if len(coords) == 0:\r\n            return img  # Obrezovanje ni potrebno\r\n        \r\n        # Pridobitev omejevalnega pravokotnika\r\n        y0, x0 = coords.min(axis=0)\r\n        y1, x1 = coords.max(axis=0)\r\n        \r\n        # Dodajanje roba\r\n        padding = 20\r\n        y0 = max(0, y0 - padding)\r\n        x0 = max(0, x0 - padding)\r\n        y1 = min(img.height, y1 + padding)\r\n        x1 = min(img.width, x1 + padding)\r\n        \r\n        return img.crop((x0, y0, x1, y1))\r\n    \r\n    def enhance_product_image(self, img):\r\n        \"\"\"Izboljšanje slike izdelka za e-trgovino\"\"\"\r\n        # Rahlo povečanje svetlosti\r\n        brightness_enhancer = ImageEnhance.Brightness(img)\r\n        img = brightness_enhancer.enhance(1.05)\r\n        \r\n        # Povečanje kontrasta\r\n        contrast_enhancer = ImageEnhance.Contrast(img)\r\n        img = contrast_enhancer.enhance(1.1)\r\n        \r\n        # Povečanje nasičenosti barv\r\n        color_enhancer = ImageEnhance.Color(img)\r\n        img = color_enhancer.enhance(1.05)\r\n        \r\n        # Povečanje ostrine\r\n        sharpness_enhancer = ImageEnhance.Sharpness(img)\r\n        img = sharpness_enhancer.enhance(1.1)\r\n        \r\n        return img\r\n    \r\n    def generate_image_variants(self, img, product_id):\r\n        \"\"\"Generiranje vseh potrebnih različic slike\"\"\"\r\n        variants = {}\r\n        \r\n        # Standardne velikosti za e-trgovino\r\n        sizes = {\r\n            'hero': (1200, 1200),\r\n            'gallery': (800, 800),\r\n            'thumbnail': (300, 300),\r\n            'zoom': (2000, 2000),\r\n            'mobile_hero': (600, 600),\r\n            'mobile_thumb': (150, 150)\r\n        }\r\n        \r\n        for variant_name, size in sizes.items():\r\n            # Spreminjanje velikosti z visoko kakovostjo resamplinga\r\n            resized = img.resize(size, Image.Resampling.LANCZOS)\r\n            variants[variant_name] = resized\r\n        \r\n        return variants\r\n    \r\n    def save_variants(self, variants, output_dir):\r\n        \"\"\"Shranjevanje vseh različic v optimiziranih formatih\"\"\"\r\n        saved_files = []\r\n        \r\n        for variant_name, img in variants.items():\r\n            base_path = os.path.join(output_dir, variant_name)\r\n            \r\n            # Shranjevanje v več formatih\r\n            for format_type in ['jpeg', 'webp']:\r\n                filename = f\"{base_path}.{format_type}\"\r\n                quality = self.get_quality_for_variant(variant_name, format_type)\r\n                \r\n                if format_type == 'jpeg':\r\n                    img.save(filename, 'JPEG', quality=quality, optimize=True, progressive=True)\r\n                elif format_type == 'webp':\r\n                    img.save(filename, 'WebP', quality=quality, optimize=True)\r\n                \r\n                saved_files.append(filename)\r\n        \r\n        return saved_files\r\n    \r\n    def get_quality_for_variant(self, variant_name, format_type):\r\n        \"\"\"Pridobi optimalno kakovost za različico in format\"\"\"\r\n        base_quality = self.config['quality_thresholds'].get(variant_name, 80)\r\n        \r\n        # Prilagoditev za format\r\n        if format_type == 'webp':\r\n            return base_quality - 5  # WebP omogoča enako kakovost pri nižji vrednosti\r\n        elif format_type == 'avif':\r\n            return base_quality - 10  # AVIF je še učinkovitejši\r\n        \r\n        return base_quality\r\n\r\n# Primer uporabe\r\nprocessor = EcommerceImageProcessor()\r\nprocessor.process_product_image('product_raw.jpg', 'output/', 'product_123')\r\n```\r\n\r\n### Odstranjevanje in standardizacija ozadja\r\n\r\nAvtomatizirana obdelava ozadja za enoten prikaz izdelkov:\r\n\r\n```python\r\ndef remove_product_background(image_path, output_path):\r\n    \"\"\"Odstrani ozadje slike izdelka z zaznavanjem robov\"\"\"\r\n    import cv2\r\n    import numpy as np\r\n    \r\n    # Branje slike\r\n    img = cv2.imread(image_path)\r\n    original = img.copy()\r\n    \r\n    # Pretvorba v sivine\r\n    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\r\n    \r\n    # Gaussovo zamegljevanje za zmanjšanje šuma\r\n    blurred = cv2.GaussianBlur(gray, (5, 5), 0)\r\n    \r\n    # Zaznavanje robov\r\n    edges = cv2.Canny(blurred, 50, 150)\r\n    \r\n    # Iskanje kontur\r\n    contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\r\n    \r\n    if contours:\r\n        # Najdi največjo konturo (predvidoma izdelek)\r\n        largest_contour = max(contours, key=cv2.contourArea)\r\n        \r\n        # Ustvari masko\r\n        mask = np.zeros(gray.shape, np.uint8)\r\n        cv2.fillPoly(mask, [largest_contour], 255)\r\n        \r\n        # Uporabi masko na originalni sliki\r\n        result = cv2.bitwise_and(original, original, mask=mask)\r\n        \r\n        # Zamenjaj ozadje z belo\r\n        result[mask == 0] = [255, 255, 255]\r\n        \r\n        cv2.imwrite(output_path, result)\r\n        return True\r\n    \r\n    return False\r\n\r\ndef standardize_product_backgrounds(input_dir, output_dir, background_color=(255, 255, 255)):\r\n    \"\"\"Standardiziraj vsa ozadja izdelkov na enotno barvo\"\"\"\r\n    for filename in os.listdir(input_dir):\r\n        if filename.lower().endswith(('.jpg', '.jpeg', '.png')):\r\n            input_path = os.path.join(input_dir, filename)\r\n            output_path = os.path.join(output_dir, filename)\r\n            \r\n            # Poskusi samodejno odstraniti ozadje\r\n            if not remove_product_background(input_path, output_path):\r\n                # Alternativa: samo belo ozadje\r\n                img = Image.open(input_path)\r\n                if img.mode == 'RGBA':\r\n                    background = Image.new('RGB', img.size, background_color)\r\n                    background.paste(img, mask=img.split()[-1])\r\n                    background.save(output_path, 'JPEG', quality=85)\r\n                else:\r\n                    img.save(output_path)\r\n```\r\n\r\n## Optimizacija za platformo\r\n\r\n### Optimizacija za Amazon Marketplace\r\n\r\nAmazon ima posebne zahteve za slike in uporablja lastne algoritme:\r\n\r\n```python\r\nclass AmazonImageOptimizer:\r\n    def __init__(self):\r\n        self.requirements = {\r\n            'main_image': {\r\n                'min_size': (1000, 1000),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'background': 'pure_white',\r\n                'product_coverage': 85  # Minimalni odstotek slike\r\n            },\r\n            'additional_images': {\r\n                'min_size': (500, 500),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'lifestyle_allowed': True\r\n            }\r\n        }\r\n    \r\n    def optimize_for_amazon(self, image_path, output_path, image_type='main'):\r\n        \"\"\"Optimiziraj sliko posebej za Amazon listing\"\"\"\r\n        img = Image.open(image_path)\r\n        \r\n        if image_type == 'main':\r\n            img = self.ensure_white_background(img)\r\n            img = self.ensure_minimum_size(img, (1000, 1000))\r\n        \r\n        # Amazon preferira barvni prostor sRGB\r\n        if img.mode != 'RGB':\r\n            img = img.convert('RGB')\r\n        \r\n        # Optimizacija velikosti datoteke ob ohranjanju kakovosti\r\n        quality = 90 if image_type == 'main' else 85\r\n        img.save(output_path, 'JPEG', quality=quality, optimize=True)\r\n        \r\n        return self.validate_amazon_requirements(output_path, image_type)\r\n    \r\n    def ensure_white_background(self, img):\r\n        \"\"\"Preveri, da ima slika popolnoma belo ozadje\"\"\"\r\n        if img.mode == 'RGBA':\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            background.paste(img, mask=img.split()[-1])\r\n            return background\r\n        return img\r\n    \r\n    def ensure_minimum_size(self, img, min_size):\r\n        \"\"\"Preveri, da slika ustreza minimalnim dimenzijam\"\"\"\r\n        if img.size[0] \u003C min_size[0] or img.size[1] \u003C min_size[1]:\r\n            img = img.resize(min_size, Image.Resampling.LANCZOS)\r\n        return img\r\n    \r\n    def validate_amazon_requirements(self, image_path, image_type):\r\n        \"\"\"Preveri skladnost slike z zahtevami Amazona\"\"\"\r\n        img = Image.open(image_path)\r\n        requirements = self.requirements[image_type]\r\n        \r\n        validation_results = {\r\n            'size_valid': (\r\n                img.size[0] >= requirements['min_size'][0] and \r\n                img.size[1] >= requirements['min_size'][1]\r\n            ),\r\n            'format_valid': image_path.upper().endswith(tuple(requirements['formats'])),\r\n            'file_size_valid': os.path.getsize(image_path) \u003C= 10 * 1024 * 1024  # Omejitev 10 MB\r\n        }\r\n        \r\n        return all(validation_results.values()), validation_results\r\n```\r\n\r\n### Optimizacija za trgovine Shopify\r\n\r\nOptimizacija za teme in zmogljivost Shopify:\r\n\r\n```javascript\r\nclass ShopifyImageOptimizer {\r\n    constructor() {\r\n        this.themeRequirements = {\r\n            'product_card': { width: 600, height: 600, quality: 80 },\r\n            'product_detail': { width: 1200, height: 1200, quality: 85 },\r\n            'product_zoom': { width: 2048, height: 2048, quality: 90 },\r\n            'collection_featured': { width: 800, height: 600, quality: 80 }\r\n        };\r\n    }\r\n    \r\n    generateShopifyImageUrls(baseImageUrl, productHandle) {\r\n        const urls = {};\r\n        \r\n        Object.entries(this.themeRequirements).forEach(([variant, specs]) => {\r\n            // Oblikovanje URL-ja za pretvorbo slik Shopify\r\n            const transformedUrl = baseImageUrl.replace('.jpg', \r\n                `_${specs.width}x${specs.height}_crop_center.jpg`);\r\n            urls[variant] = transformedUrl;\r\n        });\r\n        \r\n        return urls;\r\n    }\r\n    \r\n    generateShopifyPictureElement(productData) {\r\n        const { images, title, handle } = productData;\r\n        const mainImage = images[0];\r\n        \r\n        return `\r\n            \u003Cpicture>\r\n                \u003Csource media=\"(min-width: 1200px)\" \r\n                        srcset=\"${mainImage}_1200x1200.webp 1x, ${mainImage}_2400x2400.webp 2x\"\r\n                        type=\"image/webp\">\r\n                \u003Csource media=\"(min-width: 768px)\" \r\n                        srcset=\"${mainImage}_800x800.webp 1x, ${mainImage}_1600x1600.webp 2x\"\r\n                        type=\"image/webp\">\r\n                \u003Csource media=\"(max-width: 767px)\" \r\n                        srcset=\"${mainImage}_600x600.webp 1x, ${mainImage}_1200x1200.webp 2x\"\r\n                        type=\"image/webp\">\r\n                \u003Cimg src=\"${mainImage}_800x800.jpg\"\r\n                     srcset=\"${mainImage}_400x400.jpg 400w,\r\n                             ${mainImage}_600x600.jpg 600w,\r\n                             ${mainImage}_800x800.jpg 800w,\r\n                             ${mainImage}_1200x1200.jpg 1200w\"\r\n                     sizes=\"(max-width: 767px) 100vw, (max-width: 1023px) 50vw, 33vw\"\r\n                     alt=\"${title}\"\r\n                     loading=\"lazy\"\r\n                     data-product-handle=\"${handle}\">\r\n            \u003C/picture>\r\n        `;\r\n    }\r\n}\r\n```\r\n\r\n## Napredne strategije nalaganja za e-trgovino\r\n\r\n### Pametno nalaganje slik izdelkov\r\n\r\nPametno nalaganje na podlagi vedenja uporabnika in zmogljivosti naprave:\r\n\r\n```javascript\r\nclass EcommerceImageLoader {\r\n    constructor() {\r\n        this.userBehavior = this.trackUserBehavior();\r\n        this.deviceCapabilities = this.analyzeDevice();\r\n        this.loadingStrategies = this.initializeStrategies();\r\n    }\r\n    \r\n    trackUserBehavior() {\r\n        return {\r\n            isReturningCustomer: localStorage.getItem('visited') === 'true',\r\n            viewingHistory: JSON.parse(localStorage.getItem('viewedProducts') || '[]'),\r\n            averageSessionTime: parseInt(localStorage.getItem('avgSessionTime') || '0'),\r\n            purchaseHistory: JSON.parse(localStorage.getItem('purchases') || '[]')\r\n        };\r\n    }\r\n    \r\n    analyzeDevice() {\r\n        const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;\r\n        \r\n        return {\r\n            connectionSpeed: connection ? connection.effectiveType : '4g',\r\n            deviceMemory: navigator.deviceMemory || 4,\r\n            isLowEndDevice: navigator.deviceMemory \u003C 2,\r\n            isMobile: window.innerWidth \u003C= 768,\r\n            isSlowConnection: connection && (connection.effectiveType === 'slow-2g' || connection.effectiveType === '2g')\r\n        };\r\n    }\r\n    \r\n    initializeStrategies() {\r\n        return {\r\n            eager: this.eagerLoadingStrategy.bind(this),\r\n            progressive: this.progressiveLoadingStrategy.bind(this),\r\n            lazy: this.lazyLoadingStrategy.bind(this),\r\n            adaptive: this.adaptiveLoadingStrategy.bind(this)\r\n        };\r\n    }\r\n    \r\n    selectOptimalStrategy(productData, context) {\r\n        const { deviceCapabilities, userBehavior } = this;\r\n        \r\n        // Stalni kupci z dobro povezavo\r\n        if (userBehavior.isReturningCustomer && \r\n            userBehavior.purchaseHistory.length > 0 && \r\n            !deviceCapabilities.isSlowConnection) {\r\n            return 'eager';\r\n        }\r\n        \r\n        // Šibke naprave ali počasna povezava\r\n        if (deviceCapabilities.isLowEndDevice || deviceCapabilities.isSlowConnection) {\r\n            return 'lazy';\r\n        }\r\n        \r\n        // Mobilne naprave z dobro povezavo\r\n        if (deviceCapabilities.isMobile && !deviceCapabilities.isSlowConnection) {\r\n            return 'progressive';\r\n        }\r\n        \r\n        // Privzeto: prilagodljiva strategija\r\n        return 'adaptive';\r\n    }\r\n    \r\n    eagerLoadingStrategy(productImages) {\r\n        // Takojšnje nalaganje vseh slik za vrhunsko izkušnjo\r\n        productImages.forEach(img => {\r\n            const imageLoader = new Image();\r\n            imageLoader.src = img.dataset.src;\r\n            \r\n            if (img.dataset.srcset) {\r\n                imageLoader.srcset = img.dataset.srcset;\r\n            }\r\n            \r\n            imageLoader.onload = () => {\r\n                img.src = imageLoader.src;\r\n                if (img.dataset.srcset) {\r\n                    img.srcset = imageLoader.srcset;\r\n                }\r\n                img.classList.add('loaded');\r\n            };\r\n        });\r\n    }\r\n    \r\n    progressiveLoadingStrategy(productImages) {\r\n        // Najprej nalaganje nizke kakovosti, nato visoke\r\n        productImages.forEach(img => {\r\n            // Nalaganje nizkokakovostnega placeholderja\r\n            const lowQualitySrc = img.dataset.lowSrc || img.dataset.src.replace('_q85', '_q40');\r\n            const highQualitySrc = img.dataset.src;\r\n            \r\n            img.src = lowQualitySrc;\r\n            img.classList.add('loading');\r\n            \r\n            // Nalaganje visoko kakovostne različice\r\n            const highQualityLoader = new Image();\r\n            highQualityLoader.onload = () => {\r\n                img.src = highQualitySrc;\r\n                img.classList.remove('loading');\r\n                img.classList.add('loaded');\r\n            };\r\n            highQualityLoader.src = highQualitySrc;\r\n        });\r\n    }\r\n    \r\n    lazyLoadingStrategy(productImages) {\r\n        // Uporaba Intersection Observer za odloženo nalaganje\r\n        const observer = new IntersectionObserver((entries) => {\r\n            entries.forEach(entry => {\r\n                if (entry.isIntersecting) {\r\n                    this.loadImage(entry.target);\r\n                    observer.unobserve(entry.target);\r\n                }\r\n            });\r\n        }, { rootMargin: '100px' });\r\n        \r\n        productImages.forEach(img => observer.observe(img));\r\n    }\r\n    \r\n    adaptiveLoadingStrategy(productImages) {\r\n        // Prilagajanje na podlagi interakcije uporabnika in pomikanja\r\n        let scrollTimeout;\r\n        let isScrolling = false;\r\n        \r\n        window.addEventListener('scroll', () => {\r\n            if (!isScrolling) {\r\n                isScrolling = true;\r\n                // Takojšnje nalaganje vidnih slik ob začetku pomikanja\r\n                this.loadVisibleImages(productImages);\r\n            }\r\n            \r\n            clearTimeout(scrollTimeout);\r\n            scrollTimeout = setTimeout(() => {\r\n                isScrolling = false;\r\n            }, 150);\r\n        });\r\n        \r\n        // Takojšnje nalaganje ključnih slik nad pregibom\r\n        this.loadCriticalImages(productImages);\r\n        \r\n        // Odloženo nalaganje preostalih slik\r\n        this.lazyLoadingStrategy(productImages.filter(img => !img.dataset.critical));\r\n    }\r\n    \r\n    loadCriticalImages(productImages) {\r\n        const criticalImages = productImages.filter(img => \r\n            img.dataset.critical === 'true' || \r\n            img.getBoundingClientRect().top \u003C window.innerHeight\r\n        );\r\n        \r\n        criticalImages.forEach(img => this.loadImage(img));\r\n    }\r\n    \r\n    loadVisibleImages(productImages) {\r\n        const visibleImages = productImages.filter(img => {\r\n            const rect = img.getBoundingClientRect();\r\n            return rect.top \u003C window.innerHeight && rect.bottom > 0;\r\n        });\r\n        \r\n        visibleImages.forEach(img => this.loadImage(img));\r\n    }\r\n    \r\n    loadImage(img) {\r\n        if (img.dataset.loaded) return;\r\n        \r\n        const imageLoader = new Image();\r\n        imageLoader.onload = () => {\r\n            img.src = imageLoader.src;\r\n            if (img.dataset.srcset) {\r\n                img.srcset = imageLoader.srcset;\r\n            }\r\n            img.classList.add('loaded');\r\n            img.dataset.loaded = 'true';\r\n        };\r\n        \r\n        imageLoader.src = img.dataset.src;\r\n    }\r\n}\r\n\r\n// Inicializacija za strani izdelkov\r\n// document.addEventListener('DOMContentLoaded', () => {\r\n//     const imageLoader = new EcommerceImageLoader();\r\n//     const productImages = document.querySelectorAll('.product-image[data-src]');\r\n//     \r\n//     if (productImages.length > 0) {\r\n//         const strategy = imageLoader.selectOptimalStrategy();\r\n//         imageLoader.loadingStrategies[strategy](productImages);\r\n//     }\r\n// });\r\n```\r\n\r\n## Optimizacija zooma in 360° pogleda\r\n\r\n### Učinkovita implementacija zooma\r\n\r\nOptimizirana funkcija zoom za strani s podrobnostmi izdelka:\r\n\r\n```javascript\r\nclass ProductImageZoom {\r\n    constructor(options = {}) {\r\n        this.container = options.container;\r\n        this.zoomLevel = options.zoomLevel || 2;\r\n        this.loadingStrategy = options.loadingStrategy || 'on-demand';\r\n        this.highResImages = new Map();\r\n        \r\n        this.initializeZoom();\r\n    }\r\n    \r\n    initializeZoom() {\r\n        const zoomImages = this.container.querySelectorAll('.zoomable-image');\r\n        \r\n        zoomImages.forEach(img => {\r\n            img.addEventListener('mouseenter', this.handleMouseEnter.bind(this));\r\n            img.addEventListener('mouseleave', this.handleMouseLeave.bind(this));\r\n            img.addEventListener('mousemove', this.handleMouseMove.bind(this));\r\n        });\r\n    }\r\n    \r\n    async handleMouseEnter(event) {\r\n        const img = event.target;\r\n        const highResUrl = img.dataset.zoomSrc;\r\n        \r\n        if (!highResUrl) return;\r\n        \r\n        // Nalaganje slike visoke ločljivosti na zahtevo\r\n        if (!this.highResImages.has(highResUrl)) {\r\n            this.loadHighResImage(highResUrl);\r\n        }\r\n        \r\n        this.showZoomOverlay(img);\r\n    }\r\n    \r\n    loadHighResImage(url) {\r\n        return new Promise((resolve, reject) => {\r\n            const img = new Image();\r\n            img.onload = () => {\r\n                this.highResImages.set(url, img);\r\n                resolve(img);\r\n            };\r\n            img.onerror = reject;\r\n            img.src = url;\r\n        });\r\n    }\r\n    \r\n    showZoomOverlay(img) {\r\n        // Ustvari overlay za zoom, če ne obstaja\r\n        let overlay = img.parentNode.querySelector('.zoom-overlay');\r\n        if (!overlay) {\r\n            overlay = document.createElement('div');\r\n            overlay.className = 'zoom-overlay';\r\n            overlay.style.cssText = `\r\n                position: absolute;\r\n                top: 0;\r\n                left: 100%;\r\n                width: 300px;\r\n                height: 300px;\r\n                border: 1px solid #ddd;\r\n                background: white;\r\n                overflow: hidden;\r\n                z-index: 1000;\r\n                display: none;\r\n            `;\r\n            img.parentNode.appendChild(overlay);\r\n        }\r\n        \r\n        overlay.style.display = 'block';\r\n    }\r\n    \r\n    handleMouseMove(event) {\r\n        const img = event.target;\r\n        const overlay = img.parentNode.querySelector('.zoom-overlay');\r\n        const highResUrl = img.dataset.zoomSrc;\r\n        \r\n        if (!overlay || !this.highResImages.has(highResUrl)) return;\r\n        \r\n        const rect = img.getBoundingClientRect();\r\n        const x = (event.clientX - rect.left) / rect.width;\r\n        const y = (event.clientY - rect.top) / rect.height;\r\n        \r\n        const highResImg = this.highResImages.get(highResUrl);\r\n        \r\n        // Posodobi overlay za zoom\r\n        overlay.style.backgroundImage = `url(${highResUrl})`;\r\n        overlay.style.backgroundSize = `${highResImg.width}px ${highResImg.height}px`;\r\n        overlay.style.backgroundPosition = `-${x * (highResImg.width - 300)}px -${y * (highResImg.height - 300)}px`;\r\n    }\r\n    \r\n    handleMouseLeave(event) {\r\n        const img = event.target;\r\n        const overlay = img.parentNode.querySelector('.zoom-overlay');\r\n        \r\n        if (overlay) {\r\n            overlay.style.display = 'none';\r\n        }\r\n    }\r\n}\r\n\r\n// Optimizacija 360° pogleda izdelka\r\nclass Product360View {\r\n    constructor(container, options = {}) {\r\n        this.container = container;\r\n        this.frameCount = options.frameCount || 36;\r\n        this.autoPlay = options.autoPlay || false;\r\n        this.frames = [];\r\n        this.currentFrame = 0;\r\n        this.isLoading = false;\r\n        \r\n        this.initialize();\r\n    }\r\n    \r\n    async initialize() {\r\n        await this.loadFrames();\r\n        this.setupControls();\r\n        this.setupInteraction();\r\n    }\r\n    \r\n    async loadFrames() {\r\n        this.isLoading = true;\r\n        const baseUrl = this.container.dataset.baseUrl;\r\n        \r\n        // Progresivno nalaganje sličic\r\n        const loadPromises = [];\r\n        \r\n        for (let i = 1; i \u003C= this.frameCount; i++) {\r\n            const frameUrl = `${baseUrl}/frame_${i.toString().padStart(3, '0')}.jpg`;\r\n            loadPromises.push(this.loadFrame(frameUrl, i - 1));\r\n        }\r\n        \r\n        // Prvih nekaj sličic se naloži takoj, ostale v ozadju\r\n        await Promise.all(loadPromises.slice(0, 8));\r\n        \r\n        // Preostale sličice se naložijo v ozadju\r\n        Promise.all(loadPromises.slice(8));\r\n        \r\n        this.isLoading = false;\r\n        this.displayFrame(0);\r\n    }\r\n    \r\n    loadFrame(url, index) {\r\n        return new Promise((resolve) => {\r\n            const img = new Image();\r\n            img.onload = () => {\r\n                this.frames[index] = img;\r\n                resolve();\r\n            };\r\n            img.onerror = () => {\r\n                // Rezervna slika za neuspešno nalaganje\r\n                this.frames[index] = null;\r\n                resolve();\r\n            };\r\n            img.src = url;\r\n        });\r\n    }\r\n    \r\n    displayFrame(frameIndex) {\r\n        if (!this.frames[frameIndex]) return;\r\n        \r\n        const img = this.container.querySelector('.view-360-image') || \r\n                   this.createImageElement();\r\n        \r\n        img.src = this.frames[frameIndex].src;\r\n        this.currentFrame = frameIndex;\r\n    }\r\n    \r\n    createImageElement() {\r\n        const img = document.createElement('img');\r\n        img.className = 'view-360-image';\r\n        img.style.cssText = 'width: 100%; height: auto; display: block;';\r\n        this.container.appendChild(img);\r\n        return img;\r\n    }\r\n    \r\n    setupInteraction() {\r\n        let isDragging = false;\r\n        let startX = 0;\r\n        let startFrame = 0;\r\n        \r\n        this.container.addEventListener('mousedown', (e) => {\r\n            isDragging = true;\r\n            startX = e.clientX;\r\n            startFrame = this.currentFrame;\r\n            e.preventDefault();\r\n        });\r\n        \r\n        document.addEventListener('mousemove', (e) => {\r\n            if (!isDragging) return;\r\n            \r\n            const deltaX = e.clientX - startX;\r\n            const sensitivity = 2; // Pikslov na sličico\r\n            const frameChange = Math.floor(deltaX / sensitivity);\r\n            \r\n            let newFrame = (startFrame + frameChange) % this.frameCount;\r\n            if (newFrame \u003C 0) newFrame += this.frameCount;\r\n            \r\n            this.displayFrame(newFrame);\r\n        });\r\n        \r\n        document.addEventListener('mouseup', () => {\r\n            isDragging = false;\r\n        });\r\n    }\r\n}\r\n```\r\n\r\n## Spremljanje učinkovitosti in analitika\r\n\r\n### Spremljanje učinkovitosti slik za e-trgovino\r\n\r\nCelovito spremljanje učinkovitosti slik za e-trgovino:\r\n\r\n```javascript\r\nclass EcommerceImageAnalytics {\r\n    constructor() {\r\n        this.metrics = {\r\n            imageLoadTimes: [],\r\n            conversionTracking: new Map(),\r\n            userInteractions: [],\r\n            performanceImpact: []\r\n        };\r\n        \r\n        this.startMonitoring();\r\n    }\r\n    \r\n    startMonitoring() {\r\n        // Spremljanje učinkovitosti nalaganja slik\r\n        new PerformanceObserver((list) => {\r\n            const entries = list.getEntries();\r\n            entries.forEach(entry => {\r\n                if (this.isProductImage(entry.name)) {\r\n                    this.trackImagePerformance(entry);\r\n                }\r\n            });\r\n        }).observe({ entryTypes: ['resource'] });\r\n        \r\n        // Spremljanje interakcij uporabnikov s slikami\r\n        this.trackImageInteractions();\r\n        \r\n        // Spremljanje korelacije s konverzijami\r\n        this.trackConversionCorrelation();\r\n    }\r\n    \r\n    isProductImage(url) {\r\n        return url.includes('/products/') || \r\n               url.includes('product-images') ||\r\n               url.match(/\\/(hero|gallery|thumbnail|zoom)\\//);\r\n    }\r\n    \r\n    trackImagePerformance(entry) {\r\n        const imageData = {\r\n            url: entry.name,\r\n            loadTime: entry.responseEnd - entry.requestStart,\r\n            fileSize: entry.transferSize,\r\n            renderTime: entry.responseEnd,\r\n            imageType: this.categorizeImage(entry.name),\r\n            timestamp: Date.now()\r\n        };\r\n        \r\n        this.metrics.imageLoadTimes.push(imageData);\r\n        \r\n        // Pošlji v analitiko, če je čas nalaganja predolg\r\n        if (imageData.loadTime > 2000) {\r\n            this.reportSlowImage(imageData);\r\n        }\r\n    }\r\n    \r\n    categorizeImage(url) {\r\n        if (url.includes('hero')) return 'hero';\r\n        if (url.includes('thumbnail')) return 'thumbnail';\r\n        if (url.includes('gallery')) return 'gallery';\r\n        if (url.includes('zoom')) return 'zoom';\r\n        return 'other';\r\n    }\r\n    \r\n    trackImageInteractions() {\r\n        // Spremljanje uporabe zooma\r\n        document.addEventListener('mouseenter', (e) => {\r\n            if (e.target.classList.contains('zoomable-image')) {\r\n                this.recordInteraction('zoom_hover', e.target);\r\n            }\r\n        });\r\n        \r\n        // Spremljanje navigacije po galeriji\r\n        document.addEventListener('click', (e) => {\r\n            if (e.target.classList.contains('gallery-thumbnail')) {\r\n                this.recordInteraction('gallery_click', e.target);\r\n            }\r\n        });\r\n        \r\n        // Spremljanje interakcij s 360° pogledom\r\n        document.addEventListener('mousedown', (e) => {\r\n            if (e.target.closest('.view-360')) {\r\n                this.recordInteraction('360_interact', e.target);\r\n            }\r\n        });\r\n    }\r\n    \r\n    recordInteraction(type, element) {\r\n        const interaction = {\r\n            type: type,\r\n            productId: element.dataset.productId || this.extractProductId(element),\r\n            timestamp: Date.now(),\r\n            elementSrc: element.src || element.dataset.src,\r\n            loadTime: this.getImageLoadTime(element.src)\r\n        };\r\n        \r\n        this.metrics.userInteractions.push(interaction);\r\n    }\r\n    \r\n    trackConversionCorrelation() {\r\n        // Spremljanje dodajanja v košarico po interakciji s slikami\r\n        document.addEventListener('click', (e) => {\r\n            if (e.target.matches('.add-to-cart, .buy-now')) {\r\n                const productId = this.extractProductId(e.target);\r\n                this.correlateWithImageInteractions(productId);\r\n            }\r\n        });\r\n    }\r\n    \r\n    correlateWithImageInteractions(productId) {\r\n        const recentInteractions = this.metrics.userInteractions\r\n            .filter(interaction => \r\n                interaction.productId === productId &&\r\n                Date.now() - interaction.timestamp \u003C 300000 // Zadnjih 5 minut\r\n            );\r\n        \r\n        if (recentInteractions.length > 0) {\r\n            this.metrics.conversionTracking.set(productId, {\r\n                interactions: recentInteractions,\r\n                conversionTime: Date.now()\r\n            });\r\n        }\r\n    }\r\n    \r\n    generatePerformanceReport() {\r\n        const avgLoadTime = this.calculateAverageLoadTime();\r\n        const slowImages = this.identifySlowImages();\r\n        const interactionCorrelation = this.analyzeInteractionCorrelation();\r\n        \r\n        return {\r\n            averageImageLoadTime: avgLoadTime,\r\n            slowestImages: slowImages,\r\n            interactionToConversionRate: interactionCorrelation,\r\n            recommendations: this.generateRecommendations(avgLoadTime, slowImages)\r\n        };\r\n    }\r\n    \r\n    calculateAverageLoadTime() {\r\n        const loadTimes = this.metrics.imageLoadTimes.map(img => img.loadTime);\r\n        return loadTimes.reduce((sum, time) => sum + time, 0) / loadTimes.length;\r\n    }\r\n    \r\n    identifySlowImages() {\r\n        return this.metrics.imageLoadTimes\r\n            .filter(img => img.loadTime > 2000)\r\n            .sort((a, b) => b.loadTime - a.loadTime)\r\n            .slice(0, 10);\r\n    }\r\n    \r\n    analyzeInteractionCorrelation() {\r\n        const totalInteractions = this.metrics.userInteractions.length;\r\n        const conversionsWithInteractions = this.metrics.conversionTracking.size;\r\n        \r\n        return totalInteractions > 0 ? \r\n            (conversionsWithInteractions / totalInteractions) * 100 : 0;\r\n    }\r\n    \r\n    generateRecommendations(avgLoadTime, slowImages) {\r\n        const recommendations = [];\r\n        \r\n        if (avgLoadTime > 1500) {\r\n            recommendations.push('Razmislite o bolj agresivnem stiskanju slik');\r\n            recommendations.push('Uvedite format WebP za boljše stiskanje');\r\n        }\r\n        \r\n        if (slowImages.length > 0) {\r\n            recommendations.push('Optimizirajte najpočasneje nalagajoče se slike izdelkov');\r\n            recommendations.push('Razmislite o odloženem nalaganju za slike galerije');\r\n        }\r\n        \r\n        const heroImages = slowImages.filter(img => img.imageType === 'hero');\r\n        if (heroImages.length > 0) {\r\n            recommendations.push('Dajte prednost optimizaciji glavne slike za boljši prvi vtis');\r\n        }\r\n        \r\n        return recommendations;\r\n    }\r\n    \r\n    extractProductId(element) {\r\n        // Poskusite različne metode za pridobitev ID-ja izdelka\r\n        return element.dataset.productId ||\r\n               element.closest('[data-product-id]')?.dataset.productId ||\r\n               window.location.pathname.match(/\\/products\\/([^\\/]+)/)?.[1] ||\r\n               'unknown';\r\n    }\r\n    \r\n    getImageLoadTime(src) {\r\n        const imageMetric = this.metrics.imageLoadTimes.find(img => img.url.includes(src));\r\n        return imageMetric ? imageMetric.loadTime : null;\r\n    }\r\n    \r\n    reportSlowImage(imageData) {\r\n        // Pošlji v analitično storitev\r\n        if (typeof gtag !== 'undefined') {\r\n            gtag('event', 'slow_image_load', {\r\n                'url': imageData.url,\r\n                'load_time': imageData.loadTime,\r\n                'file_size': imageData.fileSize,\r\n                'image_type': imageData.imageType\r\n            });\r\n        }\r\n    }\r\n}\r\n\r\n// Inicializacija analitike\r\nconst imageAnalytics = new EcommerceImageAnalytics();\r\n\r\n// Periodično generiranje poročila\r\nsetInterval(() => {\r\n    const report = imageAnalytics.generatePerformanceReport();\r\n    console.log('Poročilo o učinkovitosti slik za e-trgovino:', report);\r\n}, 300000); // Vsakih 5 minut\r\n```\r\n\r\n## Zaključek\r\n\r\nOptimizacija slik izdelkov za e-trgovino je ključni dejavnik uspeha spletne prodaje, ki neposredno vpliva na konverzijo, uporabniško izkušnjo in uvrstitev v iskalnikih. Ključ je najti optimalno ravnovesje med kakovostjo slike in zmogljivostjo, ob upoštevanju posebnosti različnih kategorij izdelkov in platform.\r\n\r\nUspešna optimizacija slik za e-trgovino zahteva:\r\n\r\n1. **Pristopi, specifični za kategorijo**: Različne vrste izdelkov zahtevajo različne strategije optimizacije\r\n2. **Skladnost s platformo**: Razumevanje in upoštevanje zahtev tržnic\r\n3. **Spremljanje učinkovitosti**: Nenehno spremljanje učinkovitosti slik in vedenja uporabnikov\r\n4. **Napredne strategije nalaganja**: Pametno nalaganje glede na kontekst uporabnika in zmogljivosti naprave\r\n5. **Ohranjanje kakovosti**: Ohranjanje vizualne privlačnosti ob optimizaciji velikosti datotek\r\n\r\nZ razvojem e-trgovine z novimi tehnologijami, kot so AR-vizualizacija izdelkov, učinkovitejši algoritmi stiskanja in izboljšana mobilna izkušnja, bodo sodobne metode optimizacije in osredotočenost na konverzijo ostale ključne za konkurenčno prednost.\r\n\r\nPrihodnost optimizacije slik za e-trgovino je v sistemih, ki temeljijo na umetni inteligenci in lahko samodejno optimizirajo slike glede na vedenje uporabnika, zmogljivosti naprave in vzorce konverzije, hkrati pa ohranjajo potrebno vizualno kakovost za povečanje prodaje in zadovoljstva strank.\r\n","# E-handel Produktbildekomprimering: Salgsrettet Optimalisering\r\n\r\nE-handelssuksess avhenger sterkt av produktbildekvalitet, med studier som viser at 67% av forbrukere anser bildekvalitet som \"svært viktig\" når de gjør online-kjøp. Store bildefiler kan imidlertid påvirke sideinnlastingstider, konverteringsrater og mobilbrukeropplevelse betydelig. Denne omfattende guiden dekker avanserte teknikker for å optimalisere e-handel produktbilder samtidig som man opprettholder den visuelle kvaliteten som trengs for å drive salg.\r\n\r\n## Hvorfor E-handel Bildeoptimalisering Betyr Noe\r\n\r\n### Innvirkning på Konverteringsrater\r\n\r\nProduktbildeoptimalisering påvirker forretningsmetrikker direkte:\r\n- **Konverteringsrater**: 1-sekunds forsinkelse i sideinnlastingstid reduserer konverteringer med 7%\r\n- **Avvisningsrater**: 40% av brukere forlater nettsteder som tar mer enn 3 sekunder å laste\r\n- **Mobilhandel**: 73% av e-handelstrafikk kommer fra mobile enheter\r\n- **Søkerangeringer**: Google tar hensyn til sidehastighet i søkerangeringer\r\n- **Kundetilfredshet**: Høykvalitetsbilder øker kjøpstillit\r\n\r\n### E-handel Spesifikke Krav\r\n\r\nProduktbilder har unike optimaliseringsutfordringer:\r\n- **Flere produktvisninger**: Hovedbilde, miniatyrbilder, zoomvisninger, 360° rotasjoner\r\n- **Fargenøyaktighet**: Kritisk for mote, kosmetikk og hjemdekor\r\n- **Detaljbevaring**: Kunder må se tekstur, materialer og håndverk\r\n- **Innlastingsytelse**: Balanse mellom kvalitet og hastighet\r\n- **Kryssenhetkompatibilitet**: Konsistent opplevelse på tvers av enheter\r\n\r\n## Forstå E-handel Bildetyper\r\n\r\n### Produktbildekategorier\r\n\r\nUlike bildetyper krever forskjellige optimaliseringsmetoder:\r\n\r\n```javascript\r\nconst ecommerceImageTypes = {\r\n    hero: {\r\n        purpose: 'Primær produktvisning',\r\n        requirements: 'Høy kvalitet, rask innlasting',\r\n        sizes: ['1200x1200', '800x800', '600x600'],\r\n        quality: { jpeg: 85, webp: 80 }\r\n    },\r\n    thumbnail: {\r\n        purpose: 'Produktrutenettvisninger',\r\n        requirements: 'Liten filstørrelse, gjenkjennelig',\r\n        sizes: ['300x300', '200x200', '150x150'],\r\n        quality: { jpeg: 75, webp: 70 }\r\n    },\r\n    zoom: {\r\n        purpose: 'Detaljert produktinspeksjon',\r\n        requirements: 'Maksimal detaljbevaring',\r\n        sizes: ['2000x2000', '1600x1600'],\r\n        quality: { jpeg: 90, webp: 85 }\r\n    },\r\n    gallery: {\r\n        purpose: 'Flere produktvinkler',\r\n        requirements: 'Konsistent kvalitet, lat innlasting',\r\n        sizes: ['800x800', '600x600'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    },\r\n    lifestyle: {\r\n        purpose: 'Produkt i bruk/kontekst',\r\n        requirements: 'Optimalisert for følelse/kontekst',\r\n        sizes: ['1200x800', '800x533'],\r\n        quality: { jpeg: 80, webp: 75 }\r\n    }\r\n};\r\n```\r\n\r\n### Optimaliseringsstrategi etter Produktkategori\r\n\r\nUlike produktkategorier har spesifikke bildekrav:\r\n\r\n```python\r\ndef get_category_optimization_settings(product_category):\r\n    \"\"\"Få optimaliseringsinnstillinger for ulike produktkategorier\"\"\"\r\n    settings = {\r\n        'fashion': {\r\n            'priority': ['color_accuracy', 'texture_detail'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 90},\r\n            'critical_views': ['front', 'back', 'detail']\r\n        },\r\n        'electronics': {\r\n            'priority': ['detail_preservation', 'fast_loading'],\r\n            'format_preference': 'webp_or_avif',\r\n            'quality_range': {'min': 75, 'max': 85},\r\n            'critical_views': ['main', 'interfaces', 'size_comparison']\r\n        },\r\n        'home_decor': {\r\n            'priority': ['color_accuracy', 'lifestyle_context'],\r\n            'format_preference': 'webp_with_jpeg_fallback',\r\n            'quality_range': {'min': 80, 'max': 88},\r\n            'critical_views': ['styled', 'closeup', 'dimensions']\r\n        },\r\n        'jewelry': {\r\n            'priority': ['maximum_detail', 'color_accuracy'],\r\n            'format_preference': 'png_for_detailed_webp_for_hero',\r\n            'quality_range': {'min': 85, 'max': 95},\r\n            'critical_views': ['macro', '360_spin', 'lifestyle']\r\n        },\r\n        'books': {\r\n            'priority': ['fast_loading', 'text_readability'],\r\n            'format_preference': 'webp_aggressive_compression',\r\n            'quality_range': {'min': 70, 'max': 80},\r\n            'critical_views': ['cover', 'back', 'spine']\r\n        }\r\n    }\r\n    return settings.get(product_category, settings['electronics'])\r\n```\r\n\r\n## Avansert Produktbildebehandling\r\n\r\n### Automatisert Produktbildepipeline\r\n\r\nOmfattende automatisert behandlingssystem:\r\n\r\n```python\r\nimport os\r\nfrom PIL import Image, ImageEnhance, ImageFilter\r\nimport numpy as np\r\n\r\nclass EcommerceImageProcessor:\r\n    def __init__(self, config=None):\r\n        self.config = config or self.get_default_config()\r\n        self.supported_formats = ['jpeg', 'webp', 'avif', 'png']\r\n        \r\n    def get_default_config(self):\r\n        return {\r\n            'background_removal': True,\r\n            'auto_crop': True,\r\n            'color_enhancement': True,\r\n            'noise_reduction': True,\r\n            'watermark': False,\r\n            'quality_thresholds': {\r\n                'hero': 85,\r\n                'gallery': 80,\r\n                'thumbnail': 75,\r\n                'zoom': 90\r\n            }\r\n        }\r\n    \r\n    def process_product_image(self, input_path, output_dir, product_id):\r\n        \"\"\"Behandle et enkelt produktbilde til alle nødvendige varianter\"\"\"\r\n        img = Image.open(input_path)\r\n        \r\n        # Grunnleggende forbehandling\r\n        processed_img = self.preprocess_image(img)\r\n        \r\n        # Generer alle nødvendige størrelser og formater\r\n        variants = self.generate_image_variants(processed_img, product_id)\r\n        \r\n        # Lagre optimaliserte versjoner\r\n        saved_files = self.save_variants(variants, output_dir)\r\n        \r\n        return saved_files\r\n    \r\n    def preprocess_image(self, img):\r\n        \"\"\"Anvend grunnleggende forbehandling på produktbilde\"\"\"\r\n        # Konverter til RGB om nødvendig\r\n        if img.mode in ('RGBA', 'LA', 'P'):\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            if img.mode == 'RGBA':\r\n                background.paste(img, mask=img.split()[-1])\r\n            else:\r\n                background.paste(img)\r\n            img = background\r\n        \r\n        # Auto-beskjær for å fjerne overflødig hvitrom\r\n        if self.config['auto_crop']:\r\n            img = self.smart_crop(img)\r\n        \r\n        # Forbedre bildekvalitet\r\n        if self.config['color_enhancement']:\r\n            img = self.enhance_product_image(img)\r\n        \r\n        # Reduser støy\r\n        if self.config['noise_reduction']:\r\n            img = img.filter(ImageFilter.SMOOTH_MORE)\r\n        \r\n        return img\r\n    \r\n    def smart_crop(self, img):\r\n        \"\"\"Intelligent beskjæring av produktbilde for å fjerne overflødig bakgrunn\"\"\"\r\n        # Konverter til numpy array for analyse\r\n        img_array = np.array(img)\r\n        \r\n        # Finn begrensningsboks for ikke-hvite piksler\r\n        mask = np.any(img_array \u003C 240, axis=2)  # Ikke ren hvit\r\n        coords = np.argwhere(mask)\r\n        \r\n        if len(coords) == 0:\r\n            return img  # Ingen beskjæring nødvendig\r\n        \r\n        # Få begrensningsboks\r\n        y0, x0 = coords.min(axis=0)\r\n        y1, x1 = coords.max(axis=0)\r\n        \r\n        # Legg til polstring\r\n        padding = 20\r\n        y0 = max(0, y0 - padding)\r\n        x0 = max(0, x0 - padding)\r\n        y1 = min(img.height, y1 + padding)\r\n        x1 = min(img.width, x1 + padding)\r\n        \r\n        return img.crop((x0, y0, x1, y1))\r\n    \r\n    def enhance_product_image(self, img):\r\n        \"\"\"Forbedre produktbilde for e-handelsvisning\"\"\"\r\n        # Forbedre lysstyrke litt\r\n        brightness_enhancer = ImageEnhance.Brightness(img)\r\n        img = brightness_enhancer.enhance(1.05)\r\n        \r\n        # Forbedre kontrast\r\n        contrast_enhancer = ImageEnhance.Contrast(img)\r\n        img = contrast_enhancer.enhance(1.1)\r\n        \r\n        # Forbedre fargemetning\r\n        color_enhancer = ImageEnhance.Color(img)\r\n        img = color_enhancer.enhance(1.05)\r\n        \r\n        # Forbedre skarphet\r\n        sharpness_enhancer = ImageEnhance.Sharpness(img)\r\n        img = sharpness_enhancer.enhance(1.1)\r\n        \r\n        return img\r\n    \r\n    def generate_image_variants(self, img, product_id):\r\n        \"\"\"Generer alle nødvendige bildevarianter\"\"\"\r\n        variants = {}\r\n        \r\n        # Definer standard e-handelsstørrelser\r\n        sizes = {\r\n            'hero': (1200, 1200),\r\n            'gallery': (800, 800),\r\n            'thumbnail': (300, 300),\r\n            'zoom': (2000, 2000),\r\n            'mobile_hero': (600, 600),\r\n            'mobile_thumb': (150, 150)\r\n        }\r\n        \r\n        for variant_name, size in sizes.items():\r\n            # Endre størrelse med høykvalitets resampling\r\n            resized = img.resize(size, Image.Resampling.LANCZOS)\r\n            variants[variant_name] = resized\r\n        \r\n        return variants\r\n    \r\n    def save_variants(self, variants, output_dir):\r\n        \"\"\"Lagre alle varianter i optimaliserte formater\"\"\"\r\n        saved_files = []\r\n        \r\n        for variant_name, img in variants.items():\r\n            base_path = os.path.join(output_dir, variant_name)\r\n            \r\n            # Lagre i flere formater\r\n            for format_type in ['jpeg', 'webp']:\r\n                filename = f\"{base_path}.{format_type}\"\r\n                quality = self.get_quality_for_variant(variant_name, format_type)\r\n                \r\n                if format_type == 'jpeg':\r\n                    img.save(filename, 'JPEG', quality=quality, optimize=True, progressive=True)\r\n                elif format_type == 'webp':\r\n                    img.save(filename, 'WebP', quality=quality, optimize=True)\r\n                \r\n                saved_files.append(filename)\r\n        \r\n        return saved_files\r\n    \r\n    def get_quality_for_variant(self, variant_name, format_type):\r\n        \"\"\"Få optimal kvalitetsinnstilling for spesifikk variant og format\"\"\"\r\n        base_quality = self.config['quality_thresholds'].get(variant_name, 80)\r\n        \r\n        # Juster for format\r\n        if format_type == 'webp':\r\n            return base_quality - 5  # WebP kan oppnå samme kvalitet ved lavere innstilling\r\n        elif format_type == 'avif':\r\n            return base_quality - 10  # AVIF er enda mer effektiv\r\n        \r\n        return base_quality\r\n\r\n# Brukseksempel\r\nprocessor = EcommerceImageProcessor()\r\nprocessor.process_product_image('product_raw.jpg', 'output/', 'product_123')\r\n```\r\n\r\n### Bakgrunnsfjerning og Standardisering\r\n\r\nAutomatisert bakgrunnsbehandling for konsistent produktvisning:\r\n\r\n```python\r\ndef remove_product_background(image_path, output_path):\r\n    \"\"\"Fjern bakgrunn fra produktbilde ved hjelp av kantdeteksjon\"\"\"\r\n    import cv2\r\n    import numpy as np\r\n    \r\n    # Les bilde\r\n    img = cv2.imread(image_path)\r\n    original = img.copy()\r\n    \r\n    # Konverter til gråskala\r\n    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\r\n    \r\n    # Anvend GaussianBlur for å redusere støy\r\n    blurred = cv2.GaussianBlur(gray, (5, 5), 0)\r\n    \r\n    # Kantdeteksjon\r\n    edges = cv2.Canny(blurred, 50, 150)\r\n    \r\n    # Finn konturer\r\n    contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\r\n    \r\n    if contours:\r\n        # Finn den største konturen (antatt å være produktet)\r\n        largest_contour = max(contours, key=cv2.contourArea)\r\n        \r\n        # Opprett maske\r\n        mask = np.zeros(gray.shape, np.uint8)\r\n        cv2.fillPoly(mask, [largest_contour], 255)\r\n        \r\n        # Anvend maske på originalbilde\r\n        result = cv2.bitwise_and(original, original, mask=mask)\r\n        \r\n        # Konverter bakgrunn til hvit\r\n        result[mask == 0] = [255, 255, 255]\r\n        \r\n        cv2.imwrite(output_path, result)\r\n        return True\r\n    \r\n    return False\r\n\r\ndef standardize_product_backgrounds(input_dir, output_dir, background_color=(255, 255, 255)):\r\n    \"\"\"Standardiser alle produktbakgrunner til konsistent farge\"\"\"\r\n    for filename in os.listdir(input_dir):\r\n        if filename.lower().endswith(('.jpg', '.jpeg', '.png')):\r\n            input_path = os.path.join(input_dir, filename)\r\n            output_path = os.path.join(output_dir, filename)\r\n            \r\n            # Prøv automatisert bakgrunnsfjerning\r\n            if not remove_product_background(input_path, output_path):\r\n                # Fallback: enkel hvit bakgrunn\r\n                img = Image.open(input_path)\r\n                if img.mode == 'RGBA':\r\n                    background = Image.new('RGB', img.size, background_color)\r\n                    background.paste(img, mask=img.split()[-1])\r\n                    background.save(output_path, 'JPEG', quality=85)\r\n                else:\r\n                    img.save(output_path)\r\n```\r\n\r\n## Plattformspesifikk Optimalisering\r\n\r\n### Amazon Marketplace Optimalisering\r\n\r\nAmazon har spesifikke bildekrav og algoritmer:\r\n\r\n```python\r\nclass AmazonImageOptimizer:\r\n    def __init__(self):\r\n        self.requirements = {\r\n            'main_image': {\r\n                'min_size': (1000, 1000),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'background': 'pure_white',\r\n                'product_coverage': 85  # Minimum prosentandel av bilde\r\n            },\r\n            'additional_images': {\r\n                'min_size': (500, 500),\r\n                'max_size': (10000, 10000),\r\n                'formats': ['JPEG', 'PNG', 'GIF'],\r\n                'lifestyle_allowed': True\r\n            }\r\n        }\r\n    \r\n    def optimize_for_amazon(self, image_path, output_path, image_type='main'):\r\n        \"\"\"Optimaliser bilde spesifikt for Amazon-oppføring\"\"\"\r\n        img = Image.open(image_path)\r\n        \r\n        if image_type == 'main':\r\n            img = self.ensure_white_background(img)\r\n            img = self.ensure_minimum_size(img, (1000, 1000))\r\n        \r\n        # Amazon foretrekker sRGB fargerom\r\n        if img.mode != 'RGB':\r\n            img = img.convert('RGB')\r\n        \r\n        # Optimaliser filstørrelse samtidig som kvaliteten opprettholdes\r\n        quality = 90 if image_type == 'main' else 85\r\n        img.save(output_path, 'JPEG', quality=quality, optimize=True)\r\n        \r\n        return self.validate_amazon_requirements(output_path, image_type)\r\n    \r\n    def ensure_white_background(self, img):\r\n        \"\"\"Sikre at bildet har ren hvit bakgrunn\"\"\"\r\n        if img.mode == 'RGBA':\r\n            background = Image.new('RGB', img.size, (255, 255, 255))\r\n            background.paste(img, mask=img.split()[-1])\r\n            return background\r\n        return img\r\n    \r\n    def ensure_minimum_size(self, img, min_size):\r\n        \"\"\"Sikre at bildet oppfyller minimumsstørrelseskrav\"\"\"\r\n        if img.size[0] \u003C min_size[0] or img.size[1] \u003C min_size[1]:\r\n            img = img.resize(min_size, Image.Resampling.LANCZOS)\r\n        return img\r\n    \r\n    def validate_amazon_requirements(self, image_path, image_type):\r\n        \"\"\"Valider at bildet oppfyller Amazon-krav\"\"\"\r\n        img = Image.open(image_path)\r\n        requirements = self.requirements[image_type]\r\n        \r\n        validation_results = {\r\n            'size_valid': (\r\n                img.size[0] >= requirements['min_size'][0] and \r\n                img.size[1] >= requirements['min_size'][1]\r\n            ),\r\n            'format_valid': image_path.upper().endswith(tuple(requirements['formats'])),\r\n            'file_size_valid': os.path.getsize(image_path) \u003C= 10 * 1024 * 1024  # 10MB grense\r\n        }\r\n        \r\n        return all(validation_results.values()), validation_results\r\n```\r\n\r\n### Shopify Butikkoptimalisering\r\n\r\nOptimalisering for Shopify-temaer og ytelse:\r\n\r\n```javascript\r\nclass ShopifyImageOptimizer {\r\n    constructor() {\r\n        this.themeRequirements = {\r\n            'product_card': { width: 600, height: 600, quality: 80 },\r\n            'product_detail': { width: 1200, height: 1200, quality: 85 },\r\n            'product_zoom': { width: 2048, height: 2048, quality: 90 },\r\n            'collection_featured': { width: 800, height: 600, quality: 80 }\r\n        };\r\n    }\r\n    \r\n    generateShopifyImageUrls(baseImageUrl, productHandle) {\r\n        const urls = {};\r\n        \r\n        Object.entries(this.themeRequirements).forEach(([variant, specs]) => {\r\n            // Shopify bildetransformasjon URL-format\r\n            const transformedUrl = baseImageUrl.replace('.jpg', \r\n                `_${specs.width}x${specs.height}_crop_center.jpg`);\r\n            urls[variant] = transformedUrl;\r\n        });\r\n        \r\n        return urls;\r\n    }\r\n    \r\n    generateShopifyPictureElement(productData) {\r\n        const { images, title, handle } = productData;\r\n        const mainImage = images[0];\r\n        \r\n        return `\r\n            \u003Cpicture>\r\n                \u003Csource media=\"(min-width: 1200px)\" \r\n                        srcset=\"${mainImage}_1200x1200.webp 1x, ${mainImage}_2400x2400.webp 2x\"\r\n                        type=\"image/webp\">\r\n                \u003Csource media=\"(min-width: 768px)\" \r\n                        srcset=\"${mainImage}_800x800.webp 1x, ${mainImage}_1600x1600.webp 2x\"\r\n                        type=\"image/webp\">\r\n                \u003Csource media=\"(max-width: 767px)\" \r\n                        srcset=\"${mainImage}_600x600.webp 1x, ${mainImage}_1200x1200.webp 2x\"\r\n                        type=\"image/webp\">\r\n                \u003Cimg src=\"${mainImage}_800x800.jpg\"\r\n                     srcset=\"${mainImage}_400x400.jpg 400w,\r\n                             ${mainImage}_600x600.jpg 600w,\r\n                             ${mainImage}_800x800.jpg 800w,\r\n                             ${mainImage}_1200x1200.jpg 1200w\"\r\n                     sizes=\"(max-width: 767px) 100vw, (max-width: 1023px) 50vw, 33vw\"\r\n                     alt=\"${title}\"\r\n                     loading=\"lazy\"\r\n                     data-product-handle=\"${handle}\">\r\n            \u003C/picture>\r\n        `;\r\n    }\r\n}\r\n```\r\n\r\n## Avanserte Innlastingsstrategier for E-handel\r\n\r\n### Smart Produktbildeinnlasting\r\n\r\nIntelligent innlasting basert på brukeratferd og enhetskapasiteter:\r\n\r\n```javascript\r\nclass EcommerceImageLoader {\r\n    constructor() {\r\n        this.userBehavior = this.trackUserBehavior();\r\n        this.deviceCapabilities = this.analyzeDevice();\r\n        this.loadingStrategies = this.initializeStrategies();\r\n    }\r\n    \r\n    trackUserBehavior() {\r\n        return {\r\n            isReturningCustomer: localStorage.getItem('visited') === 'true',\r\n            viewingHistory: JSON.parse(localStorage.getItem('viewedProducts') || '[]'),\r\n            averageSessionTime: parseInt(localStorage.getItem('avgSessionTime') || '0'),\r\n            purchaseHistory: JSON.parse(localStorage.getItem('purchases') || '[]')\r\n        };\r\n    }\r\n    \r\n    analyzeDevice() {\r\n        const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;\r\n        \r\n        return {\r\n            connectionSpeed: connection ? connection.effectiveType : '4g',\r\n            deviceMemory: navigator.deviceMemory || 4,\r\n            isLowEndDevice: navigator.deviceMemory \u003C 2,\r\n            isMobile: window.innerWidth \u003C= 768,\r\n            isSlowConnection: connection && (connection.effectiveType === 'slow-2g' || connection.effectiveType === '2g')\r\n        };\r\n    }\r\n    \r\n    initializeStrategies() {\r\n        return {\r\n            eager: this.eagerLoadingStrategy.bind(this),\r\n            progressive: this.progressiveLoadingStrategy.bind(this),\r\n            lazy: this.lazyLoadingStrategy.bind(this),\r\n            adaptive: this.adaptiveLoadingStrategy.bind(this)\r\n        };\r\n    }\r\n    \r\n    selectOptimalStrategy(productData, context) {\r\n        const { deviceCapabilities, userBehavior } = this;\r\n        \r\n        // Høyverdi returkunder med gode tilkoblinger\r\n        if (userBehavior.isReturningCustomer && \r\n            userBehavior.purchaseHistory.length > 0 && \r\n            !deviceCapabilities.isSlowConnection) {\r\n            return 'eager';\r\n        }\r\n        \r\n        // Lavspesifikasjonsenheter eller trege tilkoblinger\r\n        if (deviceCapabilities.isLowEndDevice || deviceCapabilities.isSlowConnection) {\r\n            return 'lazy';\r\n        }\r\n        \r\n        // Mobile enheter med gode tilkoblinger\r\n        if (deviceCapabilities.isMobile && !deviceCapabilities.isSlowConnection) {\r\n            return 'progressive';\r\n        }\r\n        \r\n        // Standard: adaptiv strategi\r\n        return 'adaptive';\r\n    }\r\n    \r\n    eagerLoadingStrategy(productImages) {\r\n        // Last alle produktbilder umiddelbart for premium opplevelse\r\n        productImages.forEach(img => {\r\n            const imageLoader = new Image();\r\n            imageLoader.src = img.dataset.src;\r\n            \r\n            if (img.dataset.srcset) {\r\n                imageLoader.srcset = img.dataset.srcset;\r\n            }\r\n            \r\n            imageLoader.onload = () => {\r\n                img.src = imageLoader.src;\r\n                if (img.dataset.srcset) {\r\n                    img.srcset = imageLoader.srcset;\r\n                }\r\n                img.classList.add('loaded');\r\n            };\r\n        });\r\n    }\r\n    \r\n    progressiveLoadingStrategy(productImages) {\r\n        // Last lavkvalitet først, deretter høykvalitet\r\n        productImages.forEach(img => {\r\n            // Last lavkvalitets plassholder\r\n            const lowQualitySrc = img.dataset.lowSrc || img.dataset.src.replace('_q85', '_q40');\r\n            const highQualitySrc = img.dataset.src;\r\n            \r\n            img.src = lowQualitySrc;\r\n            img.classList.add('loading');\r\n            \r\n            // Last høykvalitetsversjon\r\n            const highQualityLoader = new Image();\r\n            highQualityLoader.onload = () => {\r\n                img.src = highQualitySrc;\r\n                img.classList.remove('loading');\r\n                img.classList.add('loaded');\r\n            };\r\n            highQualityLoader.src = highQualitySrc;\r\n        });\r\n    }\r\n    \r\n    lazyLoadingStrategy(productImages) {\r\n        // Bruk Intersection Observer for lat innlasting\r\n        const observer = new IntersectionObserver((entries) => {\r\n            entries.forEach(entry => {\r\n                if (entry.isIntersecting) {\r\n                    this.loadImage(entry.target);\r\n                    observer.unobserve(entry.target);\r\n                }\r\n            });\r\n        }, { rootMargin: '100px' });\r\n        \r\n        productImages.forEach(img => observer.observe(img));\r\n    }\r\n    \r\n    adaptiveLoadingStrategy(productImages) {\r\n        // Tilpass basert på brukerinteraksjon og rulleadferd\r\n        let scrollTimeout;\r\n        let isScrolling = false;\r\n        \r\n        window.addEventListener('scroll', () => {\r\n            if (!isScrolling) {\r\n                isScrolling = true;\r\n                // Last synlige bilder umiddelbart når rulling starter\r\n                this.loadVisibleImages(productImages);\r\n            }\r\n            \r\n            clearTimeout(scrollTimeout);\r\n            scrollTimeout = setTimeout(() => {\r\n                isScrolling = false;\r\n            }, 150);\r\n        });\r\n        \r\n        // Last kritiske over-fold bilder umiddelbart\r\n        this.loadCriticalImages(productImages);\r\n        \r\n        // Lat last gjenværende bilder\r\n        this.lazyLoadingStrategy(productImages.filter(img => !img.dataset.critical));\r\n    }\r\n    \r\n    loadCriticalImages(productImages) {\r\n        const criticalImages = productImages.filter(img => \r\n            img.dataset.critical === 'true' || \r\n            img.getBoundingClientRect().top \u003C window.innerHeight\r\n        );\r\n        \r\n        criticalImages.forEach(img => this.loadImage(img));\r\n    }\r\n    \r\n    loadVisibleImages(productImages) {\r\n        const visibleImages = productImages.filter(img => {\r\n            const rect = img.getBoundingClientRect();\r\n            return rect.top \u003C window.innerHeight && rect.bottom > 0;\r\n        });\r\n        \r\n        visibleImages.forEach(img => this.loadImage(img));\r\n    }\r\n    \r\n    loadImage(img) {\r\n        if (img.dataset.loaded) return;\r\n        \r\n        const imageLoader = new Image();\r\n        imageLoader.onload = () => {\r\n            img.src = imageLoader.src;\r\n            if (img.dataset.srcset) {\r\n                img.srcset = img.dataset.srcset;\r\n            }\r\n            img.classList.add('loaded');\r\n            img.dataset.loaded = 'true';\r\n        };\r\n        \r\n        imageLoader.src = img.dataset.src;\r\n    }\r\n}\r\n\r\n// Initialiser for produktsider\r\ndocument.addEventListener('DOMContentLoaded', () => {\r\n    const imageLoader = new EcommerceImageLoader();\r\n    const productImages = document.querySelectorAll('.product-image[data-src]');\r\n    \r\n    if (productImages.length > 0) {\r\n        const strategy = imageLoader.selectOptimalStrategy();\r\n        imageLoader.loadingStrategies[strategy](productImages);\r\n    }\r\n});\r\n```\r\n\r\n## Bildezoom og 360° Visningsoptimalisering\r\n\r\n### Effektiv Zoomimplementering\r\n\r\nOptimalisert bildezoomfunksjonalitet for produktdetaljsider:\r\n\r\n```javascript\r\nclass ProductImageZoom {\r\n    constructor(options = {}) {\r\n        this.container = options.container;\r\n        this.zoomLevel = options.zoomLevel || 2;\r\n        this.loadingStrategy = options.loadingStrategy || 'on-demand';\r\n        this.highResImages = new Map();\r\n        \r\n        this.initializeZoom();\r\n    }\r\n    \r\n    initializeZoom() {\r\n        const zoomImages = this.container.querySelectorAll('.zoomable-image');\r\n        \r\n        zoomImages.forEach(img => {\r\n            img.addEventListener('mouseenter', this.handleMouseEnter.bind(this));\r\n            img.addEventListener('mouseleave', this.handleMouseLeave.bind(this));\r\n            img.addEventListener('mousemove', this.handleMouseMove.bind(this));\r\n        });\r\n    }\r\n    \r\n    async handleMouseEnter(event) {\r\n        const img = event.target;\r\n        const highResUrl = img.dataset.zoomSrc;\r\n        \r\n        if (!highResUrl) return;\r\n        \r\n        // Last høyoppløsningsbilde på forespørsel\r\n        if (!this.highResImages.has(highResUrl)) {\r\n            this.loadHighResImage(highResUrl);\r\n        }\r\n        \r\n        this.showZoomOverlay(img);\r\n    }\r\n    \r\n    loadHighResImage(url) {\r\n        return new Promise((resolve, reject) => {\r\n            const img = new Image();\r\n            img.onload = () => {\r\n                this.highResImages.set(url, img);\r\n                resolve(img);\r\n            };\r\n            img.onerror = reject;\r\n            img.src = url;\r\n        });\r\n    }\r\n    \r\n    showZoomOverlay(img) {\r\n        // Opprett zoom overlay hvis det ikke eksisterer\r\n        let overlay = img.parentNode.querySelector('.zoom-overlay');\r\n        if (!overlay) {\r\n            overlay = document.createElement('div');\r\n            overlay.className = 'zoom-overlay';\r\n            overlay.style.cssText = `\r\n                position: absolute;\r\n                top: 0;\r\n                left: 100%;\r\n                width: 300px;\r\n                height: 300px;\r\n                border: 1px solid #ddd;\r\n                background: white;\r\n                overflow: hidden;\r\n                z-index: 1000;\r\n                display: none;\r\n            `;\r\n            img.parentNode.appendChild(overlay);\r\n        }\r\n        \r\n        overlay.style.display = 'block';\r\n    }\r\n    \r\n    handleMouseMove(event) {\r\n        const img = event.target;\r\n        const overlay = img.parentNode.querySelector('.zoom-overlay');\r\n        const highResUrl = img.dataset.zoomSrc;\r\n        \r\n        if (!overlay || !this.highResImages.has(highResUrl)) return;\r\n        \r\n        const rect = img.getBoundingClientRect();\r\n        const x = (event.clientX - rect.left) / rect.width;\r\n        const y = (event.clientY - rect.top) / rect.height;\r\n        \r\n        const highResImg = this.highResImages.get(highResUrl);\r\n        \r\n        // Oppdater zoom overlay\r\n        overlay.style.backgroundImage = `url(${highResUrl})`;\r\n        overlay.style.backgroundSize = `${highResImg.width}px ${highResImg.height}px`;\r\n        overlay.style.backgroundPosition = `-${x * (highResImg.width - 300)}px -${y * (highResImg.height - 300)}px`;\r\n    }\r\n    \r\n    handleMouseLeave(event) {\r\n        const img = event.target;\r\n        const overlay = img.parentNode.querySelector('.zoom-overlay');\r\n        \r\n        if (overlay) {\r\n            overlay.style.display = 'none';\r\n        }\r\n    }\r\n}\r\n\r\n// 360° produktvisningsoptimalisering\r\nclass Product360View {\r\n    constructor(container, options = {}) {\r\n        this.container = container;\r\n        this.frameCount = options.frameCount || 36;\r\n        this.autoPlay = options.autoPlay || false;\r\n        this.frames = [];\r\n        this.currentFrame = 0;\r\n        this.isLoading = false;\r\n        \r\n        this.initialize();\r\n    }\r\n    \r\n    async initialize() {\r\n        await this.loadFrames();\r\n        this.setupControls();\r\n        this.setupInteraction();\r\n    }\r\n    \r\n    async loadFrames() {\r\n        this.isLoading = true;\r\n        const baseUrl = this.container.dataset.baseUrl;\r\n        \r\n        // Last rammer progressivt\r\n        const loadPromises = [];\r\n        \r\n        for (let i = 1; i \u003C= this.frameCount; i++) {\r\n            const frameUrl = `${baseUrl}/frame_${i.toString().padStart(3, '0')}.jpg`;\r\n            loadPromises.push(this.loadFrame(frameUrl, i - 1));\r\n        }\r\n        \r\n        // Last første få rammer umiddelbart, resten progressivt\r\n        await Promise.all(loadPromises.slice(0, 8));\r\n        \r\n        // Last gjenværende rammer i bakgrunnen\r\n        Promise.all(loadPromises.slice(8));\r\n        \r\n        this.isLoading = false;\r\n        this.displayFrame(0);\r\n    }\r\n    \r\n    loadFrame(url, index) {\r\n        return new Promise((resolve) => {\r\n            const img = new Image();\r\n            img.onload = () => {\r\n                this.frames[index] = img;\r\n                resolve();\r\n            };\r\n            img.onerror = () => {\r\n                // Opprett plassholder for mislykkede lastinger\r\n                this.frames[index] = null;\r\n                resolve();\r\n            };\r\n            img.src = url;\r\n        });\r\n    }\r\n    \r\n    displayFrame(frameIndex) {\r\n        if (!this.frames[frameIndex]) return;\r\n        \r\n        const img = this.container.querySelector('.view-360-image') || \r\n                   this.createImageElement();\r\n        \r\n        img.src = this.frames[frameIndex].src;\r\n        this.currentFrame = frameIndex;\r\n    }\r\n    \r\n    createImageElement() {\r\n        const img = document.createElement('img');\r\n        img.className = 'view-360-image';\r\n        img.style.cssText = 'width: 100%; height: auto; display: block;';\r\n        this.container.appendChild(img);\r\n        return img;\r\n    }\r\n    \r\n    setupInteraction() {\r\n        let isDragging = false;\r\n        let startX = 0;\r\n        let startFrame = 0;\r\n        \r\n        this.container.addEventListener('mousedown', (e) => {\r\n            isDragging = true;\r\n            startX = e.clientX;\r\n            startFrame = this.currentFrame;\r\n            e.preventDefault();\r\n        });\r\n        \r\n        document.addEventListener('mousemove', (e) => {\r\n            if (!isDragging) return;\r\n            \r\n            const deltaX = e.clientX - startX;\r\n            const sensitivity = 2; // Piksler per ramme\r\n            const frameChange = Math.floor(deltaX / sensitivity);\r\n            \r\n            let newFrame = (startFrame + frameChange) % this.frameCount;\r\n            if (newFrame \u003C 0) newFrame += this.frameCount;\r\n            \r\n            this.displayFrame(newFrame);\r\n        });\r\n        \r\n        document.addEventListener('mouseup', () => {\r\n            isDragging = false;\r\n        });\r\n    }\r\n}\r\n```\r\n\r\n## Ytelsesovervåking og Analyse\r\n\r\n### E-handel Bildeytelsesporing\r\n\r\nOmfattende ytelsesovervåking for e-handelsbilder:\r\n\r\n```javascript\r\nclass EcommerceImageAnalytics {\r\n    constructor() {\r\n        this.metrics = {\r\n            imageLoadTimes: [],\r\n            conversionTracking: new Map(),\r\n            userInteractions: [],\r\n            performanceImpact: []\r\n        };\r\n        \r\n        this.startMonitoring();\r\n    }\r\n    \r\n    startMonitoring() {\r\n        // Overvåk bildeinnlastingsytelse\r\n        new PerformanceObserver((list) => {\r\n            const entries = list.getEntries();\r\n            entries.forEach(entry => {\r\n                if (this.isProductImage(entry.name)) {\r\n                    this.trackImagePerformance(entry);\r\n                }\r\n            });\r\n        }).observe({ entryTypes: ['resource'] });\r\n        \r\n        // Overvåk brukerinteraksjoner med bilder\r\n        this.trackImageInteractions();\r\n        \r\n        // Overvåk konverteringskorrelasjon\r\n        this.trackConversionCorrelation();\r\n    }\r\n    \r\n    isProductImage(url) {\r\n        return url.includes('/products/') || \r\n               url.includes('product-images') ||\r\n               url.match(/\\/(hero|gallery|thumbnail|zoom)\\//);\r\n    }\r\n    \r\n    trackImagePerformance(entry) {\r\n        const imageData = {\r\n            url: entry.name,\r\n            loadTime: entry.responseEnd - entry.requestStart,\r\n            fileSize: entry.transferSize,\r\n            renderTime: entry.responseEnd,\r\n            imageType: this.categorizeImage(entry.name),\r\n            timestamp: Date.now()\r\n        };\r\n        \r\n        this.metrics.imageLoadTimes.push(imageData);\r\n        \r\n        // Send til analyse hvis innlastingstid er bekymringsfull\r\n        if (imageData.loadTime > 2000) {\r\n            this.reportSlowImage(imageData);\r\n        }\r\n    }\r\n    \r\n    categorizeImage(url) {\r\n        if (url.includes('hero')) return 'hero';\r\n        if (url.includes('thumbnail')) return 'thumbnail';\r\n        if (url.includes('gallery')) return 'gallery';\r\n        if (url.includes('zoom')) return 'zoom';\r\n        return 'other';\r\n    }\r\n    \r\n    trackImageInteractions() {\r\n        // Spor bildezoombruk\r\n        document.addEventListener('mouseenter', (e) => {\r\n            if (e.target.classList.contains('zoomable-image')) {\r\n                this.recordInteraction('zoom_hover', e.target);\r\n            }\r\n        });\r\n        \r\n        // Spor bildegalleri navigasjon\r\n        document.addEventListener('click', (e) => {\r\n            if (e.target.classList.contains('gallery-thumbnail')) {\r\n                this.recordInteraction('gallery_click', e.target);\r\n            }\r\n        });\r\n        \r\n        // Spor 360° visningsinteraksjoner\r\n        document.addEventListener('mousedown', (e) => {\r\n            if (e.target.closest('.view-360')) {\r\n                this.recordInteraction('360_interact', e.target);\r\n            }\r\n        });\r\n    }\r\n    \r\n    recordInteraction(type, element) {\r\n        const interaction = {\r\n            type: type,\r\n            productId: element.dataset.productId || this.extractProductId(element),\r\n            timestamp: Date.now(),\r\n            elementSrc: element.src || element.dataset.src,\r\n            loadTime: this.getImageLoadTime(element.src)\r\n        };\r\n        \r\n        this.metrics.userInteractions.push(interaction);\r\n    }\r\n    \r\n    trackConversionCorrelation() {\r\n        // Spor når brukere legger til i handlekurv etter bildeinteraksjoner\r\n        document.addEventListener('click', (e) => {\r\n            if (e.target.matches('.add-to-cart, .buy-now')) {\r\n                const productId = this.extractProductId(e.target);\r\n                this.correlateWithImageInteractions(productId);\r\n            }\r\n        });\r\n    }\r\n    \r\n    correlateWithImageInteractions(productId) {\r\n        const recentInteractions = this.metrics.userInteractions\r\n            .filter(interaction => \r\n                interaction.productId === productId &&\r\n                Date.now() - interaction.timestamp \u003C 300000 // Siste 5 minutter\r\n            );\r\n        \r\n        if (recentInteractions.length > 0) {\r\n            this.metrics.conversionTracking.set(productId, {\r\n                interactions: recentInteractions,\r\n                conversionTime: Date.now()\r\n            });\r\n        }\r\n    }\r\n    \r\n    generatePerformanceReport() {\r\n        const avgLoadTime = this.calculateAverageLoadTime();\r\n        const slowImages = this.identifySlowImages();\r\n        const interactionCorrelation = this.analyzeInteractionCorrelation();\r\n        \r\n        return {\r\n            averageImageLoadTime: avgLoadTime,\r\n            slowestImages: slowImages,\r\n            interactionToConversionRate: interactionCorrelation,\r\n            recommendations: this.generateRecommendations(avgLoadTime, slowImages)\r\n        };\r\n    }\r\n    \r\n    calculateAverageLoadTime() {\r\n        const loadTimes = this.metrics.imageLoadTimes.map(img => img.loadTime);\r\n        return loadTimes.reduce((sum, time) => sum + time, 0) / loadTimes.length;\r\n    }\r\n    \r\n    identifySlowImages() {\r\n        return this.metrics.imageLoadTimes\r\n            .filter(img => img.loadTime > 2000)\r\n            .sort((a, b) => b.loadTime - a.loadTime)\r\n            .slice(0, 10);\r\n    }\r\n    \r\n    analyzeInteractionCorrelation() {\r\n        const totalInteractions = this.metrics.userInteractions.length;\r\n        const conversionsWithInteractions = this.metrics.conversionTracking.size;\r\n        \r\n        return totalInteractions > 0 ? \r\n            (conversionsWithInteractions / totalInteractions) * 100 : 0;\r\n    }\r\n    \r\n    generateRecommendations(avgLoadTime, slowImages) {\r\n        const recommendations = [];\r\n        \r\n        if (avgLoadTime > 1500) {\r\n            recommendations.push('Vurder mer aggressiv bildekomprimering');\r\n            recommendations.push('Implementer WebP-format for bedre komprimering');\r\n        }\r\n        \r\n        if (slowImages.length > 0) {\r\n            recommendations.push('Optimaliser de tregeste lastende produktbildene');\r\n            recommendations.push('Vurder lat innlasting for galleribilder');\r\n        }\r\n        \r\n        const heroImages = slowImages.filter(img => img.imageType === 'hero');\r\n        if (heroImages.length > 0) {\r\n            recommendations.push('Prioriter hero-bildeoptimalisering for raskere førsteinntrykk');\r\n        }\r\n        \r\n        return recommendations;\r\n    }\r\n    \r\n    extractProductId(element) {\r\n        // Prøv ulike metoder for å trekke ut produkt-ID\r\n        return element.dataset.productId ||\r\n               element.closest('[data-product-id]')?.dataset.productId ||\r\n               window.location.pathname.match(/\\/products\\/([^\\/]+)/)?.[1] ||\r\n               'unknown';\r\n    }\r\n    \r\n    getImageLoadTime(src) {\r\n        const imageMetric = this.metrics.imageLoadTimes.find(img => img.url.includes(src));\r\n        return imageMetric ? imageMetric.loadTime : null;\r\n    }\r\n    \r\n    reportSlowImage(imageData) {\r\n        // Send til analysetjeneste\r\n        if (typeof gtag !== 'undefined') {\r\n            gtag('event', 'slow_image_load', {\r\n                'url': imageData.url,\r\n                'load_time': imageData.loadTime,\r\n                'file_size': imageData.fileSize,\r\n                'image_type': imageData.imageType\r\n            });\r\n        }\r\n    }\r\n}\r\n\r\n// Initialiser analyse\r\nconst imageAnalytics = new EcommerceImageAnalytics();\r\n\r\n// Generer rapport periodisk\r\nsetInterval(() => {\r\n    const report = imageAnalytics.generatePerformanceReport();\r\n    console.log('E-handel Bildeytelsesrapport:', report);\r\n}, 300000); // Hvert 5. minutt\r\n```\r\n\r\n## Konklusjon\r\n\r\nE-handel produktbildeoptimalisering er en kritisk faktor for online detaljhandelssuksess, som direkte påvirker konverteringsrater, brukeropplevelse og søkerangeringer. Nøkkelen er å finne den optimale balansen mellom bildekvalitet og ytelse samtidig som man vurderer de spesifikke kravene til ulike produktkategorier og plattformer.\r\n\r\nVellykket e-handel bildeoptimalisering krever:\r\n\r\n1. **Kategori-spesifikke tilnærminger**: Ulike produkttyper trenger forskjellige optimaliseringsstrategier\r\n2. **Plattformoverholdelse**: Forstå og følge markedsplasskrav\r\n3. **Ytelsesovervåking**: Kontinuerlig sporing av bildeytelse og brukeratferd\r\n4. **Avanserte innlastingsstrategier**: Intelligent innlasting basert på brukerkontekst og enhetskapasiteter\r\n5. **Kvalitetsbevaring**: Opprettholde visuell appell samtidig som filstørrelser optimaliseres\r\n\r\nEttersom e-handel fortsetter å utvikle seg med nye teknologier som AR produktvisualisering, bedre komprimeringsalgoritmer og forbedrede mobilopplevelser, vil det forbli essensielt å holde seg oppdatert med optimaliseringsteknikker samtidig som man opprettholder fokus på konverteringsdrevne resultater for konkurransefortrinn.\r\n\r\nFremtiden for e-handel bildeoptimalisering ligger i AI-drevne systemer som automatisk kan optimalisere bilder basert på brukeratferd, enhetskapasiteter og konverteringsmønstre samtidig som de opprettholder den visuelle kvaliteten som er nødvendig for å drive salg og kundetilfredshet.\r\n",1772179184828]