Wie kann ich einen BMP aus einer ICO -Datei extrahieren?
-
27-10-2019 - |
Frage
Ich mache einige Arbeiten, bei denen ich sammelnde Symbole von Websites, die in einem OpenSearch -Dokument angegeben sind, programmgesteuert herunterladen und das erste Bild (vorerst) extrahieren muss, wenn es sich im ICO -Format befindet. Ich kann den ICO -Dateiheader ohne Probleme lesen und die erste Bilddatei herausschneiden. Nach dem Lesen der Wikipedia -Eintrag, das das Dateiformat erläutert Ich habe festgestellt, dass, wenn sich das Bild im Bitmap -Format befindet, die Datei unvollständig ist (es fehlt der Header). Daher muss ich diesen Header rekonstruieren, bevor ich die Daten in einer Datei speichern kann, aber ich habe ein bisschen Schwierigkeiten.
Laut dem Wikipedia -Eintrag für BMP -Dateiformat, Der Kopfzeile ist 14 Bytes lang und sollte Folgendes enthalten:
Versatzdaten0x0000
"BM", for our intents and purposes0x0002
Size of the bitmap file in bytes0x0006
Dependant on the application creating the file0x0008
Dependant on the application creating the file0x000A
Offset of the image data/pixel array
Ich dachte Schreiben Sie bei 0x000a.
Ich habe den Artikel ein paar Mal gelesen, aber ich muss zugeben, dass mein Kopf ein wenig weh tut. Dies ist meine erste Erfahrung damit, so etwas zu tun. Kann mir jemand helfen, herauszufinden, wie ich den Pixel -Array -Standort erhalten kann?
Lösung
0x0006
und 0x0008
sind reserviert, Sie sollten einfach Nullen dort einsetzen. Zu 0x000A
, Dies ist die Position, in der die tatsächlichen Bilddaten in der Datei beginnen. Normalerweise folgt der Header, den Sie hier haben 0x000E
) und die ersten vier Bytes des DIB -Headers sind seine Größe. Sie nehmen also die Größe des DIB -Headers, fügen den Startversatz hinzu (0x000E
) Und was Sie haben, ist die Position, in der die tatsächlichen Daten beginnen - das an die Position setzen 0x000A
.
Hier finden Sie Beispieldaten aus einer zufälligen Bitmap -Datei:
42 4D "BM"
2E 78 08 00 Size of the entire bitmap file (0x8782E meaning 555054 bytes)
00 00 creator1, reserved
00 00 creator2, reserved
36 00 00 00 Image data starts at offset 0x36 because the next 0x28 bytes are DIB header
28 00 00 00 DIB header started and its size is 0x28 (40 bytes)
another 36 bytes
FF FF FF First pixel of the image (white as it happens)
Wenn Sie das nehmen Favicon auf serverfault.com Als Beispiel würden Sie den Teil der Datei zwischen Offset übertragen 0x0016
und 0x013E
und bereiten Sie es mit vor mit 42 4D 36 01 00 00 00 00 00 00 36 00 00 00
. Dies gibt Ihnen eine Art korrekte Bitmap -Datei - und IrfanView zeigt sie sogar an. Daten, die in ICO -Dateien und BMP -Dateien gespeichert sind, sind jedoch nicht ganz gleich, da ICO -Dateien Transparenzinformationen speichern müssen. Aus diesem Grund hat dieses Favicon die Größe 16x32 nach seinem DIB -Header und nicht nach dem erwarteten 16x16.
Aus Wikipedia:
Bilder mit weniger als 32 Bit Farbtiefe folgen einem bestimmten Format: Das Bild wird als einzelnes Bild codiert, das aus einer Farbmaske (der "XOR -Maske") zusammen mit einer Opazitätsmaske (der "und der Maske") besteht. Die XOR -Maske muss vor der Bitmap -Daten und der Maske in den Bitmap -Daten vorangehen. Wenn das Bild in Bottom-up-Reihenfolge gespeichert ist (was es sich höchstwahrscheinlich ist), wird die XOR-Maske unterhalb der und Maske gezeichnet.
In unserem speziellen Fall bedeutet dies, dass aus 256 Bytes Bilddaten die ersten 64 Bytes die XOR -Maske sind, die letzten 64 Bytes die und Maske und nur der mittlere Teil unser Bild. In unserem speziellen Fall können Sie den Beginn der Bilddaten ändern (Offset 0x000A
) bis 0x76, um die XOR -Maske zu überspringen. Dann ändern Sie auch die Bildhöhe im DIB -Header (Offset 0x0016
) bis 0x10, um sicherzustellen, dass die und die Maske ignoriert werden. Hier geben Ihnen diese Manipulationen eine gültige Bitmap, die dem, was Sie erwartet haben, so gut wie erwartet. Im Allgemeinen könnte es besser sein, die Masken zu berücksichtigen, als sie zu ignorieren.