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 42 void 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 54 void 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 73 void 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 93 flag 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 113 uint8* 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 139 uint32 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 165 void 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 213 void 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 269 uint32 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 282 uint32 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 298 uint32 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 334 void 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 348 void 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 378 void 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