]>
git.saurik.com Git - wxWidgets.git/blob - src/tiff/contrib/addtiffo/tif_ovrcache.c
1 /******************************************************************************
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
9 ******************************************************************************
10 * Copyright (c) 2000, Frank Warmerdam
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:
19 * The above copyright notice and this permission notice shall be included
20 * in all copies or substantial portions of the Software.
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 ******************************************************************************
33 #include "tif_ovrcache.h"
36 /************************************************************************/
37 /* TIFFCreateOvrCache() */
39 /* Create an overview cache to hold two rows of blocks from an */
40 /* existing TIFF directory. */
41 /************************************************************************/
43 TIFFOvrCache
*TIFFCreateOvrCache( TIFF
*hTIFF
, toff_t nDirOffset
)
46 TIFFOvrCache
*psCache
;
47 toff_t nBaseDirOffset
;
49 psCache
= (TIFFOvrCache
*) _TIFFmalloc(sizeof(TIFFOvrCache
));
50 psCache
->nDirOffset
= nDirOffset
;
51 psCache
->hTIFF
= hTIFF
;
53 /* -------------------------------------------------------------------- */
54 /* Get definition of this raster from the TIFF file itself. */
55 /* -------------------------------------------------------------------- */
56 nBaseDirOffset
= TIFFCurrentDirOffset( psCache
->hTIFF
);
57 TIFFSetSubDirectory( hTIFF
, nDirOffset
);
59 TIFFGetField( hTIFF
, TIFFTAG_IMAGEWIDTH
, &(psCache
->nXSize
) );
60 TIFFGetField( hTIFF
, TIFFTAG_IMAGELENGTH
, &(psCache
->nYSize
) );
62 TIFFGetField( hTIFF
, TIFFTAG_BITSPERSAMPLE
, &(psCache
->nBitsPerPixel
) );
63 TIFFGetField( hTIFF
, TIFFTAG_SAMPLESPERPIXEL
, &(psCache
->nSamples
) );
64 TIFFGetField( hTIFF
, TIFFTAG_PLANARCONFIG
, &(psCache
->nPlanarConfig
) );
66 if( !TIFFIsTiled( hTIFF
) )
68 TIFFGetField( hTIFF
, TIFFTAG_ROWSPERSTRIP
, &(psCache
->nBlockYSize
) );
69 psCache
->nBlockXSize
= psCache
->nXSize
;
70 psCache
->nBytesPerBlock
= TIFFStripSize(hTIFF
);
71 psCache
->bTiled
= FALSE
;
75 TIFFGetField( hTIFF
, TIFFTAG_TILEWIDTH
, &(psCache
->nBlockXSize
) );
76 TIFFGetField( hTIFF
, TIFFTAG_TILELENGTH
, &(psCache
->nBlockYSize
) );
77 psCache
->nBytesPerBlock
= TIFFTileSize(hTIFF
);
78 psCache
->bTiled
= TRUE
;
81 /* -------------------------------------------------------------------- */
82 /* Compute some values from this. */
83 /* -------------------------------------------------------------------- */
85 psCache
->nBlocksPerRow
= (psCache
->nXSize
+ psCache
->nBlockXSize
- 1)
86 / psCache
->nBlockXSize
;
87 psCache
->nBlocksPerColumn
= (psCache
->nYSize
+ psCache
->nBlockYSize
- 1)
88 / psCache
->nBlockYSize
;
90 if (psCache
->nPlanarConfig
== PLANARCONFIG_SEPARATE
)
91 psCache
->nBytesPerRow
= psCache
->nBytesPerBlock
92 * psCache
->nBlocksPerRow
* psCache
->nSamples
;
94 psCache
->nBytesPerRow
=
95 psCache
->nBytesPerBlock
* psCache
->nBlocksPerRow
;
98 /* -------------------------------------------------------------------- */
99 /* Allocate and initialize the data buffers. */
100 /* -------------------------------------------------------------------- */
102 psCache
->pabyRow1Blocks
=
103 (unsigned char *) _TIFFmalloc(psCache
->nBytesPerRow
);
104 psCache
->pabyRow2Blocks
=
105 (unsigned char *) _TIFFmalloc(psCache
->nBytesPerRow
);
107 if( psCache
->pabyRow1Blocks
== NULL
108 || psCache
->pabyRow2Blocks
== NULL
)
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 */
116 _TIFFmemset( psCache
->pabyRow1Blocks
, 0, psCache
->nBytesPerRow
);
117 _TIFFmemset( psCache
->pabyRow2Blocks
, 0, psCache
->nBytesPerRow
);
119 psCache
->nBlockOffset
= 0;
121 TIFFSetSubDirectory( psCache
->hTIFF
, nBaseDirOffset
);
126 /************************************************************************/
127 /* TIFFWriteOvrRow() */
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 /************************************************************************/
134 static void TIFFWriteOvrRow( TIFFOvrCache
* psCache
)
137 int nRet
, iTileX
, iTileY
= psCache
->nBlockOffset
;
138 unsigned char *pabyData
;
139 toff_t nBaseDirOffset
;
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
) )
149 if( psCache
->nBitsPerPixel
== 16 )
150 TIFFSwabArrayOfShort( (uint16
*) psCache
->pabyRow1Blocks
,
151 (psCache
->nBytesPerBlock
* psCache
->nSamples
) / 2 );
153 else if( psCache
->nBitsPerPixel
== 32 )
154 TIFFSwabArrayOfLong( (uint32
*) psCache
->pabyRow1Blocks
,
155 (psCache
->nBytesPerBlock
* psCache
->nSamples
) / 4 );
157 else if( psCache
->nBitsPerPixel
== 64 )
158 TIFFSwabArrayOfDouble( (double *) psCache
->pabyRow1Blocks
,
159 (psCache
->nBytesPerBlock
* psCache
->nSamples
) / 8 );
162 /* -------------------------------------------------------------------- */
163 /* Record original directory position, so we can restore it at */
165 /* -------------------------------------------------------------------- */
166 nBaseDirOffset
= TIFFCurrentDirOffset( psCache
->hTIFF
);
167 nRet
= TIFFSetSubDirectory( psCache
->hTIFF
, psCache
->nDirOffset
);
170 /* -------------------------------------------------------------------- */
171 /* Write blocks to TIFF file. */
172 /* -------------------------------------------------------------------- */
173 for( iTileX
= 0; iTileX
< psCache
->nBlocksPerRow
; iTileX
++ )
177 if (psCache
->nPlanarConfig
== PLANARCONFIG_SEPARATE
)
181 for( iSample
= 0; iSample
< psCache
->nSamples
; iSample
++ )
183 pabyData
= TIFFGetOvrBlock( psCache
, iTileX
, iTileY
, iSample
);
185 if( psCache
->bTiled
)
187 nTileID
= TIFFComputeTile( psCache
->hTIFF
,
188 iTileX
* psCache
->nBlockXSize
,
189 iTileY
* psCache
->nBlockYSize
,
190 0, (tsample_t
) iSample
);
191 TIFFWriteEncodedTile( psCache
->hTIFF
, nTileID
,
193 TIFFTileSize(psCache
->hTIFF
) );
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
,
205 TIFFVStripSize(psCache
->hTIFF
,RowsInStrip
) );
212 pabyData
= TIFFGetOvrBlock( psCache
, iTileX
, iTileY
, 0 );
214 if( psCache
->bTiled
)
216 nTileID
= TIFFComputeTile( psCache
->hTIFF
,
217 iTileX
* psCache
->nBlockXSize
,
218 iTileY
* psCache
->nBlockYSize
,
220 TIFFWriteEncodedTile( psCache
->hTIFF
, nTileID
,
222 TIFFTileSize(psCache
->hTIFF
) );
226 nTileID
= TIFFComputeStrip( psCache
->hTIFF
,
227 iTileY
* psCache
->nBlockYSize
,
229 RowsInStrip
=psCache
->nBlockYSize
;
230 if ((iTileY
+1)*psCache
->nBlockYSize
>psCache
->nYSize
)
231 RowsInStrip
=psCache
->nYSize
-iTileY
*psCache
->nBlockYSize
;
232 TIFFWriteEncodedStrip( psCache
->hTIFF
, nTileID
,
234 TIFFVStripSize(psCache
->hTIFF
,RowsInStrip
) );
238 /* TODO: add checks on error status return of TIFFWriteEncodedTile and TIFFWriteEncodedStrip */
240 /* -------------------------------------------------------------------- */
241 /* Rotate buffers. */
242 /* -------------------------------------------------------------------- */
243 pabyData
= psCache
->pabyRow1Blocks
;
244 psCache
->pabyRow1Blocks
= psCache
->pabyRow2Blocks
;
245 psCache
->pabyRow2Blocks
= pabyData
;
247 _TIFFmemset( pabyData
, 0, psCache
->nBytesPerRow
);
249 psCache
->nBlockOffset
++;
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 */
260 /************************************************************************/
261 /* TIFFGetOvrBlock() */
262 /************************************************************************/
264 /* TODO: make TIFF_Downsample handle iSample offset, so that we can
265 * do with a single TIFFGetOvrBlock and no longer need TIFFGetOvrBlock_Subsampled */
266 unsigned char *TIFFGetOvrBlock( TIFFOvrCache
*psCache
, int iTileX
, int iTileY
,
272 if( iTileY
> psCache
->nBlockOffset
+ 1 )
273 TIFFWriteOvrRow( psCache
);
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
);
281 if (psCache
->nPlanarConfig
== PLANARCONFIG_SEPARATE
)
282 nRowOffset
= ((iTileX
* psCache
->nSamples
) + iSample
)
283 * psCache
->nBytesPerBlock
;
285 nRowOffset
= iTileX
* psCache
->nBytesPerBlock
+
286 (psCache
->nBitsPerPixel
+ 7) / 8 * iSample
;
288 if( iTileY
== psCache
->nBlockOffset
)
289 return psCache
->pabyRow1Blocks
+ nRowOffset
;
291 return psCache
->pabyRow2Blocks
+ nRowOffset
;
294 /************************************************************************/
295 /* TIFFGetOvrBlock_Subsampled() */
296 /************************************************************************/
298 unsigned char *TIFFGetOvrBlock_Subsampled( TIFFOvrCache
*psCache
,
299 int iTileX
, int iTileY
)
304 if( iTileY
> psCache
->nBlockOffset
+ 1 )
305 TIFFWriteOvrRow( psCache
);
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
);
313 nRowOffset
= iTileX
* psCache
->nBytesPerBlock
;
315 if( iTileY
== psCache
->nBlockOffset
)
316 return psCache
->pabyRow1Blocks
+ nRowOffset
;
318 return psCache
->pabyRow2Blocks
+ nRowOffset
;
321 /************************************************************************/
322 /* TIFFDestroyOvrCache() */
323 /************************************************************************/
325 void TIFFDestroyOvrCache( TIFFOvrCache
* psCache
)
328 while( psCache
->nBlockOffset
< psCache
->nBlocksPerColumn
)
329 TIFFWriteOvrRow( psCache
);
331 _TIFFfree( psCache
->pabyRow1Blocks
);
332 _TIFFfree( psCache
->pabyRow2Blocks
);
333 _TIFFfree( psCache
);