Example #1
0
/*
 * Encode a chunk of pixels.
 *
 * Uses an open addressing double hashing (no chaining) on the 
 * prefix code/next character combination.  We do a variant of
 * Knuth's algorithm D (vol. 3, sec. 6.4) along with G. Knott's
 * relatively-prime secondary probe.  Here, the modular division
 * first probe is gives way to a faster exclusive-or manipulation. 
 * Also do block compression with an adaptive reset, whereby the
 * code table is cleared when the compression ratio decreases,
 * but after the table fills.  The variable-length output codes
 * are re-sized at this point, and a CODE_CLEAR is generated
 * for the decoder. 
 */
static int
LZWEncode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
{
        register LZWCodecState *sp = EncoderState(tif);
        register long fcode;
        register hash_t *hp;
        register int h, c;
        hcode_t ent;
        long disp;
        long incount, outcount, checkpoint;
        long nextdata, nextbits;
        int free_ent, maxcode, nbits;
        tidata_t op, limit;

        (void) s;
        if (sp == NULL)
                return (0);
        /*
         * Load local state.
         */
        incount = sp->enc_incount;
        outcount = sp->enc_outcount;
        checkpoint = sp->enc_checkpoint;
        nextdata = sp->lzw_nextdata;
        nextbits = sp->lzw_nextbits;
        free_ent = sp->lzw_free_ent;
        maxcode = sp->lzw_maxcode;
        nbits = sp->lzw_nbits;
        op = tif->tif_rawcp;
        limit = sp->enc_rawlimit;
        ent = sp->enc_oldcode;

        if (ent == (hcode_t) -1 && cc > 0) {
                /*
                 * NB: This is safe because it can only happen
                 *     at the start of a strip where we know there
                 *     is space in the data buffer.
                 */
                PutNextCode(op, CODE_CLEAR);
                ent = *bp++; cc--; incount++;
        }
        while (cc > 0) {
                c = *bp++; cc--; incount++;
                fcode = ((long)c << BITS_MAX) + ent;
                h = (c << HSHIFT) ^ ent;        /* xor hashing */
#ifdef _WINDOWS
                /*
                 * Check hash index for an overflow.
                 */
                if (h >= HSIZE)
                        h -= HSIZE;
#endif
                hp = &sp->enc_hashtab[h];
                if (hp->hash == fcode) {
                        ent = hp->code;
                        continue;
                }
                if (hp->hash >= 0) {
                        /*
                         * Primary hash failed, check secondary hash.
                         */
                        disp = HSIZE - h;
                        if (h == 0)
                                disp = 1;
                        do {
                                /*
                                 * Avoid pointer arithmetic 'cuz of
                                 * wraparound problems with segments.
                                 */
                                if ((h -= disp) < 0)
                                        h += HSIZE;
                                hp = &sp->enc_hashtab[h];
                                if (hp->hash == fcode) {
                                        ent = hp->code;
                                        goto hit;
                                }
                        } while (hp->hash >= 0);
                }
                /*
                 * New entry, emit code and add to table.
                 */
                /*
                 * Verify there is space in the buffer for the code
                 * and any potential Clear code that might be emitted
                 * below.  The value of limit is setup so that there
                 * are at least 4 bytes free--room for 2 codes.
                 */
                if (op > limit) {
                        tif->tif_rawcc = (tsize_t)(op - tif->tif_rawdata);
                        TIFFFlushData1(tif);
                        op = tif->tif_rawdata;
                }
                PutNextCode(op, ent);
                ent = c;
                hp->code = free_ent++;
                hp->hash = fcode;
                if (free_ent == CODE_MAX-1) {
                        /* table is full, emit clear code and reset */
                        cl_hash(sp);
                        sp->enc_ratio = 0;
                        incount = 0;
                        outcount = 0;
                        free_ent = CODE_FIRST;
                        PutNextCode(op, CODE_CLEAR);
                        nbits = BITS_MIN;
                        maxcode = MAXCODE(BITS_MIN);
                } else {
                        /*
                         * If the next entry is going to be too big for
                         * the code size, then increase it, if possible.
                         */
                        if (free_ent > maxcode) {
                                nbits++;
                                assert(nbits <= BITS_MAX);
                                maxcode = (int) MAXCODE(nbits);
                        } else if (incount >= checkpoint) {
                                long rat;
                                /*
                                 * Check compression ratio and, if things seem
                                 * to be slipping, clear the hash table and
                                 * reset state.  The compression ratio is a
                                 * 24+8-bit fractional number.
                                 */
                                checkpoint = incount+CHECK_GAP;
                                CALCRATIO(sp, rat);
                                if (rat <= sp->enc_ratio) {
                                        cl_hash(sp);
                                        sp->enc_ratio = 0;
                                        incount = 0;
                                        outcount = 0;
                                        free_ent = CODE_FIRST;
                                        PutNextCode(op, CODE_CLEAR);
                                        nbits = BITS_MIN;
                                        maxcode = MAXCODE(BITS_MIN);
                                } else
                                        sp->enc_ratio = rat;
                        }
                }
        hit:
                ;
        }

        /*
         * Restore global state.
         */
        sp->enc_incount = incount;
        sp->enc_outcount = outcount;
        sp->enc_checkpoint = checkpoint;
        sp->enc_oldcode = ent;
        sp->lzw_nextdata = nextdata;
        sp->lzw_nextbits = nextbits;
        sp->lzw_free_ent = free_ent;
        sp->lzw_maxcode = maxcode;
        sp->lzw_nbits = nbits;
        tif->tif_rawcp = op;
        return (1);
}
Example #2
0
/*
 * Encode a run of pixels.
 */
static int
PackBitsEncode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s)
{
	unsigned char* bp = (unsigned char*) buf;
	tidata_t op, ep, lastliteral;
	long n, slop;
	int b;
	enum { BASE, LITERAL, RUN, LITERAL_RUN } state;

	(void) s;
	op = tif->tif_rawcp;
	ep = tif->tif_rawdata + tif->tif_rawdatasize;
	state = BASE;
	lastliteral = 0;
	while (cc > 0) {
		/*
		 * Find the longest string of identical bytes.
		 */
		b = *bp++, cc--, n = 1;
		for (; cc > 0 && b == *bp; cc--, bp++)
			n++;
	again:
		if (op + 2 >= ep) {		/* insure space for new data */
			/*
			 * Be careful about writing the last
			 * literal.  Must write up to that point
			 * and then copy the remainder to the
			 * front of the buffer.
			 */
			if (state == LITERAL || state == LITERAL_RUN) {
				slop = op - lastliteral;
				tif->tif_rawcc += lastliteral - tif->tif_rawcp;
				if (!TIFFFlushData1(tif))
					return (-1);
				op = tif->tif_rawcp;
				while (slop-- > 0)
					*op++ = *lastliteral++;
				lastliteral = tif->tif_rawcp;
			} else {
				tif->tif_rawcc += op - tif->tif_rawcp;
				if (!TIFFFlushData1(tif))
					return (-1);
				op = tif->tif_rawcp;
			}
		}
		switch (state) {
		case BASE:		/* initial state, set run/literal */
			if (n > 1) {
				state = RUN;
				if (n > 128) {
					*op++ = (tidata) -127;
					*op++ = (tidataval_t) b;
					n -= 128;
					goto again;
				}
				*op++ = (tidataval_t)(-(n-1));
				*op++ = (tidataval_t) b;
			} else {
				lastliteral = op;
				*op++ = 0;
				*op++ = (tidataval_t) b;
				state = LITERAL;
			}
			break;
		case LITERAL:		/* last object was literal string */
			if (n > 1) {
				state = LITERAL_RUN;
				if (n > 128) {
					*op++ = (tidata) -127;
					*op++ = (tidataval_t) b;
					n -= 128;
					goto again;
				}
				*op++ = (tidataval_t)(-(n-1));	/* encode run */
				*op++ = (tidataval_t) b;
			} else {			/* extend literal */
				if (++(*lastliteral) == 127)
					state = BASE;
				*op++ = (tidataval_t) b;
			}
			break;
		case RUN:		/* last object was run */
			if (n > 1) {
				if (n > 128) {
					*op++ = (tidata) -127;
					*op++ = (tidataval_t) b;
					n -= 128;
					goto again;
				}
				*op++ = (tidataval_t)(-(n-1));
				*op++ = (tidataval_t) b;
			} else {
				lastliteral = op;
				*op++ = 0;
				*op++ = (tidataval_t) b;
				state = LITERAL;
			}
			break;
		case LITERAL_RUN:	/* literal followed by a run */
			/*
			 * Check to see if previous run should
			 * be converted to a literal, in which
			 * case we convert literal-run-literal
			 * to a single literal.
			 */
			if (n == 1 && op[-2] == (tidata) -1 &&
			    *lastliteral < 126) {
				state = (((*lastliteral) += 2) == 127 ?
				    BASE : LITERAL);
				op[-2] = op[-1];	/* replicate */
			} else
				state = RUN;
			goto again;
		}
	}
	tif->tif_rawcc += op - tif->tif_rawcp;
	tif->tif_rawcp = op;
	return (1);
}
Example #3
0
/*
 * Encode a row of 16-bit pixels.
 */
static int
LogL16Encode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
{
	LogLuvState* sp = EncoderState(tif);
	int shft;
	tmsize_t i;
	tmsize_t j;
	tmsize_t npixels;
	uint8* op;
	int16* tp;
	int16 b;
	tmsize_t occ;
	int rc=0, mask;
	tmsize_t beg;

	assert(s == 0);
	assert(sp != NULL);
	npixels = cc / sp->pixel_size;

	if (sp->user_datafmt == SGILOGDATAFMT_16BIT)
		tp = (int16*) bp;
	else {
		tp = (int16*) sp->tbuf;
		assert(sp->tbuflen >= npixels);
		(*sp->tfunc)(sp, bp, npixels);
	}
	/* compress each byte string */
	op = tif->tif_rawcp;
	occ = tif->tif_rawdatasize - tif->tif_rawcc;
	for (shft = 2*8; (shft -= 8) >= 0; )
		for (i = 0; i < npixels; i += rc) {
			if (occ < 4) {
				tif->tif_rawcp = op;
				tif->tif_rawcc = tif->tif_rawdatasize - occ;
				if (!TIFFFlushData1(tif))
					return (-1);
				op = tif->tif_rawcp;
				occ = tif->tif_rawdatasize - tif->tif_rawcc;
			}
			mask = 0xff << shft;		/* find next run */
			for (beg = i; beg < npixels; beg += rc) {
				b = (int16) (tp[beg] & mask);
				rc = 1;
				while (rc < 127+2 && beg+rc < npixels &&
				    (tp[beg+rc] & mask) == b)
					rc++;
				if (rc >= MINRUN)
					break;		/* long enough */
			}
			if (beg-i > 1 && beg-i < MINRUN) {
				b = (int16) (tp[i] & mask);/*check short run */
				j = i+1;
				while ((tp[j++] & mask) == b)
					if (j == beg) {
						*op++ = (uint8)(128-2+j-i);
						*op++ = (uint8)(b >> shft);
						occ -= 2;
						i = beg;
						break;
					}
			}
/*
 * Write the contents of the current directory
 * to the specified file.  This routine doesn't
 * handle overwriting a directory with auxiliary
 * storage that's been changed.
 */
static int
_TIFFWriteDirectory(TIFF* tif, int done)
{
	uint16 dircount;
	toff_t diroff;
	ttag_t tag;
	uint32 nfields;
	tsize_t dirsize;
	char* data;
	TIFFDirEntry* dir;
	TIFFDirectory* td;
	unsigned long b, fields[FIELD_SETLONGS];
	int fi, nfi;

	if (tif->tif_mode == O_RDONLY)
		return (1);
	/*
	 * Clear write state so that subsequent images with
	 * different characteristics get the right buffers
	 * setup for them.
	 */
	if (done)
	{
	    if (tif->tif_flags & TIFF_POSTENCODE) {
		    tif->tif_flags &= ~TIFF_POSTENCODE;
		    if (!(*tif->tif_postencode)(tif)) {
				TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
				"Error post-encoding before directory write");
			    return (0);
		    }
	    }
	    (*tif->tif_close)(tif);		/* shutdown encoder */
	    /*
	     * Flush any data that might have been written
	     * by the compression close+cleanup routines.
	     */
	    if (tif->tif_rawcc > 0 && !TIFFFlushData1(tif)) {
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
			"Error flushing data before directory write");
		    return (0);
	    }
	    if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) {
		    _TIFFfree(tif->tif_rawdata);
		    tif->tif_rawdata = NULL;
		    tif->tif_rawcc = 0;
		    tif->tif_rawdatasize = 0;
	    }
	    tif->tif_flags &= ~(TIFF_BEENWRITING|TIFF_BUFFERSETUP);
	}

	td = &tif->tif_dir;
	/*
	 * Size the directory so that we can calculate
	 * offsets for the data items that aren't kept
	 * in-place in each field.
	 */
	nfields = 0;
	for (b = 0; b <= FIELD_LAST; b++)
		if (TIFFFieldSet(tif, b) && b != FIELD_CUSTOM)
			nfields += (b < FIELD_SUBFILETYPE ? 2 : 1);
        nfields += td->td_customValueCount;
	dirsize = nfields * sizeof (TIFFDirEntry);
	data = (char*) _TIFFmalloc(dirsize);
	if (data == NULL) {
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
		    "Cannot write directory, out of space");
		return (0);
	}
	/*
	 * Directory hasn't been placed yet, put
	 * it at the end of the file and link it
	 * into the existing directory structure.
	 */
	if (tif->tif_diroff == 0 && !TIFFLinkDirectory(tif))
		goto bad;
	tif->tif_dataoff = (toff_t)(
	    tif->tif_diroff + sizeof (uint16) + dirsize + sizeof (toff_t));
	if (tif->tif_dataoff & 1)
		tif->tif_dataoff++;
	(void) TIFFSeekFile(tif, tif->tif_dataoff, SEEK_SET);
	tif->tif_curdir++;
	dir = (TIFFDirEntry*) data;
	/*
	 * Setup external form of directory
	 * entries and write data items.
	 */
	_TIFFmemcpy(fields, td->td_fieldsset, sizeof (fields));
	/*
	 * Write out ExtraSamples tag only if
	 * extra samples are present in the data.
	 */
	if (FieldSet(fields, FIELD_EXTRASAMPLES) && !td->td_extrasamples) {
		ResetFieldBit(fields, FIELD_EXTRASAMPLES);
		nfields--;
		dirsize -= sizeof (TIFFDirEntry);
	}								/*XXX*/
	for (fi = 0, nfi = tif->tif_nfields; nfi > 0; nfi--, fi++) {
		const TIFFFieldInfo* fip = tif->tif_fieldinfo[fi];

                /*
                ** For custom fields, we test to see if the custom field
                ** is set or not.  For normal fields, we just use the
                ** FieldSet test. 
                */
                if( fip->field_bit == FIELD_CUSTOM )
                {
                    int ci, is_set = FALSE;

                    for( ci = 0; ci < td->td_customValueCount; ci++ )
                        is_set |= (td->td_customValues[ci].info == fip);

                    if( !is_set )
                        continue;
                }
		else if (!FieldSet(fields, fip->field_bit))
                    continue;


                /*
                ** Handle other fields.
                */
		switch (fip->field_bit)
                {
		case FIELD_STRIPOFFSETS:
			/*
			 * We use one field bit for both strip and tile

			 * offsets, and so must be careful in selecting
			 * the appropriate field descriptor (so that tags
			 * are written in sorted order).
			 */
			tag = isTiled(tif) ?
			    TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS;
			if (tag != fip->field_tag)
				continue;
			
			dir->tdir_tag = (uint16) tag;
			dir->tdir_type = (uint16) TIFF_LONG;
			dir->tdir_count = (uint32) td->td_nstrips;
			if (!TIFFWriteLongArray(tif, dir, td->td_stripoffset))
				goto bad;
			break;
		case FIELD_STRIPBYTECOUNTS:
			/*
			 * We use one field bit for both strip and tile
			 * byte counts, and so must be careful in selecting
			 * the appropriate field descriptor (so that tags
			 * are written in sorted order).
			 */
			tag = isTiled(tif) ?
			    TIFFTAG_TILEBYTECOUNTS : TIFFTAG_STRIPBYTECOUNTS;
			if (tag != fip->field_tag)
				continue;
			
			dir->tdir_tag = (uint16) tag;
			dir->tdir_type = (uint16) TIFF_LONG;
			dir->tdir_count = (uint32) td->td_nstrips;
			if (!TIFFWriteLongArray(tif, dir,
						td->td_stripbytecount))
				goto bad;
			break;
		case FIELD_ROWSPERSTRIP:
			TIFFSetupShortLong(tif, TIFFTAG_ROWSPERSTRIP,
			    dir, td->td_rowsperstrip);
			break;
		case FIELD_COLORMAP:
			if (!TIFFWriteShortTable(tif, TIFFTAG_COLORMAP, dir,
			    3, td->td_colormap))
				goto bad;
			break;
		case FIELD_IMAGEDIMENSIONS:
			TIFFSetupShortLong(tif, TIFFTAG_IMAGEWIDTH,
			    dir++, td->td_imagewidth);
			TIFFSetupShortLong(tif, TIFFTAG_IMAGELENGTH,
			    dir, td->td_imagelength);
			break;
		case FIELD_TILEDIMENSIONS:
			TIFFSetupShortLong(tif, TIFFTAG_TILEWIDTH,
			    dir++, td->td_tilewidth);
			TIFFSetupShortLong(tif, TIFFTAG_TILELENGTH,
			    dir, td->td_tilelength);
			break;
		case FIELD_COMPRESSION:
			TIFFSetupShort(tif, TIFFTAG_COMPRESSION,
			    dir, td->td_compression);
			break;
		case FIELD_PHOTOMETRIC:
			TIFFSetupShort(tif, TIFFTAG_PHOTOMETRIC,
			    dir, td->td_photometric);
			break;
		case FIELD_POSITION:
			WriteRationalPair(TIFF_RATIONAL,
			    TIFFTAG_XPOSITION, td->td_xposition,
			    TIFFTAG_YPOSITION, td->td_yposition);
			break;
		case FIELD_RESOLUTION:
			WriteRationalPair(TIFF_RATIONAL,
			    TIFFTAG_XRESOLUTION, td->td_xresolution,
			    TIFFTAG_YRESOLUTION, td->td_yresolution);
			break;
		case FIELD_BITSPERSAMPLE:
		case FIELD_MINSAMPLEVALUE:
		case FIELD_MAXSAMPLEVALUE:
		case FIELD_SAMPLEFORMAT:
			if (!TIFFWritePerSampleShorts(tif, fip->field_tag, dir))
				goto bad;
			break;
		case FIELD_SMINSAMPLEVALUE:
		case FIELD_SMAXSAMPLEVALUE:
			if (!TIFFWritePerSampleAnys(tif,
			    _TIFFSampleToTagType(tif), fip->field_tag, dir))
				goto bad;
			break;
		case FIELD_PAGENUMBER:
		case FIELD_HALFTONEHINTS:
		case FIELD_YCBCRSUBSAMPLING:
			if (!TIFFSetupShortPair(tif, fip->field_tag, dir))
				goto bad;
			break;
		case FIELD_INKNAMES:
			if (!TIFFWriteInkNames(tif, dir))
				goto bad;
			break;
		case FIELD_TRANSFERFUNCTION:
			if (!TIFFWriteTransferFunction(tif, dir))
				goto bad;
			break;
		case FIELD_SUBIFD:
			/*
			 * XXX: Always write this field using LONG type
			 * for backward compatibility.
			 */
			dir->tdir_tag = (uint16) fip->field_tag;
			dir->tdir_type = (uint16) TIFF_LONG;
			dir->tdir_count = (uint32) td->td_nsubifd;
			if (!TIFFWriteLongArray(tif, dir, td->td_subifd))
				goto bad;
			/*
			 * Total hack: if this directory includes a SubIFD
			 * tag then force the next <n> directories to be
			 * written as ``sub directories'' of this one.  This
			 * is used to write things like thumbnails and
			 * image masks that one wants to keep out of the
			 * normal directory linkage access mechanism.
			 */
			if (dir->tdir_count > 0) {
				tif->tif_flags |= TIFF_INSUBIFD;
				tif->tif_nsubifd = (uint16) dir->tdir_count;
				if (dir->tdir_count > 1)
					tif->tif_subifdoff = dir->tdir_offset;
				else
					tif->tif_subifdoff = (uint32)(
					      tif->tif_diroff
					    + sizeof (uint16)
					    + ((char*)&dir->tdir_offset-data));
			}
			break;
		default:
			/* XXX: Should be fixed and removed. */
			if (fip->field_tag == TIFFTAG_DOTRANGE) {
				if (!TIFFSetupShortPair(tif, fip->field_tag, dir))
					goto bad;
			}
			else if (!TIFFWriteNormalTag(tif, dir, fip))
				goto bad;
			break;
		}
		dir++;
                
                if( fip->field_bit != FIELD_CUSTOM )
                    ResetFieldBit(fields, fip->field_bit);
	}

	/*
	 * Write directory.
	 */
	dircount = (uint16) nfields;
	diroff = (uint32) tif->tif_nextdiroff;
	if (tif->tif_flags & TIFF_SWAB) {
		/*
		 * The file's byte order is opposite to the
		 * native machine architecture.  We overwrite
		 * the directory information with impunity
		 * because it'll be released below after we
		 * write it to the file.  Note that all the
		 * other tag construction routines assume that
		 * we do this byte-swapping; i.e. they only
		 * byte-swap indirect data.
		 */
		for (dir = (TIFFDirEntry*) data; dircount; dir++, dircount--) {
			TIFFSwabArrayOfShort(&dir->tdir_tag, 2);
			TIFFSwabArrayOfLong(&dir->tdir_count, 2);
		}
		dircount = (uint16) nfields;
		TIFFSwabShort(&dircount);
		TIFFSwabLong(&diroff);
	}
	(void) TIFFSeekFile(tif, tif->tif_diroff, SEEK_SET);
	if (!WriteOK(tif, &dircount, sizeof (dircount))) {
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing directory count");
		goto bad;
	}
	if (!WriteOK(tif, data, dirsize)) {
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing directory contents");
		goto bad;
	}
	if (!WriteOK(tif, &diroff, sizeof (diroff))) {
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing directory link");
		goto bad;
	}
	if (done) {
		TIFFFreeDirectory(tif);
		tif->tif_flags &= ~TIFF_DIRTYDIRECT;
		(*tif->tif_cleanup)(tif);

		/*
		* Reset directory-related state for subsequent
		* directories.
		*/
		TIFFCreateDirectory(tif);
	}
	_TIFFfree(data);
	return (1);
bad:
	_TIFFfree(data);
	return (0);
}
Example #5
0
/*
* Finish off an encoded strip by flushing it.
*/
static int
TWebPPostEncode(TIFF* tif)
{
  static const char module[] = "WebPPostEncode";
  int64_t stride;
  WebPState *sp = EncoderState(tif);
  assert(sp != NULL);

  assert(sp->state == LSTATE_INIT_ENCODE);

  stride = (int64_t)sp->sPicture.width * sp->nSamples;

#if WEBP_ENCODER_ABI_VERSION >= 0x0100
  if (sp->nSamples == 4) {
      if (!WebPPictureImportRGBA(&sp->sPicture, sp->pBuffer, (int)stride)) {
          TIFFErrorExt(tif->tif_clientdata, module,
                    "WebPPictureImportRGBA() failed" );
          return 0;
      }
  }
  else
#endif
  if (!WebPPictureImportRGB(&sp->sPicture, sp->pBuffer, (int)stride)) {
      TIFFErrorExt(tif->tif_clientdata, module,
                    "WebPPictureImportRGB() failed");
      return 0;
  }

  if (!WebPEncode(&sp->sEncoderConfig, &sp->sPicture)) {

#if WEBP_ENCODER_ABI_VERSION >= 0x0100
    const char* pszErrorMsg = NULL;
    switch(sp->sPicture.error_code) {
    case VP8_ENC_ERROR_OUT_OF_MEMORY:
        pszErrorMsg = "Out of memory"; break;
    case VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY:
        pszErrorMsg = "Out of memory while flushing bits"; break;
    case VP8_ENC_ERROR_NULL_PARAMETER:
        pszErrorMsg = "A pointer parameter is NULL"; break;
    case VP8_ENC_ERROR_INVALID_CONFIGURATION:
        pszErrorMsg = "Configuration is invalid"; break;
    case VP8_ENC_ERROR_BAD_DIMENSION:
        pszErrorMsg = "Picture has invalid width/height"; break;
    case VP8_ENC_ERROR_PARTITION0_OVERFLOW:
        pszErrorMsg = "Partition is bigger than 512k. Try using less "
            "SEGMENTS, or increase PARTITION_LIMIT value";
        break;
    case VP8_ENC_ERROR_PARTITION_OVERFLOW:
        pszErrorMsg = "Partition is bigger than 16M";
        break;
    case VP8_ENC_ERROR_BAD_WRITE:
        pszErrorMsg = "Error while fludshing bytes"; break;
    case VP8_ENC_ERROR_FILE_TOO_BIG:
        pszErrorMsg = "File is bigger than 4G"; break;
    case VP8_ENC_ERROR_USER_ABORT:
        pszErrorMsg = "User interrupted";
        break;
    default:
        TIFFErrorExt(tif->tif_clientdata, module,
                "WebPEncode returned an unknown error code: %d",
                sp->sPicture.error_code);
        pszErrorMsg = "Unknown WebP error type.";
        break;
    }
    TIFFErrorExt(tif->tif_clientdata, module,
             "WebPEncode() failed : %s", pszErrorMsg);
#else
    TIFFErrorExt(tif->tif_clientdata, module,
             "Error in WebPEncode()");
#endif
    return 0;
  }

  sp->sPicture.custom_ptr = NULL;

  if (!TIFFFlushData1(tif))
  {
    TIFFErrorExt(tif->tif_clientdata, module,
      "Error flushing TIFF WebP encoder.");
    return 0;
  }

  return 1;
}