8086 MS-DOS .COM फ़ाइल / BMP, आउटपुट फ़ाइल आकार = 2192 बाइट्स
एनकोडर
एनकोडर सी में लिखा है। इसमें दो तर्क दिए गए हैं: इनपुट फ़ाइल और आउटपुट फ़ाइल। इनपुट फ़ाइल 64x64 RAW RGB छवि है (इसका अर्थ है कि यह बस 4096 RGB ट्रिपल है)। रंगों की संख्या 4 तक सीमित है, ताकि पैलेट यथासंभव कम हो सके। यह अपने कामों में बहुत आगे-आगे है; यह केवल एक पैलेट बनाता है, पिक्सेल जोड़े को बाइट्स में पैक करता है और इसे पूर्व-निर्मित हेडर और डिकोडर प्रोग्राम के साथ एक साथ जोड़ देता है।
#include <stdio.h>
#include <stdlib.h>
#define MAXPAL 4
#define IMAGESIZE 64 * 64
int main(int argc, char **argv)
{
FILE *fin, *fout;
unsigned char *imgdata = malloc(IMAGESIZE * 3), *outdata = calloc(IMAGESIZE / 2, 1);
unsigned palette[MAXPAL] = {0};
int pal_size = 0;
if (!(fin = fopen(argv[1], "rb")))
{
fprintf(stderr, "Could not open \"%s\".\n", argv[1]);
exit(1);
}
if (!(fout = fopen(argv[2], "wb")))
{
fprintf(stderr, "Could not open \"%s\".\n", argv[2]);
exit(2);
}
fread(imgdata, 1, IMAGESIZE * 3, fin);
for (int i = 0; i < IMAGESIZE; i++)
{
// BMP saves the palette in BGR order
unsigned col = (imgdata[i * 3] << 16) | (imgdata[i * 3 + 1] << 8) | (imgdata[i * 3 + 2]), palindex;
int is_in_pal = 0;
for (int j = 0; j < pal_size; j++)
{
if (palette[j] == col)
{
palindex = j;
is_in_pal = 1;
}
}
if (!is_in_pal)
{
if (pal_size == MAXPAL)
{
fprintf(stderr, "Too many unique colours in input image.\n");
exit(3);
}
palindex = pal_size;
palette[pal_size++] = col;
}
// High nibble is left-most pixel of the pair
outdata[i / 2] |= (palindex << !(i & 1) * 4);
}
char BITMAPFILEHEADER[14] = {
0x42, 0x4D, // "BM" magic marker
0x90, 0x08, 0x00, 0x00, // FileSize
0x00, 0x00, // Reserved1
0x00, 0x00, // Reserved2
0x90, 0x00, 0x00, 0x00 // ImageOffset
};
char BITMAPINFOHEADER[40] = {
0x28, 0x00, 0x00, 0x00, // StructSize
0x40, 0x00, 0x00, 0x00, // ImageWidth
0x40, 0x00, 0x00, 0x00, // ImageHeight
0x01, 0x00, // Planes
0x04, 0x00, // BitsPerPixel
0x00, 0x00, 0x00, 0x00, // CompressionType (0 = none)
0x00, 0x00, 0x00, 0x00, // RawImagDataSize (0 is fine for non-compressed,)
0x00, 0x00, 0x00, 0x90, // HorizontalRes
// db 0, 0, 0
// nop
0xEB, 0x1A, 0x90, 0x90, // VerticalRes
// jmp Decoder
// nop
// nop
0x04, 0x00, 0x00, 0x00, // NumPaletteColours
0x00, 0x00, 0x00, 0x00, // NumImportantColours (0 = all)
};
char DECODER[74] = {
0xB8, 0x13, 0x00, 0xCD, 0x10, 0xBA, 0x00, 0xA0, 0x8E, 0xC2, 0xBA,
0xC8, 0x03, 0x31, 0xC0, 0xEE, 0x42, 0xBE, 0x38, 0x01, 0xB1, 0x04,
0xFD, 0x51, 0xB1, 0x03, 0xAC, 0xD0, 0xE8, 0xD0, 0xE8, 0xEE, 0xE2,
0xF8, 0x83, 0xC6, 0x07, 0x59, 0xE2, 0xEF, 0xFC, 0xB9, 0x00, 0x08,
0xBE, 0x90, 0x01, 0xBF, 0xC0, 0x4E, 0xAC, 0xD4, 0x10, 0x86, 0xC4,
0xAB, 0xF7, 0xC7, 0x3F, 0x00, 0x75, 0x04, 0x81, 0xEF, 0x80, 0x01,
0xE2, 0xEE, 0x31, 0xC0, 0xCD, 0x16, 0xCD, 0x20,
};
fwrite(BITMAPFILEHEADER, 1, 14, fout);
fwrite(BITMAPINFOHEADER, 1, 40, fout);
fwrite(palette, 4, 4, fout);
fwrite(DECODER, 1, 74, fout);
// BMPs are stored upside-down, because why not
for (int i = 64; i--; )
fwrite(outdata + i * 32, 1, 32, fout);
fclose(fin);
fclose(fout);
return 0;
}
आउटपुट फाइल
आउटपुट फ़ाइल एक BMP फ़ाइल है, जिसे .COM का नाम दिया जा सकता है और DOS वातावरण में चलाया जा सकता है। निष्पादन के बाद, यह वीडियो मोड 13h में बदल जाएगा और छवि प्रदर्शित करेगा।
एक BMP फ़ाइल में पहला हेडर BITMAPFILEHEADER होता है, जिसमें ImageOffset फ़ील्ड की अन्य चीजें शामिल होती हैं, जो बताती हैं कि फाइल में इमेज डेटा कहां से शुरू होता है। इसके बाद BITMAPINFOHEADER आता है जिसमें विभिन्न de- / एन्कोडिंग जानकारी होती है, उसके बाद एक पैलेट, यदि एक का उपयोग किया जाता है। ImageOffset का मान हो सकता है जो किसी भी हेडर के अंत से परे इंगित करता है, जिससे हमें डिकोडर में निवास करने के लिए एक अंतराल बनाने की अनुमति मिलती है।
BITMAPFILEHEADER
BITMAPINFOHEADER
PALETTE
<gap>
IMAGE DATA
एक और समस्या डिकोडर में प्रवेश करने की है। BITMAPFILEHEADER और BITMAPINFOHEADER के साथ यह सुनिश्चित करने के लिए छेड़छाड़ की जा सकती है कि वे कानूनी मशीन कोड हैं (जो एक गैर-वसूली योग्य राज्य का उत्पादन नहीं करता है), लेकिन पैलेट ट्रिकियर है। हम निश्चित रूप से पैलेट को कृत्रिम रूप से लंबा बना सकते हैं, और मशीन कोड को वहां रख सकते हैं, लेकिन मैंने इसके बजाय फ़ील्ड को biXPelsPerMeter और biYPelsPerMeter का उपयोग करने का विकल्प चुना, कोड को ठीक से संरेखित करने के लिए पूर्व, और बाद में डिकोडर में कूदने के लिए। इन क्षेत्रों में निश्चित रूप से उनमें कचरा होगा, लेकिन किसी भी छवि दर्शक को मैंने छवि को ठीक से प्रदर्शित करने के साथ परीक्षण किया है। मुद्रण भले ही अजीब परिणाम उत्पन्न कर सकता है।
यह है, जहाँ तक मुझे पता है, मानक-अनुरूप है।
यदि JMP
निर्देश BITMAPFILEHEADER में आरक्षित क्षेत्रों में से एक में रखा गया था , तो एक छोटी फ़ाइल बना सकता है । यह हमें 64 के बजाय -64 के रूप में छवि की ऊंचाई को स्टोर करने की अनुमति देगा, जो बीएमपी फाइलों के जादुई वंडरलैंड में इसका मतलब है कि छवि डेटा को सही तरीके से संग्रहीत किया जाता है, जो बदले में एक सरलीकृत डिकोडर के लिए अनुमति देगा।
डिकोडर
डिकोडर में कोई विशेष चाल नहीं। पैलेट एनकोडर द्वारा आबादी है, और डमी-मूल्यों के साथ यहां दिखाया गया है। यह थोड़ा कम हो सकता है अगर यह एक कीपर पर डॉस में वापस नहीं आता है, लेकिन यह इसके बिना मजेदार परीक्षण नहीं था। यदि आपको लगता है कि आपको jmp $
कुछ बाइट्स बचाने के लिए अंतिम तीन निर्देशों को बदलना चाहिए । (यदि आप करते हैं तो फ़ाइल हेडर को अपडेट करना न भूलें!)
बीएमपी स्टोरेज को बीजीआर ( आरजीबी नहीं ) ट्रिपल के रूप में संग्रहीत करता है , जीरो के साथ गद्देदार। यह वीजीए पैलेट को सामान्य से अधिक कष्टप्रद बनाता है। तथ्य यह है कि बीएमपी को उल्टा संग्रहीत किया जाता है, केवल स्वाद (और आकार) में जोड़ता है।
यहाँ NASM शैली में सूचीबद्ध:
Palette:
db 0, 0, 0, 0
db 0, 0, 0, 0
db 0, 0, 0, 0
db 0, 0, 0, 0
Decoder:
; Set screen mode
mov ax, 0x13
int 0x10
mov dx, 0xa000
mov es, dx
; Prepare to set palette
mov dx, 0x3c8
xor ax, ax
out dx, al
inc dx
mov si, Palette + 2
mov cl, 4
std
pal_loop:
push cx
mov cl, 3
pal_inner:
lodsb
shr al, 1
shr al, 1
out dx, al
loop pal_inner
add si, 7
pop cx
loop pal_loop
cld
; Copy image data to video memory
mov cx, 64 * 64 / 2
mov si, ImageData
mov di, 20160
img_loop:
lodsb
aam 16
xchg al, ah
stosw
test di, 63
jnz skip
sub di, 384
skip:
loop img_loop
; Eat a keypress
xor ax, ax
int 0x16
; Return to DOS
int 0x20
ImageData:
.exe
चुनौती के भाग के लिए किसी प्रकार का कोड जोड़ते हैं , और जब इसे देखते हैं तो.png
इस.exe
-कोड के आधार पर संशोधित पिक्सेल होते हैं । क्या यह अनुमति है जब तक यह अभी भी.png
हम देख सकते हैं? क्या आउटपुट इमेज में भी कम से कम 4 रंग होने चाहिए?