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