Avatar billede idiotbarn Nybegynder
16. april 2006 - 12:22 Der er 27 kommentarer og
2 løsninger

Billedscript, meget tung for hukommelsen

Jeg har et script hvor man, med et div, vælger hvilken del af billedet man gerne vil have som thumbnail. Der er to knapper, en Preview og en Save. Scriptet virker fint, men er temmeligt hukommelsestung. Findes der mere elegante måder at lave nedenstående på (billedet findes på serveren):


System.Drawing.Image B = Bitmap.FromFile(ImagePath);
int PicWidth = B.Width;
int PicHeight = B.Height;
B.Dispose();

int MaxWidth = 500;
int MaxHeight = 600;

//regn en scale factor, så billedet vises pænt på siden:
double ScaleFactor = ImgTool.ImageScaler(MaxWidth,MaxHeight,PicWidth,PicHeight);


Det store billede, hvorpå man skal vælge en del, hentes med(koden er reduceret):

String FileName=Request.QueryString["FileName"].ToString();
int iWidth=int.Parse(Request.QueryString["w"].ToString());
int iHeight=int.Parse(Request.QueryString["h"].ToString());
}
           
System.Drawing.Image imgFullSize = System.Drawing.Image.FromFile(FileName);
Bitmap bmNew = new Bitmap(iWidth, iHeight);               
Graphics g = Graphics.FromImage(bmNew);

g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
           
g.DrawImage(imgFullSize, new Rectangle(0,0,iWidth, iHeight));
g.Dispose();
bmNew.Save(Response.OutputStream,System.Drawing.Imaging.ImageFormat.Jpeg);


Det lille billede, som hentes hver gang man trykker Preview, hentes med: (Offset er hvor på det store billede, og rx og ry er størrelsen af det)

int rx = int.Parse(Request.QueryString["Width"].ToString());
int ry = int.Parse(Request.QueryString["Height"].ToString());

int offx = int.Parse(Request.QueryString["Offsetx"].ToString());
int offy = int.Parse(Request.QueryString["Offsety"].ToString());
           
Scaler = double.Parse(Request.QueryString["Scaler"].ToString());

rx = int.Parse(Math.Ceiling(rx/Scaler).ToString());
ry = int.Parse(Math.Ceiling(ry/Scaler).ToString());
offx = int.Parse(Math.Ceiling(offx/Scaler).ToString());
offy = int.Parse(Math.Ceiling(offy/Scaler).ToString());

String FileName=Request.QueryString["FileName"].ToString();

System.Drawing.Image imgFullSize = System.Drawing.Image.FromFile(FileName);
Bitmap bmNew = new Bitmap(66, 66);               
Graphics g = Graphics.FromImage(bmNew);

g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

g.DrawImage(imgFullSize,new Rectangle(0,0,66,66),offx,offy,rx,ry, System.Drawing.GraphicsUnit.Pixel);
g.Dispose();       
bmNew.Save(Response.OutputStream,System.Drawing.Imaging.ImageFormat.Jpeg);



Det er selvfølgeligt muligt at sætte kvaliteten ned på billederne, men er der andet der kan optimeres? (hellere et lidt langsommere script, end en outOfMemory exception)
Avatar billede snepnet Nybegynder
16. april 2006 - 12:50 #1
hvor meget hukommelse bruger du på det, og hvad er størrelsen af de resulterende billeder?
mvh
Avatar billede idiotbarn Nybegynder
16. april 2006 - 12:53 #2
Jeg ved ikke hvor meget hukommelse der bliver brugt på det, og jeg har ikke styr på hvor store billeder folk ligger op. Jeg kan selvfølgeligt bare afvise billeder der er for store, for har et eksempel på en der uploadede noget der var omkring 4000x5000px (!!!)

Ideen er lidt at jeg gerne ville kunne håndtere så store billeder hvis folk mener det er det de skal ligge op. Om det så er at konvertere den til et mindre billede først, og så arbejde med det, er ikke så vigtigt...

Det vil vel heller ikke hjælpe noget at bruge threads?
Avatar billede snepnet Nybegynder
16. april 2006 - 13:24 #3
du må finde ud af hvad problemet er.... mit gæt ville være, at transporten af billederne til/fra klienten koster så mange gange mere tid, end den tid du bruger på serveren - så hvis du optimerer koden på serveren, vil det betyde meget lidt for brugeroplevelsen.
men men ... det ville nok være en god idé hvis du prøvede at finde ud af hvor meget tid du bruger på billedbehandlingen. du kan ganske hurtigt finde ud af det ved et trace.
hvis du vil finde ud af hvor meget memory du bruger - er det sikrest at benytte en profiler af en art.

eksempel på trace:
// hvis du er i en page/kotrol-klasse
Trace.Write("Starting imagemanipulation");

// andre steder fra
HttpContext.Current.Trace.Write("Starting imagemanipulation");

hvis du så slår trace til i din web.config - kan du gå ind på:
http://<server>/<site>/Trace.axd
og se resultatet.

du kan slå det til ved at sikre at du under <system.web> har sådan en her:
<trace enabled="true" pageOutput="false"/>

du kan også få outputtet på hver side, ved at sætte pageOutput="true", men hvis du positionerer dine kontroller absolut bliver det lidt vanskeligt at læse (du kan jo prøve det).

nå men ... du kan så skrive tracemeddelelser ud når rutinen starter, og når den er færdig... så kan du se om tiden der bruges der overhovedet er værd at bekymre sig om i forhold til resten.
trace.axd giver dig en fin præsentation af det, og du kan se nøjagtig hvor lang tid tingene tager mv.

mvh
Avatar billede idiotbarn Nybegynder
16. april 2006 - 13:46 #4
ok...det vil jeg lige prøve når jeg kommer hjem. Det sker jeg får en outofmemory exception, så den må vel ligge på serveren?
Avatar billede snepnet Nybegynder
16. april 2006 - 14:21 #5
en outofmem exception... det var voldsomt... hvor sker det helt præcist?
mvh
Avatar billede idiotbarn Nybegynder
16. april 2006 - 14:31 #6
Jeg prøver lige at genskabe den...det skal lige siges det var da der var en der prøvede med 4000x5000px billedet...så det er nok ikke så underlig, for det er jo et kæmpe billede...ville gerne ha at den bare tog længere tid end at komme med en mem exception...
Avatar billede idiotbarn Nybegynder
16. april 2006 - 14:39 #7
Min stacktrace siger:
at System.Drawing.Image.FromFile(String filename, Boolean useEmbeddedColorManagement)
at System.Drawing.Image.FromFile(String filename)

Jeg kan ikke få den til at lave fejlen når den køres lokalt. Men dette er også et billede der fylder 1,44mb (3691x4829).
Avatar billede snepnet Nybegynder
16. april 2006 - 15:49 #8
System.Drawing.Image.FromFile kan kaste OutOfMemoryException's hvis formatet ikke er ok.... det kan tænkes at det er sådan noget du løber ind i.
mvh
Avatar billede idiotbarn Nybegynder
16. april 2006 - 15:51 #9
hmm...men burde dne så ikke også gøre det lokalt?
Avatar billede snepnet Nybegynder
16. april 2006 - 15:56 #10
Fra docs:
OutOfMemoryException hvis:

The file does not have a valid image format.
-or-
GDI+ does not support the pixel format of the file.

jo - det ville jeg mene.... Kan der være et issue omkring at filen ikke er gemt endnu når du kalder den kode der fejlen?

mvh
Avatar billede idiotbarn Nybegynder
16. april 2006 - 16:00 #11
Muligvis, jeg uploader den lige inden, bare med httppostedfile :

_CurrentFile.SaveAs(_CompletePath+EvaluatedName);

kan man gøre andet end at sætte et delay på, for at være sikker?
Avatar billede snepnet Nybegynder
16. april 2006 - 16:02 #12
må jeg se lidt mere af koden du gemmer med?
mvh
Avatar billede snepnet Nybegynder
16. april 2006 - 16:02 #13
(jeg bliver nødt til at smutte nu... jeg er tilbage senere).
mvh
Avatar billede idiotbarn Nybegynder
16. april 2006 - 16:04 #14
Det er helt iorden. Koden er her:

public FileUploader(String CompletePath, System.Web.HttpPostedFile File)
{
_CompletePath=CompletePath;
_CurrentFile=File;
if(!System.IO.Directory.Exists(_CompletePath))
{
    System.IO.Directory.CreateDirectory(_CompletePath);
}
}
       
public String SaveUnique()
{
    String FullFilePath = _CurrentFile.FileName.ToString();
    String FileName = System.IO.Path.GetFileName(FullFilePath);
    FileName=FileName.Substring(0,FileName.LastIndexOf(".")).Replace("&","AND");
    String FileExt = System.IO.Path.GetExtension(FullFilePath);
    String EvaluatedName = FindName(_CompletePath,FileName,FileExt).Replace(" ","_");
    _CurrentFile.SaveAs(_CompletePath+EvaluatedName);
    return EvaluatedName;
}

private String FindName(String Path,String Name, String Extention)
{
    int i = 1;
    String NewName=Name;
    while(System.IO.File.Exists(Path+NewName+Extention))
    {
        NewName=Name+"("+i+")";
        i++;
    }   
    return NewName+Extention;
}
Avatar billede snepnet Nybegynder
16. april 2006 - 20:55 #15
hmm... kan ikke lige se at der skulle være ballade... når du får fejlen - kan du så åbne filen med et almindeligt billedkiggerprogram (altså åbne den fil der ligger på serveren).
mvh
Avatar billede idiotbarn Nybegynder
16. april 2006 - 22:38 #16
Ja...kan jeg godt. Billedet bliver fint uploaded. Men selvom jeg bruger det samme billede, er det lidt forskelligt hvornår fejlen kommer. Nogen gange kommer den når jeg lige har uploaded den, og andre gange kommer den når jeg skal til at hente gennem outputstream...jeg prøver at lege lidt med at trace, og se om jeg kan finde et mønster...
Avatar billede snepnet Nybegynder
16. april 2006 - 22:45 #17
ok ... du skriver bare hvis du finder ud af noget.
mvh
Avatar billede idiotbarn Nybegynder
16. april 2006 - 23:31 #18
Den står ihvertfald af når jeg henter størrelsen:

System.Drawing.Image B = Bitmap.FromFile(ArtistImagesPath+Name);
int PicWidth = B.Width;
int PicHeight = B.Height;
B.Dispose();

Er der andre måder? Jeg kikkede godt på den da jeg skrev den...det er lidt meget at hente hele billedet ind for at få størrelsen, men kender ikke andre metoder...
Avatar billede snepnet Nybegynder
16. april 2006 - 23:59 #19
er det for et bestemt billede eller? .... har du fundet et mønster af en art?
mvh
Avatar billede idiotbarn Nybegynder
17. april 2006 - 01:57 #20
Hmm...Det virker meget som om at det simpelthen er størrelsen af billedet der sætter grænsen. Men kan man gøre andet end at bruge nogen try/catch og så give brugeren besked om at det ikke kan lade sig gøre?

Når først billederne bliver over en hvis størrelse, bliver systemet ustabilt, så man må vel selv bare skulle sætte et loft...Med mindre du har andre ideer?
Avatar billede snepnet Nybegynder
17. april 2006 - 02:41 #21
der er en max-størrelse for den slags overførsler.... mener den er 4MB (så det kan den slags billeder jo hurtigt komme op på).
hvor store skal de være før det kikser?
mvh
Avatar billede idiotbarn Nybegynder
23. april 2006 - 11:50 #22
den kiksede ved 1,44mb...men det er lidt forskelligt
Avatar billede snepnet Nybegynder
23. april 2006 - 16:18 #23
cool ... så er det tid til at genindføre disketterne ;o)
Avatar billede idiotbarn Nybegynder
01. maj 2006 - 19:15 #24
Skulle vi dele points?
Avatar billede snepnet Nybegynder
01. maj 2006 - 19:19 #25
det kan vi godt hvis du synes jeg overhovedet har fortjent nogle.... hvordan går det med det ellers? - har du stadig problemer?
mvh
Avatar billede idiotbarn Nybegynder
01. maj 2006 - 19:24 #26
Jeg har ikke fået den til at tage over 1,44mb, og det er egentligt lidt noget pis, men jeg skal igang med at forsøge mig lidt frem igen. Som sagt er tiden den bruger på det ikke så vigtigt som at undgå en fejl...Jeg vil prøve at evt gemme et midlertidigt billede som er mindre og arbejde på det i stedet for...

Pointsne er lige så meget fordi der er blevet brugt tid på det.
Avatar billede snepnet Nybegynder
01. maj 2006 - 19:37 #27
så grænsen på 1,44 ligger altså fast?
mvh
(tak for point)
Avatar billede idiotbarn Nybegynder
01. maj 2006 - 19:37 #28
Nej...det har bare været lige deromkring generelt
Avatar billede snepnet Nybegynder
01. maj 2006 - 19:58 #29
ok
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester