myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Gemeinschaft » .NET-Komponenten und C#-Snippets » Bitmap-Manipulation (MemBitmap)
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

Bitmap-Manipulation (MemBitmap)

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
zommi zommi ist männlich
myCSharp.de-Mitglied

avatar-2617.png


Dabei seit: 14.11.2007
Beiträge: 1.361
Entwicklungsumgebung: VS 2005+2010
Herkunft: Berlin


zommi ist offline

Bitmap-Manipulation (MemBitmap)

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Beschreibung:
Eine (weitere) Bitmap-Klasse zur schnellen Manipulation von Bildern.

Einleitung:
Seit längerem arbeite ich unter C++ im Bereich Bildverarbeitung. Dass da meistens alles "unsafe" abläuft, wird wahrscheinlich den meisten klar sein.
Dass sich aber andererseite managed/safe/C#-Code und Geschwindigkeit nicht immer ausschließt, hat bereits  GetPixel und SetPixel um Längen geschlagen. 800 mal schneller gezeigt.
Und da ich momentan versuche vieles auf das viel schönere großes Grinsen C# umzustellen, stell ich hier mal einen Teil - genauer gesagt die MemBitmap-Klasse online.

Da die herangehensweise eine ganz andere ist als bei der RoBitmap/FastBitmap-Klasse, ist dies mehr als spezielle Ergänzung zu sehen. Zumal meine Herangehensweise auch nicht mit dem CompactFramework funktioniert.

Implementierung:
Soweit so gut: Nun zu den Details:
Der "Trick" ist ein spezieller Konstruktor von Bitmap, der Bereits einen Speicherbereich übergeben bekommt.
Und was bringt uns das?
  • Zugriff auf die Bitmap-Bits über byte-Array (kein unsafe)
  • Erzeugung eines "echten" Bitmaps, dass die selben Bits verwendet
  • schneller Zugriff über Array-Index, Klass-Indexer, Get/SetPixel
  • Natives Laden von bmp-Dateien
"schnell" bedeutet oben, dass (dank dem guten CLR-JITter) der Zugriff über das Array genauso schnell ist, wie ein unsafe-Code mit Zeigern.

Meine groben Messungen ergaben:
(GDI+)-GetPixel: 1x
MemBitmap.GetPixel: 30x
MemBitmap[x,y,c]-Indexer: 100x
MemBitmap.Data[index]: 1000x

(Also für jeden was dabei Augenzwinkern )


Zukunft:
Die Unterstützung für die anderen PixelFormate (8BitIndexed, ...) sollen noch folgen.
(Momentan geht ja eigentlich nur 24Bit richtig)
sowie die native Unterstützung von GIF,PNG und JPEG-Dateien (dann auch JPEG2000). Und natürlich eine Speicherfunktion.

Insgesamt soll es also auch möglich sein, Bilder zu laden, zu manipulieren und wieder abzuspeichern ohne Überhaupt ein System.Drawing.Bitmap zu verwenden. (was Overhead bedeuten würde)

Code:

C#-Code:
public class MemBitmap : IDisposable
{
    #region private Fields

        private int height;
        private int width;
        private int channels;

        private System.Drawing.Imaging.PixelFormat pixelformat;

        private byte[] data;
        private int stride;

        private System.Runtime.InteropServices.GCHandle dataHandle;
        private System.Drawing.Bitmap bitmap;

    #endregion

    #region public Properties

        public int Width { get { return width; } }
        public int Height { get { return height; } }
        public int Channels { get { return channels; } }

        public System.Drawing.Imaging.PixelFormat PixelFormat { get { return pixelformat; } }

        public byte[] Data { get { return data; } }
        public IntPtr DataPtr { get { return dataHandle.AddrOfPinnedObject(); } }

    #endregion

    #region Bitmap Compatibility

        public System.Drawing.Bitmap Bitmap
        {
            get
            {
                createBitmap();
                return bitmap;
            }
        }


        private void createBitmap()
        {
            if (bitmap == null)
            {
                //Bitmap erzeugen, die auf die selben Bit-Daten verweist
                bitmap = new System.Drawing.Bitmap(width, height, stride, pixelformat, dataHandle.AddrOfPinnedObject());
            }
        }

    #endregion

    #region Pixel Access

        public byte this[int x, int y, int channel]
        {
            get { return data[y * stride + x * channels + channel]; }
            set { data[y * stride + x * channels + channel] = value; }
        }

        public System.Drawing.Color GetPixel(int x, int y)
        {
            int index = y*stride + x*channels;

            switch(pixelformat)
            {
                case System.Drawing.Imaging.PixelFormat.Format24bppRgb:
                    return System.Drawing.Color.FromArgb(data[index + 2], data[index + 1], data[index + 0]);
                default:
                    throw new NotSupportedException();
            }
        }

        public void SetPixel(int x, int y, System.Drawing.Color value)
        {
            int index = y * stride + x * channels;

            switch (pixelformat)
            {
                case System.Drawing.Imaging.PixelFormat.Format24bppRgb:
                    data[index + 0] = value.B;
                    data[index + 1] = value.G;
                    data[index + 2] = value.R;
                    break;
                default:
                    throw new NotSupportedException();
            }
        }

    #endregion

    #region Initialization

        private void loadBitmap(string fileName)
    {
        System.IO.FileStream fs = null;
        try
        {
            //Dateistrom öffnen
            fs = new System.IO.FileStream(fileName, System.IO.FileMode.Open);

            //Zwischenspeicher anlegen
            byte[] tempMem = new byte[4];

            //Dateiheader einlesen
            uint    fileLength = 0;
            uint    imageDataOffset = 0;
            {

                //ersten beiden zeichen("BM")
                fs.Read(tempMem, 0, 2);
                if (tempMem[0] != 'B' || tempMem[1] != 'M')
                    throw new NotSupportedException("Unsupported Imagetype!");

                //Dateilänge
                fs.Read(tempMem, 0, 4);
                fileLength = BitConverter.ToUInt32(tempMem, 0);

                //reservierte Bits
                fs.Read(tempMem, 0, 4);

                //Offset der Bilddaten
                fs.Read(tempMem, 0, 4);
                imageDataOffset = BitConverter.ToUInt32(tempMem, 0);
            }

            //Bitmapheader einlesen
            uint    biHeaderSize = 0;
            int     biWidth = 0;
            int     biHeight = 0;
            ushort  biPlanes = 0;
            ushort  biBitCount = 0;
            uint    biCompression = 0;
            uint    biSizeImage = 0;
            int     biXPelsPerMeter = 0;
            int     biYPelsPerMeter = 0;
            uint    biClrUsed = 0;
            uint    biClrImportant = 0;
            {

                //Größe des BitmapHeaders
                fs.Read(tempMem, 0, 4);
                biHeaderSize = BitConverter.ToUInt32(tempMem, 0);

                //Breite
                fs.Read(tempMem, 0, 4);
                biWidth = BitConverter.ToInt32(tempMem, 0);

                //Höhe
                fs.Read(tempMem, 0, 4);
                biHeight = BitConverter.ToInt32(tempMem, 0);

                //Ebenen
                fs.Read(tempMem, 0, 2);
                biPlanes = BitConverter.ToUInt16(tempMem, 0);

                //BitsPerPixel
                fs.Read(tempMem, 0, 2);
                biBitCount = BitConverter.ToUInt16(tempMem, 0);

                //Kompression
                fs.Read(tempMem, 0, 4);
                biCompression = BitConverter.ToUInt32(tempMem, 0);

                //Byte-größe der Bilddaten
                fs.Read(tempMem, 0, 4);
                biSizeImage = BitConverter.ToUInt32(tempMem, 0);

                //Horizontale Auflösung
                fs.Read(tempMem, 0, 4);
                biXPelsPerMeter = BitConverter.ToInt32(tempMem, 0);

                //Vertikale Auflösung
                fs.Read(tempMem, 0, 4);
                biYPelsPerMeter = BitConverter.ToInt32(tempMem, 0);

                //Anzahl indizierter Farben
                fs.Read(tempMem, 0, 4);
                biClrUsed = BitConverter.ToUInt32(tempMem, 0);

                //Anzahl der zum darstellen benötigten indizierten Farben
                fs.Read(tempMem, 0, 4);
                biClrImportant = BitConverter.ToUInt32(tempMem, 0);
            }


            System.Drawing.Imaging.PixelFormat pf;
            switch (biBitCount)
            {
                case 24:
                    pf = System.Drawing.Imaging.PixelFormat.Format24bppRgb;
                    break;
                default:
                    throw new NotSupportedException();
            }

            init(biWidth, biHeight, pf);

            if (biHeight < 0) //Bilddaten einlesen, wie sie kommen
            {
                fs.Read(this.data, 0, this.data.Length);
            }
            else //Bilddaten in umgekehrter Zeilenreihenfolge einlesen
            {
                for (int y = this.Height-1; y >= 0; y--)
                {
                    fs.Read(this.data, y * this.stride, this.stride);
                }
            }



        }
        finally
        {
            if (fs != null)
            {
                fs.Close();
            }
        }
    }

        private void init(int initWidth, int initHeight, System.Drawing.Imaging.PixelFormat initPixelFormat)
        {
            if (initWidth <= 0 || initHeight <= 0)
                throw new ArgumentOutOfRangeException("Negative Width or Height!");

            width = initWidth;
            height = initHeight;

            pixelformat = System.Drawing.Imaging.PixelFormat.Undefined;
            if (    initPixelFormat == System.Drawing.Imaging.PixelFormat.Format24bppRgb
                ||  initPixelFormat == System.Drawing.Imaging.PixelFormat.Format32bppArgb)
                pixelformat = initPixelFormat;
            else
                throw new ArgumentOutOfRangeException("PixelFormat not supported!");


            switch (pixelformat)
            {
                case System.Drawing.Imaging.PixelFormat.Format24bppRgb:
                    channels = 3;
                    break;
                case System.Drawing.Imaging.PixelFormat.Format32bppArgb:
                    channels = 4;
                    break;
                default:
                    throw new InvalidOperationException();
            }

            stride = (channels * width);
            int rest = stride % 4;
            if (rest != 0)
                stride += (4 - rest);

            data = new byte[stride * height];
            dataHandle = System.Runtime.InteropServices.GCHandle.Alloc(data, System.Runtime.InteropServices.GCHandleType.Pinned);
        }

        private void init(System.Drawing.Bitmap b)
        {
            init(b.Width, b.Height, b.PixelFormat);
            System.Drawing.Imaging.BitmapData bd = b.LockBits(new System.Drawing.Rectangle(0, 0, b.Width, b.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, b.PixelFormat);
            System.Runtime.InteropServices.Marshal.Copy(bd.Scan0, data, 0, data.Length);
            b.UnlockBits(bd);
        }

    #endregion

    #region Constructors


        public MemBitmap(int initWidth, int initHeight, System.Drawing.Imaging.PixelFormat initPixelFormat)
        {
            init(initWidth, initHeight, initPixelFormat);
        }

        public MemBitmap(System.Drawing.Bitmap b)
        {
            init(b);
        }


        public MemBitmap(string fileName)
        {
            if (fileName.EndsWith(".bmp"))
            {
                try
                {
                    loadBitmap(fileName);
                    return;
                }
                catch { }
            }

            System.Drawing.Bitmap b = new System.Drawing.Bitmap(fileName);
            init(b);
            b.Dispose();
        }

    #endregion

    #region Destruction

        public void Dispose()
        {
            if (bitmap != null)
            {
                bitmap.Dispose();
            }
            if (dataHandle != null)
            {
                dataHandle.Free();
            }
            data = null;
        }

    #endregion

}

beste Grüße
zommi

Schlagwörter: <Bitmap, GetPixel, SetPixel, LockBits, Bildverarbeitung>

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von zommi am 08.06.2011 12:00.

10.08.2008 22:30 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
JAck30lena JAck30lena ist männlich
myCSharp.de-Team

avatar-2653.jpg


Dabei seit: 01.10.2006
Beiträge: 11.397
Entwicklungsumgebung: Visual Studio 05/08/10 Prof.


JAck30lena ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

vielen dank für die klasse. sowas habe ich echt vermisst.

wäre es eigendlich sinnvoll die klasse als nicht serialisierbar zu kennzeichnen? immerhin ist das bitmap im heap gepinnt und der addressbasierte zugriff wäre eigendlich bei einem deserialisiertem objekt nicht mehr gültig, außer man implementiert ISeralisable und IDeserializationCallback.

weiters möchte ich hier erwähnen, das eben weil es gepinnt ist, es vorkommen kann (z.b. bei vielen kleinen bildern, die man mit der klasse lädt), das der heap fragmentiert. man erkauft sich eben diesen performancegewinn....

ist in zukunft ein .Save(...) geplant, ohne das man auf die framework-bitmap-klasse ausweichen muss, da das nicht nur ressourcen frisst, sondern auch performance und code-aufwand bedeutet?

und noch etwas kleineres. MarshalByRefObject erben?^^ das wär noch cool. so wäre der weg frei für remoting.

macht es sinn das ImmutableObject(true) attribut zu setzten? (hier bin ich mir nicht ganz sicher ... ist das jetzt ein rein designerrelevantes attribut oder hat es noch mehr zu bedeuten?)


nochmals vielen vielen lieben dank für diese klasse. ein addressbasiertes und vor allem schnelles editieren einer bitmap ist etwas, was das framework echt vermisst.


[offtopic]
ach ja:

C#-Code:
default:
                    throw new NotSupportedException();

da sagt microsoft: exception by default is not a good style.

aber das nur am rande.
[/offtopic]
11.08.2008 09:09 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
zommi zommi ist männlich
myCSharp.de-Mitglied

avatar-2617.png


Dabei seit: 14.11.2007
Beiträge: 1.361
Entwicklungsumgebung: VS 2005+2010
Herkunft: Berlin

Themenstarter Thema begonnen von zommi

zommi ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hi,

Zitat von JAck30lena:
vielen dank für die klasse.

Bitte bitte smile

Zitat von JAck30lena:
nicht serialisierbar zu kennzeichnen?

Mhh. klingt sinnvoll. Oder aber man verwendet wirklich ISerialisable und updatet es dann entsprechend.
Man müsste dann nur das zugehörige Bitmap disposen und verwerfen/neu erstellen. Ich glaube nicht, dass man dort (safe) den internen Zeiger so einfach umbiegen kann.
(Also per Reflection wärs möglich, ist ja "nur" ein privates Feld. Aber sollte man Bitmap wirklich die Privatsphäre nehmen? Augenzwinkern )

Zitat von JAck30lena:
heap fragmentiert

Man könnte das Pinnen ja auch lazy machen.
Da man die feste Position ja erst brauche, wenn jemand das Bitmap Objekt haben will.
(Später solls ja so sein, dass man dies nur will, wenn man das MemBitmap anzeigen will. Und dann könnte man ja ein allgemeines Anzeige-MemBitmap verwenden und dann das auszugeben Bild da kurz reinkopieren. Dann hat man viele unpinned MemBitmaps und ein MemBitmap (gepinned) mit Bitmap)
Aber: Da i.A. eh alle Objekte über 85000 bytes auf dem LOH (large object heap) landen und bereits ein 240*120 großes 24Bit bild darüber liegt, landen die eh alle dort und werden nich verschoben, ob nun gebpinned oder nicht.
Aber klar, bei kleineren Bildern machts was aus.
Dann scheint das lazy pinnen doch besser zu sein oda ?


Ein Save ist natürlich geplant, MarshalByRefObject... hab mich mit Remoting noch nicht beschäftigt. kA ob das geht Augenzwinkern
ImmutableObject... genauso. kA smile
(werd ich mir mal anschaun)

beste Grüße
zommi
11.08.2008 09:30 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
JAck30lena JAck30lena ist männlich
myCSharp.de-Team

avatar-2653.jpg


Dabei seit: 01.10.2006
Beiträge: 11.397
Entwicklungsumgebung: Visual Studio 05/08/10 Prof.


JAck30lena ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat:
Ein Save ist natürlich geplant, MarshalByRefObject... hab mich mit Remoting noch nicht beschäftigt. kA ob das geht

simpel... einfach erben und das wars.

Zitat:
Dann scheint das lazy pinnen doch besser zu sein oda ?

lazy und die möglichkeit es explizit zu machen ist denke ich am besten.

Zitat:
Man müsste dann nur das zugehörige Bitmap disposen und verwerfen/neu erstellen

oder mit serialisieren.
11.08.2008 09:54 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
zommi zommi ist männlich
myCSharp.de-Mitglied

avatar-2617.png


Dabei seit: 14.11.2007
Beiträge: 1.361
Entwicklungsumgebung: VS 2005+2010
Herkunft: Berlin

Themenstarter Thema begonnen von zommi

zommi ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat:
Zitat:
Man müsste dann nur das zugehörige Bitmap disposen und verwerfen/neu erstellen

oder mit serialisieren.

mhh.. schwierig.
Referenzen werden ja beim binary-serialisieren wieder neu hergestellt. Aber Bitmap hat ja intern bloß nen IntPtr auf das Object. Das wird doch wohl kaum klappen, dass der automatisch neu zugewiesen wirde?!?!

beste Grüße
zommi
11.08.2008 10:18 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
JAck30lena JAck30lena ist männlich
myCSharp.de-Team

avatar-2653.jpg


Dabei seit: 01.10.2006
Beiträge: 11.397
Entwicklungsumgebung: Visual Studio 05/08/10 Prof.


JAck30lena ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

bitmap ist aber bereits serialaisierbar.
11.08.2008 10:32 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
0815Coder
myCSharp.de-Mitglied

avatar-242.gif


Dabei seit: 08.12.2005
Beiträge: 767


0815Coder ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

hab den code nur überflogen aber aufgefallen ist mir dabei:

wärs nicht möglich (zwecks Polymorphie) direkt von Image zu erben?
11.08.2008 11:45 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
JAck30lena JAck30lena ist männlich
myCSharp.de-Team

avatar-2653.jpg


Dabei seit: 01.10.2006
Beiträge: 11.397
Entwicklungsumgebung: Visual Studio 05/08/10 Prof.


JAck30lena ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat:
wärs nicht möglich (zwecks Polymorphie) direkt von Image zu erben?

in diesem fall nein bzw überhaupt nicht sinnvoll. dafür gibt es aber auch das propertie

C#-Code:
public System.Drawing.Bitmap Bitmap
        {
            get
            {
                createBitmap();
                return bitmap;
            }
        }
11.08.2008 11:50 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
zommi zommi ist männlich
myCSharp.de-Mitglied

avatar-2617.png


Dabei seit: 14.11.2007
Beiträge: 1.361
Entwicklungsumgebung: VS 2005+2010
Herkunft: Berlin

Themenstarter Thema begonnen von zommi

zommi ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hi,

Zitat:
wärs nicht möglich (zwecks Polymorphie) direkt von Image zu erben?

Eigentlich war ja die Idee komplett ohne GDI+ auszukommen, ohne den Overhead und teilweise das Problem, dass da dann evtl mal die Handles aufgebraucht sind.
Schließlich heißt es MemBitmap, was auf Memory hindeuten soll Augenzwinkern
Also Bilder die erstmal nur was für den Speicher zum rumwerkeln sind, und evtl. noch aus Kompatibilitätsgründen die Möglichkeit bieten unter Umständen ein GDI+-Bitmap draus zu machen, um es direkt anzeigen zu können. Augenzwinkern

Aber so schlecht find ich die Idee prinzipiell nicht.
Vielleicht sollte man ein Interface nehmen und dann einzelne Bitmap# klassen anlegen, eine von Image abgeleitet, eine komplett unabhängig... mhhh Augenzwinkern

Und zu:

Zitat:
bitmap ist aber bereits serialaisierbar.

Jup stimmt. ich habs grad probiert.
Wenn ich das Bitmap darin serialisier/deserialisier dann kopiert der sich den kompletten Byte-Array-Block und dann gibs den zweimal im Speicher... Ratte ;-)
Ich kann also nicht die normale Bitmap serialisierung intern nehmen. Entweder mit Surrogaten irgendwie anders oder einfach neu erstellen.

beste Grüße
zommi
11.08.2008 12:06 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
MrSparkle MrSparkle ist männlich
myCSharp.de-Team

avatar-2159.gif


Dabei seit: 16.05.2006
Beiträge: 5.299
Herkunft: Leipzig


MrSparkle ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Im Framework 3.5 gibt es für diese Zwecke auch eigene Bitmap-Objekte, z.B. die  WriteableBitmap-Klasse oder (noch schneller) die  InteropBitmap-Klasse.

Hier gibt es einen schönen Artikel dazu, in dem der Algorithmus für das Dragon-Line Fraktal umgesetzt wird:  How to: High performance graphics in WPF

Schöne Grüße,
Christian
04.09.2008 11:08 Beiträge des Benutzers | zu Buddylist hinzufügen
Zwischen diesen beiden Beiträgen liegen mehr als 2 Monate.
userid12529
myCSharp.de-Mitglied

Dabei seit: 07.07.2008
Beiträge: 208


userid12529 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hi zommi,

und vielen Dank für die Klasse. Hab sie schon in Verwendung, wie du bereits weißt. smile

Planst du vielleicht in nächster Zeit eine Unterstützung von weiteren PixelFormats, außer Format24bppRgb? Momentan gehe ich so vor, dass ich aus einem in die Form geladenem Image-Objekt zuerst ein Bitmap-Objekt erzeuge, bei diesem dann das PixelFormat in Format24bppRgb ändere (in dem ich per Clone ein neues Bitmap-Objekt erzeuge) und aus diesem Bitmap-Objekt dann letzlich ein MemBitmap-Objekt erzeuge. Klappt alles, ich habe allerdings den Nachteil, dass ich keine transparenten Bilder verarbeiten kann, bzw. verarbeiten schon, aber die Transparenz-Informationen gehen leider verloren.

Grüße,

Isaac
25.11.2008 22:36 Beiträge des Benutzers | zu Buddylist hinzufügen
Zwischen diesen beiden Beiträgen liegen mehr als 2 Jahre.
Th69
myCSharp.de-Poweruser/ Experte

avatar-2578.jpg


Dabei seit: 01.04.2008
Beiträge: 3.470
Entwicklungsumgebung: Visual Studio 2015/17


Th69 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo zommi,

mir ist gerade ein kleiner Fehler bei dem MemBitmap-Konstruktor aufgefallen:

C#-Code:
public MemBitmap(int initWidth, int initHeight, System.Drawing.Imaging.PixelFormat initPixelFormat)
{
    init(initWidth, initHeight, initPixelFormat); // nicht 'pixelformat'
}

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Th69 am 08.06.2011 10:27.

08.06.2011 10:25 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
zommi zommi ist männlich
myCSharp.de-Mitglied

avatar-2617.png


Dabei seit: 14.11.2007
Beiträge: 1.361
Entwicklungsumgebung: VS 2005+2010
Herkunft: Berlin

Themenstarter Thema begonnen von zommi

zommi ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hi Th69,

danke! soeben ausgebessert.

beste Grüße
zommi
08.06.2011 12:01 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 11 Jahre.
Der letzte Beitrag ist älter als 8 Jahre.
Antwort erstellen


© Copyright 2003-2020 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 18.02.2020 19:39