c++ ASCII कला रूपांतरण के लिए छवि



image-processing bitmap (1)

एएससीआईआई कला रूपांतरण के लिए छवि के लिए और अधिक दृष्टिकोण हैं जो ज्यादातर सादगी के लिए मोनो-स्पेस फोंट का उपयोग करने पर आधारित हैं , मैं केवल मूल बातें ही चिपकता हूं:

पिक्सेल / क्षेत्र तीव्रता आधारित (छायांकन)

यह दृष्टिकोण एकल बिंदु के रूप में पिक्सेल के क्षेत्र के प्रत्येक पिक्सेल को संभालता है। विचार इस डॉट की औसत ग्रे स्केल तीव्रता की गणना करना है और उसके बाद गणना के लिए पर्याप्त तीव्रता वाले चरित्र के साथ इसे प्रतिस्थापित करना है। इसके लिए हमें पूर्ववर्ती तीव्रता वाले प्रत्येक प्रयोग करने योग्य पात्रों की कुछ सूची की आवश्यकता है, इसे चरित्र map कहें। अधिक तेज़ी से चुनने के लिए कौन सा चरित्र सबसे अच्छा है जिसके लिए तीव्रता दो तरीके हैं:

  1. रैखिक रूप से वितरित तीव्रता चरित्र मानचित्र

    इसलिए हम केवल उन्हीं पात्रों का उपयोग करते हैं जिनमें एक ही चरण के साथ तीव्रता अंतर होता है। दूसरे शब्दों में जब आरोही क्रमबद्ध किया गया तो:

    intensity_of(map[i])=intensity_of(map[i-1])+constant;
    

    साथ ही जब हमारे चरित्र map को क्रमबद्ध किया जाता है तो हम सीधे तीव्रता से चरित्र की गणना कर सकते हैं (कोई खोज आवश्यक नहीं है)

    character=map[intensity_of(dot)/constant];
    
  2. मनमाना वितरित तीव्रता चरित्र मानचित्र

    तो हमारे पास उपयोग करने योग्य पात्रों और उनकी तीव्रताएं हैं। हमें intensity_of(dot) सबसे नज़दीकी तीव्रता की आवश्यकता है तो फिर यदि हम map[] सॉर्ट करते हैं map[] हम बाइनरी खोज का उपयोग कर सकते हैं अन्यथा हमें O(n) खोज न्यूनतम दूरी लूप या O(1) शब्दकोश की आवश्यकता है। कभी-कभी सादगी के लिए चरित्र map[] को रैखिक रूप से वितरित के रूप में संभाला जा सकता है जिससे परिणामस्वरूप आमतौर पर अवांछित गामा विरूपण होता है जब तक आप नहीं जानते कि क्या देखना है।

तीव्रता आधारित रूपांतरण ग्रे-स्केल छवियों के लिए भी महान है (न केवल काले और सफेद)। यदि आप एक पिक्सेल के रूप में डॉट का चयन करते हैं तो परिणाम बड़ा होता है (1 पिक्सेल -> एकल वर्ण) ताकि बड़ी छवियों के लिए पहलू अनुपात को संरक्षित करने के लिए एक क्षेत्र (फ़ॉन्ट आकार का गुणा) चुना गया हो और बहुत अधिक विस्तार न करें।

यह कैसे करना है:

  1. इसलिए छवि को (ग्रे-स्केल) पिक्सेल या (आयताकार) क्षेत्रों में समान रूप से विभाजित करें
  2. प्रत्येक पिक्सेल / क्षेत्र की तीव्रता की गणना करें
  3. निकटतम तीव्रता वाले चरित्र मानचित्र से चरित्र द्वारा इसे प्रतिस्थापित करें

चरित्र map रूप में आप किसी भी वर्ण का उपयोग कर सकते हैं लेकिन परिणाम बेहतर हो जाता है यदि चरित्र में वर्ण क्षेत्र के साथ समान रूप से फैले हुए पिक्सल होते हैं। शुरुआत के लिए आप इसका उपयोग कर सकते हैं:

  • char map[10]=" .,:;ox%#@";

क्रमबद्ध रूप से वितरित होने का नाटक और नाटक।

तो यदि पिक्सेल / क्षेत्र की तीव्रता i = <0-255> तो प्रतिस्थापन वर्ण होगा

  • map[(255-i)*10/256];

अगर i==0 तो पिक्सेल / क्षेत्र काला है, अगर i==127 तो पिक्सेल / क्षेत्र ग्रे है और यदि i==255 तो पिक्सेल / क्षेत्र सफेद है। आप map[] अंदर विभिन्न पात्रों के साथ प्रयोग कर सकते हैं map[] ...

यहां सी ++ और वीसीएल में मेरा प्राचीन उदाहरण है:

AnsiString m=" .,:;ox%#@";
Graphics::TBitmap *bmp=new Graphics::TBitmap;
bmp->LoadFromFile("pic.bmp");
bmp->HandleType=bmDIB;
bmp->PixelFormat=pf24bit;

int x,y,i,c,l;
BYTE *p;
AnsiString s,endl;
endl=char(13); endl+=char(10);
l=m.Length();
s="";
for (y=0;y<bmp->Height;y++)
    {
    p=(BYTE*)bmp->ScanLine[y];
    for (x=0;x<bmp->Width;x++)
        {
        i =p[x+x+x+0];
        i+=p[x+x+x+1];
        i+=p[x+x+x+2];
        i=(i*l)/768;
        s+=m[l-i];
        }
    s+=endl;
    }
mm_log->Lines->Text=s;
mm_log->Lines->SaveToFile("pic.txt");
delete bmp;

जब तक आप बोर्लैंड / एम्बरकेडेरो पर्यावरण का उपयोग नहीं करते हैं, तब तक आपको वीसीएल सामान को प्रतिस्थापित / अनदेखा करने की आवश्यकता होती है

  • mm_log ज्ञापन है जहां टेक्स्ट mm_log जाता है
  • bmp इनपुट बिटमैप है
  • AnsiString वीसीएल प्रकार स्ट्रिंग अनुक्रमित रूप 1 है 0 से 0 char* !!!

यह परिणाम है: थोड़ा एनएसएफडब्ल्यू तीव्रता उदाहरण छवि

बाईं तरफ ASCII कला आउटपुट (फ़ॉन्ट आकार 5 पीएक्स) है, और सही इनपुट छवि पर कुछ बार ज़ूम किया गया है। जैसा कि आप देख सकते हैं कि आउटपुट बड़ा पिक्सेल -> वर्ण है। यदि आप पिक्सेल के बजाय बड़े क्षेत्रों का उपयोग करते हैं तो ज़ूम छोटा होता है लेकिन निश्चित रूप से आउटपुट कम दृष्टि से सुखद होता है। यह दृष्टिकोण कोड / प्रक्रिया के लिए बहुत आसान और तेज़ है।

जब आप अधिक उन्नत चीजें जोड़ते हैं जैसे:

  • स्वचालित नक्शा गणना
  • स्वचालित पिक्सेल / क्षेत्र आकार चयन
  • पहलू अनुपात सुधार

फिर आप बेहतर परिणामों के साथ अधिक जटिल छवियों को संसाधित कर सकते हैं:

यहां परिणाम 1: 1 अनुपात (वर्ण देखने के लिए ज़ूम करें):

बेशक क्षेत्र नमूनाकरण के लिए आप छोटे विवरण खो देते हैं। यह क्षेत्र के साथ नमूने वाले पहले उदाहरण के समान आकार की छवि है:

थोड़ा एनएसएफडब्ल्यू तीव्रता उन्नत उदाहरण छवि

जैसा कि आप देख सकते हैं कि यह बड़ी छवियों के लिए अधिक उपयुक्त है

चरित्र फिटिंग (छायांकन और ठोस ASCII कला के बीच संकर)

यह दृष्टिकोण समान तीव्रता और आकार वाले चरित्र के साथ क्षेत्र (कोई और पिक्सेल बिंदु नहीं) को प्रतिस्थापित करने का प्रयास करता है। इससे दूसरे दृष्टिकोण पर पिछले दृष्टिकोण की तुलना में बड़े फ़ॉन्ट्स के साथ बेहतर परिणाम भी मिलते हैं, यह दृष्टिकोण निश्चित रूप से धीमा है। ऐसा करने के कई तरीके हैं लेकिन मुख्य विचार छवि क्षेत्र ( dot ) और प्रस्तुत चरित्र के बीच अंतर (दूरी) की गणना करना है। आप पिक्सल के बीच abs abs के बेवकूफ योग के साथ शुरू कर सकते हैं लेकिन इससे बहुत अच्छे नतीजे नहीं आएंगे क्योंकि एक पिक्सेल शिफ्ट भी दूरी को बड़ा कर देगा, इसके बजाय आप सहसंबंध या विभिन्न मीट्रिक का उपयोग कर सकते हैं। समग्र एल्गोरिदम लगभग पिछले दृष्टिकोण जैसा ही है:

  1. इसलिए समान रूप से छवि को (ग्रे-स्केल) आयताकार क्षेत्रों में विभाजित करें
    • आदर्श रूप से समान वर्ण अनुपात के साथ फ़ॉन्ट वर्ण प्रस्तुत किए जाते हैं (यह पहलू अनुपात को संरक्षित रखेगा, यह न भूलें कि वर्ण आमतौर पर एक्स अक्ष में थोड़ा ओवरलैप करते हैं)
  2. प्रत्येक क्षेत्र की तीव्रता की गणना करें ( dot )
  3. निकटतम तीव्रता / आकार के साथ चरित्र map से चरित्र द्वारा इसे प्रतिस्थापित map

चरित्र और बिंदु के बीच दूरी की गणना कैसे करें? यह इस दृष्टिकोण का सबसे कठिन हिस्सा है। प्रयोग करते समय मैं गति, गुणवत्ता और सरलता के बीच इस समझौता को विकसित करता हूं:

  1. क्षेत्र क्षेत्र को क्षेत्र में विभाजित करें

    • अपने रूपांतरण वर्णमाला ( map ) से प्रत्येक वर्ण के बाएं, दाएं, ऊपर, नीचे, और केंद्र क्षेत्र के लिए अलग तीव्रता की गणना map
    • सभी तीव्रता को सामान्य करें ताकि वे क्षेत्र के आकार i=(i*256)/(xs*ys) पर स्वतंत्र हों
  2. आयताकार क्षेत्रों में प्रक्रिया स्रोत छवि

    • (लक्ष्य फ़ॉन्ट के समान पहलू अनुपात के साथ)
    • बुलेट 1 के समान तरीके से प्रत्येक क्षेत्र गणना तीव्रता के लिए
    • रूपांतरण वर्णमाला में तीव्रता से निकटतम मिलान पाएं
    • उत्पादन फिट चरित्र

यह फ़ॉन्ट आकार = 7 पीएक्स के लिए परिणाम है

जैसा कि आप देख सकते हैं कि आउटपुट बड़े फ़ॉन्ट आकार के साथ भी दृष्टि से प्रसन्न होता है (पिछला दृष्टिकोण उदाहरण 5px फ़ॉन्ट आकार के साथ था)। आउटपुट इनपुट छवि के रूप में मोटे तौर पर एक ही आकार है (कोई ज़ूम नहीं)। बेहतर परिणाम प्राप्त किए जाते हैं क्योंकि पात्र न केवल तीव्रता से बल्कि समग्र आकार के आधार पर मूल छवि के करीब होते हैं और इसलिए आप बड़े फोंट का उपयोग कर सकते हैं और अभी भी विवरण संरक्षित कर सकते हैं (मोटे तौर पर एक बिंदु तक)।

यहां वीसीएल आधारित रूपांतरण ऐप के लिए कोड पूरा करें:

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "win_main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
Graphics::TBitmap *bmp=new Graphics::TBitmap;
//---------------------------------------------------------------------------
class intensity
    {
public:
    char c;                 // character
    int il,ir,iu,id,ic;     // intensity of part: left,right,up,down,center
    intensity() { c=0; reset(); }
    void reset() { il=0; ir=0; iu=0; id=0; ic=0; }
    void compute(DWORD **p,int xs,int ys,int xx,int yy) // p source image, (xs,ys) area size, (xx,yy) area position
        {
        int x0=xs>>2,y0=ys>>2;
        int x1=xs-x0,y1=ys-y0;
        int x,y,i;
        reset();
        for (y=0;y<ys;y++)
         for (x=0;x<xs;x++)
            {
            i=(p[yy+y][xx+x]&255);
            if (x<=x0) il+=i;
            if (x>=x1) ir+=i;
            if (y<=x0) iu+=i;
            if (y>=x1) id+=i;
            if ((x>=x0)&&(x<=x1)
              &&(y>=y0)&&(y<=y1)) ic+=i;
            }
        // normalize
        i=xs*ys;
        il=(il<<8)/i;
        ir=(ir<<8)/i;
        iu=(iu<<8)/i;
        id=(id<<8)/i;
        ic=(ic<<8)/i;
        }
    };
//---------------------------------------------------------------------------
AnsiString bmp2txt_big(Graphics::TBitmap *bmp,TFont *font) // charcter sized areas
    {
    int i,i0,d,d0;
    int xs,ys,xf,yf,x,xx,y,yy;
    DWORD **p=NULL,**q=NULL;    // bitmap direct pixel access
    Graphics::TBitmap *tmp;     // temp bitmap for single character
    AnsiString txt="";          // output ASCII art text
    AnsiString eol="\r\n";      // end of line sequence
    intensity map[97];          // character map
    intensity gfx;

    // input image size
    xs=bmp->Width;
    ys=bmp->Height;
    // output font size
    xf=font->Size;   if (xf<0) xf=-xf;
    yf=font->Height; if (yf<0) yf=-yf;
    for (;;) // loop to simplify the dynamic allocation error handling
        {
        // allocate and init buffers
        tmp=new Graphics::TBitmap; if (tmp==NULL) break;
            // allow 32bit pixel access as DWORD/int pointer
            tmp->HandleType=bmDIB;    bmp->HandleType=bmDIB;
            tmp->PixelFormat=pf32bit; bmp->PixelFormat=pf32bit;
            // copy target font properties to tmp
            tmp->Canvas->Font->Assign(font);
            tmp->SetSize(xf,yf);
            tmp->Canvas->Font ->Color=clBlack;
            tmp->Canvas->Pen  ->Color=clWhite;
            tmp->Canvas->Brush->Color=clWhite;
            xf=tmp->Width;
            yf=tmp->Height;
        // direct pixel access to bitmaps
        p  =new DWORD*[ys];        if (p  ==NULL) break; for (y=0;y<ys;y++) p[y]=(DWORD*)bmp->ScanLine[y];
        q  =new DWORD*[yf];        if (q  ==NULL) break; for (y=0;y<yf;y++) q[y]=(DWORD*)tmp->ScanLine[y];
        // create character map
        for (x=0,d=32;d<128;d++,x++)
            {
            map[x].c=char(DWORD(d));
            // clear tmp
            tmp->Canvas->FillRect(TRect(0,0,xf,yf));
            // render tested character to tmp
            tmp->Canvas->TextOutA(0,0,map[x].c);
            // compute intensity
            map[x].compute(q,xf,yf,0,0);
            } map[x].c=0;
        // loop through image by zoomed character size step
        xf-=xf/3; // characters are usually overlaping by 1/3
        xs-=xs%xf;
        ys-=ys%yf;
        for (y=0;y<ys;y+=yf,txt+=eol)
         for (x=0;x<xs;x+=xf)
            {
            // compute intensity
            gfx.compute(p,xf,yf,x,y);
            // find closest match in map[]
            i0=0; d0=-1;
            for (i=0;map[i].c;i++)
                {
                d=abs(map[i].il-gfx.il)
                 +abs(map[i].ir-gfx.ir)
                 +abs(map[i].iu-gfx.iu)
                 +abs(map[i].id-gfx.id)
                 +abs(map[i].ic-gfx.ic);
                if ((d0<0)||(d0>d)) { d0=d; i0=i; }
                }
            // add fitted character to output
            txt+=map[i0].c;
            }
        break;
        }
    // free buffers
    if (tmp) delete tmp;
    if (p  ) delete[] p;
    return txt;
    }
//---------------------------------------------------------------------------
AnsiString bmp2txt_small(Graphics::TBitmap *bmp)    // pixel sized areas
    {
    AnsiString m=" `'.,:;i+o*%&$#@"; // constant character map
    int x,y,i,c,l;
    BYTE *p;
    AnsiString txt="",eol="\r\n";
    l=m.Length();
    bmp->HandleType=bmDIB;
    bmp->PixelFormat=pf32bit;
    for (y=0;y<bmp->Height;y++)
        {
        p=(BYTE*)bmp->ScanLine[y];
        for (x=0;x<bmp->Width;x++)
            {
            i =p[(x<<2)+0];
            i+=p[(x<<2)+1];
            i+=p[(x<<2)+2];
            i=(i*l)/768;
            txt+=m[l-i];
            }
        txt+=eol;
        }
    return txt;
    }
//---------------------------------------------------------------------------
void update()
    {
    int x0,x1,y0,y1,i,l;
    x0=bmp->Width;
    y0=bmp->Height;
    if ((x0<64)||(y0<64)) Form1->mm_txt->Text=bmp2txt_small(bmp);
     else                 Form1->mm_txt->Text=bmp2txt_big  (bmp,Form1->mm_txt->Font);
    Form1->mm_txt->Lines->SaveToFile("pic.txt");
    for (x1=0,i=1,l=Form1->mm_txt->Text.Length();i<=l;i++) if (Form1->mm_txt->Text[i]==13) { x1=i-1; break; }
    for (y1=0,i=1,l=Form1->mm_txt->Text.Length();i<=l;i++) if (Form1->mm_txt->Text[i]==13) y1++;
    x1*=abs(Form1->mm_txt->Font->Size);
    y1*=abs(Form1->mm_txt->Font->Height);
    if (y0<y1) y0=y1; x0+=x1+48;
    Form1->ClientWidth=x0;
    Form1->ClientHeight=y0;
    Form1->Caption=AnsiString().sprintf("Picture -> Text ( Font %ix%i )",abs(Form1->mm_txt->Font->Size),abs(Form1->mm_txt->Font->Height));
    }
//---------------------------------------------------------------------------
void draw()
    {
    Form1->ptb_gfx->Canvas->Draw(0,0,bmp);
    }
//---------------------------------------------------------------------------
void load(AnsiString name)
    {
    bmp->LoadFromFile(name);
    bmp->HandleType=bmDIB;
    bmp->PixelFormat=pf32bit;
    Form1->ptb_gfx->Width=bmp->Width;
    Form1->ClientHeight=bmp->Height;
    Form1->ClientWidth=(bmp->Width<<1)+32;
    }
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner)
    {
    load("pic.bmp");
    update();
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
    {
    delete bmp;
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormPaint(TObject *Sender)
    {
    draw();
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormMouseWheel(TObject *Sender, TShiftState Shift,int WheelDelta, TPoint &MousePos, bool &Handled)
    {
    int s=abs(mm_txt->Font->Size);
    if (WheelDelta<0) s--;
    if (WheelDelta>0) s++;
    mm_txt->Font->Size=s;
    update();
    }
//---------------------------------------------------------------------------

यह एक साधारण फॉर्म ऐप (फॉर्म 1) है जिसमें सिंगल TMemo mm_txt है। यह छवि "pic.bmp" लोड करता है, फिर संकल्प के अनुसार, "pic.bmp" में सहेजे गए पाठ में कनवर्ट करने के लिए किस दृष्टिकोण का उपयोग करना है और विज़ुअलाइज़ करने के लिए ज्ञापन को भेजा गया है। वीसीएल के बिना उन लोगों के लिए वीसीएल सामानों को अनदेखा करें और आपके पास किसी भी स्ट्रिंग प्रकार के साथ AnsiString को प्रतिस्थापित करें, और Graphics::TBitmap को किसी भी बिटमैप या छवि वर्ग के साथ पिक्सेल एक्सेस क्षमता के साथ निपटान करें।

बहुत महत्वपूर्ण नोट यह है कि यह mm_txt->Font की सेटिंग्स का उपयोग करता है, इसलिए सुनिश्चित करें कि आप सेट करते हैं:

  • Font->Pitch=fpFixed
  • Font->Charset=OEM_CHARSET
  • Font->Name="System"

इस काम को सही तरीके से करने के लिए अन्यथा मोनो-स्पेस के रूप में फ़ॉन्ट को संभाला नहीं जाएगा। माउस व्हील विभिन्न फ़ॉन्ट आकारों पर परिणाम देखने के लिए फ़ॉन्ट आकार को ऊपर / नीचे बदल देता है

[टिप्पणियाँ]

  • वर्ड पोर्ट्रेट विज़ुअलाइज़ेशन देखें
  • बिटमैप / फ़ाइल एक्सेस और टेक्स्ट आउटपुट क्षमताओं के साथ भाषा का उपयोग करें
  • पहले दृष्टिकोण से शुरू करने की दृढ़ता से अनुशंसा करते हैं क्योंकि यह बहुत आसान स्ट्रेट आगे और सरल है, और उसके बाद केवल दूसरे स्थान पर जाता है (जिसे पहले के संशोधन के रूप में किया जा सकता है, इसलिए कोड का अधिकांश हिस्सा वैसे भी रहता है)
  • उलटा तीव्रता (काला पिक्सल अधिकतम मान है) के साथ गणना करना एक अच्छा विचार है क्योंकि मानक पाठ पूर्वावलोकन सफेद पृष्ठभूमि पर है इसलिए बहुत बेहतर परिणाम होते हैं।
  • आप सबडिविजन जोन के आकार, गिनती और लेआउट के साथ प्रयोग कर सकते हैं या इसके बजाय 3x3 जैसे कुछ ग्रिड का उपयोग कर सकते हैं।

[संपादन 1] तुलना

अंत में एक ही इनपुट पर दो दृष्टिकोणों के बीच तुलना है:

हरे रंग की डॉट चिह्नित छवियों को दृष्टिकोण # 2 के साथ किया जाता है और लाल रंग # 1 के साथ 6 पिक्सेल फ़ॉन्ट आकार पर होते हैं। जैसा कि आप लाइट बल्ब छवि पर देख सकते हैं, आकार संवेदनशील दृष्टिकोण बहुत बेहतर है (भले ही # 1 2x ज़ूम किए गए स्रोत छवि पर किया गया हो)।

[संपादित 2] शांत ऐप

आज के नए प्रश्नों को पढ़ने के दौरान मुझे एक शांत ऐप का आइडिया मिला जो डेस्कटॉप के चुने हुए क्षेत्र को पकड़ता है और इसे लगातार ASCIIart कनवर्टर को खिलाता है और परिणाम देखता है। कोडिंग के एक घंटे बाद यह पूरा हो गया और मैं परिणाम से इतना संतुष्ट हूं कि मुझे इसे यहां जोड़ना होगा।

ठीक है ऐप सिर्फ 2 विंडोज़ से है। पहली मास्टर विंडो मूल रूप से छवि चयन और पूर्वावलोकन के बिना मेरी पुरानी कनवर्टर विंडो है (ऊपर की सभी चीजें इसमें हैं)। इसमें केवल ASCII पूर्वावलोकन और रूपांतरण सेटिंग्स हैं। दूसरी विंडो हथियाने वाले क्षेत्र चयन के लिए पारदर्शी अंदर खाली फॉर्म है (कोई कार्यक्षमता नहीं है)।

अब टाइमर पर मैं चयन क्षेत्र द्वारा चयनित क्षेत्र को पकड़ता हूं , इसे रूपांतरण में पास करता हूं और ASCIIart का पूर्वावलोकन करता हूं

तो आप उस क्षेत्र को संलग्न करते हैं जिसे आप चयन विंडो द्वारा कनवर्ट करना चाहते हैं और परिणाम को मास्टर विंडो में देखना चाहते हैं। यह एक खेल, दर्शक हो सकता है ... ऐसा लगता है:

तो अब मैं मजेदार के लिए ASCIIart में भी वीडियो देख सकता हूं। कुछ वास्तव में अच्छे हैं :)।

[Edit3]

यदि आप जीएलएसएल में इसे लागू करने की कोशिश करना चाहते हैं तो इसे देखें:

  • जीएलएसएल में फ्लोटिंग-पॉइंट संख्याओं को दशमलव अंकों में कनवर्ट करें?

प्रस्तावना

यह विषय समय-समय पर SO पर पॉप अप करता है, लेकिन आमतौर पर खराब लिखित प्रश्न होने के कारण इसे हटा दिया जाता है। जब मैंने अतिरिक्त जानकारी का अनुरोध किया तो मैंने कई ऐसे प्रश्न देखे और फिर ओपी (सामान्य कम प्रतिनिधि) से चुप्पी देखी। समय-समय पर इनपुट मेरे लिए काफी अच्छा है, मैं जवाब के साथ जवाब देने का फैसला करता हूं और सक्रिय रूप से प्रतिदिन कुछ अप-वोट प्राप्त होता है लेकिन कुछ हफ्तों के बाद प्रश्न हटा दिया जाता है / हटा दिया जाता है और सभी शुरुआत से शुरू होते हैं । तो मैंने इस क्यू एंड ए को लिखने का फैसला किया ताकि मैं इस तरह के प्रश्नों को सीधे उत्तर दोबारा जवाब देने के बिना संदर्भित कर सकूं ...

एक अन्य कारण यह भी है कि यह मेटा थ्रेड मुझ पर लक्षित है ताकि अगर आपको अतिरिक्त इनपुट मिल जाए तो टिप्पणी करने के लिए स्वतंत्र महसूस करें।

सवाल

सी ++ का उपयोग कर बिटमैप छवि को ASCII कला में कैसे परिवर्तित करें?

कुछ बाधाएं:

  • ग्रे पैमाने छवियों
  • मोनो-स्पेस फोंट का उपयोग करना
  • इसे सरल रखना (शुरुआती स्तर के प्रोग्रामर के लिए बहुत उन्नत सामग्री का उपयोग नहीं करना)

यहां एक संबंधित विकी पृष्ठ ASCII कला है (@RogerRowland के लिए धन्यवाद)





ascii-art