>  기사  >  백엔드 개발  >  C에서 비트맵 이미지를 ASCII 아트로 어떻게 변환합니까?

C에서 비트맵 이미지를 ASCII 아트로 어떻게 변환합니까?

Linda Hamilton
Linda Hamilton원래의
2024-11-03 21:50:03706검색

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

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>

여기서:

  • i는 픽셀 강도의 합입니다.
  • l은 문자 맵의 길이입니다.
  • m은 문자입니다. map
  • s는 출력 문자열입니다

문자 맞춤:

이미지를 문자와 동일한 종횡비로 직사각형 영역으로 나눕니다. . 캐릭터 영역을 구역으로 나누고 각 구역의 강도를 계산합니다. 강도와 모양이 가장 가까운 문자를 지도에서 찾습니다.

이 방법을 사용하면 더 큰 글꼴을 사용할 때 시각적으로 가장 만족스러운 결과를 얻을 수 있습니다.

코드 예:

<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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.