Exemplo n.º 1
0
        /// <summary>
        /// Erstellt eine neue Farbtabelle aus einen angegebenen JASCPalette-Objekt. <param name="pal">Die zu ladende JASC-Palette.</param>
        /// </summary>
        public ColorTable(JASCPalette pal)
        {
            // Anzahl der Farben in pal verwenden, aber maximal 256
            int count = Math.Min(pal._farben.GetLength(0), 256);

            // Alle Farben der Palette durchlaufen
            for (int i = 0; i < count; i++)
            {
                // Farbeintrag erstellen
                _colors[i] = Color.FromArgb(pal._farben[i, 0], pal._farben[i, 1], pal._farben[i, 2]);
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Lädt die Bitmap-Datei aus dem angegebenen Puffer.
        /// </summary>
        /// <param name="buffer">Der Puffer, aus dem die Bitmap-Datei gelesen werden soll.</param>
        /// <param name="pal">Optional. Gibt die zu verwendende 256er-Farbtabelle an. Sonst wird die entweder die im Bitmap angegebene oder die 50500er-Farbtabelle verwendet.</param>
        /// <param name="readFileHeader">Optional. Gibt an, ob der Dateiheader gelesen werden oder direkt mit der BITMAPINFOHEADER-Struktur begonnen werden soll.</param>
        public BitmapLoader(RAMBuffer buffer, JASCPalette pal = null, bool readFileHeader = true)
        {
            // Header laden
            _header = new Header();
            if (readFileHeader)
            {
                _header.type       = buffer.ReadUShort();
                _header.fileSize   = buffer.ReadUInteger();
                _header.reserved   = buffer.ReadUInteger();
                _header.offsetData = buffer.ReadUInteger();
            }
            else
            {
                _header.type       = 0x424D;
                _header.fileSize   = 0;
                _header.reserved   = 0;
                _header.offsetData = 54;
            }
            _header.imageHeaderSize     = buffer.ReadUInteger();
            _header.width               = buffer.ReadInteger();
            _header.height              = buffer.ReadInteger();
            _header.layerCount          = buffer.ReadUShort();
            _header.bitsPerPixel        = buffer.ReadUShort();
            _header.compression         = buffer.ReadUInteger();
            _header.size                = buffer.ReadUInteger();
            _header.xDPI                = buffer.ReadInteger();
            _header.yDPI                = buffer.ReadInteger();
            _header.colorCount          = buffer.ReadUInteger();
            _header.colorImportantCount = buffer.ReadUInteger();

            // Farbtabellenanzahl nachjustieren
            if (_header.colorCount == 0 && _header.bitsPerPixel == 8)
            {
                _header.colorCount = 256;
            }

            // Farbtabelle laden
            bool needAdjustColorTable = false;

            if (_header.colorCount > 0)
            {
                // Bildfarbtabelle laden
                _colorTable = new ColorTable(ref buffer, _header.colorCount);

                // Falls eine Palette übergeben wurde, diese mit der Bildtabelle vergleichen
                if (pal == null || pal._farben.GetLength(0) != 256)
                {
                    needAdjustColorTable = true;
                }
                else
                {
                    for (int i = 0; i < 256; ++i)
                    {
                        // Farben vergleichen
                        Color aktF = _colorTable[i];
                        if (pal._farben[i, 0] != aktF.R || pal._farben[i, 1] != aktF.G || pal._farben[i, 2] != aktF.B)
                        {
                            // Farbtabellen unterscheiden sich
                            needAdjustColorTable = true;
                            break;
                        }
                    }
                }
            }
            else
            {
                // Bei 24-Bit-Bitmaps wird die Farbtabelle später geladen
                _colorTable = null;
            }

            // Nach Bitzahl unterscheiden
            if (_header.bitsPerPixel == 8)
            {
                // Bilddatenbreite ggf. auf ein Vielfaches von 4 Bytes erhöhen
                int width  = _header.width;                // Hilfsvariable zur Performanceerhöhung (immer gleichwertig mit _header.width)
                int width2 = width;
                while (width2 % 4 != 0)
                {
                    width2++;
                }

                // Binäre Original-Bilddaten einlesen
                _imageDataBin = buffer.ReadByteArray(width2 * Math.Abs(_header.height));

                // Neues Bilddaten-Array anlegen (ohne Füllbytes)
                _imageData = new byte[width * Math.Abs(_header.height)];

                // Richtung bestimmen
                bool dirTopDown = (_header.height < 0);

                // Der bisher nächste Farbindex
                byte nearestIndex = 0;

                // Der Abstand zum bisher nächsten Farbindex
                double nearestDistance;

                // Der aktuelle Farbabstand
                double tempDistance = 0.0;

                // Bilddaten abrufen
                int height2 = Math.Abs(_header.height);
                for (int x = 0; x < width2; x++)
                {
                    for (int y = 0; y < height2; y++)
                    {
                        // Wenn es sich bei dem aktuellen Pixel um kein Füllbyte handelt, diesen übernehmen
                        if (x < width)
                        {
                            // Pixel abrufen
                            byte aktCol = _imageDataBin[y * width2 + x];

                            // TODO: 0-Indizes in 255 umwandeln??

                            // Falls nötig, Farben vergleichen
                            if (needAdjustColorTable)
                            {
                                // Alle Farbwerte abrufen
                                byte aktB = _colorTable[aktCol].B;
                                byte aktG = _colorTable[aktCol].G;
                                byte aktR = _colorTable[aktCol].R;

                                // Die zur Pixelfarbe nächste Palettenfarbe suchen
                                {
                                    // Werte zurücksetzen
                                    nearestIndex    = 0;
                                    nearestDistance = 441.673;                                     // Anfangswert: maximaler möglicher Abstand

                                    // Alle Einträge durchgehen
                                    for (int i = 0; i < 256; i++)
                                    {
                                        // Aktuelle Paletten-RGB-Werte abrufen
                                        byte pR = pal._farben[i, 0];
                                        byte pG = pal._farben[i, 1];
                                        byte pB = pal._farben[i, 2];

                                        // Gleiche Einträge sofort filtern
                                        if (aktR == pR && aktB == pB && aktG == pG)
                                        {
                                            // Paletten-Index überschreiben
                                            nearestIndex = (byte)i;

                                            // Fertig
                                            break;
                                        }

                                        // Abstand berechnen (Vektorlänge im dreidimensionalen RGB-Farbraum)
                                        tempDistance = Math.Sqrt(Math.Pow(aktR - pR, 2) + Math.Pow(aktG - pG, 2) + Math.Pow(aktB - pB, 2));

                                        // Vergleichen
                                        if (tempDistance < nearestDistance)
                                        {
                                            // Index merken
                                            nearestDistance = tempDistance;
                                            nearestIndex    = (byte)i;
                                        }
                                    }

                                    // Paletten-Index überschreiben
                                    aktCol = nearestIndex;
                                }
                            }                             // Ende Adjust-ColorTable

                            // Pixel zum Hauptbildarray hinzufügen und dabei nach Top-Down / Bottom-Up unterscheiden
                            _imageData[(dirTopDown ? y : height2 - y - 1) * width + x] = aktCol;
                        }
                    }
                }
            }
            else if (_header.bitsPerPixel == 24)
            {
                // Es handelt sich um ein 24-Bit-Bitmap, somit muss eine Farbtabelle eingeführt werden
                {
                    // Farbpalettenreader abrufen
                    JASCPalette tempPal;
                    if (pal == null)
                    {
                        tempPal = new JASCPalette(new RAMBuffer(BitmapLibrary.Properties.Resources.pal50500));
                    }
                    else
                    {
                        tempPal = pal;
                    }

                    // Farbpaletteninhalt in eigene Farbtabelle schreiben
                    _colorTable = new ColorTable();
                    for (int i = 0; i < tempPal._farben.GetLength(0); i++)
                    {
                        // Eintrag in Tabelle einfügen
                        _colorTable[i] = Color.FromArgb(tempPal._farben[i, 0], tempPal._farben[i, 1], tempPal._farben[i, 2]);

                        // Sicherheitshalber bei i = 255 abbrechen (falls Palette zu groß sein sollte)
                        if (i == 255)
                        {
                            break;
                        }
                    }
                }

                // Bilddatenbreite ggf. auf ein Vielfaches von 4 Bytes erhöhen
                int width     = _header.width;             // Hilfsvariable zur Performanceerhöhung (immer gleichwertig mit _header.width)
                int fillBytes = 0;
                while (((width * 3) + fillBytes) % 4 != 0)
                {
                    fillBytes++;
                }

                // Binäre Original-Bilddaten einlesen
                _imageDataBin = buffer.ReadByteArray((3 * width + fillBytes) * Math.Abs(_header.height));

                // Neues Bilddaten-Array anlegen (ohne Füllbytes)
                _imageData = new byte[width * Math.Abs(_header.height)];

                // Richtung bestimmen
                bool dirTopDown = (_header.height < 0);

                // Der bisher nächste Farbindex
                byte nearestIndex = 0;

                // Der Abstand zum bisher nächsten Farbindex
                double nearestDistance;

                // Der aktuelle Farbabstand
                double tempDistance = 0.0;

                // Bilddaten abrufen
                int height2 = Math.Abs(_header.height);
                for (int x = 0; x < width; x++)
                {
                    for (int y = 0; y < height2; y++)
                    {
                        // Pixel abrufen
                        byte aktB = _imageDataBin[y * (3 * width + fillBytes) + 3 * x];
                        byte aktG = _imageDataBin[y * (3 * width + fillBytes) + 3 * x + 1];
                        byte aktR = _imageDataBin[y * (3 * width + fillBytes) + 3 * x + 2];

                        // Die zur Pixelfarbe nächste Palettenfarbe suchen
                        {
                            // Werte zurücksetzen
                            nearestIndex    = 0;
                            nearestDistance = 441.673;                             // Anfangswert: maximaler möglicher Abstand

                            // Alle Einträge durchgehen
                            for (int i = 0; i < 256; i++)
                            {
                                // Aktuelle Paletten-RGB-Werte abrufen
                                byte pR = _colorTable[i].R;
                                byte pG = _colorTable[i].G;
                                byte pB = _colorTable[i].B;

                                // Gleiche Einträge sofort filtern
                                if (aktR == pR && aktB == pB && aktG == pG)
                                {
                                    // Pixel zum Hauptbildarray hinzufügen und dabei nach Top-Down / Bottom-Up unterscheiden
                                    _imageData[(dirTopDown ? y : height2 - y - 1) * width + x] = (byte)i;

                                    // Fertig
                                    break;
                                }

                                // Abstand berechnen (Vektorlänge im dreidimensionalen RGB-Farbraum)
                                tempDistance = Math.Sqrt(Math.Pow(aktR - pR, 2) + Math.Pow(aktG - pG, 2) + Math.Pow(aktB - pB, 2));

                                // Vergleichen
                                if (tempDistance < nearestDistance)
                                {
                                    // Index merken
                                    nearestDistance = tempDistance;
                                    nearestIndex    = (byte)i;
                                }
                            }

                            // Pixel zum Hauptbildarray hinzufügen und dabei nach Top-Down / Bottom-Up unterscheiden
                            _imageData[(dirTopDown ? y : height2 - y - 1) * width + x] = nearestIndex;
                        }
                    }

                    // Ggf. Füllbytes überspringen (bei Dateiende nicht)
                    if (buffer.Position < buffer.Length - fillBytes)
                    {
                        buffer.Position = (buffer.Position + fillBytes);
                    }
                }
            }
        }
Exemplo n.º 3
0
 /// <summary>
 /// Lädt die angegebene Bitmap-Datei.
 /// </summary>
 /// <param name="filename">Der Pfad zur zu ladenden Bitmap-Datei.</param>
 /// <param name="pal">Optional. Gibt die zu verwendende 256er-Farbtabelle an. Sonst wird die entweder die im Bitmap angegebene oder die 50500er-Farbtabelle verwendet.</param>
 /// <param name="readFileHeader">Optional. Gibt an, ob der Dateiheader gelesen werden oder direkt mit der BITMAPINFOHEADER-Struktur begonnen werden soll.</param>
 public BitmapLoader(string filename, JASCPalette pal = null, bool readFileHeader = true)
     : this(new RAMBuffer(filename), pal, readFileHeader)
 {
 }