update credits
[LibreOffice.git] / vcl / source / gdi / octree.cxx
blob93fb8c5de18272870f7a0f0229d03f3dfdfb40ab
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <limits.h>
23 #include <vcl/bmpacc.hxx>
24 #include <vcl/octree.hxx>
26 #include <impoct.hxx>
28 // ---------
29 // - pMask -
30 // ---------
32 static sal_uInt8 pImplMask[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
34 // -------------
35 // - NodeCache -
36 // -------------
38 ImpNodeCache::ImpNodeCache( const sal_uLong nInitSize ) :
39 pActNode( NULL )
41 const sal_uLong nSize = nInitSize + 4;
43 for( sal_uLong i = 0; i < nSize; i++ )
45 OctreeNode* pNewNode = new NODE;
47 pNewNode->pNextInCache = pActNode;
48 pActNode = pNewNode;
52 // ------------------------------------------------------------------------
54 ImpNodeCache::~ImpNodeCache()
56 while( pActNode )
58 OctreeNode* pNode = pActNode;
60 pActNode = pNode->pNextInCache;
61 delete pNode;
65 // ----------
66 // - Octree -
67 // ----------
69 Octree::Octree( const BitmapReadAccess& rReadAcc, sal_uLong nColors ) :
70 nMax ( nColors ),
71 nLeafCount ( 0L ),
72 pTree ( NULL ),
73 pAcc ( &rReadAcc )
75 pNodeCache = new ImpNodeCache( nColors );
76 memset( pReduce, 0, ( OCTREE_BITS + 1 ) * sizeof( PNODE ) );
77 ImplCreateOctree();
80 // ------------------------------------------------------------------------
82 Octree::~Octree()
84 ImplDeleteOctree( &pTree );
85 delete pNodeCache;
88 // ------------------------------------------------------------------------
90 void Octree::ImplCreateOctree()
92 if( !!*pAcc )
94 const long nWidth = pAcc->Width();
95 const long nHeight = pAcc->Height();
97 if( pAcc->HasPalette() )
99 for( long nY = 0; nY < nHeight; nY++ )
101 for( long nX = 0; nX < nWidth; nX++ )
103 pColor = &(BitmapColor&) pAcc->GetPaletteColor( pAcc->GetPixelIndex( nY, nX ) );
104 nLevel = 0L;
105 ImplAdd( &pTree );
107 while( nLeafCount > nMax )
108 ImplReduce();
112 else
114 BitmapColor aColor;
116 pColor = &aColor;
118 for( long nY = 0; nY < nHeight; nY++ )
120 for( long nX = 0; nX < nWidth; nX++ )
122 aColor = pAcc->GetPixel( nY, nX );
123 nLevel = 0L;
124 ImplAdd( &pTree );
126 while( nLeafCount > nMax )
127 ImplReduce();
134 // ------------------------------------------------------------------------
136 void Octree::ImplDeleteOctree( PPNODE ppNode )
138 for ( sal_uLong i = 0UL; i < 8UL; i++ )
140 if ( (*ppNode)->pChild[ i ] )
141 ImplDeleteOctree( &(*ppNode)->pChild[ i ] );
144 pNodeCache->ImplReleaseNode( *ppNode );
145 *ppNode = NULL;
148 // ------------------------------------------------------------------------
150 void Octree::ImplAdd( PPNODE ppNode )
152 // ggf. neuen Knoten erzeugen
153 if( !*ppNode )
155 *ppNode = pNodeCache->ImplGetFreeNode();
156 (*ppNode)->bLeaf = ( OCTREE_BITS == nLevel );
158 if( (*ppNode)->bLeaf )
159 nLeafCount++;
160 else
162 (*ppNode)->pNext = pReduce[ nLevel ];
163 pReduce[ nLevel ] = *ppNode;
167 if( (*ppNode)->bLeaf )
169 (*ppNode)->nCount++;
170 (*ppNode)->nRed += pColor->GetRed();
171 (*ppNode)->nGreen += pColor->GetGreen();
172 (*ppNode)->nBlue += pColor->GetBlue();
174 else
176 const sal_uLong nShift = 7 - nLevel;
177 const sal_uInt8 cMask = pImplMask[ nLevel ];
178 const sal_uLong nIndex = ( ( ( pColor->GetRed() & cMask ) >> nShift ) << 2 ) |
179 ( ( ( pColor->GetGreen() & cMask ) >> nShift ) << 1 ) |
180 ( ( pColor->GetBlue() & cMask ) >> nShift );
182 nLevel++;
183 ImplAdd( &(*ppNode)->pChild[ nIndex ] );
187 // ------------------------------------------------------------------------
189 void Octree::ImplReduce()
191 sal_uLong i;
192 PNODE pNode;
193 sal_uLong nRedSum = 0L;
194 sal_uLong nGreenSum = 0L;
195 sal_uLong nBlueSum = 0L;
196 sal_uLong nChildren = 0L;
198 for ( i = OCTREE_BITS - 1; i && !pReduce[i]; i-- ) {}
200 pNode = pReduce[ i ];
201 pReduce[ i ] = pNode->pNext;
203 for ( i = 0; i < 8; i++ )
205 if ( pNode->pChild[ i ] )
207 PNODE pChild = pNode->pChild[ i ];
209 nRedSum += pChild->nRed;
210 nGreenSum += pChild->nGreen;
211 nBlueSum += pChild->nBlue;
212 pNode->nCount += pChild->nCount;
214 pNodeCache->ImplReleaseNode( pNode->pChild[ i ] );
215 pNode->pChild[ i ] = NULL;
216 nChildren++;
220 pNode->bLeaf = sal_True;
221 pNode->nRed = nRedSum;
222 pNode->nGreen = nGreenSum;
223 pNode->nBlue = nBlueSum;
224 nLeafCount -= --nChildren;
227 // ------------------------------------------------------------------------
229 void Octree::CreatePalette( PNODE pNode )
231 if( pNode->bLeaf )
233 pNode->nPalIndex = nPalIndex;
234 aPal[ nPalIndex++ ] = BitmapColor( (sal_uInt8) ( (double) pNode->nRed / pNode->nCount ),
235 (sal_uInt8) ( (double) pNode->nGreen / pNode->nCount ),
236 (sal_uInt8) ( (double) pNode->nBlue / pNode->nCount ) );
238 else for( sal_uLong i = 0UL; i < 8UL; i++ )
239 if( pNode->pChild[ i ] )
240 CreatePalette( pNode->pChild[ i ] );
244 // ------------------------------------------------------------------------
246 void Octree::GetPalIndex( PNODE pNode )
248 if ( pNode->bLeaf )
249 nPalIndex = pNode->nPalIndex;
250 else
252 const sal_uLong nShift = 7 - nLevel;
253 const sal_uInt8 cMask = pImplMask[ nLevel++ ];
254 const sal_uLong nIndex = ( ( ( pColor->GetRed() & cMask ) >> nShift ) << 2 ) |
255 ( ( ( pColor->GetGreen() & cMask ) >> nShift ) << 1 ) |
256 ( ( pColor->GetBlue() & cMask ) >> nShift );
258 GetPalIndex( pNode->pChild[ nIndex ] );
262 // -------------------
263 // - InverseColorMap -
264 // -------------------
266 InverseColorMap::InverseColorMap( const BitmapPalette& rPal ) :
267 nBits( 8 - OCTREE_BITS )
269 sal_uLong* cdp;
270 sal_uInt8* crgbp;
271 const sal_uLong nColorMax = 1 << OCTREE_BITS;
272 const sal_uLong xsqr = 1 << ( nBits << 1 );
273 const sal_uLong xsqr2 = xsqr << 1;
274 const sal_uLong nColors = rPal.GetEntryCount();
275 const long x = 1L << nBits;
276 const long x2 = x >> 1L;
277 sal_uLong r, g, b;
278 long rxx, gxx, bxx;
279 long rdist, gdist, bdist;
280 long crinc, cginc, cbinc;
282 ImplCreateBuffers( nColorMax );
284 for( sal_uLong nIndex = 0; nIndex < nColors; nIndex++ )
286 const BitmapColor& rColor = rPal[ (sal_uInt16) nIndex ];
287 const sal_uInt8 cRed = rColor.GetRed();
288 const sal_uInt8 cGreen = rColor.GetGreen();
289 const sal_uInt8 cBlue = rColor.GetBlue();
291 rdist = cRed - x2;
292 gdist = cGreen - x2;
293 bdist = cBlue - x2;
294 rdist = rdist*rdist + gdist*gdist + bdist*bdist;
296 crinc = ( xsqr - ( cRed << nBits ) ) << 1L;
297 cginc = ( xsqr - ( cGreen << nBits ) ) << 1L;
298 cbinc = ( xsqr - ( cBlue << nBits ) ) << 1L;
300 cdp = (sal_uLong*) pBuffer;
301 crgbp = pMap;
303 for( r = 0, rxx = crinc; r < nColorMax; rdist += rxx, r++, rxx += xsqr2 )
305 for( g = 0, gdist = rdist, gxx = cginc; g < nColorMax; gdist += gxx, g++, gxx += xsqr2 )
307 for( b = 0, bdist = gdist, bxx = cbinc; b < nColorMax; bdist += bxx, b++, cdp++, crgbp++, bxx += xsqr2 )
308 if ( !nIndex || ( (long) *cdp ) > bdist )
310 *cdp = bdist;
311 *crgbp = (sal_uInt8) nIndex;
318 // ------------------------------------------------------------------------
320 InverseColorMap::~InverseColorMap()
322 rtl_freeMemory( pBuffer );
323 rtl_freeMemory( pMap );
326 // ------------------------------------------------------------------------
328 void InverseColorMap::ImplCreateBuffers( const sal_uLong nMax )
330 const sal_uLong nCount = nMax * nMax * nMax;
331 const sal_uLong nSize = nCount * sizeof( sal_uLong );
333 pMap = (sal_uInt8*) rtl_allocateMemory( nCount );
334 memset( pMap, 0x00, nCount );
336 pBuffer = (sal_uInt8*) rtl_allocateMemory( nSize );
337 memset( pBuffer, 0xff, nSize );
340 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */