xref: /aoo41x/main/vcl/source/gdi/octree.cxx (revision 87bc88d3)
19f62ea84SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
39f62ea84SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
49f62ea84SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
59f62ea84SAndrew Rist  * distributed with this work for additional information
69f62ea84SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
79f62ea84SAndrew Rist  * to you under the Apache License, Version 2.0 (the
89f62ea84SAndrew Rist  * "License"); you may not use this file except in compliance
99f62ea84SAndrew Rist  * with the License.  You may obtain a copy of the License at
109f62ea84SAndrew Rist  *
119f62ea84SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
129f62ea84SAndrew Rist  *
139f62ea84SAndrew Rist  * Unless required by applicable law or agreed to in writing,
149f62ea84SAndrew Rist  * software distributed under the License is distributed on an
159f62ea84SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
169f62ea84SAndrew Rist  * KIND, either express or implied.  See the License for the
179f62ea84SAndrew Rist  * specific language governing permissions and limitations
189f62ea84SAndrew Rist  * under the License.
199f62ea84SAndrew Rist  *
209f62ea84SAndrew Rist  *************************************************************/
219f62ea84SAndrew Rist 
229f62ea84SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_vcl.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <limits.h>
28cdf0e10cSrcweir 
29cdf0e10cSrcweir #include <vcl/bmpacc.hxx>
30cdf0e10cSrcweir #include <vcl/octree.hxx>
31cdf0e10cSrcweir 
32cdf0e10cSrcweir #include <impoct.hxx>
33cdf0e10cSrcweir 
34cdf0e10cSrcweir // ---------
35cdf0e10cSrcweir // - pMask -
36cdf0e10cSrcweir // ---------
37cdf0e10cSrcweir 
38cdf0e10cSrcweir static sal_uInt8 pImplMask[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
39cdf0e10cSrcweir 
40cdf0e10cSrcweir // -------------
41cdf0e10cSrcweir // - NodeCache -
42cdf0e10cSrcweir // -------------
43cdf0e10cSrcweir 
ImpNodeCache(const sal_uLong nInitSize)44cdf0e10cSrcweir ImpNodeCache::ImpNodeCache( const sal_uLong nInitSize ) :
45cdf0e10cSrcweir             pActNode( NULL )
46cdf0e10cSrcweir {
47cdf0e10cSrcweir     const sal_uLong nSize = nInitSize + 4;
48cdf0e10cSrcweir 
49cdf0e10cSrcweir     for( sal_uLong i = 0; i < nSize; i++ )
50cdf0e10cSrcweir     {
51cdf0e10cSrcweir         OctreeNode* pNewNode = new NODE;
52cdf0e10cSrcweir 
53cdf0e10cSrcweir         pNewNode->pNextInCache = pActNode;
54cdf0e10cSrcweir         pActNode = pNewNode;
55cdf0e10cSrcweir     }
56cdf0e10cSrcweir }
57cdf0e10cSrcweir 
58cdf0e10cSrcweir // ------------------------------------------------------------------------
59cdf0e10cSrcweir 
~ImpNodeCache()60cdf0e10cSrcweir ImpNodeCache::~ImpNodeCache()
61cdf0e10cSrcweir {
62cdf0e10cSrcweir     while( pActNode )
63cdf0e10cSrcweir     {
64cdf0e10cSrcweir         OctreeNode* pNode = pActNode;
65cdf0e10cSrcweir 
66cdf0e10cSrcweir         pActNode = pNode->pNextInCache;
67cdf0e10cSrcweir         delete pNode;
68cdf0e10cSrcweir     }
69cdf0e10cSrcweir }
70cdf0e10cSrcweir 
71cdf0e10cSrcweir // ----------
72cdf0e10cSrcweir // - Octree -
73cdf0e10cSrcweir // ----------
74cdf0e10cSrcweir 
Octree(sal_uLong nColors)75cdf0e10cSrcweir Octree::Octree( sal_uLong nColors ) :
76cdf0e10cSrcweir             nMax        ( nColors ),
77cdf0e10cSrcweir             nLeafCount  ( 0L ),
78cdf0e10cSrcweir             pTree       ( NULL ),
79cdf0e10cSrcweir             pAcc        ( NULL )
80cdf0e10cSrcweir {
81cdf0e10cSrcweir     pNodeCache = new ImpNodeCache( nColors );
82cdf0e10cSrcweir     memset( pReduce, 0, ( OCTREE_BITS + 1 ) * sizeof( PNODE ) );
83cdf0e10cSrcweir }
84cdf0e10cSrcweir 
85cdf0e10cSrcweir // ------------------------------------------------------------------------
86cdf0e10cSrcweir 
Octree(const BitmapReadAccess & rReadAcc,sal_uLong nColors)87cdf0e10cSrcweir Octree::Octree( const BitmapReadAccess& rReadAcc, sal_uLong nColors ) :
88cdf0e10cSrcweir             nMax        ( nColors ),
89cdf0e10cSrcweir             nLeafCount  ( 0L ),
90cdf0e10cSrcweir             pTree       ( NULL ),
91cdf0e10cSrcweir             pAcc        ( &rReadAcc )
92cdf0e10cSrcweir {
93cdf0e10cSrcweir     pNodeCache = new ImpNodeCache( nColors );
94cdf0e10cSrcweir     memset( pReduce, 0, ( OCTREE_BITS + 1 ) * sizeof( PNODE ) );
95cdf0e10cSrcweir     ImplCreateOctree();
96cdf0e10cSrcweir }
97cdf0e10cSrcweir 
98cdf0e10cSrcweir // ------------------------------------------------------------------------
99cdf0e10cSrcweir 
~Octree()100cdf0e10cSrcweir Octree::~Octree()
101cdf0e10cSrcweir {
102cdf0e10cSrcweir     ImplDeleteOctree( &pTree );
103cdf0e10cSrcweir     delete pNodeCache;
104cdf0e10cSrcweir }
105cdf0e10cSrcweir 
106cdf0e10cSrcweir // ------------------------------------------------------------------------
107cdf0e10cSrcweir 
AddColor(const BitmapColor & rColor)108cdf0e10cSrcweir void Octree::AddColor( const BitmapColor& rColor )
109cdf0e10cSrcweir {
110cdf0e10cSrcweir     pColor = &(BitmapColor&) rColor;
111cdf0e10cSrcweir     nLevel = 0L;
112cdf0e10cSrcweir     ImplAdd( &pTree );
113cdf0e10cSrcweir 
114cdf0e10cSrcweir     while( nLeafCount > nMax )
115cdf0e10cSrcweir         ImplReduce();
116cdf0e10cSrcweir }
117cdf0e10cSrcweir 
118cdf0e10cSrcweir // ------------------------------------------------------------------------
119cdf0e10cSrcweir 
ImplCreateOctree()120cdf0e10cSrcweir void Octree::ImplCreateOctree()
121cdf0e10cSrcweir {
122cdf0e10cSrcweir     if( !!*pAcc )
123cdf0e10cSrcweir     {
124cdf0e10cSrcweir         const long      nWidth = pAcc->Width();
125cdf0e10cSrcweir         const long      nHeight = pAcc->Height();
126cdf0e10cSrcweir 
127cdf0e10cSrcweir         if( pAcc->HasPalette() )
128cdf0e10cSrcweir         {
129cdf0e10cSrcweir             for( long nY = 0; nY < nHeight; nY++ )
130cdf0e10cSrcweir             {
131cdf0e10cSrcweir                 for( long nX = 0; nX < nWidth; nX++ )
132cdf0e10cSrcweir                 {
133*87bc88d3SHerbert Dürr                     pColor = &(BitmapColor&) pAcc->GetPaletteColor( pAcc->GetPixelIndex( nY, nX ) );
134cdf0e10cSrcweir                     nLevel = 0L;
135cdf0e10cSrcweir                     ImplAdd( &pTree );
136cdf0e10cSrcweir 
137cdf0e10cSrcweir                     while( nLeafCount > nMax )
138cdf0e10cSrcweir                         ImplReduce();
139cdf0e10cSrcweir                 }
140cdf0e10cSrcweir             }
141cdf0e10cSrcweir         }
142cdf0e10cSrcweir         else
143cdf0e10cSrcweir         {
144cdf0e10cSrcweir             BitmapColor aColor;
145cdf0e10cSrcweir 
146cdf0e10cSrcweir             pColor = &aColor;
147cdf0e10cSrcweir 
148cdf0e10cSrcweir             for( long nY = 0; nY < nHeight; nY++ )
149cdf0e10cSrcweir             {
150cdf0e10cSrcweir                 for( long nX = 0; nX < nWidth; nX++ )
151cdf0e10cSrcweir                 {
152cdf0e10cSrcweir                     aColor = pAcc->GetPixel( nY, nX );
153cdf0e10cSrcweir                     nLevel = 0L;
154cdf0e10cSrcweir                     ImplAdd( &pTree );
155cdf0e10cSrcweir 
156cdf0e10cSrcweir                     while( nLeafCount > nMax )
157cdf0e10cSrcweir                         ImplReduce();
158cdf0e10cSrcweir                 }
159cdf0e10cSrcweir             }
160cdf0e10cSrcweir         }
161cdf0e10cSrcweir     }
162cdf0e10cSrcweir }
163cdf0e10cSrcweir 
164cdf0e10cSrcweir // ------------------------------------------------------------------------
165cdf0e10cSrcweir 
ImplDeleteOctree(PPNODE ppNode)166cdf0e10cSrcweir void Octree::ImplDeleteOctree( PPNODE ppNode )
167cdf0e10cSrcweir {
168cdf0e10cSrcweir     for ( sal_uLong i = 0UL; i < 8UL; i++ )
169cdf0e10cSrcweir     {
170cdf0e10cSrcweir         if ( (*ppNode)->pChild[ i ] )
171cdf0e10cSrcweir             ImplDeleteOctree( &(*ppNode)->pChild[ i ] );
172cdf0e10cSrcweir     }
173cdf0e10cSrcweir 
174cdf0e10cSrcweir     pNodeCache->ImplReleaseNode( *ppNode );
175cdf0e10cSrcweir     *ppNode = NULL;
176cdf0e10cSrcweir }
177cdf0e10cSrcweir 
178cdf0e10cSrcweir // ------------------------------------------------------------------------
179cdf0e10cSrcweir 
ImplAdd(PPNODE ppNode)180cdf0e10cSrcweir void Octree::ImplAdd( PPNODE ppNode )
181cdf0e10cSrcweir {
182cdf0e10cSrcweir     // ggf. neuen Knoten erzeugen
183cdf0e10cSrcweir     if( !*ppNode )
184cdf0e10cSrcweir     {
185cdf0e10cSrcweir         *ppNode = pNodeCache->ImplGetFreeNode();
186cdf0e10cSrcweir         (*ppNode)->bLeaf = ( OCTREE_BITS == nLevel );
187cdf0e10cSrcweir 
188cdf0e10cSrcweir         if( (*ppNode)->bLeaf )
189cdf0e10cSrcweir             nLeafCount++;
190cdf0e10cSrcweir         else
191cdf0e10cSrcweir         {
192cdf0e10cSrcweir             (*ppNode)->pNext = pReduce[ nLevel ];
193cdf0e10cSrcweir             pReduce[ nLevel ] = *ppNode;
194cdf0e10cSrcweir         }
195cdf0e10cSrcweir     }
196cdf0e10cSrcweir 
197cdf0e10cSrcweir     if( (*ppNode)->bLeaf )
198cdf0e10cSrcweir     {
199cdf0e10cSrcweir         (*ppNode)->nCount++;
200cdf0e10cSrcweir         (*ppNode)->nRed += pColor->GetRed();
201cdf0e10cSrcweir         (*ppNode)->nGreen += pColor->GetGreen();
202cdf0e10cSrcweir         (*ppNode)->nBlue += pColor->GetBlue();
203cdf0e10cSrcweir     }
204cdf0e10cSrcweir     else
205cdf0e10cSrcweir     {
206cdf0e10cSrcweir         const sal_uLong nShift = 7 - nLevel;
207cdf0e10cSrcweir         const sal_uInt8  cMask = pImplMask[ nLevel ];
208cdf0e10cSrcweir         const sal_uLong nIndex = ( ( ( pColor->GetRed() & cMask ) >> nShift ) << 2 ) |
209cdf0e10cSrcweir                              ( ( ( pColor->GetGreen() & cMask ) >> nShift ) << 1 ) |
210cdf0e10cSrcweir                              ( ( pColor->GetBlue() & cMask ) >> nShift );
211cdf0e10cSrcweir 
212cdf0e10cSrcweir         nLevel++;
213cdf0e10cSrcweir         ImplAdd( &(*ppNode)->pChild[ nIndex ] );
214cdf0e10cSrcweir     }
215cdf0e10cSrcweir }
216cdf0e10cSrcweir 
217cdf0e10cSrcweir // ------------------------------------------------------------------------
218cdf0e10cSrcweir 
ImplReduce()219cdf0e10cSrcweir void Octree::ImplReduce()
220cdf0e10cSrcweir {
221cdf0e10cSrcweir     sal_uLong   i;
222cdf0e10cSrcweir     PNODE   pNode;
223cdf0e10cSrcweir     sal_uLong   nRedSum = 0L;
224cdf0e10cSrcweir     sal_uLong   nGreenSum = 0L;
225cdf0e10cSrcweir     sal_uLong   nBlueSum = 0L;
226cdf0e10cSrcweir     sal_uLong   nChilds = 0L;
227cdf0e10cSrcweir 
228cdf0e10cSrcweir     for ( i = OCTREE_BITS - 1; i && !pReduce[i]; i-- ) {}
229cdf0e10cSrcweir 
230cdf0e10cSrcweir     pNode = pReduce[ i ];
231cdf0e10cSrcweir     pReduce[ i ] = pNode->pNext;
232cdf0e10cSrcweir 
233cdf0e10cSrcweir     for ( i = 0; i < 8; i++ )
234cdf0e10cSrcweir     {
235cdf0e10cSrcweir         if ( pNode->pChild[ i ] )
236cdf0e10cSrcweir         {
237cdf0e10cSrcweir             PNODE pChild = pNode->pChild[ i ];
238cdf0e10cSrcweir 
239cdf0e10cSrcweir             nRedSum += pChild->nRed;
240cdf0e10cSrcweir             nGreenSum += pChild->nGreen;
241cdf0e10cSrcweir             nBlueSum += pChild->nBlue;
242cdf0e10cSrcweir             pNode->nCount += pChild->nCount;
243cdf0e10cSrcweir 
244cdf0e10cSrcweir             pNodeCache->ImplReleaseNode( pNode->pChild[ i ] );
245cdf0e10cSrcweir             pNode->pChild[ i ] = NULL;
246cdf0e10cSrcweir             nChilds++;
247cdf0e10cSrcweir         }
248cdf0e10cSrcweir     }
249cdf0e10cSrcweir 
250cdf0e10cSrcweir     pNode->bLeaf = sal_True;
251cdf0e10cSrcweir     pNode->nRed = nRedSum;
252cdf0e10cSrcweir     pNode->nGreen = nGreenSum;
253cdf0e10cSrcweir     pNode->nBlue = nBlueSum;
254cdf0e10cSrcweir     nLeafCount -= --nChilds;
255cdf0e10cSrcweir }
256cdf0e10cSrcweir 
257cdf0e10cSrcweir // ------------------------------------------------------------------------
258cdf0e10cSrcweir 
CreatePalette(PNODE pNode)259cdf0e10cSrcweir void Octree::CreatePalette( PNODE pNode )
260cdf0e10cSrcweir {
261cdf0e10cSrcweir     if( pNode->bLeaf )
262cdf0e10cSrcweir     {
263cdf0e10cSrcweir         pNode->nPalIndex = nPalIndex;
264cdf0e10cSrcweir         aPal[ nPalIndex++ ] = BitmapColor( (sal_uInt8) ( (double) pNode->nRed / pNode->nCount ),
265cdf0e10cSrcweir                                            (sal_uInt8) ( (double) pNode->nGreen / pNode->nCount ),
266cdf0e10cSrcweir                                            (sal_uInt8) ( (double) pNode->nBlue / pNode->nCount ) );
267cdf0e10cSrcweir     }
268cdf0e10cSrcweir     else for( sal_uLong i = 0UL; i < 8UL; i++ )
269cdf0e10cSrcweir         if( pNode->pChild[ i ] )
270cdf0e10cSrcweir             CreatePalette( pNode->pChild[ i ] );
271cdf0e10cSrcweir 
272cdf0e10cSrcweir }
273cdf0e10cSrcweir 
274cdf0e10cSrcweir // ------------------------------------------------------------------------
275cdf0e10cSrcweir 
GetPalIndex(PNODE pNode)276cdf0e10cSrcweir void Octree::GetPalIndex( PNODE pNode )
277cdf0e10cSrcweir {
278cdf0e10cSrcweir     if ( pNode->bLeaf )
279cdf0e10cSrcweir         nPalIndex = pNode->nPalIndex;
280cdf0e10cSrcweir     else
281cdf0e10cSrcweir     {
282cdf0e10cSrcweir         const sal_uLong nShift = 7 - nLevel;
283cdf0e10cSrcweir         const sal_uInt8  cMask = pImplMask[ nLevel++ ];
284cdf0e10cSrcweir         const sal_uLong nIndex = ( ( ( pColor->GetRed() & cMask ) >> nShift ) << 2 ) |
285cdf0e10cSrcweir                              ( ( ( pColor->GetGreen() & cMask ) >> nShift ) << 1 ) |
286cdf0e10cSrcweir                              ( ( pColor->GetBlue() & cMask ) >> nShift );
287cdf0e10cSrcweir 
288cdf0e10cSrcweir         GetPalIndex( pNode->pChild[ nIndex ] );
289cdf0e10cSrcweir     }
290cdf0e10cSrcweir }
291cdf0e10cSrcweir 
292cdf0e10cSrcweir // -------------------
293cdf0e10cSrcweir // - InverseColorMap -
294cdf0e10cSrcweir // -------------------
295cdf0e10cSrcweir 
InverseColorMap(const BitmapPalette & rPal)296cdf0e10cSrcweir InverseColorMap::InverseColorMap( const BitmapPalette& rPal ) :
297cdf0e10cSrcweir             nBits( 8 - OCTREE_BITS )
298cdf0e10cSrcweir {
299cdf0e10cSrcweir     sal_uLong*			cdp;
300cdf0e10cSrcweir     sal_uInt8*           crgbp;
301cdf0e10cSrcweir     const sal_uLong     nColorMax = 1 << OCTREE_BITS;
302cdf0e10cSrcweir     const sal_uLong     xsqr = 1 << ( nBits << 1 );
303cdf0e10cSrcweir     const sal_uLong     xsqr2 = xsqr << 1;
304cdf0e10cSrcweir     const sal_uLong     nColors = rPal.GetEntryCount();
305cdf0e10cSrcweir     const long      x = 1L << nBits;
306cdf0e10cSrcweir     const long      x2 = x >> 1L;
307cdf0e10cSrcweir     sal_uLong           r, g, b;
308cdf0e10cSrcweir     long            rxx, gxx, bxx;
309cdf0e10cSrcweir     long            rdist, gdist, bdist;
310cdf0e10cSrcweir     long            crinc, cginc, cbinc;
311cdf0e10cSrcweir 
312cdf0e10cSrcweir     ImplCreateBuffers( nColorMax );
313cdf0e10cSrcweir 
314cdf0e10cSrcweir     for( sal_uLong nIndex = 0; nIndex < nColors; nIndex++ )
315cdf0e10cSrcweir     {
316cdf0e10cSrcweir         const BitmapColor&  rColor = rPal[ (sal_uInt16) nIndex ];
317cdf0e10cSrcweir         const sal_uInt8			cRed = rColor.GetRed();
318cdf0e10cSrcweir         const sal_uInt8			cGreen = rColor.GetGreen();
319cdf0e10cSrcweir         const sal_uInt8			cBlue = rColor.GetBlue();
320cdf0e10cSrcweir 
321cdf0e10cSrcweir         rdist = cRed - x2;
322cdf0e10cSrcweir         gdist = cGreen - x2;
323cdf0e10cSrcweir         bdist = cBlue - x2;
324cdf0e10cSrcweir         rdist = rdist*rdist + gdist*gdist + bdist*bdist;
325cdf0e10cSrcweir 
326cdf0e10cSrcweir         crinc = ( xsqr - ( cRed << nBits ) ) << 1L;
327cdf0e10cSrcweir         cginc = ( xsqr - ( cGreen << nBits ) ) << 1L;
328cdf0e10cSrcweir         cbinc = ( xsqr - ( cBlue << nBits ) ) << 1L;
329cdf0e10cSrcweir 
330cdf0e10cSrcweir         cdp = (sal_uLong*) pBuffer;
331cdf0e10cSrcweir         crgbp = pMap;
332cdf0e10cSrcweir 
333cdf0e10cSrcweir         for( r = 0, rxx = crinc; r < nColorMax; rdist += rxx, r++, rxx += xsqr2 )
334cdf0e10cSrcweir         {
335cdf0e10cSrcweir             for( g = 0, gdist = rdist, gxx = cginc; g < nColorMax;  gdist += gxx, g++, gxx += xsqr2 )
336cdf0e10cSrcweir             {
337cdf0e10cSrcweir                 for( b = 0, bdist = gdist, bxx = cbinc; b < nColorMax; bdist += bxx, b++, cdp++, crgbp++, bxx += xsqr2 )
338cdf0e10cSrcweir                     if ( !nIndex || ( (long) *cdp ) > bdist )
339cdf0e10cSrcweir                     {
340cdf0e10cSrcweir                         *cdp = bdist;
341cdf0e10cSrcweir                         *crgbp = (sal_uInt8) nIndex;
342cdf0e10cSrcweir                     }
343cdf0e10cSrcweir             }
344cdf0e10cSrcweir         }
345cdf0e10cSrcweir     }
346cdf0e10cSrcweir }
347cdf0e10cSrcweir 
348cdf0e10cSrcweir // ------------------------------------------------------------------------
349cdf0e10cSrcweir 
~InverseColorMap()350cdf0e10cSrcweir InverseColorMap::~InverseColorMap()
351cdf0e10cSrcweir {
352cdf0e10cSrcweir     rtl_freeMemory( pBuffer );
353cdf0e10cSrcweir     rtl_freeMemory( pMap );
354cdf0e10cSrcweir }
355cdf0e10cSrcweir 
356cdf0e10cSrcweir // ------------------------------------------------------------------------
357cdf0e10cSrcweir 
ImplCreateBuffers(const sal_uLong nMax)358cdf0e10cSrcweir void InverseColorMap::ImplCreateBuffers( const sal_uLong nMax )
359cdf0e10cSrcweir {
360cdf0e10cSrcweir     const sal_uLong nCount = nMax * nMax * nMax;
361cdf0e10cSrcweir     const sal_uLong nSize = nCount * sizeof( sal_uLong );
362cdf0e10cSrcweir 
363cdf0e10cSrcweir     pMap = (sal_uInt8*) rtl_allocateMemory( nCount );
364cdf0e10cSrcweir     memset( pMap, 0x00, nCount );
365cdf0e10cSrcweir 
366cdf0e10cSrcweir     pBuffer = (sal_uInt8*) rtl_allocateMemory( nSize );
367cdf0e10cSrcweir     memset( pBuffer, 0xff, nSize );
368cdf0e10cSrcweir }
369