Avatar billede jonas82 Nybegynder
26. januar 2010 - 19:15 Der er 26 kommentarer og
2 løsninger

Out of memory. Bitmaps

Hej,

Jeg prøver at loade nogen jpg filer (ca 800kb stykket) ind i memory. Mit problem er, at det bruger vildt meget hukommelse.

Jeg fremprovokerer dette ved at loade alle filer i en mappe (100 stk) ind i hukommelsen med nedenstående kode. Dette forøger ram-forbruget med ca 1100MB. Det er jo noget mere end forventet, da 0.8MB*100 = 80MB ;-)

Gemmes det ikke internt som jpg, men som bitmap? Hvad kan jeg gøre ved det?

var files = Directory.GetFiles(@"C:\Test", "*.jpg");
            var bitmaps = new List<Bitmap>();
            foreach (var file in files)
            {
                bitmaps.Add(new Bitmap(file));
            }
Avatar billede Syska Mester
26. januar 2010 - 19:49 #1
Prøvet:
Image newImage = Image.FromFile(file);

// ouT
Avatar billede jonas82 Nybegynder
26. januar 2010 - 20:19 #2
Tak for kommentaren. Har testet det nu og det giver desværre det samme resultat.

var bitmaps = new List<System.Drawing.Image>();
            foreach (var file in files)
            {
                System.Drawing.Image newImage = System.Drawing.Image.FromFile(file);
                bitmaps.Add(newImage);
            }
Avatar billede Syska Mester
26. januar 2010 - 21:03 #3
Men hvad er du det vil/skal med de billeder ?

Der er vist en PictureBox hvis du bare skal vise dem ...

// ouT
Avatar billede jonas82 Nybegynder
26. januar 2010 - 22:05 #4
Det er nogen billeder, som læses ind fra en database som byte[], for så at kunne vælge imellem dem..

Fx et 9MP billede fylder ca 1MB når det er i bytearrayet, men når jeg fylder det i et Bitmap, Eller Image objekt æder den ca 30MB RAM. Det fatter jeg ikke lige. Når jeg læser pænt mange ind er det lidt et problem.

Jeg kan desværre ikke sådan lige lave arkitekturen om, så de indlæses få ad gangen, selvom det selvfølgelig kan blive nødvendigt ;-(
Avatar billede Syska Mester
26. januar 2010 - 22:16 #5
Pas ...

Folk gør sådan her på nettet som jeg har kunne finde ...

public Image byteArrayToImage(byte[] byteArrayIn)
{
    MemoryStream ms = new MemoryStream(byteArrayIn);
    Image returnImage = Image.FromStream(ms);
    return returnImage;
}

Tror der skal nogen andre eksperter på banen ... da jeg normalt ikke selv leger så meget med billeder.

mvh
Avatar billede jonas82 Nybegynder
27. januar 2010 - 13:28 #6
Det er noget lignede jeg gør. Gir samme resultat.
Jeg hælder meget til, at den må holde det som bitmap internt, selvom den bliver fodret med et jpg.
Tak for dine kommentarer.
Avatar billede Slettet bruger
27. januar 2010 - 14:19 #7
Først og fremmest, lad nu være med at bruge var til alt! det er en virkelig dårlig måde at programmere på!...

At læse så mange billeder ind som bitmaps/images vil altid sluge en masse ram.

For at optimere det bedst muligt, skal du undgå at læse alle ind på én gang, tag evt ét af gangen. Er det nødvendigt at have alle billede data i hukommelsen så gem det som rene byte arrays, det bruger væsentligt mindre hukommelse.

Skal du så på et tidspunkt bruge det som bitmap/image så converter det til det runtime.

MemoryStream s = new MemoryStream("dit byte array");
Image img Image.FromStream(s);

Husk i dette tilfælde IKKE at dispose din stream.

Når du så er færdig med at bruge billdet/billederne så !HUSK! at kalde dispose på det, da det først der vil rydde dine ram (måske ikke med det samme, kald evt "GC.Collect();")
Avatar billede Syska Mester
27. januar 2010 - 14:49 #8
wb-freekill:
Har du overhovedet læst hans spørgsmål ... og de efterfølgende kommentare fra ham ?

I stedet for at han selv skal svare, kan jeg da gøre det ...
1. Der skal vælges mellem alle billeder ... så at vise 1 af gangen er jo ikke specielt optimalt.

2. De er allerede gem som byte[] i hans database ( måske ikke helt optimalt, men det er en anden sag )

3. Det lader ikke til at være et problem med at dispose eller at ram ikke bliver frigivet, men at vise samtlige billeder ... kan ske man vil have et bestemt ... ud af mange som måske ligner hinanden.

Hvorfor er det dårligt at bruge "var"? Det må du gerne kommentere lidt mere på. Jeg kan ikke se hvordan det kan være dårligt at bruge det på nogen som helst måde.
Avatar billede Slettet bruger
27. januar 2010 - 15:23 #9
Det er jo ikke interessant i hvilket format det ligger i, i databasen, så det er jo totalt irrelevant. Det handler om hvilket format han benytter i sin applikations kode.

Når man håndtere så mange billeder runtime skal man helst undgå at gemme det som bitmaps eller image objekter. Så vidt jeg kan se er det han gør.

Nu nævner jeg kun dispose, fordi det meget ofte glemmes når man leger med images.

Hvad angår var, så er var oprindeligt implementeret i C#/.net til ANONYME typer, f.eks når man leger med LINQ. Her er man oftes nød til at benytte var. Specielt når vi snakker LINQ to SQL.

En af grundene til at man ikke bør benytte var i alle tilfælde er, at du ikke ud fra din deklarering af dit objekt, med mindre det sker præcis hvor du arbejder i koden, kan se af hvilken type dit objekt/array er, da det jo af sagens natur er dynamisk. Nu snakker vi selvfølgelig ikke i debug mode. Var har aldrig været tiltænkt som en erstatning for type deklareringer, det skal udelukkende bruges til dynamiske objekter!

Forestil dig denne situation:

var Data = GetData();

Hvordan vil du vide hvilken type GetDate returnere uden at undersøge GetDate nærmere. Kode skrevet sådan er uhyggeligt dårlig etik, da det gør det væsentligt sværre at vedligeholde.
Avatar billede Slettet bruger
27. januar 2010 - 15:28 #10
Avatar billede Syska Mester
27. januar 2010 - 15:46 #11
Du har stadig ikke læst hans krav kan jeg høre ... så tror bare vi stopper her ...

Men hvis du laver en funktion der hedder GetData har du også et problem ... for hvad gør GetData?

Jeg kan godt se problemet hvis du angiver dine dine metoder klasse ... som ligner "var" ... og dine metoder er flere sider lange. Så du ikke hurtigt kan se det ...

Derfor har "var" stadig sin ret ....

Og så begyndte jeg at læse linket som giver mig 100% ret, så måske et dårligt link du fandt der ...

De siger man skal følge DRY ...

og taget fra den side du linket til:

[code]
I think it should be used in those situations where the type is clearly specified elsewhere in the same statement:

Dictionary<string, List<int>> myHashMap = new Dictionary<string, List<int>>();

is a pain to read. This could be replaced by the following with no loss of clarity:

var myHashMap = new Dictionary<string, List<int>>();
[/code]
Avatar billede Slettet bruger
27. januar 2010 - 16:07 #12
Igen, jeg svarede blot på dit spørgsmål, manden har nok for længst løst problemet...

Hvordan ud fra det links tekst (ikke kommentarer) konkludere at du har ret? i modsiger jo totalt hinanden:

"The ONLY valid use is when you are incapable of knowing the type, and the only instance where that can happen:

When accessing an ANONYMOUS type

Anonymous types have no compile-time identity, so var is the only option. It's the only reason why var was added...to support anonymous types."

For dem der ikke kan tyde det engelske sprog, så siger han altså at var KUN _BØR_ benyttes i tilfælde af ANONYME typer og at det er den eneste grund til at var blev introduceret i C#
Avatar billede Slettet bruger
27. januar 2010 - 16:10 #13
Det eksempel du kommer med, er jo også helt unikt, i og med at han blot deklarere et generisk objekt hvor typen selvfølgelig er åbenlys. Der er det selvfølgelig mere pratisk blot at skrive var, men det har aldrig været tiltænkt sådan og _bør_ derfor ikke benyttes.
Avatar billede Syska Mester
27. januar 2010 - 16:25 #14
Nej, og internettet var kun til militær brug, og sådan er der så mange ting ...

Hvorfor ikke bruge det hvor det giver mening ?

var image = new Image();
Er du i tvivl om hvad typen er her ?

var t = GetSomething();

Du er kun i tvivl om fordi navngivningen af metoden er utrolig ringe .... ligesom i dit egen eksemple med GetData().

Its there now ... and its great.
Avatar billede Slettet bruger
27. januar 2010 - 16:42 #15
Hehe.. jeg gætter på du er tidligere VB programmør med de udtalelser.

Hvad angår internettet, så blev man også klogere dengang, tænk over det.

Anyways, jeg tvivler på du har lyst til, i alle tilfælde, at kalde dine metoder det de returnere. Så bliver det i hvert fald i bedste Vietnam-kode kvantitet.

Nu ved jeg ikke hvad du laver til hverdag, om du er udvikler på større projekter. Men jeg kan i så fald garantere dig for at du med tiden vil møde kollegaer der vil bruge unødvendig tid på at omkode dine vars da det forringer vedligeholdelsen af koden.
Avatar billede Syska Mester
27. januar 2010 - 17:01 #16
Jeg kommer ikke fra VB ... hader VB, men mest pga deres syntax ... jeg skal nok selv bestemme når der skal en ny linje ind :-)

Ja, man blev klogere ... men der sker stadig at ting kan bruges andre steder.

Tror måske det hele ender lidt et sted om religion om det, some like ... some dont.

Er det ikke deres problem hvis de går ind i mine metoder og laver det om?
Avatar billede Slettet bruger
27. januar 2010 - 18:31 #17
Hehe, yes VB suckes :)

Det er altid religion, men det er ikke velset af mange, det skal man være opmærksom på.
Avatar billede Syska Mester
27. januar 2010 - 19:06 #18
Korrekt, det skal også bruges de rigtige steder.

var t = (byte)1;

overstående er jo vældig sjov :-)

// ouT
Avatar billede janus_007 Nybegynder
28. januar 2010 - 19:34 #19
hehe.. spændende diskussion.

Jeg begriber slet ikke at der stadig findes modstandere af 'var', det er da den største gave i mange år til udvikleren.

Der findes rigtigt mange gode argumenter for 'var', men nok den jeg mener er fedest er at det tvinger udvikleren til at navngive med et mere sigende navn + jeg gad da godt se de store nej-sigere sidde med Linq uden 'var' *GG*, eller de undgår måske også Linq *GG* og synes det er noget pjat at man kan nøjes med 3 linjer når det nu kan laves på 20 :)

Jeg kan se buzz også har nogle rigtigt gode argumenter for navngivning :)

Nu ved jeg ikke hvad du laver til hverdag, om du er udvikler på større projekter. Men jeg kan i så fald garantere dig for at du med tiden vil møde kollegaer der vil bruge unødvendig tid på at omkode dine vars da det forringer vedligeholdelsen af koden.
hmm... Det må være de samme udviklere som stadig sidder og synes Linq, Generisk og 'var' er noget pjat :)
De samme som ikke forstår brugen af generisk og bare synes de forvirrer :)

Ak ja... jeg kan blive ved med gode eksempler.

En ting jeg glæder mig fantastisk meget til er dynamics i C#4.0, det bliver skønt at man ikke skal deklarere returtyper og metodeparameters!
Avatar billede jonas82 Nybegynder
28. januar 2010 - 22:31 #20
Kan se flere kloge mennesker har fundet interesse for mit lille spørgsmål, måske ikke helt for det der er kernen i problemet, men tak alligevel :-)

Kernen er:
Kan jeg læse billeder (jpg) ind, og vise dem på skærmen, og kun bruge ca. den hukommelse, som jpg-dataen fylder. Dette er måske "fysisk umuligt"?


Hvis det ikke kan lade sig gøre må jeg overveje en løsning ala det du nævner:

"MemoryStream s = new MemoryStream("dit byte array");
Image img Image.FromStream(s);

Husk i dette tilfælde IKKE at dispose din stream.

Når du så er færdig med at bruge billdet/billederne så !HUSK! at kalde dispose på det, da det først der vil rydde dine ram (måske ikke med det samme, kald evt "GC.Collect();")"
Avatar billede janus_007 Nybegynder
28. januar 2010 - 23:22 #21
Det lyder lidt som om du sidder med en Winapplikation? Det er fint du læser alle, men for hver række ville jeg konvertere til et jpg og gemme på disken, brug evt. Environment.SpecialFolder til at placere dem.
Herefter burde det være muligt at præsentere dem korrekt i applikationen :)

En ting er ihvertfald sikkert, du skal ikke pumpe hukommelsen op med at holde så mange billeder, medmindre du er igang med at udvikle en photoshop-klon *S*
Avatar billede jonas82 Nybegynder
29. januar 2010 - 07:52 #22
Ja, det er en windows applikation. Skal vise billeder i et listview el.l., som brugeren skal kunne vælge imellem.

I listen er det ikke nødvendigt med så stor opløsning. Løsningen er måske så at loade små thumbnails ind i listen, og gemme de store billeder på disken til visning onclick el.l.

Det er ikke ligefrem photoshop2 ;-)
Avatar billede Slettet bruger
29. januar 2010 - 21:03 #23
Hej igen

Du vil vinde rigtig meget ved at loade dem som thumbnails.
Avatar billede janus_007 Nybegynder
30. januar 2010 - 12:59 #24
Er du kommet videre med sagen Jonas?
Som nævnt skal de kun streames igennem memory og dumpes til disken, hvordan du viser dem er jo blot en smagssag :)
Avatar billede jonas82 Nybegynder
04. februar 2010 - 18:03 #25
Tak til alle der har bidraget i tråden. Jeg vil dele pointene mellem dem af jer som svarer indenfor et par dage. Tak!

Jeg endte med at gemme flere størrelser af billederne, og så kun holde dem som byte[] i memory, og så kun lave et stort Bitmap ud af det aktuelt valgte. Det virker glimrende til formålet :-)
Avatar billede Syska Mester
04. februar 2010 - 22:20 #26
svar hvis der var noget af mit som var point værd.
Avatar billede jonas82 Nybegynder
06. februar 2010 - 00:15 #27
Du må gerne lægge et svar. Tak for hjælpen :-)
Avatar billede Syska Mester
06. februar 2010 - 01:05 #28
svar
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

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