स्वयं-प्रदर्शित छवि [बंद]


11

पृष्ठभूमि

सेल्फ एक्सट्रैक्टिंग .ZIPफाइलें हैं। आमतौर पर उनके पास एक्सटेंशन होता है .EXE(और फ़ाइल को निष्पादित करके उन्हें निकाला जाएगा) लेकिन जब उनका नाम बदलकर .ZIPआप कुछ ज़िप निकालने वाले सॉफ़्टवेयर के साथ फ़ाइल खोल सकते हैं।

(यह संभव है क्योंकि .EXEफाइलों के लिए एक निश्चित हेडर की .ZIPआवश्यकता होती है, लेकिन फाइलों को एक निश्चित ट्रेलर की आवश्यकता होती है, इसलिए ऐसी फाइल का निर्माण संभव है जिसमें दोनों का .EXEहेडर और .ZIPट्रेलर हो।)

आपका कार्य:

एक प्रोग्राम बनाएं जो "सेल्फ-डिस्प्लेिंग" इमेज फाइल बनाता है:

  • कार्यक्रम कुछ 64x64 छवि (कम से कम 4 रंगों का समर्थन करेगा) इनपुट के रूप में और कुछ "संयुक्त" फ़ाइल आउटपुट के रूप में ले जाएगा
  • कार्यक्रम की आउटपुट फ़ाइल को आम छवि दर्शकों द्वारा छवि फ़ाइल के रूप में मान्यता दी जाएगी
  • छवि दर्शक के साथ आउटपुट फ़ाइल खोलते समय, इनपुट छवि प्रदर्शित की जाएगी
  • आउटपुट फ़ाइल को किसी भी ऑपरेटिंग सिस्टम या कंप्यूटर प्रकार के लिए निष्पादन योग्य फ़ाइल के रूप में भी पहचाना जाएगा

    (यदि एक असामान्य ऑपरेटिंग सिस्टम या कंप्यूटर के लिए एक फ़ाइल का उत्पादन किया जाता है, तो यह अच्छा होगा यदि एक ओपन-सोर्स पीसी एमुलेटर मौजूद है। हालांकि, इसकी आवश्यकता नहीं है।)

  • आउटपुट फ़ाइल निष्पादित करते समय, इनपुट छवि भी प्रदर्शित की जाएगी
  • यह संभव है कि (से उदाहरण के लिए फ़ाइल का नाम बदलने .PNGके लिए .COM) के लिए आवश्यक है
  • यह आवश्यक नहीं है कि प्रोग्राम और यह आउटपुट फाइल उसी OS पर चले; कार्यक्रम उदाहरण के लिए एक विंडोज प्रोग्राम और आउटपुट फाइल हो सकता है जिसे कमोडोर C64 पर निष्पादित किया जा सकता है।

कसौटी जीतना

  • प्रोग्राम जो सबसे छोटी आउटपुट फ़ाइल जीतता है
  • यदि आउटपुट फ़ाइल का आकार इनपुट छवि के आधार पर भिन्न होता है (उदाहरण के लिए क्योंकि प्रोग्राम छवि को संपीड़ित करता है), तो प्रोग्राम द्वारा बनाई गई सबसे बड़ी संभव आउटपुट फ़ाइल 4 रंगों तक की 64x64 छवि का प्रतिनिधित्व करती है।

वैसे

StackOverflow पर इस प्रश्न को पढ़ते समय मुझे निम्नलिखित प्रोग्रामिंग पहेली का विचार आया


मैंने जीतने की स्थिति के टैग (कोड-चुनौती को मेटाफॉल्फ - सबसे कम आउटपुट) के साथ जोड़ा है। इनपुट 64x64 छवि के लिए, क्या आपके पास कुछ उदाहरण चित्र हैं? इसके अलावा, क्या छवि को देखने पर भी ऐसा ही होना चाहिए? या आउटपुट इमेज और इनपुट इमेज अलग हो सकती है? अधिक ठोस होने के लिए: मान लें कि हम .exeचुनौती के भाग के लिए किसी प्रकार का कोड जोड़ते हैं , और जब इसे देखते हैं तो .pngइस .exe-कोड के आधार पर संशोधित पिक्सेल होते हैं । क्या यह अनुमति है जब तक यह अभी भी .pngहम देख सकते हैं? क्या आउटपुट इमेज में भी कम से कम 4 रंग होने चाहिए?
केविन क्रूज़सेन

2
आप "आम छवि दर्शक" कैसे परिभाषित करते हैं? उदाहरण के लिए, क्या एचटीएमएल "कोड" गिनती के साथ एक इंटरनेट ब्राउज़र है?
जो राजा

@KevinCruijssen जब छवि फ़ाइल के रूप में व्याख्या की जाती है, तो आउटपुट फ़ाइल इनपुट फ़ाइल के समान छवि का प्रतिनिधित्व करेगी: पिक्सेल में समान चौड़ाई और ऊँचाई और प्रत्येक पिक्सेल का रंग एक जैसा होगा। यदि फ़ाइल प्रारूप बिल्कुल उसी रंग पैलेट का समर्थन नहीं करते हैं, तो प्रत्येक पिक्सेल के रंग यथासंभव निकट होंगे। निष्पादन योग्य फ़ाइल के रूप में व्याख्या की गई फ़ाइल के लिए भी यही सच है। यदि आउटपुट फ़ाइल "पूर्ण स्क्रीन" प्रोग्राम का प्रतिनिधित्व करती है, तो यह स्क्रीन पर कहीं भी छवि प्रदर्शित कर सकता है (केंद्रित, ऊपरी-बाएं किनारे, ...) या इसे पूर्ण स्क्रीन आकार में फैलाएं।
मार्टिन रोसेनौ

1
@JoKing "सामान्य छवि दर्शकों द्वारा मान्यता प्राप्त" का अर्थ है कि फ़ाइल प्रारूप को या तो पहले से इंस्टॉल किए गए सॉफ़्टवेयर (जैसे HTML) के साथ अधिकांश कंप्यूटरों द्वारा पढ़ा जा सकता है या यह कि बहुत सारे उपयोगकर्ता फ़ाइल को देखने के लिए एक नि: शुल्क उपकरण डाउनलोड करते हैं ( जैसे PDF)। मैं कहूंगा कि HTML + जावास्क्रिप्ट को कोड के रूप में देखा जा सकता है, हालांकि, "छवि दर्शक" को कोड निष्पादित नहीं करना चाहिए ! तो यह कहने की अनुमति होगी कि वेब ब्राउज़र एक "छवि दर्शक" है, लेकिन इस मामले में HTML "कोड" नहीं है। या आप कह सकते हैं कि HTML + JS "कोड" है, लेकिन इस मामले में वेब ब्राउज़र "छवि दर्शक" नहीं है।
मार्टिन रोसेनौ

2
इस तरह के एक दिलचस्प सवाल को बंद करना दुखद है। जहां तक ​​मैं समझता हूं, किसी प्रश्न को फिर से खोलने से पहले किसी भी चिंताओं पर ध्यान दिया जाना चाहिए। टिप्पणियों में मुख्य बातें "आम छवि दर्शक" शब्द है, जो अस्पष्ट होने के लिए पर्याप्त रूप से धुंधला है, और निष्पादन योग्य कोड की उपस्थिति के द्वारा अनियंत्रित स्थिति में (@ केविनक्रूजसेन की चिंता के अनुसार) प्रदर्शित की जाने वाली छवि स्पष्टीकरण के योग्य है । क्या उन चिंताओं को संबोधित करने वाला एक संपादन पर्याप्त होगा? (मैं "चार रंगों चार रंगों" अस्पष्टता को नहीं समझने की बात मानता हूं।)
गैस्ट्रोपनर

जवाबों:


5

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:

अच्छा लगा। मैं जोड़ी बीएमपी / एमएस-डॉस कॉम के बारे में भी सोच रहा था; मैंने इसे लागू किया होता अगर एक सप्ताह के भीतर कोई जवाब नहीं मिलता। हालाँकि, मुझे 10K से अधिक की आवश्यकता होगी: क्योंकि मैंने यह नहीं माना था कि रजिस्टरों को शून्य-आरंभीकृत किया गया है, मैंने फ़ाइल ऑफ़सेट 2 पर एक जम्प निर्देश दिया होगा। और क्योंकि इस फ़ील्ड को BMP फ़ाइलों में "फ़ाइल आकार" के रूप में व्याख्या की गई है, मुझे "फ़ाइल आकार" फ़ील्ड सही फ़ाइल आकार का प्रतिनिधित्व करता है यह सुनिश्चित करने के लिए "डमी" बाइट्स के साथ बीएमपी फ़ाइल को भरना होगा।
मार्टिन रोसेनौ

@MartinRosenau मुझे वास्तव में रजिस्टर मूल्यों में से कुछ को ग्रहण नहीं करना था जो मैं आमतौर पर करता हूं (जैसा कि fysnet.net/yourhelp.htm के अनुसार ), हेडर क्लॉबर रजिस्टर के बाद से, और यहां तक ​​कि PSP के पहले बाइट की भी आवश्यकता होती int 0x20है ret
गैस्ट्रोपनर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.