Home | History | Annotate | Download | only in b_ImageEm
      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