[php] imagecopyresampled scaling problemen *

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • xilent_xage
  • Registratie: Februari 2005
  • Laatst online: 15-09 11:35
Hoi,

Ik heb een klein meningsverschil met imagecopyresampled en ik hoor graag van jullie dat ik ongelijk heb :)

Ik wil een plaatje in een plaatje plakken, precies waar de functie voor bedoeld is lijkt mij. Daar komen nogal wat berekeningen bij kijken, maar uiteindelijk gaat het resizen mis. Omdat het een functie is met enorm veel variabelen en ik er tureluurs van werd heb ik maar even de uitleg van php.net misbruikt om het te snappen:

PHP:
1
2
3
echo "In other words, imagecopyresampled() will take a rectangular area from src_image of width " . $width . " and height ". $height . " at position (".  $w . ",".  $h . ") and place it in a rectangular area of dst_image of width ". $new_width . " and height " . $new_height . " at position (" . $startwidth . "," . $startheight . ").";

//imagecopyresampled($phone, $src_img, $startwidth, $startheight, intval(round($w)), intval(round($h)), $new_width, $new_height, $width, $height);


Dat geeft als output:
In other words, imagecopyresampled() will take a rectangular area from src_image of width 1879 and height 1242 at position (165,0) and place it in a rectangular area of dst_image of width 242 and height 160 at position (73,21).
Mooi. Precies wat ik wil doen.

Het gebied wat ik plak heeft dus een afmeting van 1879 x 1242. En ik plak dat in een gebied met afmeting 242 x 160. Dezelfde aspect ratio, dus appeltje-eitje zou je zeggen. Hij plakt het plaatje echter op formaat 203 x 160.

Waarom?

Acties:
  • 0 Henk 'm!

  • armageddon_2k1
  • Registratie: September 2001
  • Laatst online: 27-07 10:18
Geen idee waarom. Blijkbaar doe je iets fout, maar dat kunnen we niet zien in onze glazen bol als je geen relevante code plaatst :)

Engineering is like Tetris. Succes disappears and errors accumulate.


Acties:
  • 0 Henk 'm!

  • xilent_xage
  • Registratie: Februari 2005
  • Laatst online: 15-09 11:35
Ok, ik dacht ik hou het simpel.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
function preview_mobile($source_file, $dst_dir, $cachename, $orientation){

    #load positions and dimensions according to orientation
    switch ( $orientation ){

        case "landscape" :

            $dst_x = 73;
            $dst_y = 21;

            $dst_w = 242;
            $dst_h = 160;
            $totalwidth = 386;
            $totalheight = 203;
            $cachename = str_replace("_preview_mobile", "242x160", $cachename);
            $dst_image = imagecreatefrompng($_SERVER['DOCUMENT_ROOT'] . "/_resources/landscape.png");

            break;

        case "portrait" :

            $dst_x = 20;
            $dst_y = 74;

            $dst_w = 160;
            $dst_h = 242;
            $totalwidth = 201;
            $totalheight = 388;
            $cachename = str_replace("_preview_mobile", "160x242", $cachename);
            $dst_image = imagecreatefrompng($_SERVER['DOCUMENT_ROOT'] . "/_resources/portrait.png");

            break;

    }

    #set source image sizes
    $imgsize = getimagesize($source_file);
    $old_width = $imgsize[0];
    $old_height = $imgsize[1];

    #set mime
    $mime = $imgsize['mime'];
    switch($mime){
        case 'image/gif':
            $image_create = "imagecreatefromgif";
            $image = "imagegif";
            break;

        case 'image/png':
            $image_create = "imagecreatefrompng";
            $image = "imagepng";
            $quality = 7;
            break;

        case 'image/jpeg':
            $image_create = "imagecreatefromjpeg";
            $image = "imagejpeg";
            $quality = 80;
            break;

        default:
            return false;
            break;
    }

    #calculate copy area
    $old_ratio = $old_width / $old_height;
    $new_ratio = $dst_w / $dst_h;

    if ( $new_ratio < $old_ratio) {
       $src_w = intval(round($old_width / ($old_ratio/$new_ratio)));
       $src_h = $old_height;
    }
    else {
       $src_w = $old_width;
       $src_h = intval(round($old_height / ($new_ratio/$old_ratio)));
    }
    if ( $src_h < $old_height ) { $src_y = round((($old_height - $src_h) / 2)); }
    else { $src_y = 0; }
    if ( $src_w < $old_width ) { $src_x = round((($old_width - $src_w) / 2)); }
    else { $src_x = 0; }

    #create new image
    $src_img = $image_create($source_file);
    imagesavealpha($src_img, true);
    $trans_colour = imagecolorallocatealpha($src_img, 0, 0, 0, 127);
    imagefill($src_img, 0, 0, $trans_colour);

echo "In other words, imagecopyresampled() will take a rectangular area from src_image of width " . $src_w . " and height ". $src_h . " at position (".  intval(round($src_x)) . ",".  intval(round($src_y)) . ") and place it in a rectangular area of dst_image of width ". $dst_w . " and height " . $dst_h . " at position (" . $dst_x . "," . $dst_y . ").";
die();

    #copy source over image
    imagecopyresampled($dst_image, $src_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);

    #write the image
    imagepng($dst_image, $dst_dir);
    imagedestroy($dst_image);

}

[ Voor 14% gewijzigd door xilent_xage op 02-06-2016 13:40 ]


Acties:
  • 0 Henk 'm!

  • mcDavid
  • Registratie: April 2008
  • Laatst online: 02-10 08:45
Begin eens met het echo'en van de variablen die je de imagecopyresampled() in schuift. Daar zit er ongetwijfeld een tussen die niet is wat je verwacht dat 'ie is.

Vervolgens uitzoeken hoe dat komt.

Acties:
  • 0 Henk 'm!

  • xilent_xage
  • Registratie: Februari 2005
  • Laatst online: 15-09 11:35
In regel 89 echo ik alle variabelen die de functie ingaan, en die staan allemaal goed. Wat valt er meer aan te debuggen?

Acties:
  • 0 Henk 'm!

  • kaesve
  • Registratie: Maart 2009
  • Laatst online: 16-05 03:04
Sowieso zou ik je variabelen hernoemen. Je zegt in je eerste post dat je verwacht dat $startwidth en $startheight de (x,y) is waar naartoe wordt gekopieerd, maar daarna geef je ze aan de resample functie als source (x,y). Lijkt mij dus dat de volgorde van je variabelen niet klopt. Dat zou duidelijker zijn als je variabele namen ook aangeven dat het om de dest_x gaat, ipv een breedte.

Acties:
  • 0 Henk 'm!

  • xilent_xage
  • Registratie: Februari 2005
  • Laatst online: 15-09 11:35
Huh? Ik geef ze toch als 3e en 4e variabele mee? Volgens de documentatie zijn dat "x-coordinate of destination point" en "y-coordinate of destination point". Staat gewoon goed toch, of snap ik het nu verkeerd?

Edit: Toch maar even code opgeschoond, maar geen succes.

[ Voor 12% gewijzigd door xilent_xage op 02-06-2016 13:38 ]


Acties:
  • 0 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
"width 1879 and height 1242 at position (165,0)"

1879 + 165 + 165 = 2209
100 / 1242 * 160 = 12.88%
2209 / 100 * 12.88 = 284.51

Zoals je ziet kom ik al op een andere waarde uit dan jouw 242 maar dat is alleen als $src_image 2209 breed is.
src_image lijkt 1896 breed te zijn (203 / 12.88 * 100 + 160 + 160)

[ Voor 7% gewijzigd door DJMaze op 02-06-2016 15:30 . Reden: Foute berekening gefixt ]

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • kaesve
  • Registratie: Maart 2009
  • Laatst online: 16-05 03:04
xilent_xage schreef op donderdag 02 juni 2016 @ 13:30:
Huh? Ik geef ze toch als 3e en 4e variabele mee? Volgens de documentatie zijn dat "x-coordinate of destination point" en "y-coordinate of destination point". Staat gewoon goed toch, of snap ik het nu verkeerd?

Edit: Toch maar even code opgeschoond, maar geen succes.
Ik lees inderdaad verkeerd, excuus.

Acties:
  • 0 Henk 'm!

  • xilent_xage
  • Registratie: Februari 2005
  • Laatst online: 15-09 11:35
DJMaze schreef op donderdag 02 juni 2016 @ 13:39:
"width 1879 and height 1242 at position (165,0)"

1879 - 165 = 1714
De src_image is veel groter. Daaruit snij ik een gebied van 1879 x 1242 vanaf 165,0. Ik wil het wegsnijden tbv aspect ratio gelijkmatig aan de randen doen, omdat het onderwerp meestal in het midden staat.
DJMaze schreef op donderdag 02 juni 2016 @ 13:39:
100 / 1242 * 160 = 12.88%
1714 / 100 * 12.88 = 220.76

Zoals je ziet kom ik al op een andere waarde uit dan jouw 242 maar dat is alleen als $src_image 1879 breed is.
src_image lijkt 1736 breed te zijn (203 / 12.88 * 100 + 160)
Het klinkt alsof je de oplossing hebt, maar ik kan je niet volgen. Wat bereken je en waarom?
Zie mijn opmerking hierboven. Interpreteer ik die variabelen soms verkeerd?

[ Voor 28% gewijzigd door xilent_xage op 02-06-2016 14:10 ]


Acties:
  • +1 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
Simpel...

imagecopyresampled() knipt een deel uit $src_image en plakt dat in $dst_image

Stel je hebt een afbeelding van 100x100.

$src_x = 10
$src_y = 10
$src_w = 80
$src_h = 80
Je knipt dan een stuk van 80x80 uit beginnend vanaf 10,10 en dat past.

$src_x = 10
$src_y = 10
$src_w = 100
$src_h = 100
Je knipt dan een stuk van 90x90 en niet van 100x100 omdat hij begint bij 10,10

Je berekeningen moet je anders opbouwen:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$dst_w = 160;
$dst_h = 242;
$old_width = 1600;
$old_height = 1200;

$w_ratio = $old_width / $dst_w; // bijv: 1600 / 160 = 10
$h_ratio = $old_height / $dst_h; // bijv: 1200 / 242 = 4.958677
$src_x = $src_y = 0;
if ($w_ratio > $h_ratio) {
    $src_w = round($old_width * $h_ratio / $w_ratio);
    $src_h = $old_height;
    $src_x = round(($old_width - $src_w) / 2);
} else if ($w_ratio < $h_ratio) {
    $src_w = $old_width;
    $src_h = round($old_height * $w_ratio / $h_ratio);
    $src_y = round(($old_height - $src_h) / 2);
} else {
    $src_w = $old_width;
    $src_h = $old_height;
}

Note: dit werkt alleen als $src groter is dan $dst
xilent_xage schreef op donderdag 02 juni 2016 @ 13:51:
De src_image is veel groter. Daaruit snij ik een gebied van 1879 x 1242 vanaf 165,0. Ik wil het wegsnijden tbv aspect ratio gelijkmatig aan de randen doen, omdat het onderwerp meestal in het midden staat.
Je source is vast breder, maar is en blijft 1242 hoog.
Op basis van jouw berekening is de afbeelding 2209 pixels breed (pixel meer of minder)

[ Voor 38% gewijzigd door DJMaze op 02-06-2016 15:31 . Reden: Bugfix: src_w /src_h berekening ]

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • xilent_xage
  • Registratie: Februari 2005
  • Laatst online: 15-09 11:35
Ja, maar dan doet ie iets anders dan ik wil :)

Wat ik probeer te doen is:

1. Snij de src zodanig bij dat ie dezelfde aspectratio heeft als het stuk wat gekopieerd moet worden. Dat betekent dat je óf iets van de hoogte óf iets van de breedte moet afsnijden. Het snijden wil ik gelijkmatig aan de randen doen. Dus als de src te breed is gaat er aan beide zijkanten iets af, als ie te hoog is aan de boven-en onderkant.

2. Daarna schalen naar de juiste grootte en plakken.

Acties:
  • 0 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
Dat is niet iets anders, dat is precies wat mijn php doet :p
P.S. Ik bleek in mijn gehaastheid wel een bug te hebben. Die is gefixt.
Je hebt in ieder geval nog niet verteld wat de exacte maat is van $source_file....

[ Voor 84% gewijzigd door DJMaze op 02-06-2016 16:21 ]

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • xilent_xage
  • Registratie: Februari 2005
  • Laatst online: 15-09 11:35
En toch genereert die berekening precies hetzelfde issue :)
De src wordt op 203 x 160 over het plaatje heengeplakt ipv de gewenste 242 x 160

Hier in actie: https://omgevings.info/_r.../preview_mobile/landscape

En de grootte van d src file kan natuurlijk veranderen, ik wil een generieke functie. Maar in dit geval is het 2208 x 1242

[ Voor 51% gewijzigd door xilent_xage op 02-06-2016 16:38 ]


Acties:
  • 0 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
xilent_xage schreef op donderdag 02 juni 2016 @ 16:28:
En toch genereert die berekening precies hetzelfde issue :)
De src wordt op 203 x 160 over het plaatje heengeplakt ipv de gewenste 242 x 160

Hier in actie: https://omgevings.info/_r.../preview_mobile/landscape

En de grootte van d src file kan natuurlijk veranderen, ik wil een generieke functie. Maar in dit geval is het 2208 x 1242
Hmmm ik heb net jouw en mijn code getest op een 2208x1242 afbeelding en die past perfect.
GD Version 2.1.1
Zie http://dragonflycms.org/tests/gd2/
En de afbeelding: http://dragonflycms.org/tests/gd2/lorumpixel.jpg

[ Voor 4% gewijzigd door DJMaze op 02-06-2016 16:58 ]

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • xilent_xage
  • Registratie: Februari 2005
  • Laatst online: 15-09 11:35
jemig zit hier echt al 2 dagen op te klooien, lijkt het aan de afbeelding te liggen. Jouw afbeelding doet t inderdaad prima.Misschien moet ik dit in een ander forum vragen, maar enig idee wat er mis is met die afbeelding?

https://omgevings.info/_a...64848814574fd1ae8caf7.png

Acties:
  • 0 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
Haal de volgende regels weg uit je code
PHP:
1
2
3
    imagesavealpha($src_img, true);
    $trans_colour = imagecolorallocatealpha($src_img, 0, 0, 0, 127);
    imagefill($src_img, 0, 0, $trans_colour);

Daar had ik overheen gelezen, die horen er niet. Maar maakt het wel logisch nu ik je afbeelding ook heb.

Pak eens een image editor zoals GiMP, pak de paint bucket en vul de linkerkant van de afbeelding met rood ofzo en met een threshold van 0 (dus alleen identieke kleuren).
Je ziet dan een verschil.

Bovenstaande code die je moet verwijderen maakt namelijk een bepaalde kleur transparant. Vandaar :)

P.S. misschien topic titel aanpassen in: "Haat aan alpha channels"

[ Voor 9% gewijzigd door DJMaze op 02-06-2016 18:05 ]

Maak je niet druk, dat doet de compressor maar

Pagina: 1