Question

Je suis en train d'écrire une image légère application de visualisation. Cependant, il y a des limites de la mémoire du système avec .NET.

Lorsque vous essayez de charger de grandes bitmaps ( 9000 x 9000 px ou plus, 24 bits), je reçois un System.OutOfMemoryException. Ceci est sur un PC Windows 2000 avec 2 Go de RAM (dont 1,3 Go est épuisé). Il faut aussi beaucoup de temps pour tenter de charger les fichiers.

Le code suivant génère cette erreur:

Image image = new Bitmap(filename);
using (Graphics gfx = this.CreateGraphics())
{
    gfx.DrawImage(image, new Point(0, 0));
}

En fait ce code:

Stream stream = (Stream)File.OpenRead(filename);
Image image = Image.FromStream(stream, false, false);
using (Graphics gfx = this.CreateGraphics())
{
    gfx.DrawImage(image, new Rectangle(0, 0, 100, 100), 4000, 4000, 100, 100, GraphicsUnit.Pixel);
}

En outre, il suffit de faire ceci:

Bitmap bitmap = new Bitmap(filename);
IntPtr handle = bitmap.GetHbitmap();

Le dernier code a été conçu pour être utilisé avec GDI. Lors de mes recherches, je trouve que cela est en fait un problème de mémoire où .NET tente d'allouer deux fois plus que nécessaire dans un seul bloc Contigous de mémoire.

http://bytes.com/groups/net-c/ bitmaps-grand-279493-dessin

Je sais que d'autres applications (Internet Explorer, MS Paint, etc.) qu'il est possible d'ouvrir de grandes images, et assez rapidement. Ma question est, Comment puis-je utiliser un grand bitmaps avec .NET?

Y at-il de toute façon de les diffuser, ou non-mémoire de les charger?

Était-ce utile?

La solution

Ceci est une question en deux parties. La première question est de savoir comment vous pouvez charger de grandes images sans manquer de mémoire (1), le second est sur l'amélioration des performances de chargement (2).

(1) concider une application comme Photoshop où vous avez la possibilité de travailler avec d'énormes images sur la consommation Gigabites le système de fichiers. Garder l'image entière en mémoire et ont encore suffisamment de mémoire pour effectuer des opérations (filtres, traitement d'images et ainsi de suite, ou même simplement en ajoutant des couches) serait impossible sur la plupart des systèmes (même les systèmes x64 8gb).

C'est pourquoi des applications telles que celui-ci utilise le concept de fichiers d'échange. En interne Je suppose que Photoshop utilise un format de fichier propriétaire, adapté à leur conception d'applications et construit pour supporter des charges partielles du swap, leur permettant de charger des parties d'un fichier dans la mémoire à traiter.

(2) peut être améliorée performance de la société (beaucoup) en écrivant des chargeurs sur mesure pour chaque format de fichier. Cela vous oblige à lire sur les en-têtes de fichier et la structure des formats de fichiers que vous souhaitez travailler. Une fois que vous avez obtenu la main de celui-ci son pas **** **** que dur, mais ce n'est pas aussi trivial que faire un appel de méthode.

Par exemple, vous pouvez google pour FastBitmap voir des exemples sur la façon dont vous pouvez charger une image bitmap (BMP) fichier très rapide, il a inclus décoder l'en-tête bitmap. Cela impliquait Pinvoke et de vous donner une idée sur ce que vous êtes contre, vous devrez définir les structues bitmap tels que

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public struct BITMAPFILEHEADER
        {
            public Int16 bfType;
            public Int32 bfSize;
            public Int16 bfReserved1;
            public Int16 bfReserved2;
            public Int32 bfOffBits;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct BITMAPINFO
        {
            public BITMAPINFOHEADER bmiHeader;
            public RGBQUAD bmiColors;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct BITMAPINFOHEADER
        {
            public uint biSize;
            public int biWidth;
            public int biHeight;
            public ushort biPlanes;
            public ushort biBitCount;
            public BitmapCompression biCompression;
            public uint biSizeImage;
            public int biXPelsPerMeter;
            public int biYPelsPerMeter;
            public uint biClrUsed;
            public uint biClrImportant;
        }

Peut-être travailler avec la création d'un DIB ( http://www.herdsoft.com/ti /davincie/imex3j8i.htm ) et bizarreries telles que les données stockées « à l'envers » dans un bitmap que vous devez prendre en compte ou vous verrez une image miroir quand u l'ouvrir: -)

Maintenant que juste pour bitmaps. Disons que vous vouliez faire alors PNG que vous aurez besoin de faire des choses similaires, mais décoder l'en-tête de PNG, qui, dans sa forme la plus simple isnt que dur, mais si vous voulez obtenir un support complet spécification PNG, alors vous êtes un tour amusant: - )

PNG est différent de dire un bitmap, car il utilise un format à base de morceau où il a « têtes », vous pouvez loacate pour trouver les données diffrent. Exemple de quelques morceaux que j'ai utilisé tout en jouant avec le format était

    string[] chunks =  
new string[] {"?PNG", "IHDR","PLTE","IDAT","IEND","tRNS",
"cHRM","gAMA","iCCP","sBIT","sRGB","tEXt","zTXt","iTXt",
"bKGD","hIST","pHYs","sPLT","tIME"};

Vous allez aussi devoir apprendre Adler32 checksums pour les fichiers PNG. Donc, chaque format de fichier que vous voulez faire serait d'ajouter un ensemble de défis différents.

Je souhaite vraiment que je pourrais donner d'autres exemples complets de code source dans ma réponse, mais c'est un sujet complexe, et pour être honnête, je ne l'ai pas mis en place un échange moi-même donc je ne serais pas en mesure de donner trop de conseils solides sur ce .

La réponse courte est que le traitement d'image cababilities dans la BCL est pas chaud. La réponse moyenne serait d'essayer de trouver si quelqu'un a écrit une bibliothèque d'images qui pourraient vous aider et la longue réponse serait de tirer vers le haut vos manches et écrire le noyau de votre demande vous-même.

Puisque vous me connaissez dans la vraie vie, vous savez où me trouver;)

Autres conseils

Pour une réponse vraiment complète, je voudrais utiliser réflecteur pour regarder le code source de Paint.NET ( http: / /www.getpaint.net/ ); un programme d'édition graphique avancé écrit en C #.

(comme indiqué dans le commentaire, Paint.NET utilisé pour être open source, mais est maintenant la source fermée).

Qu'en est-il:

Image image = new Bitmap(filename);
using (Graphics gfx = Graphics.FromImage(image))
{    
// Stuff
}

juste une solution rapide, j'ai eu le même problème, je créé une deuxième instance de bitmap et passé le bitmap dans le constructeur.

Pouvez-vous créer un nouveau, blanc, bitmap des mêmes dimensions et la profondeur de couleur? Si tel est le cas, vous savez au moins que votre environnement peut gérer l'image. Ensuite, le problème réside dans le sous-système de chargement d'image, comme bien sûr votre lien indiqué pourrait être le cas.

Je suppose que vous pouvez écrire vos propres chargeurs bitmap, mais qui est beaucoup de travail pour les formats non triviales, donc je ne dirais pas qu'il.

Peut-être il y a des bibliothèques de remplacement disponibles que le travail autour de ces questions avec les chargeurs standards?

Vous dites que ce n'est pas le chargement du bitmap, mais le rendu qui provoque une sortie de la mémoire?

Si oui, pouvez-vous utiliser Bitmap.LockBits pour obtenir Ahold des pixels et d'écrire une image de base vous Resizer?

Une chose m'a frappé. Dessines-tu l'image entière et non seulement la partie visible? Vous ne devriez pas tirer une plus grande partie de l'image que vous montrez dans votre application, utilisez les x, y, largeur et paramètres Hauteur Jambe pour limiter la zone sélectionnée.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top