Het .net framework is groot. Ontzettend groot zelfs. Toen ik net begon met het werken in .net gebeurde het regelmatig dat ik erg goede stukken code produceerde, alleen maar om er achter te komen dat die functionaliteit allang kant en klaar in de een of andere class beschikbaar was.
Uiteraard, na verloop van tijd kwamen die momenten steeds minder voor: ik begon mijn weg in het framework behoorlijk te kennen. Ik voelde me zeker, ik wist de weg, ik weet wat er allemaal beschikbaar is. En toch…
Gisteren gebeurde het weer. Een collega stelde mij de vraag waar hij moest kijken als hij plaatjes wilde verkleinen. Ik vertelde hem dat hij even in System.Drawing.Image moest gaan kijken, en begon met hem te vertellen hoe je daar met GDI+ plaatjes kunt beïnvloeden. En toen zag ik hem staan: de method GetThumbnailImage. Ik had daar nog nooit van gehoord, maar het doet precies wat we nodig hadden! Het framework deed het weer: mijn mooie voorbeeld code is totaal overbodig gemaakt door een kant en klare method waar ik het bestaan niet eens van wist!
Maar aangezien ik toch graag voorbeelden lever, laat ik hier zien wat je met die method kunt doen.
We kennen het probleem: we hebben veel foto’s, en die willen we op een webpage zetten. Die foto’s zijn groot en dus willen we een thumbnail pagina maken waarin we een overzicht van de beschikbare foto’s geven.
Nu kunnen we in PhotoShop of Acrylic de foto’s inladen en een verkleinde kopie opslaan in een aparte locatie opslaan. Op de thumbnails pagina laden we dan de kleine plaatjes in en die laten we linken naar de originele, grote foto’s.
Maar waarom zouden we het onszelf moeilijk maken? Waarom niet gewoon een repository met foto’s en dan de webapplicatie de thumbnails laten genereren? Dat was dus precies waar mijn collega naar op zoek was.
Om dat te bereiken maak ik een aparte pagina in mijn web applicatie, met de naam myImage.aspx. Dit is een aspx pagina die een plaatje teruggeeft. Dat heeft als gevolg dat je hem als ‘src’ kunt gebruiken in een <img> tag. De code is als volgt:
protected void Page_Load(object sender, EventArgs e)
{
// Haal het plaatje op
string fileName = Server.MapPath("image/test.jpg");
Image sourceImage = Image.FromFile( fileName );
// Nu even de nieuwe afmetingen berekenen
double percentage;
if( !double.TryParse( Request.QueryString[ "percentage" ], out percentage ))
{
// Ergens ging iets fout, we nemen als default 50%
percentage = 50;
}
// Bereken de nieuwe waardes
int imageHeight = (Int32)(sourceImage.Height * (percentage / 100));
int imageWidth = (Int32)(sourceImage.Width * ( percentage / 100 ));
// Stel de contenttype in als image/jpeg, zodat de aanroepende <img>
// tag er iets mee kan doen.
Response.ContentType = "image/jpeg";
// Creeer de nutteloze callback
Image.GetThumbnailImageAbort lCallBack = new Image.GetThumbnailImageAbort(this.ImageLoadAbort);
// Maak de thumbnail aan
Image thumbNail = sourceImage.GetThumbnailImage(imageWidth,
imageHeight,
lCallBack,
System.IntPtr.Zero);
// en stream deze naar de response zodat hij in de <img> terecht komt
thumbNail.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
// That's all!
}
// Dit is de callback van de GetThumbnailImage. Wordt niet gebruikt, is toch nodig...
private bool ImageLoadAbort( )
{
return true;
}
Je roept deze pagina aan door ergens in je pagina's de volgende regel op te nemen:
<img src="myImage.aspx?percentage=50" alt="Some image" />
En meer is er niet nodig!
Er zitten twee slimmigheidjes in deze code. Ten eerste maken we van de contenttype een ‘image/jpeg’. Dat houdt in dat de pagina dus geen standaard HTML teruggeeft, zoals gebruikelijk in een aspx, maar dat de inhoud een binair plaatje bevat.
Het tweede is het gebruik van de GetThumbnailImage method. Je geeft hem de afmetingen mee, je geeft hem het adres van een callback mee (die wordt niet gebruikt, maar is wel verplicht) en je geeft hem de data voor de callback mee (de callback wordt niet gebruikt dus de data kan IntPtr.Zero zijn). En dat plaatje streamen we naar de Response. Simpel, niet waar?
Het Framework blijft me verbazen….