Heim  >  Artikel  >  Backend-Entwicklung  >  Wie konvertiert man ein Bitmap-Bild in ASCII-Grafik in C?

Wie konvertiert man ein Bitmap-Bild in ASCII-Grafik in C?

Linda Hamilton
Linda HamiltonOriginal
2024-11-03 21:50:03706Durchsuche

How do you convert a bitmap image to ASCII art in C  ?

Konvertierung von Bildern in ASCII-Grafiken in C

Bei der Konvertierung eines Bitmap-Bildes in ASCII-Grafiken müssen monoproportionale Schriftarten verwendet und der Prozess einfach gehalten werden. Es gibt zwei Hauptansätze:

Pixel-/Flächenintensitätsbasiert:

Dieser Ansatz behandelt jedes Pixel oder jeden Pixelbereich als einen einzelnen Punkt. Es berechnet die durchschnittliche Graustufenintensität des Punktes und ersetzt sie durch ein Zeichen mit der nächstgelegenen Intensität.

Zeichenanpassung (hybrid):

Dieser Ansatz versucht, Bereiche zu ersetzen (zeichenförmig) mit Zeichen ähnlicher Intensität und Form. Es führt zu besseren Ergebnissen, ist jedoch aufgrund der Berechnungen langsamer.

Detaillierte Implementierung:

Pixel-/Flächenintensitätsbasiert:

Teilen Sie das Bild in Graustufenpixel oder rechteckige Bereiche (Punkte) ein. Berechnen Sie die Intensität jedes Punkts. Ersetzen Sie es durch ein Zeichen aus einer Zeichentabelle (vorberechnete Intensitäten) mit der nächstgelegenen Intensität.

Eine Beispielzeichentabelle: " .,:;ox%#@&"

Intensitätsberechnung:

<code class="C++">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];</code>

wobei:

  • i die Summe der Pixelintensitäten ist
  • l die Länge der Zeichentabelle ist
  • m das Zeichen ist Karte
  • s ist die Ausgabezeichenfolge

Zeichenanpassung:

Teilen Sie das Bild in rechteckige Bereiche mit dem gleichen Seitenverhältnis wie die Zeichen . Teilen Sie den Zeichenbereich in Zonen ein und berechnen Sie die Intensität jeder Zone. Finden Sie das Zeichen in der Karte mit der besten Intensität und Formanpassung.

Dieser Ansatz führt zu den besten und optisch ansprechendsten Ergebnissen, wenn Sie größere Schriftarten verwenden.

Codebeispiel:

<code class="C++">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;
}</code>

Das obige ist der detaillierte Inhalt vonWie konvertiert man ein Bitmap-Bild in ASCII-Grafik in C?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn