চিত্রটি ASCII শিল্প রূপান্তর করতে


105

প্রোলগ

এই সাবজেক্টটি এখানে সময়ে সময়ে স্ট্যাক ওভারফ্লোতে পপ আপ হয় তবে এটি একটি দুর্বল লিখিত প্রশ্ন হওয়ার কারণে এটি সরানো হয়। আমি এই জাতীয় অনেকগুলি প্রশ্ন দেখেছি এবং তারপরে অতিরিক্ত তথ্যের জন্য অনুরোধ করা হলে ওপি (স্বাভাবিক লো রেপ) থেকে নীরবতা রেখেছি । সময়ে সময়ে যদি ইনপুটটি আমার পক্ষে যথেষ্ট ভাল হয় তবে আমি একটি উত্তর দিয়ে সাড়া দেওয়ার সিদ্ধান্ত নিয়েছি এবং এটি সচল থাকাকালীন প্রতিদিন প্রতিদিন কয়েকটি আপ-ভোট পায় তবে কয়েক সপ্তাহ পরে প্রশ্নটি মুছে ফেলা / মুছে ফেলা হয় এবং সমস্ত থেকে শুরু হয় শুরু সুতরাং আমি এই প্রশ্নোত্তর লিখতে সিদ্ধান্ত নিয়েছি তাই উত্তরগুলি বারবার লিখে না দিয়ে সরাসরি এই জাতীয় প্রশ্নগুলি উল্লেখ করতে পারি…

আরেকটি কারণও হ'ল এই মেটা থ্রেডটি আমার লক্ষ্যবস্তু তাই আপনি যদি অতিরিক্ত ইনপুট পান তবে বিনা দ্বিধায় মন্তব্য করুন।

প্রশ্ন

আমি কীভাবে সি ++ ব্যবহার করে বিটম্যাপ চিত্রকে ASCII আর্টে রূপান্তর করতে পারি ?

কিছু বাধা:

  • ধূসর স্কেল ইমেজ
  • মনো-স্পেসড ফন্ট ব্যবহার করে
  • এটিকে সহজ করে তোলা (প্রাথমিক স্তরের প্রোগ্রামারদের জন্য খুব উন্নত জিনিস ব্যবহার না করা)

এখানে সম্পর্কিত উইকিপিডিয়া পৃষ্ঠা ASCII শিল্প (@ রোজাররোল্যান্ডকে ধন্যবাদ)।

এখানে ASCII আর্ট রূপান্তর প্রশ্নোত্তর সাথে অনুরূপ গোলকধাঁধা


এই উইকি পৃষ্ঠাটি একটি রেফারেন্স হিসাবে ব্যবহার করে আপনি কোন ধরণের এএসসিআইআই আর্টের উল্লেখ করছেন তা পরিষ্কার করে বলতে পারেন? এটি আমার কাছে "চিত্র থেকে টেক্সট রূপান্তর" এর মতো মনে হচ্ছে যা গ্রেস্কেল পিক্সেল থেকে সংশ্লিষ্ট পাঠ্য চরিত্রের জন্য "সরল" চেহারা - তাই আমি ভাবছি আপনি অন্যরকম কিছু বোঝেন কিনা। দেখে মনে হচ্ছে আপনি যাইহোক এটির নিজের উত্তর দিতে চলেছেন .....
রজার রোল্যান্ড

সংশ্লিষ্ট: stackoverflow.com/q/26347985/2564301
Jongware

@ রোজাররোল্যান্ড উভয়ই সহজ (কেবলমাত্র গ্রেস্কেলের তীব্রতা ভিত্তিক) এবং আরও উন্নত অ্যাকাউন্টগুলি গ্রহণ করা অক্ষরের
আকারও

4
যদিও আপনার কাজ দুর্দান্ত, আমি অবশ্যই নমুনাগুলির একটি নির্বাচনের প্রশংসা করব যা কিছুটা বেশি এসএফডাব্লু।
কিমিওট করুন

@ টিমকাস্টেলিজানস যদি আপনি এই প্রবন্ধটি পড়ে থাকেন তবে আপনি দেখতে পাচ্ছেন যে এই জাতীয় উত্তরটি প্রথমবারের মতো অনুরোধ করা হয়নি (এবং বেশিরভাগ ভোটার যেখানে পূর্ববর্তী কয়েকটি প্রশ্নের সাথে পরিচিত তাই বাকিরা সেই অনুযায়ী ভোট দিয়েছেন), কারণ এটি প্রশ্নোত্তর নয় কেবল প্রশ্ন আমি কিউ অংশের সাথে খুব বেশি সময় নষ্ট করিনি (যা আমি স্বীকার করি যে আমার পক্ষে দোষ) প্রশ্নটিতে কয়েকটি সীমাবদ্ধতা যুক্ত করেছি যদি আপনি কোনও উন্নত ব্যক্তিদের সম্পাদনা করতে নির্দ্বিধায় পান তবে।
স্পেকট্রে

উত্তর:


156

এএসসিআইআই আর্ট রূপান্তরকে চিত্রের জন্য আরও পন্থা রয়েছে যা বেশিরভাগ মনো-ফাঁক ফন্টগুলি ব্যবহারের উপর ভিত্তি করে । সরলতার জন্য, আমি কেবল বুনিয়াদিগুলিতে আছি:

পিক্সেল / অঞ্চল তীব্রতা ভিত্তিক (শেডিং)

এই পদ্ধতির একক ডট হিসাবে পিক্সেলের ক্ষেত্রের প্রতিটি পিক্সেল পরিচালনা করে। ধারণাটি হ'ল এই বিন্দুর গড় ধূসর স্কেল তীব্রতা গণনা করা এবং তারপরে এটির সাথে এটির সাথে ঘনিষ্ঠ পর্যায়ে ঘনত্বের সাথে চরিত্রটি প্রতিস্থাপন করা হবে। তার জন্য আমাদের ব্যবহারযোগ্য অক্ষরগুলির কয়েকটি তালিকা প্রয়োজন, প্রতিটি পূর্বের তীব্রতার সাথে। একে একে একটি চরিত্র বলি map। কোন তীব্রতার জন্য কোন চরিত্রটি সেরা তা আরও দ্রুত চয়ন করার জন্য দুটি উপায় রয়েছে:

  1. রৈখিকভাবে বিতরণ করা তীব্রতা চরিত্রের মানচিত্র

    সুতরাং আমরা কেবলমাত্র অক্ষর ব্যবহার করি যার একই ধাপের সাথে একটি তাত্পর্যপূর্ণ পার্থক্য রয়েছে। অন্য কথায়, যখন আরোহণের বাছাই করা হয় তখন:

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

    এছাড়াও যখন আমাদের চরিত্রটি mapসাজানো হয় তখন আমরা তীব্রতা থেকে সরাসরি চরিত্রটি গণনা করতে পারি (অনুসন্ধানের প্রয়োজন নেই)

     character = map[intensity_of(dot)/constant];
    
  2. নির্বিচারে বিতরণ করা তীব্রতা চরিত্রের মানচিত্র

    সুতরাং আমরা ব্যবহারযোগ্য অক্ষর এবং তাদের তীব্রতা অ্যারে আছে। আমাদের intensity_of(dot)আবার map[]সান্নিধ্যের সন্ধান করতে হবে যদি আমরা আবার বাছাই করি তবে আমরা বাইনারি অনুসন্ধান ব্যবহার করতে পারি, অন্যথায় আমাদের O(n)সন্ধানের ন্যূনতম দূরত্বের লুপ বা O(1)অভিধান প্রয়োজন। কখনও কখনও সরলতার জন্য, চরিত্রটি map[]রৈখিকভাবে বিতরণ হিসাবে পরিচালনা করা যায়, একটি সামান্য গামা বিকৃতি ঘটায়, ফলস্বরূপ সাধারণত অদেখা হয় যদি না আপনি কী সন্ধান করতে চান তবে।

ধূসর-স্কেল চিত্রগুলির জন্য (কেবল কালো এবং সাদা নয়) তীব্রতা ভিত্তিক রূপান্তরকরণ দুর্দান্ত। আপনি যদি বিন্দুটিকে একটি একক পিক্সেল হিসাবে নির্বাচন করেন, ফলাফলটি বড় (এক পিক্সেল -> একক অক্ষর) পায়, তাই বৃহত্তর চিত্রগুলির জন্য দিক অনুপাত সংরক্ষণের পরিবর্তে একটি অঞ্চল (ফন্টের আকারের গুণ) নির্বাচন করা হয় এবং খুব বেশি বড় করা হবে না।

এটা কিভাবে করতে হবে:

  1. সমানভাবে (ধূসর স্কেল) পিক্সেল বা ছবিটি ভাগ (আয়তক্ষেত্রাকার) এলাকায় বিন্দু গুলি
  2. প্রতিটি পিক্সেল / ক্ষেত্রের তীব্রতা গণনা করুন
  3. চরিত্রের মানচিত্র থেকে কাছের তীব্রতার সাথে অক্ষর দ্বারা প্রতিস্থাপন করুন

চরিত্র হিসাবে mapআপনি যে কোনও অক্ষর ব্যবহার করতে পারেন, তবে চরিত্রটি ক্ষেত্রের ক্ষেত্রের সাথে একইভাবে পিক্সেল ছড়িয়ে ছড়িয়ে থাকলে ফলাফল আরও ভাল হয়। প্রারম্ভিকদের জন্য আপনি ব্যবহার করতে পারেন:

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

সাজানো অবতীর্ণ এবং রৈখিকভাবে বিতরণ করার ভান করা।

সুতরাং যদি পিক্সেল / ক্ষেত্রের তীব্রতা হয় i = <0-255>তবে প্রতিস্থাপনের অক্ষর হবে

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

i==0তারপরে যদি পিক্সেল / অঞ্চলটি কালো হয়, তবে i==127পিক্সেল / ক্ষেত্র ধূসর হয় এবং যদি হয় i==255তবে পিক্সেল / অঞ্চলটি সাদা। আপনি ভিতরে বিভিন্ন অক্ষর নিয়ে পরীক্ষা করতে পারেন 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 পাঠ্য আউটপুট করা হয় এমন মেমো
  • bmp ইনপুট বিটম্যাপ
  • AnsiStringভিসিএল টাইপ স্ট্রিংটি 1 থেকে সূচকযুক্ত, 0 থেকে নয় char*!!!

এটি ফলাফল: সামান্য NSFW তীব্রতার উদাহরণ চিত্র ity

বামদিকে ASCII আর্ট আউটপুট (ফন্টের আকার 5 পিক্সেল) এবং ডানদিকে কিছু বার জুম করা হয়েছে। আপনি দেখতে পাচ্ছেন, আউটপুটটি বড় পিক্সেল -> অক্ষর। আপনি যদি পিক্সেলের পরিবর্তে বৃহত্তর অঞ্চল ব্যবহার করেন তবে জুমটি ছোট, তবে আউটপুটটি দৃশ্যত কম আকর্ষণীয় হবে।এই পদ্ধতির কোড / প্রক্রিয়া খুব সহজ এবং দ্রুত।

আপনি যখন আরও উন্নত জিনিস যুক্ত করেন:

  • স্বয়ংক্রিয় মানচিত্রের গণনা
  • স্বয়ংক্রিয় পিক্সেল / অঞ্চল আকার নির্বাচন
  • দিক অনুপাত সংশোধন

তারপরে আপনি আরও ভাল ফলাফল সহ আরও জটিল চিত্রগুলি প্রক্রিয়া করতে পারেন:

এখানে 1: 1 অনুপাতের ফলাফল (অক্ষরগুলি দেখতে জুম করুন):

তীব্রতা উন্নত উদাহরণ

অবশ্যই, ক্ষেত্রের নমুনা নেওয়ার জন্য আপনি ছোট বিশদটি হারাবেন। অঞ্চলগুলির সাথে নমুনাযুক্ত প্রথম উদাহরণ হিসাবে এটি একই আকারের একটি চিত্র:

সামান্য NSFW তীব্রতা উন্নত উদাহরণ চিত্র

আপনি দেখতে পাচ্ছেন যে এটি বড় চিত্রগুলির জন্য আরও উপযুক্ত suited

ক্যারেক্টার ফিটিং (শেডিং এবং কঠিন এএসসিআইআই আর্টের মধ্যে সংকর)

এই পদ্ধতির ক্ষেত্রটি (আর একক পিক্সেল বিন্দুগুলি) অনুরূপ তীব্রতা এবং আকারের সাথে অক্ষরের সাথে প্রতিস্থাপন করার চেষ্টা করে। এটি আগের পদ্ধতির তুলনায় বড় ফন্টগুলির সাথেও আরও ভাল ফলাফলের দিকে পরিচালিত করে। অন্যদিকে, এই পদ্ধতিটি অবশ্যই কিছুটা ধীর। এটি করার আরও অনেক উপায় রয়েছে তবে মূল ধারণাটি হ'ল চিত্রের ক্ষেত্রের ( dot) এবং রেন্ডার করা চরিত্রের মধ্যে পার্থক্য (দূরত্ব) গণনা করা। আপনি পিক্সেলের মধ্যে নিখুঁত পার্থক্যের নিষ্পাপ যোগ দিয়ে শুরু করতে পারেন, তবে এটি খুব ভাল ফলাফলের দিকে পরিচালিত করবে না এমনকি এক পিক্সেল শিফটও দূরত্বকে বড় করে তুলবে। পরিবর্তে আপনি পারস্পরিক সম্পর্ক বা বিভিন্ন মেট্রিক ব্যবহার করতে পারেন। সামগ্রিক অ্যালগরিদম পূর্ববর্তী পদ্ধতির মতো প্রায়:

  1. তাই সমানভাবে ছবিতে ভাগ (ধূসর স্কেল) আয়তক্ষেত্রাকার এলাকা বিন্দু 'র

    আদর্শভাবে রেন্ডার করা ফন্টের অক্ষরগুলির মতো একই অনুপাতের অনুপাত সহ (এটি অনুপাতের রেশিও সংরক্ষণ করবে characters

  2. প্রতিটি অঞ্চলের তীব্রতা গণনা করুন ( dot)

  3. mapনিকটতম তীব্রতা / আকারের সাথে চরিত্র থেকে একটি অক্ষর দ্বারা এটি প্রতিস্থাপন করুন

আমরা কীভাবে একটি অক্ষর এবং বিন্দুর মধ্যে দূরত্ব গণনা করতে পারি? এটি এই পদ্ধতির সবচেয়ে শক্ত অংশ। পরীক্ষা করার সময়, আমি গতি, গুণমান এবং সরলতার মধ্যে এই সমঝোতাটি বিকাশ করি:

  1. অঞ্চলগুলিতে চরিত্রের অঞ্চল ভাগ করুন

    অঞ্চলগুলি

    • আপনার রূপান্তর বর্ণমালা ( map) থেকে প্রতিটি অক্ষরের বাম, ডান, উপরে, নীচে এবং কেন্দ্রের জোনের জন্য পৃথক তীব্রতা গণনা করুন ।
    • সমস্ত তীব্রতা স্বাভাবিক করুন, তাই তারা ক্ষেত্রের আকারে স্বাধীন i=(i*256)/(xs*ys)
  2. আয়তক্ষেত্র অঞ্চলে উত্স চিত্রটি প্রক্রিয়া করুন

    • (লক্ষ্য ফন্ট হিসাবে একই দিক অনুপাত সহ)
    • প্রতিটি ক্ষেত্রের জন্য, বুলেট # 1 এর মতোই তীব্রতাটি গণনা করুন
    • রূপান্তর বর্ণমালায় তীব্রতা থেকে নিকটতম মিলটি সন্ধান করুন
    • লাগানো অক্ষর আউটপুট

এটি ফন্টের আকার = 7 পিক্সেলের জন্য ফলাফল

চরিত্র ফিটিং উদাহরণ

আপনি দেখতে পাচ্ছেন, বড় আকারের ফন্ট আকার ব্যবহার করেও আউটপুট দৃশ্যত আনন্দদায়ক হয় (পূর্ববর্তী পদ্ধতির উদাহরণটি 5 পিক্সেলের ফন্টের আকারের সাথে ছিল)। আউটপুট মোটামুটি একই আকারের ইনপুট চিত্রের (জুম নেই)। আরও ভাল ফলাফল অর্জন করা যায় কারণ অক্ষরগুলি কেবলমাত্র তীব্রতার দ্বারা নয়, সামগ্রিক আকারের দ্বারাও মূল চিত্রের আরও কাছাকাছি থাকে এবং তাই আপনি বৃহত্তর ফন্টগুলি ব্যবহার করতে পারেন এবং এখনও বিশদ সংরক্ষণ করতে পারেন (অবশ্যই অবধি)।

ভিসিএল-ভিত্তিক রূপান্তর অ্যাপ্লিকেশনটির জন্য এখানে সম্পূর্ণ কোড:

//---------------------------------------------------------------------------
#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) // Character  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;        // Temporary 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 initialise buffers
        tmp = new Graphics::TBitmap;
        if (tmp==NULL)
            break;

        // Allow 32 bit 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 the image by zoomed character size step
        xf -= xf/3; // Characters are usually overlapping 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 the 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();
}

//---------------------------------------------------------------------------

এটি একটি ফর্ম অ্যাপ্লিকেশন ( Form1) এর TMemo mm_txtমধ্যে একক সহ সহজ । এটি একটি চিত্র লোড করে "pic.bmp"এবং তারপরে রেজোলিউশন অনুসারে, পাঠ্যে রূপান্তর করতে কোন পদ্ধতির ব্যবহার করতে হয় যা "pic.txt"ভিজ্যুয়ালাইজ করার জন্য মেমোতে সংরক্ষণ করা হয় এবং মেমোতে প্রেরণ করা হয় তা চয়ন করুন।

ভিসিএল নয় তাদের জন্য, ভিসিএল স্টাফকে উপেক্ষা করুন এবং AnsiStringআপনার যে কোনও স্ট্রিং টাইপ এবং Graphics::TBitmapপিক্সেল অ্যাক্সেসের সামর্থ্য সহ আপনার বিটম্যাপ বা চিত্র শ্রেণীর সাথে প্রতিস্থাপন করুন ।

একটি খুব গুরুত্বপূর্ণ নোটটি হ'ল এটির সেটিংস ব্যবহার করে mm_txt->Font, তাই আপনি সেট করেছেন তা নিশ্চিত করুন:

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

এই কাজটি সঠিকভাবে করতে, অন্যথায় ফন্টটি মনো-স্পেস ব্যবধান হিসাবে পরিচালিত হবে না। মাউস হুইল বিভিন্ন ফন্টের আকারের ফলাফল দেখতে স্রেফ উপরে / নীচে ফন্টের আকার পরিবর্তন করে।

[মন্তব্য]

  • দেখা শব্দ প্রতিকৃতি
  • বিটম্যাপ / ফাইল অ্যাক্সেস এবং পাঠ্য আউটপুট ক্ষমতা সহ একটি ভাষা ব্যবহার করুন
  • আমি দৃ approach়ভাবে প্রথম পদ্ধতির সাথে শুরু করার পরামর্শ দিচ্ছি কারণ এটি খুব সহজ সরল এবং সহজ, এবং কেবল তখনই দ্বিতীয়টিতে চলে যান (যা প্রথমটির পরিবর্তন হিসাবে করা যেতে পারে, তাই বেশিরভাগ কোড যেমন হয় তেমন থাকে)
  • বিপরীত তীব্রতার সাথে গণনা করা ভাল ধারণা (কালো পিক্সেল সর্বাধিক মান) কারণ মানক পাঠ্য পূর্বরূপটি একটি সাদা ব্যাকগ্রাউন্ডে রয়েছে, সুতরাং আরও ভাল ফলাফলের দিকে নিয়ে যায়।
  • আপনি মহকুমা অঞ্চলগুলির আকার, গণনা এবং লেআউট নিয়ে পরীক্ষা করতে পারেন বা তার 3x3পরিবর্তে কিছু গ্রিড ব্যবহার করতে পারেন ।

তুলনা

অবশেষে এখানে একই ইনপুটটিতে দুটি পদ্ধতির মধ্যে একটি তুলনা করা হয়েছে:

তুলনা

সবুজ বিন্দু চিহ্নিত চিত্র পদ্ধতির শেষ হয়ে গেলে # 2 এবং লাল বেশী # 1 ছয় পিক্সেল ফন্টের আকার উপর, সব। আপনি যেমন হালকা বাল্বের ছবিতে দেখতে পাচ্ছেন, আকৃতি সংবেদনশীল পদ্ধতিটি আরও ভাল (এমনকি # 1 হলেও) একটি 2x জুম উৎস ছবিতে সম্পন্ন করা হয়)।

শীতল আবেদন

আজকের নতুন প্রশ্নগুলি পড়ার সময়, আমি একটি দুর্দান্ত অ্যাপ্লিকেশন সম্পর্কে ধারণা পেয়েছিলাম যা ডেস্কটপের একটি নির্বাচিত অঞ্চলকে ধরে এবং এএসসিআইআরটিতে ক্রমাগত এটি ফিড করে দেয় এবং ফলাফলটি দেখে। কোডিংয়ের এক ঘন্টা পরে, এটি হয়ে গেছে এবং ফলাফলের সাথে আমি এতটাই সন্তুষ্ট যে আমাকে অবশ্যই এটি এখানে যুক্ত করতে হবে।

ঠিক আছে অ্যাপ্লিকেশনটিতে মাত্র দুটি উইন্ডো রয়েছে। চিত্রের নির্বাচন এবং পূর্বরূপ ছাড়াই প্রথম মাস্টার উইন্ডোটি মূলত আমার পুরানো কনভার্টর উইন্ডো (উপরের সমস্ত জিনিস এতে রয়েছে)। এটিতে কেবল ASCII পূর্বরূপ এবং রূপান্তর সেটিংস রয়েছে। দ্বিতীয় উইন্ডোটি দখল অঞ্চল নির্বাচনের জন্য স্বচ্ছ ভিতরে ভিতরে একটি ফাঁকা ফর্ম (কোনও কার্যকারিতা নেই)।

এখন একটি টাইমারে, আমি কেবল নির্বাচন ফর্মটি দ্বারা নির্বাচিত অঞ্চলটি দখল করি, রূপান্তর করতে এটি পাস করি এবং ASCIIart প্রাকদর্শন করি

সুতরাং আপনি নির্বাচন অঞ্চলটি রূপান্তর করতে চান এমন একটি অঞ্চল আবদ্ধ করুন এবং ফলাফলটি মাস্টার উইন্ডোতে দেখুন। এটি কোনও গেম, দর্শক ইত্যাদি হতে পারে like

ASCIIart গ্র্যাবার উদাহরণ

তাই এখন আমি মজাদার জন্য ASCIIart এ এমনকি ভিডিওগুলি দেখতে পারি । কিছু সত্যিই চমৎকার :)।

হাত

আপনি যদি এটি জিএলএসএলে প্রয়োগ করার চেষ্টা করতে চান তবে এটি একবার দেখুন:


30
আপনি এখানে একটি অবিশ্বাস্য কাজ করেছেন! ধন্যবাদ! এবং আমি ASCII সেন্সরিং ভালবাসি!
আন্ডার বিগুড়ি 11

4
উন্নতির জন্য একটি পরামর্শ: কেবলমাত্র তীব্রতা নয়, নির্দেশমূলক ডেরিভেটিভগুলি তৈরি করুন work
ইয়াক্ক - অ্যাডাম নেভ্রামামন্ট

4
@ ইয়াক্ক যত্ন নিয়ে বিস্তারিত বলবেন?
tariksbl

4
@ তারিক হয় কেবলমাত্র তীব্রতার সাথে নয়, ডেরিভেটিভগুলিতেও মেলে: বা, ব্যান্ড পাস প্রান্তগুলি উন্নত করে। মূলত তীব্রতা কেবলমাত্র লোকেরা দেখেন না: তারা গ্রেডিয়েন্টস এবং প্রান্তগুলি দেখেন।
ইয়াক্ক - অ্যাডাম নেভ্রামামন্ট

4
@ ইয়াক্ক অঞ্চল মহকুমা পরোক্ষভাবে এ জাতীয় কাজ করে। 3x3জোন হিসাবে একটি হ্যান্ডেল চরিত্রগুলি করা এবং ডিসিটির তুলনা করা আরও ভাল হতে পারে তবে তার ফলে পারফরম্যান্স হ্রাস পাবে বলে আমি মনে করি।
স্পেকট্রে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.