Produktbilder immer quadratisch - wie?

Hallo,

ich versuche derzeit sämtliche Produktbilder im Template/System auf ein quadratisches Format zu bekommen.

Oxid behält leider immer die original Porportionen bei. Ich möchte aber, dass z.b. ein 100x50 Bild auf 100x100 vergrößert/verkleinert wird, und zwar mit weißem oder transparentem Hintergrund. (In Photoshop wäre das die Canvas-Size/Leinwandgröße).

Irgendwie kriege ich das nicht umgesetzt, wäre aber für mich für ein konsistentes Layout wichtig.

Grüße
Volker

damit die Bilddatei wirklich 100x100 ist, musst du die Bilder erst durch Photoshop durchjagen und mit Batch Verarbeitung dann alle “quadratisieren”. Danach kannst du sie hochladen.

Oder wenn es nur so aussehen soll, dann mach ein 100x100 px container und da drin kannst du das Bild als Hintergrundbild nehmen und es auf die Größe mit CSS background-size skalieren lassen

Der Weg über Photoshop scheidet eher aus. Der Shop wird ca. 25.000 Artikel mit hoher Fluktuation haben.

Bietet der Oxid-Image Prozessor keine Funktion für “Canvas Size”. In Magento ist das Standard.duckundweg

Den Weg über CSS und background-size etc. wollte ich vermeiden, da das ganze Layout fluide und responsive ist und somit mit prozentwerten der Container gearbeitet wird und ich manuelle Höhenangaben im CSS vermeiden möchte. Zudem sind die Bilder in Slidern drin, was es nochmal umständlicher macht.
Ich könnte den Equalizer des JS-Frameworks nutzen, aber das ist ist wenig elegant und zu langsam/unschön.

Welchen ImageProzessor nutzt Oxid? Vielleicht gibt es hier ja mehr Optionen als gedacht oder man könnte ihn umbauen?

photoshop war nur eine Möglichkeit, gibt genug anderer Programme

Schau Dir in core/utils die oxpicgenerator an. Ist gar nicht so kompliziert. Auf Stackoverflow gibts auch genug lesestoff um canvas-/image-size zu manipulieren.
https://www.google.cz/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=php+gd+canvas+size+stackoverflow

Danke an MeisterYoda für den Tipp.

Ich habe nun in der oxpicgenerator.php etwas rumgewerkelt (später wirds natürlich ein neues eigenes modul mit override). Zumindest ist dies schonmal die richtige Datei für die Bildverarbeitung. :slight_smile:

Allerdings komme ich noch nicht ganz an des gewünschte Ergebnis. Ich habe jetzt versucht so wenig wie möglich zu manipulieren und wollte folgende Logik implementieren:

[ol]
[li]Das Bild wird standardmäßig proportional verkleinert (Oxid-nativ)
[/li][li]NEU: Das verkleinerte Bild aus 1. soll nun in ein neues leeres quadratisches CanvasBild zentriert eingefügt werden. Anschließend erfolgt die Ausgabe des neuen “CanvasBilds” in eien Datei.
[/li][/ol]

folgende Funktionen habe ich dabei angepasst/ergänzt, der Rest ist original geblieben:

  1. Neue Funktion für die CanvasBild Erzeugung:

/**
     * Creates and copies the resized image and places it on our empty (square) canvas image
     *
     * @param string $sDestinationImage file + path of destination
     * @param string $sSourceImage      file + path of source
     * @param int    $iCanvasWidth      new width of the image
     * @param int    $iCanvasHeight     new height of the image
     * @param array  $aImageInfo        additional info
     * @param string $sTarget           target file path
     * @param int    $iGdVer            used gd version
     *
     * @return bool
     */
    function copyCanvasImage( $sDestinationCanvasImage, $sSourceResizedImage, $iCanvasWidth, $iCanvasHeight, $aImageInfo, $sTarget, $iGdVer ) {

        // get image offsets to center image in canvas
        // SEE: http://stackoverflow.com/questions/15998348/extend-image-canvas-with-gd-or-imagick
        list($srcWidth, $srcHeight) = getimagesize($sSourceResizedImage);

        $off_x = (int) round(($iCanvasWidth - $srcWidth) / 2);
        $off_y = (int) round(($iCanvasHeight - $srcHeight) / 2);
        
        $canvasSuccess = imagecopyresampled( $sDestinationCanvasImage, $sSourceResizedImage, $off_x, $off_y, 0, 0, $iCanvasWidth, $iCanvasHeight, $aImageInfo[0], $aImageInfo[1] );
        
        return $canvasSuccess;
    }

  1. Funktion resizeJpeg angepasst:

    /**
     * Creates resized JPG image. Returns path of new file if creation
     * succeed. On error returns FALSE
     *
     * @param string   $sSrc              JPG source
     * @param string   $sTarget           new image location
     * @param int      $iWidth            new width
     * @param int      $iHeight           new height
     * @param int      $aImageInfo        original width
     * @param int      $iGdVer            GD library version
     * @param resource $hDestinationImage destination image handle
     * @param int      $iDefQuality       new image quality
     *
     * @return string | false
     */
    function resizeJpeg( $sSrc, $sTarget, $iWidth, $iHeight, $aImageInfo, $iGdVer, $hDestinationImage, $iDefQuality )
    {
        $aResult = checkSizeAndCopy( $sSrc, $sTarget, $iWidth, $iHeight, $aImageInfo[0], $aImageInfo[1] );
        if ( is_array( $aResult ) ) {
            list( $iNewWidth, $iNewHeight ) = $aResult;
            if ( $hDestinationImage === null ) {
                $hDestinationImage = $iGdVer == 1 ? imagecreate( $iNewWidth, $iNewHeight ) : imagecreatetruecolor( $iNewWidth, $iNewHeight );
            }
            // LUXMEDIA MOD
            // Create Images based on Canvas
            if ( $hDestinationCanvasImage === null ) {
                $hDestinationCanvasImage = $iGdVer == 1 ? imagecreate( $iWidth, $iHeight ) : imagecreatetruecolor( $iWidth, $iHeight );
                // make the canvas, fill it with $white background
                $white = imagecolorallocate($hDestinationCanvasImage, 255, 255, 255);
                imagefilledrectangle($hDestinationCanvasImage, 0, 0, $iWidth, $iHeight, $white);
            }
            // EOF - LUXMEDIA MOD

            $hSourceImage = imagecreatefromjpeg( $sSrc );

            if ( copyAlteredImage( $hDestinationImage, $hSourceImage, $iNewWidth, $iNewHeight, $aImageInfo, $sTarget, $iGdVer ) ) {
                // LUXMEDIA MOD
                if ( copyCanvasImage( $hDestinationCanvasImage, $hDestinationImage, $iWidth, $iHeight, $aImageInfo, $sTarget, $iGdVer ) ) {
                    // imagejpeg( $hDestinationImage, $sTarget, $iDefQuality );
                    imagejpeg( $hDestinationCanvasImage, $sTarget, $iDefQuality );
                    imagedestroy( $hDestinationCanvasImage );
                    imagedestroy( $hDestinationImage );
                    imagedestroy( $hSourceImage );
                }
                // EOF - LUXMEDIA MOD
            }
        }

        return makeReadable( $sTarget );
    }

[B]Das Problem:[/B]
[ul]
[li]Ich erhalte nun quadratische Bilder mit weißem Hintergrund in gewünschter Größe - CHECK
[/li][li]Allerdings befinden sich in diesen quadratischen Bildern nun nochmals verkleinert (ziemlich genau die Hälfte) quadratische Bilder mit schwarzem Hintergrund in denen sich wiederum die tatsächlichen Bilder nochmals verkleinert in den linken oberen Ecke befinden - FAIL :confused:
[/li][/ul]

Garantiert ein Denk- oder Tippfehler. Hat jemand eine Idee oder einen Hinweis für mich?

Grüße
Volker

Ok, habs selbst hinbekommen, hier meine Lösung: :smiley:

Meine neue copyCanvasImage() Funktion sieht nun so aus:


    /**
     * Creates and copies the resized image and places it on our empty (square) canvas image
     *
     * @param string $sDestinationImage file + path of destination
     * @param string $sSourceImage      file + path of source
     * @param int    $iCanvasWidth      new width of the image
     * @param int    $iCanvasHeight     new height of the image
     * @param array  $srcWidth          width of source image
     * @param string $srcHeight         height of source image
     * @param int    $iGdVer            used gd version
     *
     * @return bool
     */
    function copyCanvasImage( $sDestImage, $sSrcImage, $iCanvasWidth, $iCanvasHeight, $srcWidth, $srcHeight, $iGdVer ) {

        // dimensions and offset for image centering
        if ($srcWidth > $srcHeight) {
            $iFinalWidth = $iCanvasWidth;
            //respect the ratio
            $iFinalHeight = round($srcHeight / $srcWidth * $iCanvasHeight);
            //set the offset
            $posY = ceil(($iFinalWidth - $iFinalHeight) / 2);
            $posX = 0;
        } elseif ($srcHeight > $srcWidth) {
            $iFinalHeight = $iCanvasHeight;
            $iFinalWidth = round($srcWidth / $srcHeight * $iCanvasWidth);
            $posX = ceil(($iFinalHeight - $iFinalWidth) / 2);
            $posY = 0;
        } else {
            $iFinalWidth = $iCanvasWidth;
            $iFinalHeight = $iCanvasHeight;
            $posX = $posY = 0;
        }
        
        $canvasSuccess = imagecopyresampled( $sDestImage, $sSrcImage, $posX, $posY, 0, 0, $iFinalWidth, $iFinalHeight, $srcWidth, $srcHeight );
        
        return $canvasSuccess;
    }

und die modifizierte resizeJpeg() nun so:


    function resizeJpeg( $sSrc, $sTarget, $iWidth, $iHeight, $aImageInfo, $iGdVer, $hDestinationImage, $iDefQuality )
    {
        $aResult = checkSizeAndCopy( $sSrc, $sTarget, $iWidth, $iHeight, $aImageInfo[0], $aImageInfo[1] );
        if ( is_array( $aResult ) ) {
            list( $iNewWidth, $iNewHeight ) = $aResult;
            // LUXMEDIA MOD
            list($srcWidth, $srcHeight) = getimagesize($sSrc);
            // EOF - LUXMEDIA MOD
            if ( $hDestinationImage === null ) {
                // LUXMEDIA MOD
                // Create Images based on Canvas
                // $hDestinationImage = $iGdVer == 1 ? imagecreate( $iNewWidth, $iNewHeight ) : imagecreatetruecolor( $iNewWidth, $iNewHeight );
                $hDestinationImage = imagecreatetruecolor( $iWidth, $iHeight );
                // make the canvas, fill it with $white background
                $bg = imagecolorallocate($hDestinationImage, 255, 255, 255);
                imagefill($hDestinationImage, 0, 0, $bg);
                // EOF - LUXMEDIA MOD
            }
            
            $hSourceImage = imagecreatefromjpeg( $sSrc );

            // LUXMEDIA MOD
            // if ( copyAlteredImage( $hDestinationImage, $hSourceImage, $iNewWidth, $iNewHeight, $aImageInfo, $sTarget, $iGdVer ) ) {
            if ( copyCanvasImage( $hDestinationImage, $hSourceImage, $iWidth, $iHeight, $srcWidth, $srcHeight, $iGdVer ) ) {
            // EOF - LUXMEDIA MOD
                imagejpeg( $hDestinationImage, $sTarget, $iDefQuality );
                imagedestroy( $hDestinationImage );
                imagedestroy( $hSourceImage );
                
            }
        }

        return makeReadable( $sTarget );
    }

Wenn noch einen Fehler gefunden hat oder Optimierungsvorschläge für meine bisherige Funktion hat … immer gerne :slight_smile:

Welches Modul muss ich eigentlich überschreiben, um meine neuen ImageProcessing Funktionen in ein eigenes Modul zu packen?