kubawal Temat założony przez niniejszego użytkownika |
Algorytm blit - 'wklejanie' z offsetem » 2014-09-26 21:15:34 Witam. Mam funkcję blit(), która 'wkleja' fragment obrazu w lewym górnym rogu innego. Potrzebuję jednak zaimplementować możliwość wklejania w dowolnym miejscu obrazu docelowego. I tu pojawia się problem: o ile jest to łatwe przy adresowaniu obraz[x][y], to przy adrsowaniu ciągłym ( obraz[y * width + x]) nie mogę tego zaprogramować. Na dodatek każdy piksel zajmuje cztery miejsca w vectorze (R, G, B i A), czyli: Rxy = obraz[ y * width + x ]; Gxy = obraz[ y * width + x + 1 ]; Bxy = obraz[ y * width + x + 2 ]; Axy = obraz[ y * width + x + 3 ];
Oto moja wersja z wklejaniem w górnym lewym rogu: unsigned blit( const Img & src, Img & dest, const Rect & srcreg ) { if( dest.w < srcreg.rd.x - srcreg.lt.x ) return 0; if( dest.h < srcreg.rd.y - srcreg.lt.y ) return 0; if( dest.px.size() != dest.w * dest.h * 4 ) return 0; unsigned n = 0; for( int i =( reg.lt.y * src.w + reg.lt.x ) * 4; i < src.px.size(); i += 4 ) { unsigned y =( i / 4 ) / src.w; unsigned x =( i / 4 ) % src.w; if( isInRect( Point( x, y ), reg ) ) { dest.px[ n + 0 ] = src.px[ i + 0 ]; dest.px[ n + 1 ] = src.px[ i + 1 ]; dest.px[ n + 2 ] = src.px[ i + 2 ]; dest.px[ n + 3 ] = src.px[ i + 3 ]; n += 4; } if( y > reg.rd.y ) break; } return n / 4; }
struct Img { vector < unsigned char > px; unsigned w, h; };
struct Point { unsigned x, y; };
struct Rect { Point lt, rd; };
Jeśli macie jakiś pomysł, to piszcie. |
|
stryku |
» 2014-09-26 22:02:59 o takie coś chodziło? unsigned blit( const Img & src, Img & dest, const Rect & srcreg, const Point & start ) { if( dest.w < srcreg.rd.x - srcreg.lt.x ) return 0; if( dest.h < srcreg.rd.y - srcreg.lt.y ) return 0; if( dest.px.size() != dest.w * dest.h * 4 ) return 0; unsigned n = start.y * dst.w + start.x; for( int i =( reg.lt.y * src.w + reg.lt.x ) * 4; i < src.px.size(); i += 4 ) { unsigned y =( i / 4 ) / src.w; unsigned x =( i / 4 ) % src.w; if( isInRect( Point( x, y ), reg ) ) { dest.px[ n + 0 ] = src.px[ i + 0 ]; dest.px[ n + 1 ] = src.px[ i + 1 ]; dest.px[ n + 2 ] = src.px[ i + 2 ]; dest.px[ n + 3 ] = src.px[ i + 3 ]; n += 4; } if( y > reg.rd.y ) break; } return n / 4; }
|
|
kubawal Temat założony przez niniejszego użytkownika |
» 2014-09-26 22:24:03 Nie, bo układ rzędów i kolumn źródła nie bedzie zachowany, np fragment 1 linijki wklei się w 2 albo na odwrót. Takie proste to nie jest :)
|
|
pekfos |
» 2014-09-26 22:36:31 Takie proste to nie jest :) |
Jest. Główny problem to połapać się w tym, co już napisałeś. Zrób sobie funkcję wstawiającą piksel w określony współrzędnymi punkt na obrazie. Może być tylko na kartce, jak sam pozbierasz myśli to już nie będzie potrzebna. |
|
stryku |
» 2014-09-26 22:45:20 unsigned blit( const Img & src, Img & dest, const Rect & srcreg, const Point & start ) { if( dest.w < srcreg.rd.x - srcreg.lt.x ) return 0; if( dest.h < srcreg.rd.y - srcreg.lt.y ) return 0; if( dest.px.size() != dest.w * dest.h * 4 ) return 0; unsigned n = start.y * dst.w + start.x; for( int y = 0; y < 4 * src.h; y += 4 ) { for( int x = 0; x < 4 * src.w; x += 4 ) { if( isInRect( Point( x, y ), reg ) ) { int tmp = n + y * src.w + x; dest.px[ tmp + 0 ] = src.px[ tmp + 0 ]; dest.px[ tmp + 1 ] = src.px[ tmp + 1 ]; dest.px[ tmp + 2 ] = src.px[ tmp + 2 ]; dest.px[ tmp + 3 ] = src.px[ tmp + 3 ]; } if( y > reg.rd.y ) break; } } return n / 4; }
To? :d |
|
kubawal Temat założony przez niniejszego użytkownika |
» 2014-09-27 14:14:21 Ja też coś pokodziłem i wyszło mi coś takiego: struct Img { Color getPixel( unsigned x, unsigned y ) const { unsigned n = y * w + x; return Color( px[ n ], px[ n + 1 ], px[ n + 2 ], px[ n + 3 ] ); } void setPixel( unsigned x, unsigned y, Color c ) { unsigned n = y * w + x; px[ n ] = c.r; px[ n + 1 ] = c.g; px[ n + 2 ] = c.b; px[ n + 3 ] = c.a; } }
unsigned blit( const Img & src, Img & dest, const Rect & srcreg, Point destPoint = Point() ) { if( dest.w < srcreg.rd.x - srcreg.lt.x + destPoint.x ) return 0; if( dest.h < srcreg.rd.y - srcreg.lt.y + destPoint.y ) return 0; unsigned dx = destPoint.x, dy = destPoint.y; for( int i =( srcreg.lt.y * src.w + srcreg.lt.x ) * 4; i < src.px.size(); i += 4 ) { unsigned y =( i / 4 ) / src.w; unsigned x =( i / 4 ) % src.w; if( isInRect( Point( x, y ), srcreg ) ) { dest.setPixel( dx, dy, src.getPixel( x, y ) ); if( dx == srcreg.rd.x - srcreg.lt.x + destPoint.x - 1 ) { dx = 0; dy++; if( dy == srcreg.rd.y - srcreg.lt.y + destPoint.y ) break; } else dx++; } } return 1; }
Jednak wychodzą z tego randomowe pikselki, których jest tym więcej, im więcej pikseli funkcja ma skopoiwać :( |
|
pekfos |
» 2014-09-27 15:23:55 Złe n w funkcjach pomocniczych. |
|
kubawal Temat założony przez niniejszego użytkownika |
» 2014-09-27 20:30:53 Teraz wychodzą randomowe kreski (to już lepiej niż pikselki ;D ). Dobry wynik jest tylko w wypadku wklejania w punkcie (0, 0). Wiem, że nie jest to błąd przejściowy, za każdym uruchomieniem programu daje dokładnie taki sam wynik. |
|
« 1 » 2 |