5.21. Skala, vänd och beskär¶
De föregående underavsnitten arbetade alla på pixlar på samma positioner som de startade i. Transform-familjen ändrar på det. Skalning skickar varje indatapixel till en annan utdataposition, möjligen till flera utdatapositioner samtidigt (vid uppskalning) eller till en position som delas med flera andra indatapixlar (vid nedskalning). Vändning och rotation gör samma sak genom en annan avbildning. Beskärning behåller en rektangulär delmängd av indatapixlar och kasserar resten.
Bildmodulen exponerar den familjen genom tre metoder som delar de flesta av sina argument och det mesta av sitt beteende:
copy()– producera en kopia av bilden, eventuellt skalad, beskuren eller omorienterad.crop()– samma operation somcopy, men med förväntningen att applikationen ska plocka ut en delrektangel ur källan.scale()– samma igen, med förväntningen att applikationen ska ändra storlek på resultatet.
De tre delar samma argument och samma transformmaskineri; skillnaden är var resultatet hamnar som standard. copy() producerar en ny bild, medan crop() och scale() modifierar källan på plats.
5.21.2. Interpolation: AREA, BILINEAR, BICUBIC¶
När skalning skickar varje utdatapixel till en position som inte sammanfaller med någon enskild indatapixel måste metoden välja vilket värde som ska skrivas. Tre flaggor styr hur:
image.BILINEAR interpolerar mellan de fyra närmaste indatapixlarna viktade efter sitt avstånd från utdatapositionen. Resultatet är jämnare än närmaste granne, utan synliga taggar på diagonala linjer, men den extra aritmetiken kostar omkring fyra gånger så mycket som genomgången med närmaste granne. Det rätta valet för det mesta uppskalningsarbetet och för alla icke-heltaliga skalfaktorer.
image.BICUBIC interpolerar mellan de sexton närmaste indatapixlarna med hjälp av en kubisk kurva, vilket ger ännu jämnare resultat till priset av ännu mer aritmetik. Bästa kvalitet för de kostnadskänsliga applikationer som behöver det; sällan värt den extra beräkningen för live-bildrutor som IDE:n bara kommer att visa.
image.AREA beräknar medelvärdet av varje indatapixel som faller inom utdatapixelns yta – den rätta algoritmen för nedskalning. Bilinjär och bikubisk är interpolatorer: de uppskattar ett värde mellan källpixlar, vilket är vad uppskalning behöver, men vid nedskalning täcker varje utdatapixel många källpixlar och en interpolator läser bara de få närmaste – detaljerna den hoppar över kommer tillbaka som vikning. image.AREA vägar i stället in varje täckt pixel i medelvärdet.
Standardskalningsalgoritmen utan någon hint är närmaste granne, vilket är den billigaste och det rätta svaret när källan redan har destinationens pixelupplösning.
5.21.3. Orientering: vändningar och rotationer¶
Orienteringsflaggorna är en liten uppsättning booleska transformationer som komponeras fritt med varandra och med interpolationsflaggorna:
image.VFLIPvänder bilden vertikalt (toppen blir botten).image.HMIRRORspeglar den horisontellt (vänster blir höger).image.TRANSPOSEbyter plats på x- och y-axlarna (rader blir kolumner).
De flesta rotationer kommer från att komponera dessa tre. Modulen exponerar även namngivna genvägar:
image.ROTATE_90(=VFLIP | TRANSPOSE)image.ROTATE_180(=HMIRROR | VFLIP)image.ROTATE_270(=HMIRROR | TRANSPOSE)
I kod:
img.copy(hint=image.ROTATE_90, copy_to_fb=True)
5.21.4. Hantering av bildförhållande¶
När källans bildförhållande inte matchar rektangeln den ritas in i, avgör tre flaggor vad som ska göras med skillnaden:
image.SCALE_ASPECT_KEEP bevarar källans bildförhållande och letterboxar resultatet – källan skalas tills den får plats inuti destinationen, med tomma (noll) pixlar som fyller ut resten av destinationen. Det rätta valet när det är viktigare att hålla källan oförvrängd än att fylla hela utdatan.
image.SCALE_ASPECT_EXPAND bevarar källans bildförhållande och beskär den – källan skalas tills den fyller destinationen, med de delar som sträcker sig utanför destinationen bortklippta. Det rätta valet när det är viktigare att fylla hela utdatan än att se varje del av källan.
image.SCALE_ASPECT_IGNORE ignorerar bildförhållandet och sträcker ut källan så att den fyller destinationen, och accepterar vilken förvrängning det än medför. Det rätta valet när applikationen redan har tagit hänsyn till förvrängningen – när destinationens dimensioner i själva verket inte är en rektangel av samma scen, till exempel.
Standardvärdet (ingen bildförhållandeflagga satt) är detsamma som SCALE_ASPECT_IGNORE: sträck ut för att fylla. Applikationer som bryr sig om bildförhållande anger uttryckligen en av de tre.
5.21.5. När man ska välja vilken¶
De flesta storleksändringar använder scale() med ett par x_scale / y_scale och en interpolations-hint:
img.scale(x_scale=0.5, y_scale=0.5, hint=image.AREA)
De flesta rotationer använder samma anrop med hint=image.ROTATE_90 eller liknande.
Beskärning använder crop() med en icke-standard roi:
img.crop(roi=(40, 30, 200, 150))
När källan måste överleva operationen – att fånga en referensbildruta, att ta en miniatyrbild av en bildruta som är på väg att behandlas destruktivt – producerar copy() resultatet som en ny bild och lämnar källan orörd:
thumbnail = img.copy(x_scale=0.25, y_scale=0.25, hint=image.AREA)
Det standardbeteendet är den verkliga skillnaden bakom de tre namnen: scale och crop transformerar på plats, copy allokerar. Nyckelorden för resultatplacering överbryggar gapet: copy=True på scale eller crop allokerar resultatet som en separat heap-buffert i stället för att skriva över källan, och copy_to_fb=True på någon av de tre placerar det i bildbufferten för IDE-förhandsgranskningen.