]> git.saurik.com Git - wxWidgets.git/blob - src/tiff/contrib/addtiffo/tif_ovrcache.c
Make wxOwnerDrawnComboBox::DoGetBestSize() twice as fast.
[wxWidgets.git] / src / tiff / contrib / addtiffo / tif_ovrcache.c
1 /******************************************************************************
2 *
3 * Project: TIFF Overview Builder
4 * Purpose: Library functions to maintain two rows of tiles or two strips
5 * of data for output overviews as an output cache.
6 * Author: Frank Warmerdam, warmerdam@pobox.com
7 *
8 ******************************************************************************
9 * Copyright (c) 2000, Frank Warmerdam
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included
19 * in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 * DEALINGS IN THE SOFTWARE.
28 ******************************************************************************
29 */
30
31 #include "tiffiop.h"
32 #include "tif_ovrcache.h"
33 #include <assert.h>
34
35 /************************************************************************/
36 /* TIFFCreateOvrCache() */
37 /* */
38 /* Create an overview cache to hold two rows of blocks from an */
39 /* existing TIFF directory. */
40 /************************************************************************/
41
42 TIFFOvrCache *TIFFCreateOvrCache( TIFF *hTIFF, toff_t nDirOffset )
43
44 {
45 TIFFOvrCache *psCache;
46 toff_t nBaseDirOffset;
47
48 psCache = (TIFFOvrCache *) _TIFFmalloc(sizeof(TIFFOvrCache));
49 psCache->nDirOffset = nDirOffset;
50 psCache->hTIFF = hTIFF;
51
52 /* -------------------------------------------------------------------- */
53 /* Get definition of this raster from the TIFF file itself. */
54 /* -------------------------------------------------------------------- */
55 nBaseDirOffset = TIFFCurrentDirOffset( psCache->hTIFF );
56 TIFFSetSubDirectory( hTIFF, nDirOffset );
57
58 TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &(psCache->nXSize) );
59 TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &(psCache->nYSize) );
60
61 TIFFGetField( hTIFF, TIFFTAG_BITSPERSAMPLE, &(psCache->nBitsPerPixel) );
62 TIFFGetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, &(psCache->nSamples) );
63 TIFFGetField( hTIFF, TIFFTAG_PLANARCONFIG, &(psCache->nPlanarConfig) );
64
65 if( !TIFFIsTiled( hTIFF ) )
66 {
67 TIFFGetField( hTIFF, TIFFTAG_ROWSPERSTRIP, &(psCache->nBlockYSize) );
68 psCache->nBlockXSize = psCache->nXSize;
69 psCache->nBytesPerBlock = TIFFStripSize(hTIFF);
70 psCache->bTiled = FALSE;
71 }
72 else
73 {
74 TIFFGetField( hTIFF, TIFFTAG_TILEWIDTH, &(psCache->nBlockXSize) );
75 TIFFGetField( hTIFF, TIFFTAG_TILELENGTH, &(psCache->nBlockYSize) );
76 psCache->nBytesPerBlock = TIFFTileSize(hTIFF);
77 psCache->bTiled = TRUE;
78 }
79
80 /* -------------------------------------------------------------------- */
81 /* Compute some values from this. */
82 /* -------------------------------------------------------------------- */
83
84 psCache->nBlocksPerRow = (psCache->nXSize + psCache->nBlockXSize - 1)
85 / psCache->nBlockXSize;
86 psCache->nBlocksPerColumn = (psCache->nYSize + psCache->nBlockYSize - 1)
87 / psCache->nBlockYSize;
88
89 if (psCache->nPlanarConfig == PLANARCONFIG_SEPARATE)
90 psCache->nBytesPerRow = psCache->nBytesPerBlock
91 * psCache->nBlocksPerRow * psCache->nSamples;
92 else
93 psCache->nBytesPerRow =
94 psCache->nBytesPerBlock * psCache->nBlocksPerRow;
95
96
97 /* -------------------------------------------------------------------- */
98 /* Allocate and initialize the data buffers. */
99 /* -------------------------------------------------------------------- */
100
101 psCache->pabyRow1Blocks =
102 (unsigned char *) _TIFFmalloc(psCache->nBytesPerRow);
103 psCache->pabyRow2Blocks =
104 (unsigned char *) _TIFFmalloc(psCache->nBytesPerRow);
105
106 if( psCache->pabyRow1Blocks == NULL
107 || psCache->pabyRow2Blocks == NULL )
108 {
109 TIFFErrorExt( hTIFF->tif_clientdata, hTIFF->tif_name,
110 "Can't allocate memory for overview cache." );
111 /* TODO: use of TIFFError is inconsistent with use of fprintf in addtiffo.c, sort out */
112 return NULL;
113 }
114
115 _TIFFmemset( psCache->pabyRow1Blocks, 0, psCache->nBytesPerRow );
116 _TIFFmemset( psCache->pabyRow2Blocks, 0, psCache->nBytesPerRow );
117
118 psCache->nBlockOffset = 0;
119
120 TIFFSetSubDirectory( psCache->hTIFF, nBaseDirOffset );
121
122 return psCache;
123 }
124
125 /************************************************************************/
126 /* TIFFWriteOvrRow() */
127 /* */
128 /* Write one entire row of blocks (row 1) to the tiff file, and */
129 /* then rotate the block buffers, essentially moving things */
130 /* down by one block. */
131 /************************************************************************/
132
133 static void TIFFWriteOvrRow( TIFFOvrCache * psCache )
134
135 {
136 int nRet, iTileX, iTileY = psCache->nBlockOffset;
137 unsigned char *pabyData;
138 toff_t nBaseDirOffset;
139 uint32 RowsInStrip;
140
141 /* -------------------------------------------------------------------- */
142 /* If the output cache is multi-byte per sample, and the file */
143 /* being written to is of a different byte order than the current */
144 /* platform, we will need to byte swap the data. */
145 /* -------------------------------------------------------------------- */
146 if( TIFFIsByteSwapped(psCache->hTIFF) )
147 {
148 if( psCache->nBitsPerPixel == 16 )
149 TIFFSwabArrayOfShort( (uint16 *) psCache->pabyRow1Blocks,
150 (psCache->nBytesPerBlock * psCache->nSamples) / 2 );
151
152 else if( psCache->nBitsPerPixel == 32 )
153 TIFFSwabArrayOfLong( (uint32 *) psCache->pabyRow1Blocks,
154 (psCache->nBytesPerBlock * psCache->nSamples) / 4 );
155
156 else if( psCache->nBitsPerPixel == 64 )
157 TIFFSwabArrayOfDouble( (double *) psCache->pabyRow1Blocks,
158 (psCache->nBytesPerBlock * psCache->nSamples) / 8 );
159 }
160
161 /* -------------------------------------------------------------------- */
162 /* Record original directory position, so we can restore it at */
163 /* end. */
164 /* -------------------------------------------------------------------- */
165 nBaseDirOffset = TIFFCurrentDirOffset( psCache->hTIFF );
166 nRet = TIFFSetSubDirectory( psCache->hTIFF, psCache->nDirOffset );
167 assert( nRet == 1 );
168
169 /* -------------------------------------------------------------------- */
170 /* Write blocks to TIFF file. */
171 /* -------------------------------------------------------------------- */
172 for( iTileX = 0; iTileX < psCache->nBlocksPerRow; iTileX++ )
173 {
174 int nTileID;
175
176 if (psCache->nPlanarConfig == PLANARCONFIG_SEPARATE)
177 {
178 int iSample;
179
180 for( iSample = 0; iSample < psCache->nSamples; iSample++ )
181 {
182 pabyData = TIFFGetOvrBlock( psCache, iTileX, iTileY, iSample );
183
184 if( psCache->bTiled )
185 {
186 nTileID = TIFFComputeTile( psCache->hTIFF,
187 iTileX * psCache->nBlockXSize,
188 iTileY * psCache->nBlockYSize,
189 0, (tsample_t) iSample );
190 TIFFWriteEncodedTile( psCache->hTIFF, nTileID,
191 pabyData,
192 TIFFTileSize(psCache->hTIFF) );
193 }
194 else
195 {
196 nTileID = TIFFComputeStrip( psCache->hTIFF,
197 iTileY * psCache->nBlockYSize,
198 (tsample_t) iSample );
199 RowsInStrip=psCache->nBlockYSize;
200 if ((iTileY+1)*psCache->nBlockYSize>psCache->nYSize)
201 RowsInStrip=psCache->nYSize-iTileY*psCache->nBlockYSize;
202 TIFFWriteEncodedStrip( psCache->hTIFF, nTileID,
203 pabyData,
204 TIFFVStripSize(psCache->hTIFF,RowsInStrip) );
205 }
206 }
207
208 }
209 else
210 {
211 pabyData = TIFFGetOvrBlock( psCache, iTileX, iTileY, 0 );
212
213 if( psCache->bTiled )
214 {
215 nTileID = TIFFComputeTile( psCache->hTIFF,
216 iTileX * psCache->nBlockXSize,
217 iTileY * psCache->nBlockYSize,
218 0, 0 );
219 TIFFWriteEncodedTile( psCache->hTIFF, nTileID,
220 pabyData,
221 TIFFTileSize(psCache->hTIFF) );
222 }
223 else
224 {
225 nTileID = TIFFComputeStrip( psCache->hTIFF,
226 iTileY * psCache->nBlockYSize,
227 0 );
228 RowsInStrip=psCache->nBlockYSize;
229 if ((iTileY+1)*psCache->nBlockYSize>psCache->nYSize)
230 RowsInStrip=psCache->nYSize-iTileY*psCache->nBlockYSize;
231 TIFFWriteEncodedStrip( psCache->hTIFF, nTileID,
232 pabyData,
233 TIFFVStripSize(psCache->hTIFF,RowsInStrip) );
234 }
235 }
236 }
237 /* TODO: add checks on error status return of TIFFWriteEncodedTile and TIFFWriteEncodedStrip */
238
239 /* -------------------------------------------------------------------- */
240 /* Rotate buffers. */
241 /* -------------------------------------------------------------------- */
242 pabyData = psCache->pabyRow1Blocks;
243 psCache->pabyRow1Blocks = psCache->pabyRow2Blocks;
244 psCache->pabyRow2Blocks = pabyData;
245
246 _TIFFmemset( pabyData, 0, psCache->nBytesPerRow );
247
248 psCache->nBlockOffset++;
249
250 /* -------------------------------------------------------------------- */
251 /* Restore access to original directory. */
252 /* -------------------------------------------------------------------- */
253 TIFFFlush( psCache->hTIFF );
254 /* TODO: add checks on error status return of TIFFFlush */
255 TIFFSetSubDirectory( psCache->hTIFF, nBaseDirOffset );
256 /* TODO: add checks on error status return of TIFFSetSubDirectory */
257 }
258
259 /************************************************************************/
260 /* TIFFGetOvrBlock() */
261 /************************************************************************/
262
263 /* TODO: make TIFF_Downsample handle iSample offset, so that we can
264 * do with a single TIFFGetOvrBlock and no longer need TIFFGetOvrBlock_Subsampled */
265 unsigned char *TIFFGetOvrBlock( TIFFOvrCache *psCache, int iTileX, int iTileY,
266 int iSample )
267
268 {
269 int nRowOffset;
270
271 if( iTileY > psCache->nBlockOffset + 1 )
272 TIFFWriteOvrRow( psCache );
273
274 assert( iTileX >= 0 && iTileX < psCache->nBlocksPerRow );
275 assert( iTileY >= 0 && iTileY < psCache->nBlocksPerColumn );
276 assert( iTileY >= psCache->nBlockOffset
277 && iTileY < psCache->nBlockOffset+2 );
278 assert( iSample >= 0 && iSample < psCache->nSamples );
279
280 if (psCache->nPlanarConfig == PLANARCONFIG_SEPARATE)
281 nRowOffset = ((iTileX * psCache->nSamples) + iSample)
282 * psCache->nBytesPerBlock;
283 else
284 nRowOffset = iTileX * psCache->nBytesPerBlock +
285 (psCache->nBitsPerPixel + 7) / 8 * iSample;
286
287 if( iTileY == psCache->nBlockOffset )
288 return psCache->pabyRow1Blocks + nRowOffset;
289 else
290 return psCache->pabyRow2Blocks + nRowOffset;
291 }
292
293 /************************************************************************/
294 /* TIFFGetOvrBlock_Subsampled() */
295 /************************************************************************/
296
297 unsigned char *TIFFGetOvrBlock_Subsampled( TIFFOvrCache *psCache,
298 int iTileX, int iTileY )
299
300 {
301 int nRowOffset;
302
303 if( iTileY > psCache->nBlockOffset + 1 )
304 TIFFWriteOvrRow( psCache );
305
306 assert( iTileX >= 0 && iTileX < psCache->nBlocksPerRow );
307 assert( iTileY >= 0 && iTileY < psCache->nBlocksPerColumn );
308 assert( iTileY >= psCache->nBlockOffset
309 && iTileY < psCache->nBlockOffset+2 );
310 assert( psCache->nPlanarConfig != PLANARCONFIG_SEPARATE );
311
312 nRowOffset = iTileX * psCache->nBytesPerBlock;
313
314 if( iTileY == psCache->nBlockOffset )
315 return psCache->pabyRow1Blocks + nRowOffset;
316 else
317 return psCache->pabyRow2Blocks + nRowOffset;
318 }
319
320 /************************************************************************/
321 /* TIFFDestroyOvrCache() */
322 /************************************************************************/
323
324 void TIFFDestroyOvrCache( TIFFOvrCache * psCache )
325
326 {
327 while( psCache->nBlockOffset < psCache->nBlocksPerColumn )
328 TIFFWriteOvrRow( psCache );
329
330 _TIFFfree( psCache->pabyRow1Blocks );
331 _TIFFfree( psCache->pabyRow2Blocks );
332 _TIFFfree( psCache );
333 }
334 /*
335 * Local Variables:
336 * mode: c
337 * c-basic-offset: 8
338 * fill-column: 78
339 * End:
340 */