8086 MS-DOS .COM dosyası / BMP, çıktı dosyası boyutu = 2192 bayt
Encoder
Kodlayıcı C ile yazılır. İki argüman alır: Girdi dosyası ve çıktı dosyası. Giriş dosyası 64x64 RAW RGB görüntüsüdür (yani sadece 4096 RGB üçlüsüdür). Renk sayısı 4 ile sınırlıdır, böylece palet mümkün olduğunca kısa olabilir. Yaptıklarında çok basittir; sadece bir palet oluşturur, piksel çiftlerini baytlara paketler ve önceden hazırlanmış üstbilgiler ve kod çözücü programı ile yapıştırır.
#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;
}
Çıktı dosyası
Çıktı dosyası .COM olarak yeniden adlandırılabilen ve DOS ortamında çalıştırılabilen bir BMP dosyasıdır. Yürütme üzerine, 13h video moduna geçecek ve görüntüyü gösterecektir.
Bir BMP dosyası, görüntü verilerinin dosyada nerede başladığını gösteren ImageOffset alanını içeren ilk başlık BITMAPFILEHEADER'a sahiptir. Bundan sonra BITMAPINFOHEADER çeşitli kod çözme / kodlama bilgileri, ardından bir palet kullanılırsa gelir. ImageOffset, herhangi bir üstbilginin sonunu aşan bir değere sahip olabilir, bu da kod çözücünün oturması için bir boşluk oluşturmamızı sağlar.
BITMAPFILEHEADER
BITMAPINFOHEADER
PALETTE
<gap>
IMAGE DATA
Başka bir sorun, kod çözücüye girmektir. BITMAPFILEHEADER ve BITMAPINFOHEADER, yasal makine kodu olduklarından (kurtarılamayan bir durum üretmeyen) emin olmak için kullanılabilir, ancak palet daha karmaşıktır. Elbette paleti yapay olarak daha uzun yapabilir ve makine kodunu oraya koyabiliriz, ancak bunun yerine biXPelsPerMeter ve biYPelsPerMeter alanlarını, kodun düzgün hizalanmasını sağlamak için ikincisini ve kod çözücüye atlamayı seçtim. Bu alanların elbette içlerinde çöp olacaktır, ancak test ettiğim herhangi bir görüntü görüntüleyici görüntünün iyi olduğunu gösterir. Yine de yazdırmak tuhaf sonuçlar doğurabilir.
Bildiğim kadarıyla standart uyumlu.
JMP
Talimatlar BITMAPFILEHEADER içindeki ayrılmış alanlardan birine yerleştirilirse daha kısa bir dosya oluşturulabilir . Bu, görüntü yüksekliğini 64 yerine -64 olarak depolamamıza izin verir, bu da BMP dosyalarının büyülü harikalar diyarında görüntü verilerinin doğru şekilde saklandığı anlamına gelir ve bu da basitleştirilmiş bir kod çözücüye izin verir.
şifre çözücü
Kod çözücüde belirli bir hile yok. Palet kodlayıcı tarafından doldurulur ve burada kukla değerlerle gösterilir. Bir tuşa basıldığında DOS'a dönmezse biraz daha kısa olabilir, ancak onsuz eğlenceli bir test değildi. Gerektiğini düşünüyorsanız, jmp $
birkaç bayt kaydetmek için son üç talimatı değiştirebilirsiniz . (İsterseniz dosya başlıklarını güncellemeyi unutmayın!)
BMP paletleri , sıfırlarla doldurulmuş BGR ( RGB değil ) üçüzleri olarak saklar . Bu, VGA paletini ayarlamayı normalden daha can sıkıcı hale getirir. BMP'lerin baş aşağı saklanması sadece lezzete (ve boyuta) katkıda bulunur.
NASM tarzında listelenmiştir:
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
zorluğun bir kısmı için bir çeşit kod ekliyoruz ve bunu olarak.png
görüntülerken bu.exe
-koduna dayalı değiştirilmiş pikseller var . Hala.png
görüntüleyebildiğimiz sürece buna izin veriliyor mu? Çıktı görüntüsünün de en az 4 rengi olması gerekir mi?