1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: octree.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #include <vcl/bmpacc.hxx>
35 #include <vcl/impoct.hxx>
36 #include <vcl/octree.hxx>
42 static BYTE pImplMask
[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
48 ImpNodeCache::ImpNodeCache( const ULONG nInitSize
) :
51 const ULONG nSize
= nInitSize
+ 4;
53 for( ULONG i
= 0; i
< nSize
; i
++ )
55 OctreeNode
* pNewNode
= new NODE
;
57 pNewNode
->pNextInCache
= pActNode
;
62 // ------------------------------------------------------------------------
64 ImpNodeCache::~ImpNodeCache()
68 OctreeNode
* pNode
= pActNode
;
70 pActNode
= pNode
->pNextInCache
;
79 Octree::Octree( ULONG nColors
) :
85 pNodeCache
= new ImpNodeCache( nColors
);
86 memset( pReduce
, 0, ( OCTREE_BITS
+ 1 ) * sizeof( PNODE
) );
89 // ------------------------------------------------------------------------
91 Octree::Octree( const BitmapReadAccess
& rReadAcc
, ULONG nColors
) :
97 pNodeCache
= new ImpNodeCache( nColors
);
98 memset( pReduce
, 0, ( OCTREE_BITS
+ 1 ) * sizeof( PNODE
) );
102 // ------------------------------------------------------------------------
106 ImplDeleteOctree( &pTree
);
110 // ------------------------------------------------------------------------
112 void Octree::AddColor( const BitmapColor
& rColor
)
114 pColor
= &(BitmapColor
&) rColor
;
118 while( nLeafCount
> nMax
)
122 // ------------------------------------------------------------------------
124 void Octree::ImplCreateOctree()
128 const long nWidth
= pAcc
->Width();
129 const long nHeight
= pAcc
->Height();
131 if( pAcc
->HasPalette() )
133 for( long nY
= 0; nY
< nHeight
; nY
++ )
135 for( long nX
= 0; nX
< nWidth
; nX
++ )
137 pColor
= &(BitmapColor
&) pAcc
->GetPaletteColor( pAcc
->GetPixel( nY
, nX
) );
141 while( nLeafCount
> nMax
)
152 for( long nY
= 0; nY
< nHeight
; nY
++ )
154 for( long nX
= 0; nX
< nWidth
; nX
++ )
156 aColor
= pAcc
->GetPixel( nY
, nX
);
160 while( nLeafCount
> nMax
)
168 // ------------------------------------------------------------------------
170 void Octree::ImplDeleteOctree( PPNODE ppNode
)
172 for ( ULONG i
= 0UL; i
< 8UL; i
++ )
174 if ( (*ppNode
)->pChild
[ i
] )
175 ImplDeleteOctree( &(*ppNode
)->pChild
[ i
] );
178 pNodeCache
->ImplReleaseNode( *ppNode
);
182 // ------------------------------------------------------------------------
184 void Octree::ImplAdd( PPNODE ppNode
)
186 // ggf. neuen Knoten erzeugen
189 *ppNode
= pNodeCache
->ImplGetFreeNode();
190 (*ppNode
)->bLeaf
= ( OCTREE_BITS
== nLevel
);
192 if( (*ppNode
)->bLeaf
)
196 (*ppNode
)->pNext
= pReduce
[ nLevel
];
197 pReduce
[ nLevel
] = *ppNode
;
201 if( (*ppNode
)->bLeaf
)
204 (*ppNode
)->nRed
+= pColor
->GetRed();
205 (*ppNode
)->nGreen
+= pColor
->GetGreen();
206 (*ppNode
)->nBlue
+= pColor
->GetBlue();
210 const ULONG nShift
= 7 - nLevel
;
211 const BYTE cMask
= pImplMask
[ nLevel
];
212 const ULONG nIndex
= ( ( ( pColor
->GetRed() & cMask
) >> nShift
) << 2 ) |
213 ( ( ( pColor
->GetGreen() & cMask
) >> nShift
) << 1 ) |
214 ( ( pColor
->GetBlue() & cMask
) >> nShift
);
217 ImplAdd( &(*ppNode
)->pChild
[ nIndex
] );
221 // ------------------------------------------------------------------------
223 void Octree::ImplReduce()
228 ULONG nGreenSum
= 0L;
232 for ( i
= OCTREE_BITS
- 1; i
&& !pReduce
[i
]; i
-- ) {}
234 pNode
= pReduce
[ i
];
235 pReduce
[ i
] = pNode
->pNext
;
237 for ( i
= 0; i
< 8; i
++ )
239 if ( pNode
->pChild
[ i
] )
241 PNODE pChild
= pNode
->pChild
[ i
];
243 nRedSum
+= pChild
->nRed
;
244 nGreenSum
+= pChild
->nGreen
;
245 nBlueSum
+= pChild
->nBlue
;
246 pNode
->nCount
+= pChild
->nCount
;
248 pNodeCache
->ImplReleaseNode( pNode
->pChild
[ i
] );
249 pNode
->pChild
[ i
] = NULL
;
255 pNode
->nRed
= nRedSum
;
256 pNode
->nGreen
= nGreenSum
;
257 pNode
->nBlue
= nBlueSum
;
258 nLeafCount
-= --nChilds
;
261 // ------------------------------------------------------------------------
263 void Octree::CreatePalette( PNODE pNode
)
267 pNode
->nPalIndex
= nPalIndex
;
268 aPal
[ nPalIndex
++ ] = BitmapColor( (BYTE
) ( (double) pNode
->nRed
/ pNode
->nCount
),
269 (BYTE
) ( (double) pNode
->nGreen
/ pNode
->nCount
),
270 (BYTE
) ( (double) pNode
->nBlue
/ pNode
->nCount
) );
272 else for( ULONG i
= 0UL; i
< 8UL; i
++ )
273 if( pNode
->pChild
[ i
] )
274 CreatePalette( pNode
->pChild
[ i
] );
278 // ------------------------------------------------------------------------
280 void Octree::GetPalIndex( PNODE pNode
)
283 nPalIndex
= pNode
->nPalIndex
;
286 const ULONG nShift
= 7 - nLevel
;
287 const BYTE cMask
= pImplMask
[ nLevel
++ ];
288 const ULONG nIndex
= ( ( ( pColor
->GetRed() & cMask
) >> nShift
) << 2 ) |
289 ( ( ( pColor
->GetGreen() & cMask
) >> nShift
) << 1 ) |
290 ( ( pColor
->GetBlue() & cMask
) >> nShift
);
292 GetPalIndex( pNode
->pChild
[ nIndex
] );
296 // -------------------
297 // - InverseColorMap -
298 // -------------------
300 InverseColorMap::InverseColorMap( const BitmapPalette
& rPal
) :
301 nBits( 8 - OCTREE_BITS
)
305 const ULONG nColorMax
= 1 << OCTREE_BITS
;
306 const ULONG xsqr
= 1 << ( nBits
<< 1 );
307 const ULONG xsqr2
= xsqr
<< 1;
308 const ULONG nColors
= rPal
.GetEntryCount();
309 const long x
= 1L << nBits
;
310 const long x2
= x
>> 1L;
313 long rdist
, gdist
, bdist
;
314 long crinc
, cginc
, cbinc
;
316 ImplCreateBuffers( nColorMax
);
318 for( ULONG nIndex
= 0; nIndex
< nColors
; nIndex
++ )
320 const BitmapColor
& rColor
= rPal
[ (USHORT
) nIndex
];
321 const BYTE cRed
= rColor
.GetRed();
322 const BYTE cGreen
= rColor
.GetGreen();
323 const BYTE cBlue
= rColor
.GetBlue();
328 rdist
= rdist
*rdist
+ gdist
*gdist
+ bdist
*bdist
;
330 crinc
= ( xsqr
- ( cRed
<< nBits
) ) << 1L;
331 cginc
= ( xsqr
- ( cGreen
<< nBits
) ) << 1L;
332 cbinc
= ( xsqr
- ( cBlue
<< nBits
) ) << 1L;
334 cdp
= (ULONG
*) pBuffer
;
337 for( r
= 0, rxx
= crinc
; r
< nColorMax
; rdist
+= rxx
, r
++, rxx
+= xsqr2
)
339 for( g
= 0, gdist
= rdist
, gxx
= cginc
; g
< nColorMax
; gdist
+= gxx
, g
++, gxx
+= xsqr2
)
341 for( b
= 0, bdist
= gdist
, bxx
= cbinc
; b
< nColorMax
; bdist
+= bxx
, b
++, cdp
++, crgbp
++, bxx
+= xsqr2
)
342 if ( !nIndex
|| ( (long) *cdp
) > bdist
)
345 *crgbp
= (BYTE
) nIndex
;
352 // ------------------------------------------------------------------------
354 InverseColorMap::~InverseColorMap()
356 rtl_freeMemory( pBuffer
);
357 rtl_freeMemory( pMap
);
360 // ------------------------------------------------------------------------
362 void InverseColorMap::ImplCreateBuffers( const ULONG nMax
)
364 const ULONG nCount
= nMax
* nMax
* nMax
;
365 const ULONG nSize
= nCount
* sizeof( ULONG
);
367 pMap
= (BYTE
*) rtl_allocateMemory( nCount
);
368 memset( pMap
, 0x00, nCount
);
370 pBuffer
= (BYTE
*) rtl_allocateMemory( nSize
);
371 memset( pBuffer
, 0xff, nSize
);