(компьютерная графика) радиальное искажение изображения - PullRequest
0 голосов
/ 10 марта 2012

Мне нужно создать эффект, который радиально искажает растровое изображение, радиально растягивая или уменьшая его «слои пикселей» (как показано на рисунке):

http://i.stack.imgur.com/V6Voo.png

цветными кружками (их толщина) показано преобразование, которое применяется к изображению

Какой подход мне выбрать? У меня есть растровое изображение (массив пикселей) и другое растровое изображение, которое должно быть результатом применения такого фильтра (в результате на растровом изображении должна быть какая-то круглая водная рябь). Где я мог прочитать о создании таких эффектов? Спасибо.

Ответы [ 2 ]

0 голосов
/ 10 марта 2012

Что ж, наиболее точные результаты будут получены при сопоставлении евклидовых координат с полярной матрицей. Тогда вы очень легко сможете их растянуть. Затем просто переведите их обратно в евклидово представление и сохраните. Я напишу и отредактирую с некоторым кодом в секунду.

Хорошо, я немного увлекся, но вот мой код. Он возьмет растровое изображение, преобразует его в полярные координаты и из них и сохраняет его. Теперь радиальное искажение должно быть легким.

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#define PI 3.141592654

#define C_R 1000
#define C_S 1000
#define C_M 2000

typedef struct{ int r,g,b; } color;
typedef struct{ int t; color* data; int w, h; } bitmap;
typedef struct{ int t; color* data; int r, s, w, h; } r_bitmap;

bitmap* bmp_load_from_file( const char* fname ){
    FILE* b = fopen( fname, "rb" );
    if( b <= 0 ) return 0;
    int num;
    fscanf( b, "BM%n", &num );
    if( num < 2 ) return 0;
    struct{ int size, reserved, offset;
        int hsize, wid, hig, planes:16, bpp:16, comp, bmpsize, hres, vres, colors, important; } head;
    fread( &head, 13, 4, b );
    bitmap* bmp = malloc( sizeof( bitmap ) );
    bmp->data = malloc( head.wid * head.hig * sizeof( color ) );
    bmp->w = head.wid;
    bmp->h = head.hig;
    for( int y = head.hig - 1; y >= 0; --y ){
        int x;
        for( x = 0; x < head.wid; ++x ){
            color t;
            t.r = fgetc( b );
            t.g = fgetc( b );
            t.b = fgetc( b );
            bmp->data[x+y*bmp->w] = t;
        }
        x*=3;
        while( x%4 != 0 ){
            ++x;
            fgetc( b );
        }
    }
    bmp->t = 0;
    fclose( b );
    return bmp;
}

void bmp_save( const char* fname, bitmap* bmp ){
    FILE* b = fopen( fname, "wb" );
    if( b <= 0 ) return 0;
    struct{ int size, reserved, offset;
        int hsize, wid, hig, planes:16, bpp:16, comp, bmpsize, hres, vres, colors, important; } head;
    fprintf( b, "BM" );
    head.size = 3 * (bmp->w+4)/4*4 * bmp->h + 54;
    head.offset = 54;
    head.hsize = 40;
    head.wid = bmp->w;
    head.hig = bmp->h;
    head.planes = 1;
    head.bpp = 24;
    head.comp = 0;
    head.bmpsize = 3 * (bmp->w+4)/4*4 * bmp->h;
    head.hres = 72;
    head.vres = 72;
    head.colors = 0;
    head.important = 0;
    fwrite( &head, 13, 4, b );
    for( int y = bmp->h - 1; y >= 0; --y ){
        int x;
        for( x = 0; x < bmp->w; ++x ){
            fputc( bmp->data[x + y * bmp->w].r, b );
            fputc( bmp->data[x + y * bmp->w].g, b );
            fputc( bmp->data[x + y * bmp->w].b, b );
        }
        x*=3;
        while( x % 4 != 0 ){
            ++x;
            fputc(0, b);
        }
    }
    fclose( b );
}

color color_mix( color a, color b, int offset ){ /*offset is a value between 0 and 255 to determine the weight. the lower it is the more color a gets*/
    //if( offset > 255 || offset < 0)
        //printf("%i\t", offset);
    a.r += ( b.r - a.r ) * offset / 255;
    a.g += ( b.g - a.g ) * offset / 255;
    a.b += ( b.b - a.b ) * offset / 255;
    return a;
}

r_bitmap* bmp_to_r( bitmap* b ){
    r_bitmap* r = malloc( sizeof( r_bitmap ) );
    r->t = 1;
    int radius = sqrt( b->w * b->w + b->h * b->h ) / 2 * C_R / C_M + 2;
    int step = C_S * ( b->w + b->h ) / C_M;
    r->data = malloc( radius * step * sizeof( color ) );
    r->r = radius;
    r->s = step;
    r->w = b->w;
    r->h = b->h;
    color black = {0, 0, 0};
    for( double i = 0; i < radius; ++ i ){
        for( double j = 0; j < step; ++j ){
            double x = i * C_M * cos( 2 * PI * j / step ) / C_R + b->w / 2;
            double y = i * C_M * sin( 2 * PI * j / step ) / C_R + b->h / 2;
            int ix = x;
            int iy = y;
            if( x < 0 || x >= b->w || y < 0 || y >= b->h )
                r->data[(int)(j + i * step)] = black;
            else{
                color tmp = b->data[ix + iy * b->w];
                if( iy < b->h - 1 ){
                    int off = 255 * (y - iy);
                    tmp = color_mix( tmp, b->data[ix + (iy+1) * b->w], off );
                }
                if( ix < b->w - 1 ){
                    int off = 255 * ( x - ix );
                    tmp = color_mix( tmp, b->data[ix +1 + iy * b->w], off );
                }
                r->data[(int)(j + i * step)] = tmp;
            }
        }
    }
    return r;
}

bitmap* bmp_from_r( r_bitmap* r ){
    bitmap* b = malloc( sizeof( bitmap ) );
    b->t = 0;
    b->data = malloc( r->w * r->h * sizeof( color ) );
    b->w = r->w;
    b->h = r->h;
    for( int y = 0; y < b->h; ++y ){
        for( int x = 0; x < b->w; ++x ){
            int tx = x - b->w/2;
            int ty = y - b->h/2;

            double rad = sqrt( tx*tx+ty*ty ) * C_R / C_M;
            double s = atan2( ty, tx );
            if( s < 0 ) s += 2 * PI;
            s *= r->s / ( 2 * PI );

            int is = s;
            int irad = rad;

            color tmp = r->data[(int)(is + irad * r->s)];
            /*if( x > 0 && x < r->w - 1 && y > 0 && y < r->h - 1 ){
                tmp = color_mix(tmp, r->data[((int)(is+1)%r->s + irad * r->s)], abs(255* rad - floor(rad)));
                tmp = color_mix(tmp, r->data[(is + (irad + 1) * r->s)], abs(255* s - floor(s)));
            }*/
            b->data[x+y*b->w] = tmp;
        }
    }
    return b;
}



int main( ) {
    bitmap* b = bmp_load_from_file( "foo.bmp" );
    r_bitmap* r = bmp_to_r( b );
    bitmap* c = bmp_from_r( r );
    bmp_save( "lol.bmp", c );

}
0 голосов
/ 10 марта 2012

Попробуйте посмотреть здесь

http://www.jhlabs.com/ip/blurring.html

Увеличение и размытие изображения

это Java, но, тем не менее, оно может подойти вашему запросу.

...