C에서 이미지를 ASCII 아트로 변환
비트맵 이미지를 ASCII 아트로 변환하려면 고정폭 글꼴을 사용하고 프로세스를 단순하게 유지해야 합니다. 두 가지 주요 접근 방식이 있습니다.
픽셀/영역 강도 기반:
이 접근 방식은 각 픽셀 또는 픽셀 영역을 단일 점으로 처리합니다. 점의 평균 그레이 스케일 강도를 계산하고 이를 가장 가까운 강도의 문자로 대체합니다.
문자 맞춤(하이브리드):
이 접근 방식은 영역을 대체하려고 시도합니다. (문자 모양) 비슷한 강도와 모양의 문자를 사용합니다. 더 나은 결과를 얻을 수 있지만 계산으로 인해 속도가 느려집니다.
세부 구현:
픽셀/영역 강도 기반:
이미지를 회색조 픽셀 또는 직사각형 영역(점)으로 나눕니다. 각 점의 강도를 계산합니다. 가장 가까운 강도를 갖는 문자 맵(미리 계산된 강도)의 문자로 바꾸십시오.
샘플 문자 맵: " .,:;ox%#@&"
강도 계산:
<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>
여기서:
문자 맞춤:
이미지를 문자와 동일한 종횡비로 직사각형 영역으로 나눕니다. . 캐릭터 영역을 구역으로 나누고 각 구역의 강도를 계산합니다. 강도와 모양이 가장 가까운 문자를 지도에서 찾습니다.
이 방법을 사용하면 더 큰 글꼴을 사용할 때 시각적으로 가장 만족스러운 결과를 얻을 수 있습니다.
코드 예:
<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>
위 내용은 C에서 비트맵 이미지를 ASCII 아트로 어떻게 변환합니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!