1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17/* ---- includes ----------------------------------------------------------- */ 18 19#include "b_BasicEm/Math.h" 20#include "b_BasicEm/Functions.h" 21#include "b_ImageEm/Functions.h" 22#include "b_ImageEm/UInt8PyramidalImage.h" 23 24/* ------------------------------------------------------------------------- */ 25 26/* ========================================================================= */ 27/* */ 28/* ---- \ghd{ auxiliary functions } ---------------------------------------- */ 29/* */ 30/* ========================================================================= */ 31 32/* ------------------------------------------------------------------------- */ 33 34/* ========================================================================= */ 35/* */ 36/* ---- \ghd{ constructor / destructor } ----------------------------------- */ 37/* */ 38/* ========================================================================= */ 39 40/* ------------------------------------------------------------------------- */ 41 42void bim_UInt8PyramidalImage_init( struct bbs_Context* cpA, 43 struct bim_UInt8PyramidalImage* ptrA ) 44{ 45 bbs_UInt8Arr_init( cpA, &ptrA->arrE ); 46 ptrA->widthE = 0; 47 ptrA->heightE = 0; 48 ptrA->depthE = 0; 49 ptrA->typeE = bim_UINT8_PYRAMIDAL_IMG; 50} 51 52/* ------------------------------------------------------------------------- */ 53 54void bim_UInt8PyramidalImage_exit( struct bbs_Context* cpA, 55 struct bim_UInt8PyramidalImage* ptrA ) 56{ 57 bbs_UInt8Arr_exit( cpA, &ptrA->arrE ); 58 ptrA->widthE = 0; 59 ptrA->heightE = 0; 60 ptrA->depthE = 0; 61} 62 63/* ------------------------------------------------------------------------- */ 64 65/* ========================================================================= */ 66/* */ 67/* ---- \ghd{ operators } -------------------------------------------------- */ 68/* */ 69/* ========================================================================= */ 70 71/* ------------------------------------------------------------------------- */ 72 73void bim_UInt8PyramidalImage_copy( struct bbs_Context* cpA, 74 struct bim_UInt8PyramidalImage* ptrA, 75 const struct bim_UInt8PyramidalImage* srcPtrA ) 76{ 77#ifdef DEBUG1 78 if( ptrA->arrE.allocatedSizeE < srcPtrA->arrE.allocatedSizeE ) 79 { 80 bbs_ERROR0( "void bim_UInt8PyramidalImage_copy( ... ):\n" 81 "Unsufficient allocated memory in destination image" ); 82 return; 83 } 84#endif 85 ptrA->widthE = srcPtrA->widthE; 86 ptrA->heightE = srcPtrA->heightE; 87 ptrA->depthE = srcPtrA->depthE; 88 bbs_UInt8Arr_copy( cpA, &ptrA->arrE, &srcPtrA->arrE ); 89} 90 91/* ------------------------------------------------------------------------- */ 92 93flag bim_UInt8PyramidalImage_equal( struct bbs_Context* cpA, 94 const struct bim_UInt8PyramidalImage* ptrA, 95 const struct bim_UInt8PyramidalImage* srcPtrA ) 96{ 97 if( ptrA->widthE != srcPtrA->widthE ) return FALSE; 98 if( ptrA->heightE != srcPtrA->heightE ) return FALSE; 99 if( ptrA->depthE != srcPtrA->depthE ) return FALSE; 100 return bbs_UInt8Arr_equal( cpA, &ptrA->arrE, &srcPtrA->arrE ); 101} 102 103/* ------------------------------------------------------------------------- */ 104 105/* ========================================================================= */ 106/* */ 107/* ---- \ghd{ query functions } -------------------------------------------- */ 108/* */ 109/* ========================================================================= */ 110 111/* ------------------------------------------------------------------------- */ 112 113uint8* bim_UInt8PyramidalImage_arrPtr( struct bbs_Context* cpA, 114 const struct bim_UInt8PyramidalImage* ptrA, 115 uint32 levelA ) 116{ 117 uint32 iL; 118 uint32 offsL = 0; 119 uint32 baseSizeL = ptrA->widthE * ptrA->heightE; 120 121#ifdef DEBUG2 122 if( levelA >= ptrA->depthE ) 123 { 124 bbs_ERROR2( "uint8* bim_UInt8PyramidalImage_arrPtr( struct bim_UInt8PyramidalImage* ptrA, uint32 levelA ):\n" 125 "levelA = %i out of range [0,%i]", levelA, ptrA->depthE - 1 ); 126 return NULL; 127 } 128#endif 129 130 for( iL = 0; iL < levelA; iL++ ) 131 { 132 offsL += ( baseSizeL >> ( iL * 2 ) ); 133 } 134 return ptrA->arrE.arrPtrE + offsL; 135} 136 137/* ------------------------------------------------------------------------- */ 138 139uint32 bim_UInt8PyramidalImage_heapSize( struct bbs_Context* cpA, 140 const struct bim_UInt8PyramidalImage* ptrA, 141 uint32 widthA, 142 uint32 heightA, 143 uint32 depthA ) 144{ 145 uint32 baseSizeL = widthA * heightA; 146 uint32 sizeL = 0; 147 uint32 iL; 148 for( iL = 0; iL < depthA; iL++ ) 149 { 150 sizeL += ( baseSizeL >> ( iL * 2 ) ); 151 } 152 return bbs_UInt8Arr_heapSize( cpA, &ptrA->arrE, sizeL ); 153} 154 155/* ------------------------------------------------------------------------- */ 156 157/* ========================================================================= */ 158/* */ 159/* ---- \ghd{ modify functions } ------------------------------------------- */ 160/* */ 161/* ========================================================================= */ 162 163/* ------------------------------------------------------------------------- */ 164 165void bim_UInt8PyramidalImage_create( struct bbs_Context* cpA, 166 struct bim_UInt8PyramidalImage* ptrA, 167 uint32 widthA, uint32 heightA, 168 uint32 depthA, 169 struct bbs_MemSeg* mspA ) 170{ 171 uint32 baseSizeL = widthA * heightA; 172 uint32 sizeL = 0; 173 uint32 iL; 174 if( bbs_Context_error( cpA ) ) return; 175 for( iL = 0; iL < depthA; iL++ ) 176 { 177 sizeL += ( baseSizeL >> ( iL * 2 ) ); 178 } 179 180 if( ptrA->arrE.arrPtrE != 0 ) 181 { 182 bim_UInt8PyramidalImage_size( cpA, ptrA, widthA, heightA, depthA ); 183 return; 184 } 185 186#ifdef DEBUG1 187 { 188 uint32 depthMaskL = ( 1 << ( depthA - 1 ) ) - 1; 189 if( depthA == 0 ) 190 { 191 bbs_ERROR0( "void bim_UInt8PyramidalImage_create( struct bim_UInt8PyramidalImage* ptrA, uint32 widthA, uint32 heightA, uint32 depthA ):\n" 192 "depthA must be > 0" ); 193 return; 194 } 195 if( ( ( widthA & depthMaskL ) > 0 ) || ( ( heightA & depthMaskL ) > 0 ) ) 196 { 197 bbs_ERROR1( "void bim_UInt8PyramidalImage_create( struct bim_UInt8PyramidalImage* ptrA, uint32 widthA, uint32 heightA, uint32 depthA ):\n" 198 "widthA and heightA must be divisible by %i", depthMaskL + 1 ); 199 return; 200 } 201 } 202#endif 203 204 ptrA->widthE = widthA; 205 ptrA->heightE = heightA; 206 ptrA->depthE = depthA; 207 208 bbs_UInt8Arr_create( cpA, &ptrA->arrE, sizeL, mspA ); 209} 210 211/* ------------------------------------------------------------------------- */ 212 213void bim_UInt8PyramidalImage_size( struct bbs_Context* cpA, 214 struct bim_UInt8PyramidalImage* ptrA, 215 uint32 widthA, 216 uint32 heightA, 217 uint32 depthA ) 218{ 219 uint32 baseSizeL = widthA * heightA; 220 uint32 sizeL = 0; 221 uint32 iL; 222 223#ifdef DEBUG1 224 uint32 depthMaskL = ( 1 << ( depthA - 1 ) ) - 1; 225 if( depthA == 0 ) 226 { 227 bbs_ERROR0( "void bim_UInt8PyramidalImage_size( struct bim_UInt8PyramidalImage* ptrA, uint32 widthA, uint32 heightA, uint32 depthA ):\n" 228 "depthA must be > 0" ); 229 return; 230 } 231 232 if( ( ( widthA & depthMaskL ) > 0 ) || ( ( heightA & depthMaskL ) > 0 ) ) 233 { 234 bbs_ERROR1( "void bim_UInt8PyramidalImage_size( struct bim_UInt8PyramidalImage* ptrA, uint32 widthA, uint32 heightA, uint32 depthA ):\n" 235 "widthA and heightA must be divisible by %i", depthMaskL + 1 ); 236 return; 237 } 238#endif 239 240 ptrA->widthE = widthA; 241 ptrA->heightE = heightA; 242 ptrA->depthE = depthA; 243 244 for( iL = 0; iL < depthA; iL++ ) 245 { 246 sizeL += ( baseSizeL >> ( iL * 2 ) ); 247 } 248#ifdef DEBUG1 249 if( sizeL > ptrA->arrE.allocatedSizeE ) 250 { 251 bbs_ERROR0( "void bim_UInt8PyramidalImage_size( struct bim_UInt8PyramidalImage* ptrA, uint32 widthA, uint32 heightA, uint32 depthA ):\n" 252 "Insufficient allocated memory." ); 253 return; 254 } 255#endif 256 bbs_UInt8Arr_size( cpA, &ptrA->arrE, sizeL ); 257} 258 259/* ------------------------------------------------------------------------- */ 260 261/* ========================================================================= */ 262/* */ 263/* ---- \ghd{ I/O } -------------------------------------------------------- */ 264/* */ 265/* ========================================================================= */ 266 267/* ------------------------------------------------------------------------- */ 268 269uint32 bim_UInt8PyramidalImage_memSize( struct bbs_Context* cpA, 270 const struct bim_UInt8PyramidalImage* ptrA ) 271{ 272 return bbs_SIZEOF16( uint32 ) 273 + bbs_SIZEOF16( uint32 ) /* version */ 274 + bbs_SIZEOF16( ptrA->widthE ) 275 + bbs_SIZEOF16( ptrA->heightE ) 276 + bbs_SIZEOF16( ptrA->depthE ) 277 + bbs_UInt8Arr_memSize( cpA, &ptrA->arrE ); 278} 279 280/* ------------------------------------------------------------------------- */ 281 282uint32 bim_UInt8PyramidalImage_memWrite( struct bbs_Context* cpA, 283 const struct bim_UInt8PyramidalImage* ptrA, 284 uint16* memPtrA ) 285{ 286 uint32 memSizeL = bim_UInt8PyramidalImage_memSize( cpA, ptrA ); 287 memPtrA += bbs_memWrite32( &memSizeL, memPtrA ); 288 memPtrA += bbs_memWriteUInt32( bim_UINT8_PYRAMIDAL_IMAGE_VERSION, memPtrA ); 289 memPtrA += bbs_memWrite32( &ptrA->widthE, memPtrA ); 290 memPtrA += bbs_memWrite32( &ptrA->heightE, memPtrA ); 291 memPtrA += bbs_memWrite32( &ptrA->depthE, memPtrA ); 292 bbs_UInt8Arr_memWrite( cpA, &ptrA->arrE, memPtrA ); 293 return memSizeL; 294} 295 296/* ------------------------------------------------------------------------- */ 297 298uint32 bim_UInt8PyramidalImage_memRead( struct bbs_Context* cpA, 299 struct bim_UInt8PyramidalImage* ptrA, 300 const uint16* memPtrA, 301 struct bbs_MemSeg* mspA ) 302{ 303 uint32 memSizeL, versionL, widthL, heightL, depthL; 304 if( bbs_Context_error( cpA ) ) return 0; 305 memPtrA += bbs_memRead32( &memSizeL, memPtrA ); 306 memPtrA += bbs_memReadVersion32( cpA, &versionL, bim_UINT8_PYRAMIDAL_IMAGE_VERSION, memPtrA ); 307 memPtrA += bbs_memRead32( &widthL, memPtrA ); 308 memPtrA += bbs_memRead32( &heightL, memPtrA ); 309 memPtrA += bbs_memRead32( &depthL, memPtrA ); 310 311 ptrA->widthE = widthL; 312 ptrA->heightE = heightL; 313 ptrA->depthE = depthL; 314 bbs_UInt8Arr_memRead( cpA, &ptrA->arrE, memPtrA, mspA ); 315 316 if( memSizeL != bim_UInt8PyramidalImage_memSize( cpA, ptrA ) ) 317 { 318 bbs_ERR0( bbs_ERR_CORRUPT_DATA, "uint32 bim_UInt8PyramidalImage_memRead( const struct bim_UInt8PyramidalImage* ptrA, const void* memPtrA ):\n" 319 "size mismatch" ); 320 return 0; 321 } 322 323 return memSizeL; 324} 325 326/* ------------------------------------------------------------------------- */ 327 328/* ========================================================================= */ 329/* */ 330/* ---- \ghd{ exec functions } --------------------------------------------- */ 331/* */ 332/* ========================================================================= */ 333 334void bim_UInt8PyramidalImage_overlayUInt8( struct bbs_Context* cpA, 335 const struct bim_UInt8PyramidalImage* ptrA, 336 struct bim_UInt8Image* uint8ImageA ) 337{ 338 uint8ImageA->widthE = ptrA->widthE; 339 uint8ImageA->heightE = ptrA->heightE; 340 uint8ImageA->arrE.sizeE = ptrA->widthE * ptrA->heightE; 341 uint8ImageA->arrE.allocatedSizeE = ptrA->widthE * ptrA->heightE; 342 uint8ImageA->arrE.arrPtrE = ptrA->arrE.arrPtrE; 343 uint8ImageA->arrE.mspE = 0; 344} 345 346/* ------------------------------------------------------------------------- */ 347 348void bim_UInt8PyramidalImage_recompute( struct bbs_Context* cpA, 349 struct bim_UInt8PyramidalImage* dstPtrA ) 350{ 351 uint32 iL, jL, layerL, widthL, heightL; 352 uint8 *srcL, *dstL; 353 354 /* process remaining layers */ 355 widthL = dstPtrA->widthE; 356 heightL = dstPtrA->heightE; 357 srcL = dstPtrA->arrE.arrPtrE; 358 dstL = srcL + widthL * heightL; 359 for( layerL = 1; layerL < dstPtrA->depthE; layerL++ ) 360 { 361 for( jL = ( heightL >> 1 ); jL > 0; jL-- ) 362 { 363 for( iL = ( widthL >> 1 ); iL > 0; iL-- ) 364 { 365 /* averaging with roundig */ 366 *dstL++ = ( ( *srcL + *( srcL + 1 ) + *( srcL + widthL ) + *( srcL + widthL + 1 ) ) + 2 ) >> 2; 367 srcL += 2; 368 } 369 srcL += widthL; 370 } 371 widthL >>= 1; 372 heightL >>= 1; 373 } 374} 375 376/* ------------------------------------------------------------------------- */ 377 378void bim_UInt8PyramidalImage_importUInt8( struct bbs_Context* cpA, 379 struct bim_UInt8PyramidalImage* dstPtrA, 380 const struct bim_UInt8Image* srcPtrA, 381 uint32 depthA ) 382{ 383 384 bim_UInt8PyramidalImage_size( cpA, dstPtrA, srcPtrA->widthE, srcPtrA->heightE, depthA ); 385 386 if( srcPtrA->arrE.sizeE & 1 ) 387 { 388 bbs_ERROR0( "void bim_UInt8PyramidalImage_importUInt8(....):\n" 389 "Size of source image must be even.\n" ); 390 return; 391 392 } 393 394 /* copy first layer */ 395 bbs_memcpy16( dstPtrA->arrE.arrPtrE, srcPtrA->arrE.arrPtrE, srcPtrA->arrE.sizeE >> 1 ); 396 397 bim_UInt8PyramidalImage_recompute( cpA, dstPtrA ); 398} 399 400/* ------------------------------------------------------------------------- */ 401 402/* ========================================================================= */ 403 404 405