[PHP] problemen met imagecopy

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Goedendag,

Wat ik wil bereiken: Ik heb meerdere plaatjes (png), die in een bepaalde volgorde 1 grote afbeelding moeten vormen. De kleine plaatjes noem ik "tiles", de grote afbeelding "map". Elke tile staat voor een sector, 49 px breed.

Elke tile heeft in een database een x en y positie. 0 = 1e positie.
[tile met (1,0) begint dus op pixel(49, 0)]

Aan het begin van het script laad ik alle tiles in $this->tiles, met als key de naam van de tile waarmee die in de database staat en value de resource naar de afbeelding, (10 stuks, 2 kb per stuk), en met het volgende script plaats ik ze:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
while( $sector = mysql_fetch_array( $result, MYSQL_ASSOC ) )
            {
                # sector kan uit meerdere tile's bestaan
                $tileParts = explode( ',', $sector['s_tile'] );
                
                foreach( $tileParts as $tilePart )
                {
                    //echo $tilePart . '-';
                    
                    // bool imagecopymerge ( resource dst_im, resource src_im, int dst_x, int dst_y, int src_x, int src_y, int src_w, int src_h, int pct )
                    imagecopy( $map, $this->tiles[ $tilePart ], ( $this->sectorSize['width'] * $sector['s_x'] ), ( $this->sectorSize['height'] * $sector['s_y'] ), 0, 0, $this->sectorSize['width'], $this->sectorSize['height'] );     
                }                           
            }
            header( 'Content-type: image/png' );
            header( 'Content-Length: ' . strlen( $map ) );
            imagepng( $map );


Alles gaat goed, tot een onduidelijk moment. De ene keer plaatst het script maar 15 (van de 21) tiles, een andere keer stopt die als er in een keer een andere komt, die die al wel eerder heeft gebruikt.

Ik heb zover ik weet alles gecontroleerd, de tiles zijn allemaal geladen, $this->tiles is compleet, maar toch loopt hij soms stuk.

Zie ik iets over het hoofd? Is die functie misschien gewoon brak?

Alvast bedankt!

php: 5.1.2, gdlib: 2.0.28 compatible

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Ik kan me voorstellen dat het geheugentechnisch een ramp is om zoveel plaatjes tegelijk open te hebben voor een simpel PHP-script in zo'n slecht geoptimaliseerde oplossing als GD. Kun je de images niet openen op het moment dat je ze nodig hebt, daarna op het plaatje kopiëren en dan weer sluiten, en dàn pas de volgende iteratie van je loop in gaan? Mogelijk gaat het dan beter. :)

offtopic:
Je hebt je waarden comma separated in je database staan? Je weet hoop ik wel dat dat niet netjes is? Zo nee: zoek dan eens op wat normaliseren van databases inhoudt. :)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Hm.. misschien is dat wel het proberen waard, maar lijkt me erg raar als het al door 20 Kb op z'n bek kan gaan... maar ik zal het zo 's proberen :)

offtopic:
Ik heb de tiles per sector in een SET veld. Waarom zou dat niet netjes zijn? Het is tenminste een combinatie van tiles, en wat is de toegevoegde waarde van een cross-table (ben even de goede naam kwijt)?


[edit]
Je hebt het over slecht geoptimaliseerde GD, is er dan misschien een beter alternatief?

[edit2]
Ik gebruik nu onderstaande stuk in de loop, maar zelfde probleem...
PHP:
1
2
3
$tile = imagecreatefrompng( 'images/tiles/' . $tilePart . '.png' );
imagecopy( $map, $tile, ( $this->sectorSize['width'] * $sector['s_x'] ), ( $this->sectorSize['height'] * $sector['s_y'] ), 0, 0, $this->sectorSize['width'], $this->sectorSize['height'] );
imagedestroy( $tile );

[ Voor 44% gewijzigd door Verwijderd op 18-02-2006 10:54 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Hm...moet niet gekker worden...

Als ik $map naar een bestand (map.png) schrijf, en dus niet het script de png direct laat afbeelden, werk het gewoon prima?!

Erg leuk natuurlijk dat het werkt, maar ik wil gewoon dat het script direct een png uit spuugt. Iemand eniig idee hoe dit kan?

Acties:
  • 0 Henk 'm!

Verwijderd

Misschien heeft het weinig met je probleem te maken - ik weet het wel zeker - maar waarom sla je de uiteindelijk te genereren afbeelding op als een x-aantal tiles? Waarom sla je de afbeelding niet in één keer op? Ik hoop dat dit een praktische oorzaak heeft want om eerlijk te zijn kruipt bij mij een gevoel omhoog als `deze-constructie-kan-beter`. Maar nogmaals, dat heeft natuurlijk weinig met het rare probleem te maken, wat naar alle waarschijnlijkheid te maken heeft met het feit dat je inderdaad teveel images opent in je script, zoals -NMe- aangeeft.

Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 16:28
Verwijderd schreef op vrijdag 17 februari 2006 @ 22:50:
PHP:
15
16
header( 'Content-Length: ' . strlen( $map ) );
imagepng( $map );
Is het mogelijk dat het hier op stuk gaat? $map is geen string maar een resource ofzoiets; ik weet niet wat strlen() er mee doet maar het lijkt me niet dat het resultaat gelijk is aan de lengte van het plaatje dat volgt. Ik kan me voorstellen dat browsers het plaatje maar half inlezen als je een ongeldige Content-Length meegeeft, dus geef 'm ofwel helemaal niet mee of (beter) geef 'm de juiste lengte.

edit:
(Zie -NMe- voor juiste code. ;))

[ Voor 26% gewijzigd door Soultaker op 18-02-2006 13:47 ]


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Verwijderd schreef op zaterdag 18 februari 2006 @ 08:46:
Hm.. misschien is dat wel het proberen waard, maar lijkt me erg raar als het al door 20 Kb op z'n bek kan gaan... maar ik zal het zo 's proberen :)
Dat zijn geen 20KB. Als je over (bijvoorbeeld) PNG's praat, dan praat je over compressie met behulp van een palet. Om daarmee te kunnen werken moet GD ze eerst uitpakken naar een formaat waar het mee overweg kan; rauwe imagedata. Met imagecreatefrompng maak je dus geheugen aan voor zo'n ding, wat je voor een 24-bits afbeelding breedte x hoogte x 3 bytes kost. Elke afbeelding van 49x49 kost je dus zo'n 7KB aan geheugenruimte. Daarnaast heb je de grote afbeelding nog waar alles in komt te staan, en die is 147 x 343 (uitgaande van je beschrijving in je startpost), wat neerkomt op ~150KB.

Al met al nog niet genoeg om de geheugenlimiet van PHP te bereiken, maar ik heb nog nooit zoveel plaatjes open gehad met GD; wellicht dat daar ook gewoon een limiet aan zat, dus vandaar mijn opmerking. :)
offtopic:
Ik heb de tiles per sector in een SET veld. Waarom zou dat niet netjes zijn? Het is tenminste een combinatie van tiles, en wat is de toegevoegde waarde van een cross-table (ben even de goede naam kwijt)?
Kruistabel ja, of pivot table op zijn Engels. :P En met een set is het inderdaad nog wel redelijk netjes te doen, al was het misschien logischer om er toch die kruistabel van te maken. Maar zolang het een bewuste keuze is ben ik allang blij, de meeste mensen die hier voor zo'n oplossing kiezen doen het omdat ze niet beter weten. :P
[edit]
Je hebt het over slecht geoptimaliseerde GD, is er dan misschien een beter alternatief?
P&W FAQ - Image Manipulation in PHP ;)
[edit2]
Ik gebruik nu onderstaande stuk in de loop, maar zelfde probleem...
PHP:
1
2
3
$tile = imagecreatefrompng( 'images/tiles/' . $tilePart . '.png' );
imagecopy( $map, $tile, ( $this->sectorSize['width'] * $sector['s_x'] ), ( $this->sectorSize['height'] * $sector['s_y'] ), 0, 0, $this->sectorSize['width'], $this->sectorSize['height'] );
imagedestroy( $tile );
Hmm, het was een poging waard. :)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Soultaker schreef op zaterdag 18 februari 2006 @ 13:19:
PHP:
15
16
17
$data = imagepng($map);
header('Content-Length: '.strlen($data));
imagepng($data);
Dat kan niet werken. Imagepng print direct de image naar de gebruiker toe, dus je drukt nu twee keer wat af. En de tweede keer dat je imagepng aanroept doe je dat met een ongeldige parameter, want $data is geen image resource. Wat je wil kan natuurlijk wel met behulp van output buffering.
PHP:
15
16
17
18
ob_start();
imagepng($map);
header('Content-Length: '.strlen(ob_get_contents()));
ob_end_flush();

edit:
Ow, en imagepng returnt een boolean, en niet de data die afgedrukt wordt. :P

[ Voor 8% gewijzigd door NMe op 18-02-2006 13:35 ]

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 16:28
-NMe- schreef op zaterdag 18 februari 2006 @ 13:33:
Dat kan niet werken. Imagepng print direct de image naar de gebruiker toe, dus je drukt nu twee keer wat af.
Ah, tnx. Ik dacht er niet bij na. Overigens kun je i.p.v. strlen(ob_get_contents()) dan weer beter direct ob_get_size() gebruiken; dat scheelt weer een potentieel dure stringconstructie. ;)

[ Voor 48% gewijzigd door Soultaker op 18-02-2006 13:52 ]


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Ah, inderdaad. Niet bij stilgestaan. :)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
tnx @Soultaker & -NMe- _/-\o_

Ik zal ook 's kijken naar dat ImageMagick, maar ik denk dat ik toch bij GDlib blijf. Zoveel zware dingen ben ik nou ook weer niet van plan, en ik denk niet dat veel hosts ImageMagick ondersteunen?
Pagina: 1