Plugin Directory

Changeset 3662711


Ignore:
Timestamp:
08/24/2026 06:19:47 AM (2 months ago)
Author:
wpaluchmits
Message:

1.2.74: derywat WebP/AVIF skalowany do max_dimension przed kodowaniem, fallback Imagick->GD przy limicie policy.xml, wlasny cache-control dla avif/webp w bloku .htaccess

Location:
mits-image-optimizer
Files:
4 edited
1 copied

Legend:

Unmodified
Added
Removed
  • mits-image-optimizer/tags/1.2.74/mits-image-optimizer.php

    r3654055 r3662711  
    33 * Plugin Name:       MITS Image Optimizer
    44 * Description:       Auto-compress images on upload, bulk convert to WebP & AVIF, configure .htaccess for next-gen serving, scan for oversized images, and audit your site.
    5  * Version:           1.2.72
     5 * Version:           1.2.74
    66 * Requires at least: 6.0
    77 * Requires PHP:      8.0
    … …  
    1515if ( ! defined( 'ABSPATH' ) ) exit;
    1616
    17 define( 'MITS_OPT_VERSION', '1.2.72' );
     17define( 'MITS_OPT_VERSION', '1.2.74' );
    1818define( 'MITS_OPT_FILE',    __FILE__ );
    1919define( 'MITS_OPT_DIR',     plugin_dir_path( __FILE__ ) );
    … …  
    656656            "</FilesMatch>\n" .
    657657            "</IfModule>\n" .
     658            // WAZNE (wyuczone na produkcji): nie polegamy na tym, ze reszta .htaccess
     659            // strony ma juz wpis ExpiresByType dla image/avif. Wiele gotowych configow
     660            // WP ma go dla image/webp, ale nie dla avif (bo avif jest nowszy) - taki
     661            // plik wtedy dostawal domyslny czas cache serwera (bywa to zaledwie 7 dni)
     662            // zamiast miesiecy jak reszta obrazkow. Wlasny, samodzielny wpis w bloku
     663            // wtyczki gwarantuje poprawny cache niezaleznie od reszty konfiguracji.
     664            "<IfModule mod_expires.c>\n" .
     665            "ExpiresActive On\n" .
     666            "ExpiresByType image/avif \"access plus 1 year\"\n" .
     667            "ExpiresByType image/webp \"access plus 1 year\"\n" .
     668            "</IfModule>\n" .
     669            "<IfModule mod_headers.c>\n" .
     670            "<FilesMatch \"(?i)\\.(avif|webp)$\">\n" .
     671            "Header set Cache-Control \"public, max-age=31536000, immutable\"\n" .
     672            "</FilesMatch>\n" .
     673            "</IfModule>\n" .
    658674            self::HTA_MARKER_END . "\n";
    659675    }
    … …  
    16371653    /* ── WebP convert ────────────────────────────────────────────── */
    16381654
     1655    /**
     1656     * Derywat (WebP/AVIF) NIGDY nie moze byc wiekszy niz oryginal. Stare zdjecia
     1657     * z aparatu bywaja w pelnej rozdzielczosci (8000px+), a nikt tak duzych nie
     1658     * wyswietla w przegladarce - kodowanie ich 1:1 daje plik WIEKSZY od oryginalu
     1659     * zamiast oszczednosci. Ograniczamy dluzszy bok do max_dimension z ustawien,
     1660     * tak samo jak juz robi compress_imagick()/compress_gd() dla kompresji originalu.
     1661     * NIE dotyka $src - operuje wylacznie na obiekcie/zasobie w pamieci.
     1662     */
     1663    private function resize_for_derivative_imagick( Imagick $img, int $max ): void {
     1664        if ( $img->getImageWidth() > $max || $img->getImageHeight() > $max ) {
     1665            $img->resizeImage( $max, $max, Imagick::FILTER_LANCZOS, 1, true );
     1666        }
     1667    }
     1668
     1669    private function resize_for_derivative_gd( $img, int $max ) {
     1670        $w = imagesx( $img ); $h = imagesy( $img );
     1671        if ( $w <= $max && $h <= $max ) return $img;
     1672        $ratio = min( $max / $w, $max / $h );
     1673        $nw = (int) round( $w * $ratio ); $nh = (int) round( $h * $ratio );
     1674        $res = imagecreatetruecolor( $nw, $nh );
     1675        imagealphablending( $res, false ); imagesavealpha( $res, true );
     1676        imagefill( $res, 0, 0, imagecolorallocatealpha( $res, 0, 0, 0, 127 ) );
     1677        imagecopyresampled( $res, $img, 0, 0, 0, 0, $nw, $nh, $w, $h );
     1678        imagedestroy( $img );
     1679        return $res;
     1680    }
     1681
    16391682    private function convert_to_webp( string $src ): array {
    16401683        $ext  = strtolower( pathinfo( $src, PATHINFO_EXTENSION ) );
    16411684        $dest = preg_replace( '/\.(jpg|jpeg|png|gif)$/i', '.webp', $src );
     1685        $max  = (int) $this->get_settings()['max_dimension'];
    16421686        try {
     1687            $imagick_failed = false;
    16431688            if ( extension_loaded( 'imagick' ) ) {
    1644                 $img = new Imagick( $src );
    16451689                try {
    1646                     $img->setImageFormat( 'webp' );
    1647                     $img->setImageCompressionQuality( self::WEBP_QUALITY );
    1648                     $img->writeImage( $dest );
    1649                 } finally {
    1650                     $img->destroy();
     1690                    $img = new Imagick( $src );
     1691                    try {
     1692                        $this->resize_for_derivative_imagick( $img, $max );
     1693                        $img->setImageFormat( 'webp' );
     1694                        $img->setImageCompressionQuality( self::WEBP_QUALITY );
     1695                        $img->writeImage( $dest );
     1696                    } finally {
     1697                        $img->destroy();
     1698                    }
     1699                } catch ( Throwable $e ) {
     1700                    // Np. limit policy.xml (szerokosc/wysokosc/area) na bardzo duzych
     1701                    // zdjeciach z aparatu - Imagick odmawia otwarcia pliku. GD tego
     1702                    // limitu nie ma, wiec probujemy nim zamiast od razu zglaszac blad.
     1703                    $imagick_failed = true;
    16511704                }
    1652             } elseif ( extension_loaded( 'gd' ) && function_exists( 'imagewebp' ) ) {
     1705            }
     1706            if ( ! extension_loaded( 'imagick' ) || $imagick_failed ) {
     1707                if ( ! ( extension_loaded( 'gd' ) && function_exists( 'imagewebp' ) ) ) {
     1708                    return [ 'status' => 'error', 'reason' => $imagick_failed ? 'imagick_failed_no_gd_fallback' : 'no_gd_imagick' ];
     1709                }
    16531710                $img = match ( $ext ) {
    16541711                    'jpg', 'jpeg' => imagecreatefromjpeg( $src ),
    … …  
    16591716                if ( ! $img ) return [ 'status' => 'error', 'reason' => 'cannot_load' ];
    16601717                if ( $ext === 'png' ) { imagepalettetotruecolor( $img ); imagealphablending( $img, true ); imagesavealpha( $img, true ); }
     1718                $img = $this->resize_for_derivative_gd( $img, $max );
    16611719                imagewebp( $img, $dest, self::WEBP_QUALITY );
    16621720                imagedestroy( $img );
    1663             } else {
    1664                 return [ 'status' => 'error', 'reason' => 'no_gd_imagick' ];
    16651721            }
    16661722            $os = @filesize( $src ) ?: 0;
    … …  
    24122468        try {
    24132469            $sup = $this->avif_supported();
     2470            $max = (int) $this->get_settings()['max_dimension'];
     2471            $imagick_failed = false;
    24142472            if ( $sup['imagick'] ) {
    2415                 $img = new Imagick( $src );
    24162473                try {
    2417                     if ( $img->getNumberImages() > 1 ) $img->setFirstIterator();
    2418                     $img = $img->mergeImageLayers( Imagick::LAYERMETHOD_FLATTEN );
    2419                     $img->setImageFormat( 'avif' );
    2420                     $img->setImageCompressionQuality( self::AVIF_QUALITY );
    2421                     $img->writeImage( $dest );
    2422                 } finally {
    2423                     $img->destroy();
     2474                    $img = new Imagick( $src );
     2475                    try {
     2476                        if ( $img->getNumberImages() > 1 ) $img->setFirstIterator();
     2477                        $img = $img->mergeImageLayers( Imagick::LAYERMETHOD_FLATTEN );
     2478                        $this->resize_for_derivative_imagick( $img, $max );
     2479                        $img->setImageFormat( 'avif' );
     2480                        $img->setImageCompressionQuality( self::AVIF_QUALITY );
     2481                        $img->writeImage( $dest );
     2482                    } finally {
     2483                        $img->destroy();
     2484                    }
     2485                } catch ( Throwable $e ) {
     2486                    // Tak samo jak w convert_to_webp(): bardzo duze zdjecia potrafia
     2487                    // przekroczyc limit policy.xml Imagicka (szerokosc/wysokosc/area).
     2488                    // GD tego limitu nie ma - probujemy nim zamiast od razu zglaszac blad.
     2489                    if ( ! $sup['gd'] ) return [ 'status' => 'error', 'reason' => 'imagick: ' . $e->getMessage() ];
     2490                    $imagick_failed = true;
    24242491                }
    2425             } elseif ( $sup['gd'] ) {
     2492            }
     2493            if ( $imagick_failed || ( ! $sup['imagick'] && $sup['gd'] ) ) {
    24262494                $img = match ( $ext ) {
    24272495                    'jpg', 'jpeg' => imagecreatefromjpeg( $src ),
    … …  
    24362504                    imagesavealpha( $img, true );
    24372505                }
     2506                $img = $this->resize_for_derivative_gd( $img, $max );
    24382507                imageavif( $img, $dest, self::AVIF_QUALITY );
    24392508                imagedestroy( $img );
    2440             } elseif ( $sup['cli'] ) {
     2509            } elseif ( ! $sup['imagick'] && ! $sup['gd'] && $sup['cli'] ) {
    24412510                // avifenc nie czyta WebP — dekodujemy najpierw do PNG (dwebp albo GD).
     2511                // Ta sama okazja sluzy do przeskalowania - avifenc nie ma wlasnej opcji
     2512                // zmiany rozmiaru, wiec bardzo duze zdjecia trzeba zmniejszyc PRZED
     2513                // podaniem mu pliku (inaczej ten sam problem co bez skalowania: derywat
     2514                // wiekszy od oryginalu).
    24422515                $tmp_png = '';
    24432516                $input   = $src;
     2517                if ( function_exists( 'getimagesize' ) && $ext !== 'webp' ) {
     2518                    $info = @getimagesize( $src );
     2519                    if ( $info && ( $info[0] > $max || $info[1] > $max ) && function_exists( 'imagecreatefromjpeg' ) ) {
     2520                        $im = $ext === 'png' ? @imagecreatefrompng( $src ) : @imagecreatefromjpeg( $src );
     2521                        if ( $im ) {
     2522                            $im = $this->resize_for_derivative_gd( $im, $max );
     2523                            $tmp_png = $src . '.mits-tmp-' . wp_generate_password( 6, false ) . '.png';
     2524                            imagepng( $im, $tmp_png );
     2525                            imagedestroy( $im );
     2526                            $input = $tmp_png;
     2527                        }
     2528                    }
     2529                }
    24442530                if ( $ext === 'webp' ) {
    24452531                    $tmp_png = preg_replace( '/\.webp$/i', '', $src ) . '.mits-tmp-' . wp_generate_password( 6, false ) . '.png';
    … …  
    24472533                    if ( function_exists( 'imagecreatefromwebp' ) ) {
    24482534                        $im = @imagecreatefromwebp( $src );
    2449                         if ( $im ) { $ok = imagepng( $im, $tmp_png ); imagedestroy( $im ); }
     2535                        if ( $im ) { $im = $this->resize_for_derivative_gd( $im, $max ); $ok = imagepng( $im, $tmp_png ); imagedestroy( $im ); }
    24502536                    }
    24512537                    if ( ! $ok ) {
  • mits-image-optimizer/tags/1.2.74/readme.txt

    r3654055 r3662711  
    55Tested up to: 7.0
    66Requires PHP: 8.0
    7 Stable tag: 1.2.72
     7Stable tag: 1.2.74
    88License: GPL-2.0-or-later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
    … …  
    9494
    9595== Changelog ==
     96
     97= 1.2.74 =
     98* .htaccess: blok wtyczki dostaje teraz WŁASNE reguły ExpiresByType/Cache-Control dla
     99  .avif i .webp (1 rok, immutable), zamiast polegać na tym, że reszta .htaccess strony
     100  już ma wpis dla image/avif. Ustalone na produkcji: wiele gotowych configów WP ma
     101  ExpiresByType image/webp, ale nie ma image/avif (bo avif jest nowszy format) - taki
     102  plik dostawał wtedy domyślny czas cache serwera (bywa to zaledwie 7 dni) zamiast
     103  miesięcy jak reszta obrazków, mimo że sam plik był już poprawnie skompresowany.
     104
     105= 1.2.73 =
     106* WebP/AVIF: derywat jest teraz skalowany do max_dimension PRZED kodowaniem (tak jak
     107  od dawna robi to funkcja kompresji oryginału). Wcześniej convert_to_webp()/
     108  convert_to_avif() kodowały w pełnej rozdzielczości źródła - dla zdjęć prosto
     109  z aparatu (8000px+) dawało to plik .webp/.avif WIĘKSZY od oryginału, bo próg
     110  15% oszczędności i tak go kasował, marnując czas konwersji. Ustalone na
     111  produkcji: zdjęcie 2560x1706 (7 MB) dawało 4,8 MB "avif" zamiast ~300 KB.
     112* AVIF/WebP: jeśli Imagick odmówi otwarcia bardzo dużego pliku (limit width/height/area
     113  w policy.xml serwera - poza naszą kontrolą na hostingu współdzielonym), konwersja
     114  teraz automatycznie próbuje przez GD zamiast od razu zgłaszać błąd. GD tego limitu
     115  nie ma. Wcześniej taki plik kończył się błędem i nigdy nie dostawał derywatu.
     116* AVIF (ścieżka CLI/avifenc): to samo skalowanie zastosowane też tutaj - avifenc nie ma
     117  własnej opcji resize, więc dla dużych zdjęć trzeba je zmniejszyć przed podaniem mu pliku.
    96118
    97119= 1.2.72 =
  • mits-image-optimizer/trunk/mits-image-optimizer.php

    r3654055 r3662711  
    33 * Plugin Name:       MITS Image Optimizer
    44 * Description:       Auto-compress images on upload, bulk convert to WebP & AVIF, configure .htaccess for next-gen serving, scan for oversized images, and audit your site.
    5  * Version:           1.2.72
     5 * Version:           1.2.74
    66 * Requires at least: 6.0
    77 * Requires PHP:      8.0
    … …  
    1515if ( ! defined( 'ABSPATH' ) ) exit;
    1616
    17 define( 'MITS_OPT_VERSION', '1.2.72' );
     17define( 'MITS_OPT_VERSION', '1.2.74' );
    1818define( 'MITS_OPT_FILE',    __FILE__ );
    1919define( 'MITS_OPT_DIR',     plugin_dir_path( __FILE__ ) );
    … …  
    656656            "</FilesMatch>\n" .
    657657            "</IfModule>\n" .
     658            // WAZNE (wyuczone na produkcji): nie polegamy na tym, ze reszta .htaccess
     659            // strony ma juz wpis ExpiresByType dla image/avif. Wiele gotowych configow
     660            // WP ma go dla image/webp, ale nie dla avif (bo avif jest nowszy) - taki
     661            // plik wtedy dostawal domyslny czas cache serwera (bywa to zaledwie 7 dni)
     662            // zamiast miesiecy jak reszta obrazkow. Wlasny, samodzielny wpis w bloku
     663            // wtyczki gwarantuje poprawny cache niezaleznie od reszty konfiguracji.
     664            "<IfModule mod_expires.c>\n" .
     665            "ExpiresActive On\n" .
     666            "ExpiresByType image/avif \"access plus 1 year\"\n" .
     667            "ExpiresByType image/webp \"access plus 1 year\"\n" .
     668            "</IfModule>\n" .
     669            "<IfModule mod_headers.c>\n" .
     670            "<FilesMatch \"(?i)\\.(avif|webp)$\">\n" .
     671            "Header set Cache-Control \"public, max-age=31536000, immutable\"\n" .
     672            "</FilesMatch>\n" .
     673            "</IfModule>\n" .
    658674            self::HTA_MARKER_END . "\n";
    659675    }
    … …  
    16371653    /* ── WebP convert ────────────────────────────────────────────── */
    16381654
     1655    /**
     1656     * Derywat (WebP/AVIF) NIGDY nie moze byc wiekszy niz oryginal. Stare zdjecia
     1657     * z aparatu bywaja w pelnej rozdzielczosci (8000px+), a nikt tak duzych nie
     1658     * wyswietla w przegladarce - kodowanie ich 1:1 daje plik WIEKSZY od oryginalu
     1659     * zamiast oszczednosci. Ograniczamy dluzszy bok do max_dimension z ustawien,
     1660     * tak samo jak juz robi compress_imagick()/compress_gd() dla kompresji originalu.
     1661     * NIE dotyka $src - operuje wylacznie na obiekcie/zasobie w pamieci.
     1662     */
     1663    private function resize_for_derivative_imagick( Imagick $img, int $max ): void {
     1664        if ( $img->getImageWidth() > $max || $img->getImageHeight() > $max ) {
     1665            $img->resizeImage( $max, $max, Imagick::FILTER_LANCZOS, 1, true );
     1666        }
     1667    }
     1668
     1669    private function resize_for_derivative_gd( $img, int $max ) {
     1670        $w = imagesx( $img ); $h = imagesy( $img );
     1671        if ( $w <= $max && $h <= $max ) return $img;
     1672        $ratio = min( $max / $w, $max / $h );
     1673        $nw = (int) round( $w * $ratio ); $nh = (int) round( $h * $ratio );
     1674        $res = imagecreatetruecolor( $nw, $nh );
     1675        imagealphablending( $res, false ); imagesavealpha( $res, true );
     1676        imagefill( $res, 0, 0, imagecolorallocatealpha( $res, 0, 0, 0, 127 ) );
     1677        imagecopyresampled( $res, $img, 0, 0, 0, 0, $nw, $nh, $w, $h );
     1678        imagedestroy( $img );
     1679        return $res;
     1680    }
     1681
    16391682    private function convert_to_webp( string $src ): array {
    16401683        $ext  = strtolower( pathinfo( $src, PATHINFO_EXTENSION ) );
    16411684        $dest = preg_replace( '/\.(jpg|jpeg|png|gif)$/i', '.webp', $src );
     1685        $max  = (int) $this->get_settings()['max_dimension'];
    16421686        try {
     1687            $imagick_failed = false;
    16431688            if ( extension_loaded( 'imagick' ) ) {
    1644                 $img = new Imagick( $src );
    16451689                try {
    1646                     $img->setImageFormat( 'webp' );
    1647                     $img->setImageCompressionQuality( self::WEBP_QUALITY );
    1648                     $img->writeImage( $dest );
    1649                 } finally {
    1650                     $img->destroy();
     1690                    $img = new Imagick( $src );
     1691                    try {
     1692                        $this->resize_for_derivative_imagick( $img, $max );
     1693                        $img->setImageFormat( 'webp' );
     1694                        $img->setImageCompressionQuality( self::WEBP_QUALITY );
     1695                        $img->writeImage( $dest );
     1696                    } finally {
     1697                        $img->destroy();
     1698                    }
     1699                } catch ( Throwable $e ) {
     1700                    // Np. limit policy.xml (szerokosc/wysokosc/area) na bardzo duzych
     1701                    // zdjeciach z aparatu - Imagick odmawia otwarcia pliku. GD tego
     1702                    // limitu nie ma, wiec probujemy nim zamiast od razu zglaszac blad.
     1703                    $imagick_failed = true;
    16511704                }
    1652             } elseif ( extension_loaded( 'gd' ) && function_exists( 'imagewebp' ) ) {
     1705            }
     1706            if ( ! extension_loaded( 'imagick' ) || $imagick_failed ) {
     1707                if ( ! ( extension_loaded( 'gd' ) && function_exists( 'imagewebp' ) ) ) {
     1708                    return [ 'status' => 'error', 'reason' => $imagick_failed ? 'imagick_failed_no_gd_fallback' : 'no_gd_imagick' ];
     1709                }
    16531710                $img = match ( $ext ) {
    16541711                    'jpg', 'jpeg' => imagecreatefromjpeg( $src ),
    … …  
    16591716                if ( ! $img ) return [ 'status' => 'error', 'reason' => 'cannot_load' ];
    16601717                if ( $ext === 'png' ) { imagepalettetotruecolor( $img ); imagealphablending( $img, true ); imagesavealpha( $img, true ); }
     1718                $img = $this->resize_for_derivative_gd( $img, $max );
    16611719                imagewebp( $img, $dest, self::WEBP_QUALITY );
    16621720                imagedestroy( $img );
    1663             } else {
    1664                 return [ 'status' => 'error', 'reason' => 'no_gd_imagick' ];
    16651721            }
    16661722            $os = @filesize( $src ) ?: 0;
    … …  
    24122468        try {
    24132469            $sup = $this->avif_supported();
     2470            $max = (int) $this->get_settings()['max_dimension'];
     2471            $imagick_failed = false;
    24142472            if ( $sup['imagick'] ) {
    2415                 $img = new Imagick( $src );
    24162473                try {
    2417                     if ( $img->getNumberImages() > 1 ) $img->setFirstIterator();
    2418                     $img = $img->mergeImageLayers( Imagick::LAYERMETHOD_FLATTEN );
    2419                     $img->setImageFormat( 'avif' );
    2420                     $img->setImageCompressionQuality( self::AVIF_QUALITY );
    2421                     $img->writeImage( $dest );
    2422                 } finally {
    2423                     $img->destroy();
     2474                    $img = new Imagick( $src );
     2475                    try {
     2476                        if ( $img->getNumberImages() > 1 ) $img->setFirstIterator();
     2477                        $img = $img->mergeImageLayers( Imagick::LAYERMETHOD_FLATTEN );
     2478                        $this->resize_for_derivative_imagick( $img, $max );
     2479                        $img->setImageFormat( 'avif' );
     2480                        $img->setImageCompressionQuality( self::AVIF_QUALITY );
     2481                        $img->writeImage( $dest );
     2482                    } finally {
     2483                        $img->destroy();
     2484                    }
     2485                } catch ( Throwable $e ) {
     2486                    // Tak samo jak w convert_to_webp(): bardzo duze zdjecia potrafia
     2487                    // przekroczyc limit policy.xml Imagicka (szerokosc/wysokosc/area).
     2488                    // GD tego limitu nie ma - probujemy nim zamiast od razu zglaszac blad.
     2489                    if ( ! $sup['gd'] ) return [ 'status' => 'error', 'reason' => 'imagick: ' . $e->getMessage() ];
     2490                    $imagick_failed = true;
    24242491                }
    2425             } elseif ( $sup['gd'] ) {
     2492            }
     2493            if ( $imagick_failed || ( ! $sup['imagick'] && $sup['gd'] ) ) {
    24262494                $img = match ( $ext ) {
    24272495                    'jpg', 'jpeg' => imagecreatefromjpeg( $src ),
    … …  
    24362504                    imagesavealpha( $img, true );
    24372505                }
     2506                $img = $this->resize_for_derivative_gd( $img, $max );
    24382507                imageavif( $img, $dest, self::AVIF_QUALITY );
    24392508                imagedestroy( $img );
    2440             } elseif ( $sup['cli'] ) {
     2509            } elseif ( ! $sup['imagick'] && ! $sup['gd'] && $sup['cli'] ) {
    24412510                // avifenc nie czyta WebP — dekodujemy najpierw do PNG (dwebp albo GD).
     2511                // Ta sama okazja sluzy do przeskalowania - avifenc nie ma wlasnej opcji
     2512                // zmiany rozmiaru, wiec bardzo duze zdjecia trzeba zmniejszyc PRZED
     2513                // podaniem mu pliku (inaczej ten sam problem co bez skalowania: derywat
     2514                // wiekszy od oryginalu).
    24422515                $tmp_png = '';
    24432516                $input   = $src;
     2517                if ( function_exists( 'getimagesize' ) && $ext !== 'webp' ) {
     2518                    $info = @getimagesize( $src );
     2519                    if ( $info && ( $info[0] > $max || $info[1] > $max ) && function_exists( 'imagecreatefromjpeg' ) ) {
     2520                        $im = $ext === 'png' ? @imagecreatefrompng( $src ) : @imagecreatefromjpeg( $src );
     2521                        if ( $im ) {
     2522                            $im = $this->resize_for_derivative_gd( $im, $max );
     2523                            $tmp_png = $src . '.mits-tmp-' . wp_generate_password( 6, false ) . '.png';
     2524                            imagepng( $im, $tmp_png );
     2525                            imagedestroy( $im );
     2526                            $input = $tmp_png;
     2527                        }
     2528                    }
     2529                }
    24442530                if ( $ext === 'webp' ) {
    24452531                    $tmp_png = preg_replace( '/\.webp$/i', '', $src ) . '.mits-tmp-' . wp_generate_password( 6, false ) . '.png';
    … …  
    24472533                    if ( function_exists( 'imagecreatefromwebp' ) ) {
    24482534                        $im = @imagecreatefromwebp( $src );
    2449                         if ( $im ) { $ok = imagepng( $im, $tmp_png ); imagedestroy( $im ); }
     2535                        if ( $im ) { $im = $this->resize_for_derivative_gd( $im, $max ); $ok = imagepng( $im, $tmp_png ); imagedestroy( $im ); }
    24502536                    }
    24512537                    if ( ! $ok ) {
  • mits-image-optimizer/trunk/readme.txt

    r3654055 r3662711  
    55Tested up to: 7.0
    66Requires PHP: 8.0
    7 Stable tag: 1.2.72
     7Stable tag: 1.2.74
    88License: GPL-2.0-or-later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
    … …  
    9494
    9595== Changelog ==
     96
     97= 1.2.74 =
     98* .htaccess: blok wtyczki dostaje teraz WŁASNE reguły ExpiresByType/Cache-Control dla
     99  .avif i .webp (1 rok, immutable), zamiast polegać na tym, że reszta .htaccess strony
     100  już ma wpis dla image/avif. Ustalone na produkcji: wiele gotowych configów WP ma
     101  ExpiresByType image/webp, ale nie ma image/avif (bo avif jest nowszy format) - taki
     102  plik dostawał wtedy domyślny czas cache serwera (bywa to zaledwie 7 dni) zamiast
     103  miesięcy jak reszta obrazków, mimo że sam plik był już poprawnie skompresowany.
     104
     105= 1.2.73 =
     106* WebP/AVIF: derywat jest teraz skalowany do max_dimension PRZED kodowaniem (tak jak
     107  od dawna robi to funkcja kompresji oryginału). Wcześniej convert_to_webp()/
     108  convert_to_avif() kodowały w pełnej rozdzielczości źródła - dla zdjęć prosto
     109  z aparatu (8000px+) dawało to plik .webp/.avif WIĘKSZY od oryginału, bo próg
     110  15% oszczędności i tak go kasował, marnując czas konwersji. Ustalone na
     111  produkcji: zdjęcie 2560x1706 (7 MB) dawało 4,8 MB "avif" zamiast ~300 KB.
     112* AVIF/WebP: jeśli Imagick odmówi otwarcia bardzo dużego pliku (limit width/height/area
     113  w policy.xml serwera - poza naszą kontrolą na hostingu współdzielonym), konwersja
     114  teraz automatycznie próbuje przez GD zamiast od razu zgłaszać błąd. GD tego limitu
     115  nie ma. Wcześniej taki plik kończył się błędem i nigdy nie dostawał derywatu.
     116* AVIF (ścieżka CLI/avifenc): to samo skalowanie zastosowane też tutaj - avifenc nie ma
     117  własnej opcji resize, więc dla dużych zdjęć trzeba je zmniejszyć przed podaniem mu pliku.
    96118
    97119= 1.2.72 =
Note: See TracChangeset for help on using the changeset viewer.