Announcement

Collapse
No announcement yet.

C# Bitmap mit Marshal.Copy()

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • C# Bitmap mit Marshal.Copy()

    Hi,

    und zwar habe ich folgendes Problem. Ich habe mir eine Application gebastelt die Bilder von verschiedenen Quellen einließt. (Bitmap.FromFile() -> Zum Beispiel)
    Da ich diese Bilder dann mit verschiedenen Algorithmen bearbeiten möchte (Laplace, Sobelfilter usw.) erstelle ich mir aus diesen eigelesenen Bildern Byte - Arrays. Habe im Internet ein relativ gutes Codefragment gefunden, dass dies mithilfe von Marshal.Copy bewerkstelligt. (Geht auch bei großen Bildern relativ schnell)

    Nun habe ich aber ein Problem beim Verständnis der Byte - Reihenfolge der Bilder.
    (Dazu ein Beispiel)
    Wenn ich nun ein Bild habe das in RGB abgespeichert ist (PixelFormat.Format24bppRgb) habe ich ja pro Pixel drei Bytewerte. Wenn das Bild nun quadratisch ist, kann ich mithilfe von zwei einfachen for Schleifen durch das Bild durchiterieren. (Von oben links nach unten Rechts) Wenn das Bild aber nun nicht quadratisch sondern Rechteckig ist, kommt es auf das Bildformat an (jpg, png usw....)

    Was ich nun eigentlich genau suche wäre eine Referenz wo beschrieben ist, wie ich von den unterschiedlichen Bildformaten die Bytes auslesen muss, damit ich diese auch sinnvoll bearbeiten kann!

    Ich hoffe man kann mein Problem erahnen ^^
    Anbei noch ein Bild, das es noch etwas klarer machen sollte!
    (Es sind drei unterschiedliche Fotos drauf, bei denen ich einfach immer mit den gleichen beiden for Schleifen Pixel schwarz mache)

    Mit freundlichen Grüßen

    BaDo

    hilfe.jpg

  • #2
    gif, jpg, png usw. sind SPEICHERFORMATE! Keine Formate in dem ein Bild im Speicher vorliegt. Das ist immer das Bitmapformat. Dessen Header gibt Auskunft über die Höhe und Breite des Bildes. Des Weiteren werden 4 Bytes pro Pixel verwandt

    BITMAP-FILEHEADER-STRUCTUR
    int 2 Byte "BM"
    long 4 Byte Länge der Datei
    int 2 Byte Reserviert = 0
    int 2 Byte Reserviert = 0
    long 4 Byte Beginn der Rasterdaten
    BITMAP-INFO-HEADER-STRUCTUR
    long 4 Bytes Länge der Bitmap-Info-Header-Structur (Windows = 40)
    long 4 Bytes Breite des Bildes
    long 4 Bytes Höhe des Bildes
    int 2 Bytes Planes (Windows = 1)
    int 2 Bytes Anzahl der Farben (1 = 2, 4 = 16, 8 = 256, 24 = 16 Mio)
    long 4 Bytes Kompression (0 = ohne, 1 = 8 Bit RLE, 2 = 4 Bit RLE)
    long 4 Bytes Größe des unkomp. Bildes
    long 4 Bytes horz. Anzahl von Rasterpunkte pro Meter
    long 4 Bytes vert. Anzahl von Rasterpunkte pro Meter
    long 4 Bytes Anzahl der erford. Platteneinträge (0 = alle)
    long 4Bytes Anzahl der wichtigen Farben (0 = alle)
    anschl.
    Farbwerte BLUE,GREEN,RED,RESERVED = 4 Bytes je Farbe (bsp. 256 Farben = 1024 Bytes)
    Christian

    Comment


    • #3
      Hi,

      und danke für die schnelle Antwort.
      Das mit den Speicher Formaten ist schon mal gut
      (Dachte mir schon das ich da was falsch verstehe, nachdem es bei quadratischen Bildern egal zu sein scheint!)

      Anbei der (vereinfachte) Code den ich benutze um die Bitmaps in ein Byte[] umzuwandeln.

      Code:
      private int DataStride;
      private PixelFormat internalFormat;
      private int width;
      private int height;
      private byte[] dataMatrix;
      
      private void UpdateDataMatrix(Bitmap image) 
              {
                  BitmapData Bdata = image.LockBits(new Rectangle(0, 0, width, height),
                      ImageLockMode.ReadOnly, internalFormat);
                  
                  dataMatrix = new byte[Bdata.Stride * Bdata.Height];
                  DataStride = Bdata.Stride;
                  Marshal.Copy(Bdata.Scan0, dataMatrix, 0, dataMatrix.Length);
      
                  if (internalFormat == PixelFormat.Format1bppIndexed || 
                      internalFormat == PixelFormat.Format4bppIndexed || 
                      internalFormat == PixelFormat.Format8bppIndexed || 
                      internalFormat == PixelFormat.Indexed)
                      internalColorPalette = image.Palette;
      
                  image.UnlockBits(Bdata);
              }
      Wenn ich das so mache, bekomme ich ja die Headerinformationen die du vorher beschrieben hast nicht mit in mein Bytearray. Sondern wirklich nur die Contentbytes
      (nenne ich die mal ^^)

      Jetzt muss ich aber doch anzweifeln was du über die 4 Bytes pro Pixel sagst, weil wenn ich ein Graustufenbild öffnen will (zum Beispiel) hätte dieses das PixelFormat.Format8bppIndexed und wird in meinem Datenarray auch nur mit 1nem Byte hinterlegt.


      lg

      Comment


      • #4
        Gut, dann zweifle halt...

        http://en.wikipedia.org/wiki/BMP_file_format
        Zuletzt editiert von Christian Marquardt; 22.10.2012, 20:13.
        Christian

        Comment


        • #5
          Ok vielleicht habe ich mich gestern falsch ausgedrückt ...
          *Bin schon froh das du so schnell geantwortet hast*

          Ich will es mal so versuchen ich glaub dir alles was du oben geschrieben hast!

          Aber:

          Wenn ich eine Bilddatei (test.jpg -> Graustufen) die sagen wir 2x2pixel groß ist, mit der oben angeführten Methode einlese, dann habe ich nach dem Aufruf dieser Methode ein Array mit genau 4 Werten drinnen... (nicht 16 oder gar noch mehr zwecks Header)

          Es sind einfach wirklich genau nur 4.


          lg

          Comment


          • #6
            Hallo zusammen,

            was Christian schreibt, das die Daten immer vier Byte-weise abgelegt sind, stimmt nicht ganz - die abgelegten Daten werden immer auf 4 Byte aufgefüllt, was dann Dein image Container davon aber wirklich beinhaltet kann eine ganz andere Geschichte sein - ich habe mich mit dem image Container noch nicht befasst ich würde aber behaupten das dieser kein exaktes Abbild des Speichers ist, sondern die Daten schon interpretiert hat (und deswegen um die überflüssigen Daten bereinigt), aber im angehängten Wiki Eintrag steht bei Punkt 2.5.3 alles drinnen was Du brauchst. Sehr ausführlich und eigentlich sehr gut verständlich.

            Gruß Womble

            Comment


            • #7
              Dann lese ich mir das mal durch
              Ich danke euch beiden nochmal!


              lg

              Comment


              • #8
                Ich rede von BYTES! Und ein 32-Bit Wert besteht aus 4 Bytes. Wenn ich davon 3 verwende (RGB) bleibt 1 übrig!

                http://de.wikipedia.org/wiki/Windows_Bitmap

                Wovon Womble redet ist

                Die Länge jeder Zeile ist ein Vielfaches von 4 Bytes, falls erforderlich, wird mit Nullbytes aufgefüllt.
                Christian

                Comment


                • #9
                  Die Länge jeder Zeile ist ein Vielfaches von 4 Bytes
                  Und die Länge in Bytes einer Zeile ist der Stride. Wer die Width hat und den Stride sollte sich Bytes per Pixel sehr leicht ausrechnen können wenn man der 4 nicht traut

                  Comment


                  • #10
                    Sorry, ich hatte oben überlesen das er es nur von 24bit Bildern hat

                    Comment

                    Working...
                    X