PHP, MySQL, CSS, XHTML, JavaScript
26. May. 2007
PHP / MySQL
Jeg prøver egentlig å unngå det å skrive komplette koder her på bloggen min. Jeg har lyst til at andre skal lese og tenke over det jeg skriver, og dermed lære ting selv. Videre vil jeg også at bloggen skal være et sted der hvor jeg kan skrive forskjellige teknikker og metoder som jeg har erfart fungerer godt og kanskje andre kan videreutvikle de metodene.
Denne artikkelen nedenfor handler om hvordan du kan bruke GD til å utføre forskjellige bildemanipuleringer i PHP. Du må kunne belage deg på å få noen matematiske formler opp i fleisen, men det vil være ganske simpel matematikk, så tror det er overkommelig for de fleste parter.
Jeg kommer til å gjennomgå
Når man normalt skal lage et simpelt bilde med tekst, kan man bruke imagestring(). Der kan du også bruke en egendefinert font, med hjelp av imageloadfont(). Med imageloadfont() kan man ikke bruke TTF (True Type) font, og da er man i grunn like langt. Derfor må vi bruke en funksjon som heter imagettftext().
Syntaksen til imagettftext() ser slik ut:
På vanlige kordinatsystem/grafer i matematikken er det positive verdier på x-aksen til høyre og over x-aksen på y-aksen. Slik er det ikke i GD. Her er positive verdier på x-aksen til høyre, og y-aksen har positive verdier på under x-aksen. Det vil si at vi finner origo helt oppe til venstre. Dette er viktig å huske på når vi skal plassere forskjellige ting inne i bildet vi lager.
I manualen under imagettfbbox(), finner vi hvilke indekser som gjør hva i arrayen som blir returnert. De er det viktig å tenke seg godt om, på hva de vil gjøre.
Slik, nå er vi klare til å regne ut hvor høy teksten vil være, og hvor bred den vil være.
Om man er vandt med matematikk så vet man hva ∆ vil si. ∆ er delta, og betyr differanse. Nå skal vi finne ∆ mellom x-aksen, fra det hjørnet lengst fra origo, til det nærmest. Den kaller vi ∆x. Det samme er med y-aksen, hvor vi skal finne ∆y. ∆y er differansen mellom hjørnet lengst nede, og hjørnet lengst oppe (bunnpunkt og toppunkt). Så er det på tide vi bruker den logikken vi har. Hva skal trekkes fra?
Her er formlene
∆x = x₂- x₁
∆y = y₂- y₁
Det blir korrekt, siden y₂ er det siste vi måler, og ligger lengst unna. (Størst tall - minst tall).
Dette kan vi nå lage en funksjon ut av. Og jeg valgte å gjøre det slik:
Der returnerer vi bredden og høyden slik som vi vil ha det.
Og da kan vi bare bruke det til å sette inn i imagecreatetruecolor(). Vi vil også fylle bakgrunnen med en hvit farge. I RGB verdi så er hvit (255, 255, 255). Og det er den fargen jeg vil ha som bakgrunn. Derfor bruker jeg:
Hvor $im er resursbildet jeg lagde med imagecreatetruecolor(). Med det samme setter jeg også opp en farge til, som er svart. Svart har RGB verdien (0, 0, 0) og derfor blir det slik:
Nå har jeg kommet så langt at jeg har funnet ut bredden og høyden, lagd et bilde med de målene og satt to farger. Da ser kodene slik ut:
Men som jeg sa tidligere vil jeg gjerne ha en bakgrunn, og jeg må jo lage teksten.
For å lage bakgrunn bruker jeg imagefilledrectangle(), med samme kordinater basert ut fra origo som bildet er. Derfor blir det slik, etter koden ovenfor:
Jeg vil ha hvit som bakgrunn, og bruker derfor fargen jeg har satt ovenfor.
Da gjenstår det bare å skrive på teksten, og det å lage bildet selvfølgelig. Som nevnt tidligere bruker vi imagettftext() til å skrive på teksten. Og den bruker vi slik:
Grunnen til at jeg bruker $text_ratio['height'] som y-kordinat er at imagettftext() ikke baserer seg på "øverst til venstre" punktet slik som imagestring() gjør, men på bunnlinjen til teksten. Det vil si der de fleste bokstavene starter. Slik som nederste hjørnet til venstre på "M", men ikke nederste hjørnet på "g". Derfor er ikke denne artikkelen komplett, da du må finne bunnpunkt til slike bokstaver og ha det som høyde, men denne artikkelen er kun en innføring, så får du ta sluttstegene selv. Når du har lest igjennom alt dette burde du ha en idé på hva du skal gjøre.
Da er vi ferdig med å lage murene til bildet, og vi må lage det og lime sammen alle bitene. Jeg lager dette med imagepng(), uten å lagre det, bare å vise det. Derfor må jeg sette hvilken type dokumentet er med en header() funksjon. Til slutt frigjør jeg minne ved å brike imagedestroy().
Slutten vil altså bli slik:
Der vil man kunne skrive ut et bilde med valgfri tekst og TTF font med dynamisk bredde og høyde. Men husk det jeg sa, du må lage noe som tar hensyn til lave bokstaver som går under den typografiske grunnlinjen til bokstavene.
Nå skal jeg vise dere hvordan dere kan finne andre delen av sidene når dere kun oppgir en ønsket forminsket størrelse. Dette er til når dere skal resize bilder.
Om jeg sier at jeg vil ha et bilde som er 200 piksler bredt, og høyden skal følge på slik at AR blir fulgt (dvs aspect ratio). Proporsjonene blir ikke ødelagt med andre ord.
Da må jeg inn med matematikken min igjen. Vi må finne en faktor som vi kan gange den andre siden med for at den skal følge på. Den enkleste måten, syns jeg, er å finne hvor mye prosent vi forminsker med, og gange den andre med det for at den skal følge på. Så la oss si at jeg forminsker et bilde på 1000 piksler i bredden til 100 piksler i bredden. Det vil da si at den er 10 % av bredden. Og om jeg ganger høyden med 10 % da, vil den beholde proporsjonene.
Formel for å finne ut prosent er slik:
% = 1 - ((gammel_størrelse - ny_størrelse) / gammel_størrelse)
Jeg finner gammel størrelse på bildet, ved å bruke getimagesize.
Slik at jeg kan lage en funksjon som ser slik ut:
Der har du de komplette kodene. Jeg finner de gamle dimensjonene, sjekker hvilken av bredde og høyde som er satt av de nye dimensjonene, og fyller ut den som er tom. Formelen blir brukt til utregningen.
Verre en det er det faktisk ikke. Jeg kommer ikke til å forklare dypere en dette, for det er ikke mye mer å forklare, men mest fordi jeg har nå skrevet ganske lenge og er ganske lei av å skrive.
Da har vi det. Hvordan du kan lage tekst med dynamiske dimensjoner, og hvordan du kan regne ut andre dimensjonen ved resizing og holde AR slik den skal være.
Om det er noe oppslutning i denne artikkelen, kan jeg skrive en til, om hvordan jeg kan få watermark på bilder jeg laster opp.
Innlegget ble postet 26.05.07 19:00 og ligger under kategorien PHP / MySQL. Du kan abonnere på kommentarene ved å bruke RSS 2.0 feed. Du kan legge til kommenter, eller trackback fra din blogg/side.
Denn skal prøves :)
Anders Moen skrev dette 3 Juni, 2007 12:15 - Sitér
Jeg har laget et script som generer et bilde med titlene til de tre siste postene i bloggen min, til bruk på forumer etc. Jeg bruker imagecreatetruecolor og imagettftext med en TrueType-font, men teksten blir svært hakkete (dog antialiased). Har du noen løsning på det?
Du kan se hva jeg mener her:
http://www.ronny-andre.no/sistepost.php
Ronny-André skrev dette 11 August, 2007 15:37 - Sitér
Har du løst dette? Bildet ser helt fint ut med meg, og er ikke hakkete i det heletatt.
Mikael Brevik skrev dette 11 August, 2007 17:41 - Sitér
Ja, eller "løst" da. Jeg prøvde meg med fonten Helvetica Neue, og da ble den veldig rar. Men jeg prøvde med Verdana i stedet, og da så den mye bedre ut, men jeg er ikke heelt fornøyd. Den ser litt "crisp" ut, hvis du skjønner?
Ronny-André skrev dette 11 August, 2007 18:00 - Sitér
Ser veldig smooth ut med meg nå. Kan ikke se noen form for crisp. Grunnen til at du opplevde det tidligere kan være font i forhold til fontstørrelse, eller lignende.
Jeg måtte nesten ha sett på kodene du bruker, for å anslå hvor feilen ligger.
Mikael Brevik skrev dette 13 August, 2007 21:23 - Sitér