Stránkování obrázku v ASP.NET
Tak přátelé jsem opět zde , dneska si uděláme malou blbůstku. Vytvoříme webovou stránku,
ktera bude stránkovat obrázek. Stránkování znamená, že máme větší
množství dat (třebas články, všemožné seznamy atp. ale i obrázek) a
tyto nemůžeme poslat celé do stránky, protože by to prohlížeč nebo
počítač nezvládl přechroustat. Budeme mít tedy větší obrázek řekněme
1600x1200 pixelů, ale může být třebas i mnohem větší např 20000x20000
bodů. Do stránky ale dorazí obrázek mnohem menších rozměrů např
300x300px. Jak na to?
Nejprve vyjděme z nějakého datového zdroje. Zde vyjdu z 24bitového obrázku rozměrů 1600x1200, který převedu do nepakované formy tak, že každý pixel je reprezentován třemi byty. Dostanu tak soubor velikosti 1600x1200x3 (složky{byty} red/green/blue) = dostávám soubor velikosti 5760000 B, kde celý obrázek je zaznamenán řádek po řádku. Tuto operaci mi umožní jakýkoliv kvalitní bitmapový program, nazvěme takto připravený soubor např. praha.rgb.
Nenechejme se zmást extrémní velikostí souboru, ta nám v ničem nevadí
(pouze soubor zabírá velké místo na disku , protože přístup ke
skutečnému aktuálnímu výřezu provedeme skokem v souboru na přesné místo
začátku řádků. Skoky v souborech jsou od pradávna běžně používané a
proto velmi rychlé. Celý program je pak sledem pár příkazů:
private void Page_Load(object sender, System.EventArgs e) { // odchytime vstupni souradnice int X = Int32.Parse(Request.QueryString.Get("x")); int Y = Int32.Parse(Request.QueryString.Get("y")); // do hlavicky odpovedi dosadime, ze se jedna o obrazek Response.ContentType = "image/jpeg"; String strBitmapFile = @"D:\Cesta\k\souboru\data\praha.rgb"; // originalni velikosti obrazku int OriginalWidth = 1600; int OriginalHeight = 1200; int Width = 300; int Height = 300; // aktualni levy horni roh vyrezu int SeekX = X; int SeekY = Y; // dochytani souradnic mimo obrazek <0 if (SeekX < 0) SeekX = 0; if (SeekY < 0) SeekY = 0; // totez, ale > jak rozmery obrazku if (SeekX > OriginalWidth - Width) SeekX = OriginalWidth - Width; if (SeekY > OriginalHeight - Height) SeekY = OriginalHeight - Height; FileStream fs = new FileStream(strBitmapFile, FileMode.Open, FileAccess.Read); byte[] bin = new byte[Width*Height*3]; // cyklujem celou vyskou obrazku for (int i=0; i<Height; i++) { // skocime na pozici, kde skutecne zacina radek fs.Seek((OriginalWidth*3)*(SeekY+i)+SeekX*3, SeekOrigin.Begin); fs.Read(bin, i*Width*3, Width*3); } fs.Close(); // Vytvor bitmapu System.Drawing.Bitmap Obr = new Bitmap(Width, Height, PixelFormat.Format24bppRgb); // vytvor bitmapu z dat (cyklujem celou mrizkou bodu) for(int i=0; i<Height; i++) for(int j=0; j<Width; j++) { Obr.SetPixel(j, i, Color.FromArgb(bin[(i*Height+j)*3+0], bin[(i*Height+j)*3+1], bin[(i*Height+j)*3+2])); } // pridame blbinku / informacni textik Graphics objGrafika = Graphics.FromImage(Obr); objGrafika.DrawString("by Michael – Hepbeg Club 2004", new Font("Arial", 8), Brushes.Black, 5.0f, 5.0f, StringFormat.GenericDefault); Obr.Save(Response.OutputStream, ImageFormat.Jpeg); }
Nejprve vezmeme jako vstup do stránky (z querystringu) souřadnice levého horního rohu. Do hlavičky HTTP odpovědi dáme, že výstupní stream je obrázek (Response.ContentType), dále deklarujem stringovou proměnnou určující umístění hlavního souboru. Deklarujeme také promenné určující velikosti zdroj. a cíl. obrázku. Následuje kontrola levého horního rohu (souřadnice, zda není mimo rozsah), zamezíme tím runtime chybu chybného skoku v souboru. Dále otevřeme soubor a deklarujeme pole bytů ve velikosti výsledného obrázku * 3 složky (red/green/blue). No a načítáme data do pole, přičemž si skáčeme vždy na pozici, kde je začátek řádku výsledného obrázku. Po načtení dat, zavřeme soubor, vytvoříme bitmapu (System.Drawing.Bitmap), a nakopírujeme data – pixel po pixelu do bitmapy. Přidáme informační text a výsledek naší práce uložíme, v našem případě do výstupního streamu ASPx stránky, ale můžeme i do souboru... Hlavní ovládací stránka ale bude obyčejná HTML stránka s IFRAME, kde budeme načítat obrázek. Na stránku dáme ještě 4 obrázky, pro směr posunu a jednoduchý klientský script, který bude občerstvovat IFRAME. Takto může vypadat JS:
<SCRIPT LANGUAGE="JavaScript"> // 2004 by Michael var intAktX = 870; var intAktY = 580; var cstPlus = 290; // pripocitaci / odecitaci promenna function fncNahoru() { intAktY -= cstPlus; fncOdesli(); } function fncDolu() { intAktY += cstPlus; fncOdesli(); } function fncDoleva() { intAktX -= cstPlus; fncOdesli(); } function fncDoprava() { intAktX += cstPlus; fncOdesli(); } function fncOdesli() { var elmCurr = document.getElementById('MyIFrame'); elmCurr.src = 'str_obr.aspx?x='+ intAktX + '&y=' + intAktY; } </SCRIPT>
Nepředpokládám valné použití stránkování obrázku (hlavně kvůli
velikosti zdrojového souboru , spíše popsaný postup lze bezproblému modifikovat a použít
např. pro hromadné rozesílání novoročních pozdravů speciálně
modifikované pro každého zákazníka (budou např. v databázi), může se
takto vytvářet on-line výstupní grafy (tuším že některé zde použité
objekty mají jíž nějaké metody na grafy např. koláčový zabudované),
různé statistiky apod. ve fantazii se meze nekladou, tak vše, příště
konečně začněme rozebírat 8 dam.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 319x (160.69 kB)
Aplikace je včetně zdrojových kódů v jazyce C#