00001
00002
00003
00004 #include <OBLOB2.H>
00005 #include <ALL.H>
00006 #include <COLCODE.H>
00007 #include <OBITMAP.H>
00008
00009
00010
00011 #define BACKGROUND_COLOR TRANSPARENT_CODE
00012 #define DEFAULT_BLOB2D_SIZE 0x1000
00013 #define DEFAULT_BLOB2D_INC 0x100
00014
00015 Blob2D::Blob2D() {
00016 left_edge = top_edge = width = height = 0;
00017 alloc_size = DEFAULT_BLOB2D_SIZE;
00018 ptr = (Bitmap *)mem_add(alloc_size);
00019 ptr->init(width, height);
00020 }
00021
00022 Blob2D::Blob2D( Blob2D &b ) {
00023 left_edge = b.left_edge;
00024 top_edge = b.top_edge;
00025 width = b.width;
00026 height = b.height;
00027 alloc_size = b.alloc_size;
00028
00029 err_when( width < 0 );
00030 err_when( height < 0 );
00031
00032 ptr = (Bitmap *)mem_add(alloc_size);
00033 memcpy(ptr, b.ptr, alloc_size);
00034
00035 }
00036
00037 Blob2D::~Blob2D() {
00038 mem_del(ptr);
00039 }
00040
00041 Blob2D& Blob2D::operator=(Blob2D &b) {
00042 left_edge = b.left_edge;
00043 top_edge = b.top_edge;
00044 width = b.width;
00045 height = b.height;
00046
00047 err_when( width < 0 );
00048 err_when( height < 0 );
00049
00050 size_t siz = Bitmap::size(width,height);
00051 if( alloc_size < siz ) {
00052 mem_del(ptr);
00053 alloc_size = b.alloc_size;
00054 ptr = (Bitmap *)mem_add(alloc_size);
00055 }
00056 memcpy(ptr, b.ptr, siz);
00057
00058
00059
00060 return *this;
00061 }
00062
00063 void Blob2D::resize(short destLeft, short destTop, short destWidth, short destHeight) {
00064 if( width == 0 && height == 0) {
00065 size_t siz = Bitmap::size(destWidth,destHeight);
00066 if( alloc_size < siz ) {
00067 mem_del(ptr);
00068 ptr = (Bitmap *)mem_add((alloc_size = siz + DEFAULT_BLOB2D_INC));
00069 }
00070 memset(ptr, BACKGROUND_COLOR, siz);
00071 ptr->init(destWidth, destHeight);
00072 }
00073 else if( destWidth == 0 && destHeight == 0 ) {
00074 err_when(!ptr);
00075 ptr->init(destWidth, destHeight);
00076 }
00077 else if( left_edge == destLeft && top_edge == destTop && width == destWidth ) {
00078 if( destHeight == height )
00079 return;
00080
00081 size_t siz = Bitmap::size(destWidth,destHeight);
00082 if( alloc_size < siz ) {
00083 ptr = (Bitmap *)mem_resize(ptr, (alloc_size = siz + DEFAULT_BLOB2D_INC));
00084 }
00085
00086 if( destHeight > height && destWidth > 0 ) {
00087 int y2 = top_edge+height;
00088 height = destHeight;
00089
00090
00091 fill_area(destLeft, top_edge+height, destLeft+destWidth-1, destTop+destHeight-1, BACKGROUND_COLOR, 0);
00092 }
00093 }
00094 else if( left_edge <= destLeft && top_edge <= destTop &&
00095 left_edge+width >= destLeft+destWidth && top_edge+height >= destTop+destHeight) {
00096
00097 unsigned char *src = ptr->get_ptr(destLeft-left_edge, destTop-top_edge);
00098 int srcPitch = ptr->get_pitch();
00099 ptr->init(destWidth, destHeight);
00100 unsigned char *dest = ptr->get_ptr();
00101 int destPitch = ptr->get_pitch();
00102
00103 for(int y = 0; y < destHeight; ++y, src += srcPitch, dest += destPitch )
00104 memmove(dest, src, destWidth);
00105
00106
00107 }
00108 else {
00109
00110
00111 short copyLeft, copyTop, copyWidth, copyHeight;
00112 copyLeft = max(destLeft, left_edge);
00113 copyTop = max(destTop, top_edge);
00114 copyWidth = min(destLeft + destWidth, left_edge + width) - copyLeft;
00115 copyHeight = min(destTop + destHeight, top_edge + height) - copyTop; {
00116
00117 size_t siz = Bitmap::size(destWidth, destHeight);
00118 Bitmap *newPtr = (Bitmap *)mem_add(siz + DEFAULT_BLOB2D_INC);
00119 memset(newPtr, BACKGROUND_COLOR, siz);
00120 newPtr->init(destWidth, destHeight);
00121
00122 if( copyWidth > 0 && copyHeight > 0 ) {
00123 int yCount = 0;
00124 unsigned char *src = ptr->get_ptr(copyLeft-left_edge, yCount+copyTop-top_edge );
00125 unsigned char *dest = newPtr->get_ptr(copyLeft-destLeft, yCount+copyTop-destTop );
00126
00127 for( ; yCount < copyHeight; ++yCount, src += ptr->get_pitch(), dest += ptr->get_pitch() ) {
00128
00129
00130 memcpy(dest, src, copyWidth);
00131 }
00132 }
00133
00134
00135 left_edge = destLeft;
00136 top_edge = destTop;
00137 width = destWidth;
00138 height = destHeight;
00139 mem_del(ptr);
00140 ptr = newPtr;
00141 }
00142
00143
00144 if( top_edge < copyTop && width > 0) {
00145 fill_area(left_edge, top_edge, left_edge+width-1, copyTop, BACKGROUND_COLOR, 0 );
00146 }
00147
00148
00149 if( top_edge+height > copyTop+copyHeight && width > 0) {
00150 fill_area(left_edge, copyTop+copyHeight, left_edge+width-1, top_edge+height-1, BACKGROUND_COLOR, 0 );
00151 }
00152
00153
00154 if( left_edge < copyLeft && destHeight > 0) {
00155 fill_area(left_edge, copyTop, copyLeft-1, copyTop+copyHeight-1,
00156 BACKGROUND_COLOR, 0);
00157 }
00158
00159
00160 if( left_edge+width > copyLeft+copyWidth && destHeight > 0 ) {
00161 fill_area(copyLeft+copyWidth, copyTop, left_edge+width, copyTop+copyHeight-1,
00162 BACKGROUND_COLOR, 0);
00163 }
00164 }
00165
00166 left_edge = destLeft;
00167 top_edge = destTop;
00168 width = destWidth;
00169 height = destHeight;
00170 }
00171
00172 int Blob2D::extend_to(short x, short y) {
00173 int resizeFlag = 0;
00174 short newLeft = left_edge;
00175 short newTop = top_edge;
00176 short newWidth = width;
00177 short newHeight = height;
00178
00179 if( x < left_edge ) {
00180 newLeft = x;
00181 newWidth = left_edge + width - newLeft;
00182 resizeFlag = 1;
00183 }
00184 if( x >= left_edge+width ) {
00185 newWidth = x - newLeft + 1;
00186 resizeFlag = 1;
00187 }
00188 if( y < top_edge ) {
00189 newTop = y;
00190 newHeight = top_edge + height - newTop;
00191 resizeFlag = 1;
00192 }
00193 if( y >= top_edge+height ) {
00194 newHeight = y - newTop + 1;
00195 resizeFlag = 1;
00196 }
00197
00198 if( resizeFlag ) {
00199 resize( newLeft, newTop, newWidth, newHeight );
00200 }
00201
00202 return resizeFlag;
00203 }
00204
00205 int Blob2D::extend_to(short x1, short y1, short x2, short y2) {
00206 int resizeFlag = 0;
00207 short newLeft = left_edge;
00208 short newTop = top_edge;
00209 short newWidth = width;
00210 short newHeight = height;
00211
00212 if( x1 < left_edge ) {
00213 newLeft = x1;
00214 newWidth = left_edge + width - newLeft;
00215 resizeFlag = 1;
00216 }
00217 if( x2 >= left_edge+width ) {
00218 newWidth = x2 - newLeft + 1;
00219 resizeFlag = 1;
00220 }
00221 if( y1 < top_edge ) {
00222 newTop = y1;
00223 newHeight = top_edge + height - newTop;
00224 resizeFlag = 1;
00225 }
00226 if( y2 >= top_edge+height ) {
00227 newHeight = y2 - newTop + 1;
00228 resizeFlag = 1;
00229 }
00230
00231 if( resizeFlag ) {
00232 resize( newLeft, newTop, newWidth, newHeight );
00233 }
00234
00235 return resizeFlag;
00236 }
00237
00238 unsigned char *Blob2D::p(short x, short y, int autoExtend) {
00239 if( autoExtend ) {
00240 extend_to(x, y);
00241 }
00242 else {
00243 if( x < left_edge || x >= left_edge+width
00244 || y < top_edge || y >= top_edge+height )
00245 return NULL;
00246 }
00247
00248 return ptr->get_ptr(x-left_edge, y-top_edge);
00249 }
00250
00251 void Blob2D::fill_area(short x1, short y1, short x2, short y2, unsigned char color,
00252 int autoExtend) {
00253 if( autoExtend ) {
00254 extend_to(x1, y1, x2, y2);
00255 }
00256 else {
00257
00258 if( x1 < left_edge )
00259 x1 = left_edge;
00260 if( x2 >= left_edge+width )
00261 x2 = left_edge+width-1;
00262 if( y1 < top_edge )
00263 y1 = top_edge;
00264 if( y2 >= top_edge+height )
00265 y2 = top_edge+height-1;
00266
00267 if( x2 < x1 || y2 < y1 )
00268 return;
00269 }
00270
00271 int y = y1;
00272 unsigned char *dest = ptr->get_ptr( x1 - left_edge, y - top_edge );
00273 for( ; y <= y2; ++y, dest += width )
00274 memset(dest, color, x2-x1+1);
00275 }
00276
00277 void Blob2D::auto_clip( short *pLeft, short *pTop, short *pWidth, short *pHeight, int autoResize) {
00278 short x1, y1, x2, y2;
00279 int pitch = ptr->get_pitch();
00280
00281 y1 = 0;
00282 y2 = height - 1;
00283 x1 = 0;
00284 x2 = width - 1;
00285
00286
00287 for( ; y1 <= y2; --y2) {
00288 int x = x1;
00289 unsigned char *src = ptr->get_ptr(x, y2);
00290 for( ; x <= x2; ++x, ++src ) {
00291 if( *src != BACKGROUND_COLOR )
00292 break;
00293 }
00294 if( x <= x2 )
00295 break;
00296 }
00297
00298
00299 for( ; y1 <= y2; ++y1 ) {
00300 int x = x1;
00301 unsigned char *src = ptr->get_ptr(x, y1);
00302 for( ; x <= x2; ++x, ++src ) {
00303 if( *src != BACKGROUND_COLOR )
00304 break;
00305 }
00306 if( x <= x2 )
00307 break;
00308 }
00309
00310
00311 for( ; x1 <= x2; --x2) {
00312 int y = y1;
00313 unsigned char *src = ptr->get_ptr(x1, y);
00314 for( ; y <= y2; ++y, src+=pitch ) {
00315 if( *src != BACKGROUND_COLOR )
00316 break;
00317 }
00318 if( y <= y2 )
00319 break;
00320 }
00321
00322
00323 for( ; x1 <= x2; ++x1 ) {
00324 int y = y1;
00325 unsigned char *src = ptr->get_ptr(x1, y);
00326 for( ; y <= y2; ++y, src+=pitch ) {
00327 if( *src != BACKGROUND_COLOR )
00328 break;
00329 }
00330 if( y <= y2 )
00331 break;
00332 }
00333
00334 if( pLeft )
00335 *pLeft = x1 + left_edge;
00336 if( pTop )
00337 *pTop = y1 + top_edge;
00338 if( pWidth )
00339 *pWidth = x2 - x1 + 1;
00340 if( pHeight )
00341 *pHeight = y2 - y1 + 1;
00342
00343 if( autoResize ) {
00344 resize(x1+left_edge, y1+top_edge, x2-x1+1, y2-y1+1);
00345 ptr = (Bitmap *)mem_resize(ptr, (alloc_size = ptr->size()) );
00346 }
00347 }
00348
00349 void Blob2D::clear() {
00350 err_when(!ptr);
00351 ptr->init(0, 0);
00352
00353 left_edge = 0;
00354 top_edge = 0;
00355 width = 0;
00356 height = 0;
00357 }