]> git.saurik.com Git - wxWidgets.git/blob - src/tiff/tif_write.c
key handling
[wxWidgets.git] / src / tiff / tif_write.c
1 /* $Header$ */
2
3 /*
4 * Copyright (c) 1988-1997 Sam Leffler
5 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
6 *
7 * Permission to use, copy, modify, distribute, and sell this software and
8 * its documentation for any purpose is hereby granted without fee, provided
9 * that (i) the above copyright notices and this permission notice appear in
10 * all copies of the software and related documentation, and (ii) the names of
11 * Sam Leffler and Silicon Graphics may not be used in any advertising or
12 * publicity relating to the software without the specific, prior written
13 * permission of Sam Leffler and Silicon Graphics.
14 *
15 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
17 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
18 *
19 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
20 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
21 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
22 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
23 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
24 * OF THIS SOFTWARE.
25 */
26
27 /*
28 * TIFF Library.
29 *
30 * Scanline-oriented Write Support
31 */
32 #include "tiffiop.h"
33 #include <assert.h>
34 #include <stdio.h>
35
36 #define STRIPINCR 20 /* expansion factor on strip array */
37
38 #define WRITECHECKSTRIPS(tif, module) \
39 (((tif)->tif_flags&TIFF_BEENWRITING) || TIFFWriteCheck((tif),0,module))
40 #define WRITECHECKTILES(tif, module) \
41 (((tif)->tif_flags&TIFF_BEENWRITING) || TIFFWriteCheck((tif),1,module))
42 #define BUFFERCHECK(tif) \
43 (((tif)->tif_flags & TIFF_BUFFERSETUP) || \
44 TIFFWriteBufferSetup((tif), NULL, (tsize_t) -1))
45
46 static int TIFFWriteCheck(TIFF*, int, const char*);
47 static int TIFFGrowStrips(TIFF*, int, const char*);
48 static int TIFFAppendToStrip(TIFF*, tstrip_t, tidata_t, tsize_t);
49 static int TIFFSetupStrips(TIFF*);
50
51 int
52 TIFFWriteScanline(TIFF* tif, tdata_t buf, uint32 row, tsample_t sample)
53 {
54 static const char module[] = "TIFFWriteScanline";
55 register TIFFDirectory *td;
56 int status, imagegrew = 0;
57 tstrip_t strip;
58
59 if (!WRITECHECKSTRIPS(tif, module))
60 return (-1);
61 /*
62 * Handle delayed allocation of data buffer. This
63 * permits it to be sized more intelligently (using
64 * directory information).
65 */
66 if (!BUFFERCHECK(tif))
67 return (-1);
68 td = &tif->tif_dir;
69 /*
70 * Extend image length if needed
71 * (but only for PlanarConfig=1).
72 */
73 if (row >= td->td_imagelength) { /* extend image */
74 if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
75 TIFFError(tif->tif_name,
76 "Can not change \"ImageLength\" when using separate planes");
77 return (-1);
78 }
79 td->td_imagelength = row+1;
80 imagegrew = 1;
81 }
82 /*
83 * Calculate strip and check for crossings.
84 */
85 if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
86 if (sample >= td->td_samplesperpixel) {
87 TIFFError(tif->tif_name,
88 "%d: Sample out of range, max %d",
89 sample, td->td_samplesperpixel);
90 return (-1);
91 }
92 strip = sample*td->td_stripsperimage + row/td->td_rowsperstrip;
93 } else
94 strip = row / td->td_rowsperstrip;
95 if (strip != tif->tif_curstrip) {
96 /*
97 * Changing strips -- flush any data present.
98 */
99 if (!TIFFFlushData(tif))
100 return (-1);
101 tif->tif_curstrip = strip;
102 /*
103 * Watch out for a growing image. The value of
104 * strips/image will initially be 1 (since it
105 * can't be deduced until the imagelength is known).
106 */
107 if (strip >= td->td_stripsperimage && imagegrew)
108 td->td_stripsperimage =
109 TIFFhowmany(td->td_imagelength,td->td_rowsperstrip);
110 tif->tif_row =
111 (strip % td->td_stripsperimage) * td->td_rowsperstrip;
112 if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
113 if (!(*tif->tif_setupencode)(tif))
114 return (-1);
115 tif->tif_flags |= TIFF_CODERSETUP;
116 }
117 if (!(*tif->tif_preencode)(tif, sample))
118 return (-1);
119 tif->tif_flags |= TIFF_POSTENCODE;
120 }
121 /*
122 * Check strip array to make sure there's space.
123 * We don't support dynamically growing files that
124 * have data organized in separate bitplanes because
125 * it's too painful. In that case we require that
126 * the imagelength be set properly before the first
127 * write (so that the strips array will be fully
128 * allocated above).
129 */
130 if (strip >= td->td_nstrips && !TIFFGrowStrips(tif, 1, module))
131 return (-1);
132 /*
133 * Ensure the write is either sequential or at the
134 * beginning of a strip (or that we can randomly
135 * access the data -- i.e. no encoding).
136 */
137 if (row != tif->tif_row) {
138 if (row < tif->tif_row) {
139 /*
140 * Moving backwards within the same strip:
141 * backup to the start and then decode
142 * forward (below).
143 */
144 tif->tif_row = (strip % td->td_stripsperimage) *
145 td->td_rowsperstrip;
146 tif->tif_rawcp = tif->tif_rawdata;
147 }
148 /*
149 * Seek forward to the desired row.
150 */
151 if (!(*tif->tif_seek)(tif, row - tif->tif_row))
152 return (-1);
153 tif->tif_row = row;
154 }
155 status = (*tif->tif_encoderow)(tif, (tidata_t) buf,
156 tif->tif_scanlinesize, sample);
157 tif->tif_row++;
158 return (status);
159 }
160
161 /*
162 * Encode the supplied data and write it to the
163 * specified strip. There must be space for the
164 * data; we don't check if strips overlap!
165 *
166 * NB: Image length must be setup before writing.
167 */
168 tsize_t
169 TIFFWriteEncodedStrip(TIFF* tif, tstrip_t strip, tdata_t data, tsize_t cc)
170 {
171 static const char module[] = "TIFFWriteEncodedStrip";
172 TIFFDirectory *td = &tif->tif_dir;
173 tsample_t sample;
174
175 if (!WRITECHECKSTRIPS(tif, module))
176 return ((tsize_t) -1);
177 /*
178 * Check strip array to make sure there's space.
179 * We don't support dynamically growing files that
180 * have data organized in separate bitplanes because
181 * it's too painful. In that case we require that
182 * the imagelength be set properly before the first
183 * write (so that the strips array will be fully
184 * allocated above).
185 */
186 if (strip >= td->td_nstrips) {
187 if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
188 TIFFError(tif->tif_name,
189 "Can not grow image by strips when using separate planes");
190 return ((tsize_t) -1);
191 }
192 if (!TIFFGrowStrips(tif, 1, module))
193 return ((tsize_t) -1);
194 td->td_stripsperimage =
195 TIFFhowmany(td->td_imagelength, td->td_rowsperstrip);
196 }
197 /*
198 * Handle delayed allocation of data buffer. This
199 * permits it to be sized according to the directory
200 * info.
201 */
202 if (!BUFFERCHECK(tif))
203 return ((tsize_t) -1);
204 tif->tif_curstrip = strip;
205 tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
206 if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
207 if (!(*tif->tif_setupencode)(tif))
208 return ((tsize_t) -1);
209 tif->tif_flags |= TIFF_CODERSETUP;
210 }
211 tif->tif_flags &= ~TIFF_POSTENCODE;
212 sample = (tsample_t)(strip / td->td_stripsperimage);
213 if (!(*tif->tif_preencode)(tif, sample))
214 return ((tsize_t) -1);
215 if (!(*tif->tif_encodestrip)(tif, (tidata_t) data, cc, sample))
216 return ((tsize_t) 0);
217 if (!(*tif->tif_postencode)(tif))
218 return ((tsize_t) -1);
219 if (!isFillOrder(tif, td->td_fillorder) &&
220 (tif->tif_flags & TIFF_NOBITREV) == 0)
221 TIFFReverseBits(tif->tif_rawdata, tif->tif_rawcc);
222 if (tif->tif_rawcc > 0 &&
223 !TIFFAppendToStrip(tif, strip, tif->tif_rawdata, tif->tif_rawcc))
224 return ((tsize_t) -1);
225 tif->tif_rawcc = 0;
226 tif->tif_rawcp = tif->tif_rawdata;
227 return (cc);
228 }
229
230 /*
231 * Write the supplied data to the specified strip.
232 * There must be space for the data; we don't check
233 * if strips overlap!
234 *
235 * NB: Image length must be setup before writing.
236 */
237 tsize_t
238 TIFFWriteRawStrip(TIFF* tif, tstrip_t strip, tdata_t data, tsize_t cc)
239 {
240 static const char module[] = "TIFFWriteRawStrip";
241 TIFFDirectory *td = &tif->tif_dir;
242
243 if (!WRITECHECKSTRIPS(tif, module))
244 return ((tsize_t) -1);
245 /*
246 * Check strip array to make sure there's space.
247 * We don't support dynamically growing files that
248 * have data organized in separate bitplanes because
249 * it's too painful. In that case we require that
250 * the imagelength be set properly before the first
251 * write (so that the strips array will be fully
252 * allocated above).
253 */
254 if (strip >= td->td_nstrips) {
255 if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
256 TIFFError(tif->tif_name,
257 "Can not grow image by strips when using separate planes");
258 return ((tsize_t) -1);
259 }
260 /*
261 * Watch out for a growing image. The value of
262 * strips/image will initially be 1 (since it
263 * can't be deduced until the imagelength is known).
264 */
265 if (strip >= td->td_stripsperimage)
266 td->td_stripsperimage =
267 TIFFhowmany(td->td_imagelength,td->td_rowsperstrip);
268 if (!TIFFGrowStrips(tif, 1, module))
269 return ((tsize_t) -1);
270 }
271 tif->tif_curstrip = strip;
272 tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
273 return (TIFFAppendToStrip(tif, strip, (tidata_t) data, cc) ?
274 cc : (tsize_t) -1);
275 }
276
277 /*
278 * Write and compress a tile of data. The
279 * tile is selected by the (x,y,z,s) coordinates.
280 */
281 tsize_t
282 TIFFWriteTile(TIFF* tif,
283 tdata_t buf, uint32 x, uint32 y, uint32 z, tsample_t s)
284 {
285 if (!TIFFCheckTile(tif, x, y, z, s))
286 return (-1);
287 /*
288 * NB: A tile size of -1 is used instead of tif_tilesize knowing
289 * that TIFFWriteEncodedTile will clamp this to the tile size.
290 * This is done because the tile size may not be defined until
291 * after the output buffer is setup in TIFFWriteBufferSetup.
292 */
293 return (TIFFWriteEncodedTile(tif,
294 TIFFComputeTile(tif, x, y, z, s), buf, (tsize_t) -1));
295 }
296
297 /*
298 * Encode the supplied data and write it to the
299 * specified tile. There must be space for the
300 * data. The function clamps individual writes
301 * to a tile to the tile size, but does not (and
302 * can not) check that multiple writes to the same
303 * tile do not write more than tile size data.
304 *
305 * NB: Image length must be setup before writing; this
306 * interface does not support automatically growing
307 * the image on each write (as TIFFWriteScanline does).
308 */
309 tsize_t
310 TIFFWriteEncodedTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc)
311 {
312 static const char module[] = "TIFFWriteEncodedTile";
313 TIFFDirectory *td;
314 tsample_t sample;
315
316 if (!WRITECHECKTILES(tif, module))
317 return ((tsize_t) -1);
318 td = &tif->tif_dir;
319 if (tile >= td->td_nstrips) {
320 TIFFError(module, "%s: Tile %lu out of range, max %lu",
321 tif->tif_name, (u_long) tile, (u_long) td->td_nstrips);
322 return ((tsize_t) -1);
323 }
324 /*
325 * Handle delayed allocation of data buffer. This
326 * permits it to be sized more intelligently (using
327 * directory information).
328 */
329 if (!BUFFERCHECK(tif))
330 return ((tsize_t) -1);
331 tif->tif_curtile = tile;
332 /*
333 * Compute tiles per row & per column to compute
334 * current row and column
335 */
336 tif->tif_row = (tile % TIFFhowmany(td->td_imagelength, td->td_tilelength))
337 * td->td_tilelength;
338 tif->tif_col = (tile % TIFFhowmany(td->td_imagewidth, td->td_tilewidth))
339 * td->td_tilewidth;
340
341 if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
342 if (!(*tif->tif_setupencode)(tif))
343 return ((tsize_t) -1);
344 tif->tif_flags |= TIFF_CODERSETUP;
345 }
346 tif->tif_flags &= ~TIFF_POSTENCODE;
347 sample = (tsample_t)(tile/td->td_stripsperimage);
348 if (!(*tif->tif_preencode)(tif, sample))
349 return ((tsize_t) -1);
350 /*
351 * Clamp write amount to the tile size. This is mostly
352 * done so that callers can pass in some large number
353 * (e.g. -1) and have the tile size used instead.
354 */
355 if ((uint32) cc > tif->tif_tilesize)
356 cc = tif->tif_tilesize;
357 if (!(*tif->tif_encodetile)(tif, (tidata_t) data, cc, sample))
358 return ((tsize_t) 0);
359 if (!(*tif->tif_postencode)(tif))
360 return ((tsize_t) -1);
361 if (!isFillOrder(tif, td->td_fillorder) &&
362 (tif->tif_flags & TIFF_NOBITREV) == 0)
363 TIFFReverseBits((u_char *)tif->tif_rawdata, tif->tif_rawcc);
364 if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile,
365 tif->tif_rawdata, tif->tif_rawcc))
366 return ((tsize_t) -1);
367 tif->tif_rawcc = 0;
368 tif->tif_rawcp = tif->tif_rawdata;
369 return (cc);
370 }
371
372 /*
373 * Write the supplied data to the specified strip.
374 * There must be space for the data; we don't check
375 * if strips overlap!
376 *
377 * NB: Image length must be setup before writing; this
378 * interface does not support automatically growing
379 * the image on each write (as TIFFWriteScanline does).
380 */
381 tsize_t
382 TIFFWriteRawTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc)
383 {
384 static const char module[] = "TIFFWriteRawTile";
385
386 if (!WRITECHECKTILES(tif, module))
387 return ((tsize_t) -1);
388 if (tile >= tif->tif_dir.td_nstrips) {
389 TIFFError(module, "%s: Tile %lu out of range, max %lu",
390 tif->tif_name, (u_long) tile,
391 (u_long) tif->tif_dir.td_nstrips);
392 return ((tsize_t) -1);
393 }
394 return (TIFFAppendToStrip(tif, tile, (tidata_t) data, cc) ?
395 cc : (tsize_t) -1);
396 }
397
398 #define isUnspecified(tif, f) \
399 (TIFFFieldSet(tif,f) && (tif)->tif_dir.td_imagelength == 0)
400
401 static int
402 TIFFSetupStrips(TIFF* tif)
403 {
404 TIFFDirectory* td = &tif->tif_dir;
405
406 if (isTiled(tif))
407 td->td_stripsperimage =
408 isUnspecified(tif, FIELD_TILEDIMENSIONS) ?
409 td->td_samplesperpixel : TIFFNumberOfTiles(tif);
410 else
411 td->td_stripsperimage =
412 isUnspecified(tif, FIELD_ROWSPERSTRIP) ?
413 td->td_samplesperpixel : TIFFNumberOfStrips(tif);
414 td->td_nstrips = td->td_stripsperimage;
415 if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
416 td->td_stripsperimage /= td->td_samplesperpixel;
417 td->td_stripoffset = (uint32 *)
418 _TIFFmalloc(td->td_nstrips * sizeof (uint32));
419 td->td_stripbytecount = (uint32 *)
420 _TIFFmalloc(td->td_nstrips * sizeof (uint32));
421 if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL)
422 return (0);
423 /*
424 * Place data at the end-of-file
425 * (by setting offsets to zero).
426 */
427 _TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint32));
428 _TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint32));
429 TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
430 TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
431 return (1);
432 }
433 #undef isUnspecified
434
435 /*
436 * Verify file is writable and that the directory
437 * information is setup properly. In doing the latter
438 * we also "freeze" the state of the directory so
439 * that important information is not changed.
440 */
441 static int
442 TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
443 {
444 if (tif->tif_mode == O_RDONLY) {
445 TIFFError(module, "%s: File not open for writing",
446 tif->tif_name);
447 return (0);
448 }
449 if (tiles ^ isTiled(tif)) {
450 TIFFError(tif->tif_name, tiles ?
451 "Can not write tiles to a stripped image" :
452 "Can not write scanlines to a tiled image");
453 return (0);
454 }
455 /*
456 * On the first write verify all the required information
457 * has been setup and initialize any data structures that
458 * had to wait until directory information was set.
459 * Note that a lot of our work is assumed to remain valid
460 * because we disallow any of the important parameters
461 * from changing after we start writing (i.e. once
462 * TIFF_BEENWRITING is set, TIFFSetField will only allow
463 * the image's length to be changed).
464 */
465 if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) {
466 TIFFError(module,
467 "%s: Must set \"ImageWidth\" before writing data",
468 tif->tif_name);
469 return (0);
470 }
471 if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) {
472 TIFFError(module,
473 "%s: Must set \"PlanarConfiguration\" before writing data",
474 tif->tif_name);
475 return (0);
476 }
477 if (tif->tif_dir.td_stripoffset == NULL && !TIFFSetupStrips(tif)) {
478 tif->tif_dir.td_nstrips = 0;
479 TIFFError(module, "%s: No space for %s arrays",
480 tif->tif_name, isTiled(tif) ? "tile" : "strip");
481 return (0);
482 }
483 tif->tif_tilesize = TIFFTileSize(tif);
484 tif->tif_scanlinesize = TIFFScanlineSize(tif);
485 tif->tif_flags |= TIFF_BEENWRITING;
486 return (1);
487 }
488
489 /*
490 * Setup the raw data buffer used for encoding.
491 */
492 int
493 TIFFWriteBufferSetup(TIFF* tif, tdata_t bp, tsize_t size)
494 {
495 static const char module[] = "TIFFWriteBufferSetup";
496
497 if (tif->tif_rawdata) {
498 if (tif->tif_flags & TIFF_MYBUFFER) {
499 _TIFFfree(tif->tif_rawdata);
500 tif->tif_flags &= ~TIFF_MYBUFFER;
501 }
502 tif->tif_rawdata = NULL;
503 }
504 if (size == (tsize_t) -1) {
505 size = (isTiled(tif) ?
506 tif->tif_tilesize : tif->tif_scanlinesize);
507 /*
508 * Make raw data buffer at least 8K
509 */
510 if (size < 8*1024)
511 size = 8*1024;
512 bp = NULL; /* NB: force malloc */
513 }
514 if (bp == NULL) {
515 bp = _TIFFmalloc(size);
516 if (bp == NULL) {
517 TIFFError(module, "%s: No space for output buffer",
518 tif->tif_name);
519 return (0);
520 }
521 tif->tif_flags |= TIFF_MYBUFFER;
522 } else
523 tif->tif_flags &= ~TIFF_MYBUFFER;
524 tif->tif_rawdata = (tidata_t) bp;
525 tif->tif_rawdatasize = size;
526 tif->tif_rawcc = 0;
527 tif->tif_rawcp = tif->tif_rawdata;
528 tif->tif_flags |= TIFF_BUFFERSETUP;
529 return (1);
530 }
531
532 /*
533 * Grow the strip data structures by delta strips.
534 */
535 static int
536 TIFFGrowStrips(TIFF* tif, int delta, const char* module)
537 {
538 TIFFDirectory *td = &tif->tif_dir;
539
540 assert(td->td_planarconfig == PLANARCONFIG_CONTIG);
541 td->td_stripoffset = (uint32*)_TIFFrealloc(td->td_stripoffset,
542 (td->td_nstrips + delta) * sizeof (uint32));
543 td->td_stripbytecount = (uint32*)_TIFFrealloc(td->td_stripbytecount,
544 (td->td_nstrips + delta) * sizeof (uint32));
545 if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL) {
546 td->td_nstrips = 0;
547 TIFFError(module, "%s: No space to expand strip arrays",
548 tif->tif_name);
549 return (0);
550 }
551 _TIFFmemset(td->td_stripoffset+td->td_nstrips, 0, delta*sizeof (uint32));
552 _TIFFmemset(td->td_stripbytecount+td->td_nstrips, 0, delta*sizeof (uint32));
553 td->td_nstrips += delta;
554 return (1);
555 }
556
557 /*
558 * Append the data to the specified strip.
559 *
560 * NB: We don't check that there's space in the
561 * file (i.e. that strips do not overlap).
562 */
563 static int
564 TIFFAppendToStrip(TIFF* tif, tstrip_t strip, tidata_t data, tsize_t cc)
565 {
566 TIFFDirectory *td = &tif->tif_dir;
567 static const char module[] = "TIFFAppendToStrip";
568
569 if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) {
570 /*
571 * No current offset, set the current strip.
572 */
573 if (td->td_stripoffset[strip] != 0) {
574 if (!SeekOK(tif, td->td_stripoffset[strip])) {
575 TIFFError(module,
576 "%s: Seek error at scanline %lu",
577 tif->tif_name, (u_long) tif->tif_row);
578 return (0);
579 }
580 } else
581 td->td_stripoffset[strip] =
582 TIFFSeekFile(tif, (toff_t) 0, SEEK_END);
583 tif->tif_curoff = td->td_stripoffset[strip];
584 }
585 if (!WriteOK(tif, data, cc)) {
586 TIFFError(module, "%s: Write error at scanline %lu",
587 tif->tif_name, (u_long) tif->tif_row);
588 return (0);
589 }
590 tif->tif_curoff += cc;
591 td->td_stripbytecount[strip] += cc;
592 return (1);
593 }
594
595 /*
596 * Internal version of TIFFFlushData that can be
597 * called by ``encodestrip routines'' w/o concern
598 * for infinite recursion.
599 */
600 int
601 TIFFFlushData1(TIFF* tif)
602 {
603 if (tif->tif_rawcc > 0) {
604 if (!isFillOrder(tif, tif->tif_dir.td_fillorder) &&
605 (tif->tif_flags & TIFF_NOBITREV) == 0)
606 TIFFReverseBits((u_char *)tif->tif_rawdata,
607 tif->tif_rawcc);
608 if (!TIFFAppendToStrip(tif,
609 isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip,
610 tif->tif_rawdata, tif->tif_rawcc))
611 return (0);
612 tif->tif_rawcc = 0;
613 tif->tif_rawcp = tif->tif_rawdata;
614 }
615 return (1);
616 }
617
618 /*
619 * Set the current write offset. This should only be
620 * used to set the offset to a known previous location
621 * (very carefully), or to 0 so that the next write gets
622 * appended to the end of the file.
623 */
624 void
625 TIFFSetWriteOffset(TIFF* tif, toff_t off)
626 {
627 tif->tif_curoff = off;
628 }