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:
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!