Subversion Repositories Scribus

Rev

Rev 16771 | Rev 19721 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
15796 fschmid 1
/*
2
 * The Progressive Graphics File; http://www.libpgf.org
16771 fschmid 3
 *
15796 fschmid 4
 * $Date: 2006-05-18 16:03:32 +0200 (Do, 18 Mai 2006) $
5
 * $Revision: 194 $
16771 fschmid 6
 *
15796 fschmid 7
 * This file Copyright (C) 2006 xeraina GmbH, Switzerland
16771 fschmid 8
 *
15796 fschmid 9
 * This program is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
11
 * as published by the Free Software Foundation; either version 2.1
12
 * of the License, or (at your option) any later version.
16771 fschmid 13
 *
15796 fschmid 14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
16771 fschmid 18
 *
15796 fschmid 19
 * You should have received a copy of the GNU General Public License
20
 * along with this program; if not, write to the Free Software
18122 mrdocs 21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
15796 fschmid 22
 */
23
 
16771 fschmid 24
//////////////////////////////////////////////////////////////////////
25
/// @file WaveletTransform.cpp
26
/// @brief PGF wavelet transform class implementation
27
/// @author C. Stamm
28
 
15796 fschmid 29
#include "WaveletTransform.h"
30
 
31
#define c1 1    // best value 1
32
#define c2 2    // best value 2
33
 
34
//////////////////////////////////////////////////////////////////////////
35
// Constructor: Constructs a wavelet transform pyramid of given size and levels.
36
// @param width The width of the original image (at level 0) in pixels
37
// @param height The height of the original image (at level 0) in pixels
38
// @param levels The number of levels (>= 0)
39
// @param data Input data of subband LL at level 0
16771 fschmid 40
CWaveletTransform::CWaveletTransform(UINT32 width, UINT32 height, int levels, DataT* data) :
15796 fschmid 41
#ifdef __PGFROISUPPORT__
16771 fschmid 42
m_ROIs(levels + 1),
15796 fschmid 43
#endif
44
m_nLevels(levels + 1), m_subband(0) {
45
        ASSERT(m_nLevels > 0 && m_nLevels <= MaxLevel + 1);
46
        InitSubbands(width, height, data);
47
}
48
 
49
/////////////////////////////////////////////////////////////////////
50
// Initialize size subbands on all levels
51
void CWaveletTransform::InitSubbands(UINT32 width, UINT32 height, DataT* data) {
52
        if (m_subband) Destroy();
53
 
54
        // create subbands
55
        m_subband = new CSubband[m_nLevels][NSubbands];
56
 
57
        // init subbands
58
        UINT32 loWidth = width;
59
        UINT32 hiWidth = width;
60
        UINT32 loHeight = height;
61
        UINT32 hiHeight = height;
62
 
63
        for (int level = 0; level < m_nLevels; level++) {
64
                m_subband[level][LL].Initialize(loWidth, loHeight, level, LL);  // LL
65
                m_subband[level][HL].Initialize(hiWidth, loHeight, level, HL);  //    HL
66
                m_subband[level][LH].Initialize(loWidth, hiHeight, level, LH);  // LH
67
                m_subband[level][HH].Initialize(hiWidth, hiHeight, level, HH);  //    HH
68
                hiWidth = loWidth >> 1;                 hiHeight = loHeight >> 1;
69
                loWidth = (loWidth + 1) >> 1;   loHeight = (loHeight + 1) >> 1;
70
        }
71
        if (data) {
72
                m_subband[0][LL].SetBuffer(data);
73
        }
74
}
75
 
76
//////////////////////////////////////////////////////////////////////////
77
// Compute fast forward wavelet transform of LL subband at given level and
78
// stores result on all 4 subbands of level + 1.
79
// Wavelet transform used in writing a PGF file
80
// Forward Transform of srcBand and split and store it into subbands on destLevel
81
// high pass filter at even positions: 1/4(-2, 4, -2)
82
// low pass filter at odd positions: 1/8(-1, 2, 6, 2, -1)
83
// @param level A wavelet transform pyramid level (>= 0 && < Levels())
84
void CWaveletTransform::ForwardTransform(int level) {
85
        ASSERT(level >= 0 && level < m_nLevels - 1);
86
        const int destLevel = level + 1;
87
        ASSERT(m_subband[destLevel]);
88
        CSubband* srcBand = &m_subband[level][LL]; ASSERT(srcBand);
89
        const UINT32 width = srcBand->GetWidth();
90
        const UINT32 height = srcBand->GetHeight();
91
        DataT* src = srcBand->GetBuffer(); ASSERT(src);
92
        UINT32 row0, row1, row2, row3;
93
        UINT32 i, k;
94
 
95
        // Allocate memory for next transform level
96
        for (i=0; i < NSubbands; i++) {
97
                m_subband[destLevel][i].AllocMemory();
98
        }
99
 
100
        if (height >= FilterHeight) {
101
                // transform LL subband
102
                // top border handling
103
                row0 = 0; row1 = width; row2 = row1 + width;
104
                ForwardRow(&src[row0], width);
105
                ForwardRow(&src[row1], width);
106
                ForwardRow(&src[row2], width);
107
                for (k=0; k < width; k++) {
108
                        src[row1] -= ((src[row0] + src[row2] + c1) >> 1);
109
                        src[row0] += ((src[row1] + c1) >> 1);
110
                        row0++; row1++; row2++;
111
                }
112
                LinearToMallat(destLevel, &src[0], &src[row0], width);
113
 
114
                // middle part
115
                row3 = row2 + width;
116
                for (i=3; i < height-1; i += 2) {
117
                        ForwardRow(&src[row2], width);
118
                        ForwardRow(&src[row3], width);
119
                        for (k=0; k < width; k++) {
120
                                src[row2] -= ((src[row1] + src[row3] + c1) >> 1);
121
                                src[row1] += ((src[row0] + src[row2] + c2) >> 2);
122
                                row0++; row1++; row2++; row3++;
123
                        }
124
                        LinearToMallat(destLevel, &src[row0], &src[row1], width);
125
                        row0 = row1; row1 = row2; row2 = row3; row3 += width;
126
                }
127
 
128
                // bottom border handling
129
                if (height & 1) {
130
                        for (k=0; k < width; k++) {
131
                                src[row1] += ((src[row0] + c1) >> 1);
132
                                row0++; row1++;
133
                        }
134
                        LinearToMallat(destLevel, &src[row0], NULL, width);
135
                } else {
136
                        ForwardRow(&src[row2], width);
137
                        for (k=0; k < width; k++) {
138
                                src[row2] -= src[row1];
139
                                src[row1] += ((src[row0] + src[row2] + c2) >> 2);
140
                                row0++; row1++; row2++;
141
                        }
142
                        LinearToMallat(destLevel, &src[row0], &src[row1], width);
143
                }
144
        } else {
145
                // if height to small
146
                row0 = 0; row1 = width;
147
                // first part
148
                for (k=0; k < height; k += 2) {
149
                        ForwardRow(&src[row0], width);
150
                        ForwardRow(&src[row1], width);
151
                        LinearToMallat(destLevel, &src[row0], &src[row1], width);
152
                        row0 += width << 1; row1 += width << 1;
153
                }
154
                // bottom
155
                if (height & 1) {
156
                        LinearToMallat(destLevel, &src[row0], NULL, width);
157
                }
158
        }
159
 
160
        // free source band
161
        srcBand->FreeMemory();
162
}
163
 
164
//////////////////////////////////////////////////////////////
165
// Forward transform one row
166
// high pass filter at even positions: 1/4(-2, 4, -2)
167
// low pass filter at odd positions: 1/8(-1, 2, 6, 2, -1)
168
void CWaveletTransform::ForwardRow(DataT* src, UINT32 width) {
169
        if (width >= FilterWidth) {
170
                UINT32 i = 3;
171
 
172
                // left border handling
173
                src[1] -= ((src[0] + src[2] + c1) >> 1);
174
                src[0] += ((src[1] + c1) >> 1);
16771 fschmid 175
 
15796 fschmid 176
                // middle part
177
                for (; i < width-1; i += 2) {
178
                        src[i] -= ((src[i-1] + src[i+1] + c1) >> 1);
179
                        src[i-1] += ((src[i-2] + src[i] + c2) >> 2);
180
                }
181
 
182
                // right border handling
183
                if (width & 1) {
184
                        src[i-1] += ((src[i-2] + c1) >> 1);
185
                } else {
186
                        src[i] -= src[i-1];
187
                        src[i-1] += ((src[i-2] + src[i] + c2) >> 2);
188
                }
189
        }
190
}
191
 
192
/////////////////////////////////////////////////////////////////
193
// Copy transformed rows loRow and hiRow to subbands LL,HL,LH,HH
194
void CWaveletTransform::LinearToMallat(int destLevel, DataT* loRow, DataT* hiRow, UINT32 width) {
195
        const UINT32 wquot = width >> 1;
196
        const bool wrem = width & 1;
197
        CSubband &ll = m_subband[destLevel][LL], &hl = m_subband[destLevel][HL];
198
        CSubband &lh = m_subband[destLevel][LH], &hh = m_subband[destLevel][HH];
199
        UINT32 i;
200
 
201
        if (hiRow) {
202
                for (i=0; i < wquot; i++) {
203
                        ll.WriteBuffer(*loRow++);       // first access, than increment
204
                        hl.WriteBuffer(*loRow++);
205
                        lh.WriteBuffer(*hiRow++);       // first access, than increment
206
                        hh.WriteBuffer(*hiRow++);
207
                }
208
                if (wrem) {
209
                        ll.WriteBuffer(*loRow);
210
                        lh.WriteBuffer(*hiRow);
211
                }
212
        } else {
213
                for (i=0; i < wquot; i++) {
214
                        ll.WriteBuffer(*loRow++);       // first access, than increment
215
                        hl.WriteBuffer(*loRow++);
216
                }
217
                if (wrem) ll.WriteBuffer(*loRow);
218
        }
219
}
220
 
221
//////////////////////////////////////////////////////////////////////////
222
// Compute fast inverse wavelet transform of all 4 subbands of given level and
223
// stores result in LL subband of level - 1.
224
// Inverse wavelet transform used in reading a PGF file
225
// Inverse Transform srcLevel and combine to destBand
226
// inverse high pass filter for even positions: 1/4(-1, 4, -1)
227
// inverse low pass filter for odd positions: 1/8(-1, 4, 6, 4, -1)
228
// @param srcLevel A wavelet transform pyramid level (> 0 && <= Levels())
229
// @param w [out] A pointer to the returned width of subband LL (in pixels)
230
// @param h [out] A pointer to the returned height of subband LL (in pixels)
231
// @param data [out] A pointer to the returned array of image data
232
void CWaveletTransform::InverseTransform(int srcLevel, UINT32* w, UINT32* h, DataT** data) {
233
        ASSERT(srcLevel > 0 && srcLevel < m_nLevels);
234
        const int destLevel = srcLevel - 1;
235
        ASSERT(m_subband[destLevel]);
236
        CSubband* destBand = &m_subband[destLevel][LL];
237
        const UINT32 width = destBand->GetWidth();
238
        const UINT32 height = destBand->GetHeight();
239
        UINT32 row0, row1, row2, row3, i, k, origin = 0;
240
 
16771 fschmid 241
        // allocate memory for the results of the inverse transform
15796 fschmid 242
        destBand->AllocMemory();
243
        DataT* dest = destBand->GetBuffer();
244
 
245
#ifdef __PGFROISUPPORT__
246
        const UINT32 srcLeft = (m_ROIs.ROIisSupported()) ? m_ROIs.Left(srcLevel) : 0;
247
        const UINT32 srcTop = (m_ROIs.ROIisSupported()) ? m_ROIs.Top(srcLevel) : 0;
248
        UINT32 destWidth = destBand->BufferWidth(); // destination buffer width; is valid only after AllocMemory
249
        PGFRect destROI = (m_ROIs.ROIisSupported()) ? m_ROIs.GetROI(destLevel) : PGFRect(0, 0, width, height);
250
        destROI.right = destROI.left + destWidth;
251
        destROI.bottom = __min(destROI.bottom, height);
252
        UINT32 destHeight = destROI.Height(); // destination buffer height
253
 
254
        // update destination ROI
255
        if (destROI.left & 1) {
256
                destROI.left++;
257
                origin++;
258
                destWidth--;
259
        }
260
        if (destROI.top & 1) {
261
                destROI.top++;
262
                origin += destWidth;
263
                destHeight--;
264
        }
265
 
266
        // init source buffer position
267
        UINT32 left = destROI.left >> 1;
268
        UINT32 top = destROI.top >> 1;
269
 
270
        left -= srcLeft;
271
        top -= srcTop;
272
        for (i=0; i < NSubbands; i++) {
273
                m_subband[srcLevel][i].InitBuffPos(left, top);
274
        }
275
#else
276
        PGFRect destROI(0, 0, width, height);
277
        const UINT32 destWidth = width; // destination buffer width
278
        const UINT32 destHeight = height; // destination buffer height
279
 
280
        // init source buffer position
281
        for (i=0; i < NSubbands; i++) {
282
                m_subband[srcLevel][i].InitBuffPos();
283
        }
284
#endif
285
 
286
        if (destHeight >= FilterHeight) {
287
                // top border handling
288
                row0 = origin; row1 = row0 + destWidth;
289
                MallatToLinear(srcLevel, &dest[row0], &dest[row1], destWidth);
290
                for (k=0; k < destWidth; k++) {
291
                        ASSERT(row0 < destBand->m_size);
292
                        ASSERT(row1 < destBand->m_size);
293
                        dest[row0] -= ((dest[row1] + c1) >> 1);
294
                        row0++; row1++;
295
                }
296
 
297
                // middle part
298
                row2 = row1; row1 = row0; row0 = row0 - destWidth; row3 = row2 + destWidth;
299
                for (i=destROI.top + 2; i < destROI.bottom - 1; i += 2) {
300
                        MallatToLinear(srcLevel, &dest[row2], &dest[row3], destWidth);
301
                        for (k=0; k < destWidth; k++) {
302
                                ASSERT(row0 < destBand->m_size);
303
                                ASSERT(row1 < destBand->m_size);
304
                                ASSERT(row2 < destBand->m_size);
305
                                ASSERT(row3 < destBand->m_size);
306
                                dest[row2] -= ((dest[row1] + dest[row3] + c2) >> 2);
307
                                dest[row1] += ((dest[row0] + dest[row2] + c1) >> 1);
308
                                row0++; row1++; row2++; row3++;
309
                        }
310
                        InverseRow(&dest[row0 - destWidth], destWidth);
311
                        InverseRow(&dest[row1 - destWidth], destWidth);
312
                        row0 = row1; row1 = row2; row2 = row3; row3 += destWidth;
313
                }
314
 
315
                // bottom border handling
316
                if (destHeight & 1) {
317
                        MallatToLinear(srcLevel, &dest[row2], 0, destWidth);
318
                        for (k=0; k < destWidth; k++) {
319
                                ASSERT(row0 < destBand->m_size);
320
                                ASSERT(row1 < destBand->m_size);
321
                                ASSERT(row2 < destBand->m_size);
322
                                dest[row2] -= ((dest[row1] + c1) >> 1);
323
                                dest[row1] += ((dest[row0] + dest[row2] + c1) >> 1);
324
                                row0++; row1++; row2++;
325
                        }
326
                        InverseRow(&dest[row0 - destWidth], destWidth);
327
                        InverseRow(&dest[row1 - destWidth], destWidth);
328
                        InverseRow(&dest[row2 - destWidth], destWidth);
329
                } else {
330
                        for (k=0; k < destWidth; k++) {
331
                                ASSERT(row0 < destBand->m_size);
332
                                ASSERT(row1 < destBand->m_size);
333
                                dest[row1] += dest[row0];
334
                                row0++; row1++;
335
                        }
336
                        InverseRow(&dest[row0 - destWidth], destWidth);
337
                        InverseRow(&dest[row1 - destWidth], destWidth);
338
                }
339
        } else {
340
                // destHeight to small
341
                row0 = origin; row1 = row0 + destWidth;
342
                // first part
343
                for (k=0; k < destHeight; k += 2) {
344
                        MallatToLinear(srcLevel, &dest[row0], &dest[row1], destWidth);
345
                        InverseRow(&dest[row0], destWidth);
346
                        InverseRow(&dest[row1], destWidth);
347
                        row0 += destWidth << 1; row1 += destWidth << 1;
348
                }
349
                // bottom
350
                if (destHeight & 1) {
351
                        MallatToLinear(srcLevel, &dest[row0], 0, destWidth);
352
                        InverseRow(&dest[row0], destWidth);
16771 fschmid 353
                }
15796 fschmid 354
        }
355
 
356
        // free memory of the current srcLevel
357
        for (i=0; i < NSubbands; i++) {
358
                m_subband[srcLevel][i].FreeMemory();
359
        }
360
 
361
        // return info
362
        *w = destWidth;
363
        *h = destHeight;
364
//      *w = width;
365
//      *h = height;
366
        *data = dest;
367
}
368
 
369
//////////////////////////////////////////////////////////////////////
370
// Inverse Wavelet Transform of one row
371
// inverse high pass filter for even positions: 1/4(-1, 4, -1)
372
// inverse low pass filter for odd positions: 1/8(-1, 4, 6, 4, -1)
373
void CWaveletTransform::InverseRow(DataT* dest, UINT32 width) {
374
        if (width >= FilterWidth) {
375
                UINT32 i = 2;
376
 
377
                // left border handling
378
                dest[0] -= ((dest[1] + c1) >> 1);
379
 
380
                // middle part
381
                for (; i < width - 1; i += 2) {
382
                        dest[i] -= ((dest[i-1] + dest[i+1] + c2) >> 2);
383
                        dest[i-1] += ((dest[i-2] + dest[i] + c1) >> 1);
384
                }
385
 
386
                // right border handling
387
                if (width & 1) {
388
                        dest[i] -= ((dest[i-1] + c1) >> 1);
389
                        dest[i-1] += ((dest[i-2] + dest[i] + c1) >> 1);
390
                } else {
391
                        dest[i-1] += dest[i-2];
392
                }
393
        }
394
}
395
 
396
///////////////////////////////////////////////////////////////////
397
// Copy transformed coefficients from subbands LL,HL,LH,HH to interleaved format
398
void CWaveletTransform::MallatToLinear(int srcLevel, DataT* loRow, DataT* hiRow, UINT32 width) {
399
        const UINT32 wquot = width >> 1;
400
        const bool wrem = width & 1;
401
        CSubband &ll = m_subband[srcLevel][LL], &hl = m_subband[srcLevel][HL];
402
        CSubband &lh = m_subband[srcLevel][LH], &hh = m_subband[srcLevel][HH];
403
        UINT32 i;
404
 
405
        if (hiRow) {
16771 fschmid 406
        #ifdef __PGFROISUPPORT__
407
                const bool storePos = wquot < ll.BufferWidth();
408
                UINT32 llPos = 0, hlPos = 0, lhPos = 0, hhPos = 0;
15796 fschmid 409
 
16771 fschmid 410
                if (storePos) {
411
                        // save current src buffer positions
412
                        llPos = ll.GetBuffPos();
413
                        hlPos = hl.GetBuffPos();
414
                        lhPos = lh.GetBuffPos();
415
                        hhPos = hh.GetBuffPos();
416
                }
417
        #endif
15796 fschmid 418
 
419
                for (i=0; i < wquot; i++) {
420
                        *loRow++ = ll.ReadBuffer();// first access, than increment
421
                        *loRow++ = hl.ReadBuffer();// first access, than increment
422
                        *hiRow++ = lh.ReadBuffer();// first access, than increment
423
                        *hiRow++ = hh.ReadBuffer();// first access, than increment
424
                }
425
 
426
                if (wrem) {
427
                        *loRow++ = ll.ReadBuffer();// first access, than increment
428
                        *hiRow++ = lh.ReadBuffer();// first access, than increment
429
                }
430
 
16771 fschmid 431
        #ifdef __PGFROISUPPORT__
432
                if (storePos) {
433
                        // increment src buffer positions
434
                        ll.IncBuffRow(llPos);
435
                        hl.IncBuffRow(hlPos);
436
                        lh.IncBuffRow(lhPos);
437
                        hh.IncBuffRow(hhPos);
438
                }
439
        #endif
15796 fschmid 440
 
441
        } else {
16771 fschmid 442
        #ifdef __PGFROISUPPORT__
443
                const bool storePos = wquot < ll.BufferWidth();
444
                UINT32 llPos = 0, hlPos = 0;
15796 fschmid 445
 
16771 fschmid 446
                if (storePos) {
447
                        // save current src buffer positions
448
                        llPos = ll.GetBuffPos();
449
                        hlPos = hl.GetBuffPos();
450
                }
451
        #endif
15796 fschmid 452
 
453
                for (i=0; i < wquot; i++) {
454
                        *loRow++ = ll.ReadBuffer();// first access, than increment
455
                        *loRow++ = hl.ReadBuffer();// first access, than increment
456
                }
457
                if (wrem) *loRow++ = ll.ReadBuffer();
458
 
16771 fschmid 459
        #ifdef __PGFROISUPPORT__
460
                if (storePos) {
461
                        // increment src buffer positions
462
                        ll.IncBuffRow(llPos);
463
                        hl.IncBuffRow(hlPos);
464
                }
465
        #endif
15796 fschmid 466
        }
467
}
468
 
469
#ifdef __PGFROISUPPORT__
470
//////////////////////////////////////////////////////////////////////
471
/// Compute and store ROIs for each level
472
/// @param rect rectangular region of interest (ROI)
473
void CWaveletTransform::SetROI(const PGFRect& rect) {
474
        // create and init ROIs
475
        SetROI();
476
 
477
        // create tile indices
478
        m_ROIs.CreateIndices();
479
 
480
        // compute tile indices
481
        m_ROIs.ComputeIndices(m_subband[0][LL].GetWidth(), m_subband[0][LL].GetHeight(), rect);
482
 
483
        // compute ROIs
484
        UINT32 w, h;
485
        PGFRect r;
486
 
487
        for (int i=0; i < m_nLevels; i++) {
488
                const PGFRect& indices = m_ROIs.GetIndices(i);
489
                m_subband[i][LL].TilePosition(indices.left, indices.top, r.left, r.top, w, h);
490
                //if (r.left & 1) r.left++;     // ensures ROI starts at an even position
491
                //if (r.top & 1) r.top++;               // ensures ROI starts at an even position
492
                m_subband[i][LL].TilePosition(indices.right - 1, indices.bottom - 1, r.right, r.bottom, w, h);
493
                r.right += w;
494
                r.bottom += h;
495
                m_ROIs.SetROI(i, r);
496
        }
497
}
498
 
499
//////////////////////////////////////////////////////////////////////
500
/// For each subband set a reference to ROI information
501
void CWaveletTransform::SetROI() {
502
        // create and init ROIs
503
        m_ROIs.CreateROIs();
504
 
505
        // set ROI references
506
        for (int i=0; i < m_nLevels; i++) {
507
                m_ROIs.SetROI(i, PGFRect(0, 0, m_subband[i][LL].GetWidth(), m_subband[i][LL].GetHeight()));
508
                m_subband[i][LL].SetROI(&m_ROIs);       // LL
509
                m_subband[i][HL].SetROI(&m_ROIs);       //    HL
510
                m_subband[i][LH].SetROI(&m_ROIs);       // LH
511
                m_subband[i][HH].SetROI(&m_ROIs);       //    HH
512
        }
513
}
514
 
515
/////////////////////////////////////////////////////////////////////
516
 
517
/////////////////////////////////////////////////////////////////////
518
void CROIs::CreateROIs() {
519
        if (!m_ROIs) {
16771 fschmid 520
                // create ROIs
15796 fschmid 521
                m_ROIs = new PGFRect[m_nLevels];
522
        }
523
}
524
 
525
/////////////////////////////////////////////////////////////////////
526
void CROIs::CreateIndices() {
527
        if (!m_indices) {
16771 fschmid 528
                // create tile indices
15796 fschmid 529
                m_indices = new PGFRect[m_nLevels];
530
        }
531
}
532
 
533
//////////////////////////////////////////////////////////////////////
534
/// Computes a tile index either in x- or y-direction for a given image position.
535
/// @param width PGF image width
536
/// @param height PGF image height
537
/// @param pos A valid image position: (0 <= pos < width) or (0 <= pos < height)
538
/// @param horizontal If true, then pos must be a x-value, otherwise a y-value
539
/// @param isMin If true, then pos is left/top, else pos right/bottom
540
void CROIs::ComputeTileIndex(UINT32 width, UINT32 height, UINT32 pos, bool horizontal, bool isMin) {
541
        ASSERT(m_indices);
542
 
543
        UINT32 m;
544
        UINT32 tileIndex = 0;
545
        UINT32 tileMin = 0, tileMax = (horizontal) ? width : height;
546
        ASSERT(pos <= tileMax);
547
 
548
        // compute tile index with binary search
549
        for (int i=m_nLevels - 1; i >= 0; i--) {
550
                // store values
551
                if (horizontal) {
552
                        if (isMin) {
553
                                m_indices[i].left = tileIndex;
554
                        } else {
555
                                m_indices[i].right = tileIndex + 1;
556
                        }
557
                } else {
558
                        if (isMin) {
559
                                m_indices[i].top = tileIndex;
560
                        } else {
561
                                m_indices[i].bottom = tileIndex + 1;
562
                        }
563
                }
564
 
565
                // compute values
566
                tileIndex <<= 1;
567
                m = (tileMin + tileMax)/2;
568
                if (pos >= m) {
569
                        tileMin = m;
570
                        tileIndex++;
571
                } else {
572
                        tileMax = m;
573
                }
574
        }
575
}
576
 
577
/////////////////////////////////////////////////////////////////////
578
/// Compute tile indices for given rectangle (ROI)
579
/// @param width PGF image width
580
/// @param height PGF image height
581
/// @param rect ROI
582
void CROIs::ComputeIndices(UINT32 width, UINT32 height, const PGFRect& rect) {
583
        ComputeTileIndex(width, height, rect.left, true, true);
584
        ComputeTileIndex(width, height, rect.top, false, true);
585
        ComputeTileIndex(width, height, rect.right, true, false);
586
        ComputeTileIndex(width, height, rect.bottom, false, false);
587
}
588
 
589
#endif // __PGFROISUPPORT__