static int
Fax3SetupState(TIFF* tif)
{
	static const char module[] = "Fax3SetupState";
	TIFFDirectory* td = &tif->tif_dir;
	Fax3BaseState* sp = Fax3State(tif);
	int needsRefLine;
	Fax3CodecState* dsp = (Fax3CodecState*) Fax3State(tif);
	tmsize_t rowbytes;
	uint32 rowpixels, nruns;

	if (td->td_bitspersample != 1) {
		TIFFErrorExt(tif->tif_clientdata, module,
		    "Bits/sample must be 1 for Group 3/4 encoding/decoding");
		return (0);
	}
	/*
	 * Calculate the scanline/tile widths.
	 */
	if (isTiled(tif)) {
		rowbytes = TIFFTileRowSize(tif);
		rowpixels = td->td_tilewidth;
	} else {
		rowbytes = TIFFScanlineSize(tif);
		rowpixels = td->td_imagewidth;
	}
	sp->rowbytes = rowbytes;
	sp->rowpixels = rowpixels;
	/*
	 * Allocate any additional space required for decoding/encoding.
	 */
	needsRefLine = (
	    (sp->groupoptions & GROUP3OPT_2DENCODING) ||
	    td->td_compression == COMPRESSION_CCITTFAX4
	);

	nruns = needsRefLine ? 2*TIFFroundup_32(rowpixels,32) : rowpixels;
	nruns += 3;
	dsp->runs = (uint32*) _TIFFCheckMalloc(tif, 2*nruns, sizeof (uint32),
					  "for Group 3/4 run arrays");
	if (dsp->runs == NULL)
		return (0);
	dsp->curruns = dsp->runs;
	if (needsRefLine)
		dsp->refruns = dsp->runs + nruns;
	else
		dsp->refruns = NULL;
	if (td->td_compression == COMPRESSION_CCITTFAX3
	    && is2DEncoding(dsp)) {	/* NB: default is 1D routine */
		tif->tif_decoderow = Fax3Decode2D;
		tif->tif_decodestrip = Fax3Decode2D;
		tif->tif_decodetile = Fax3Decode2D;
	}

	if (needsRefLine) {		/* 2d encoding */
		Fax3CodecState* esp = EncoderState(tif);
		/*
		 * 2d encoding requires a scanline
		 * buffer for the ``reference line''; the
		 * scanline against which delta encoding
		 * is referenced.  The reference line must
		 * be initialized to be ``white'' (done elsewhere).
		 */
		esp->refline = (unsigned char*) _TIFFmalloc(rowbytes);
		if (esp->refline == NULL) {
			TIFFErrorExt(tif->tif_clientdata, module,
			    "No space for Group 3/4 reference line");
			return (0);
		}
	} else					/* 1d encoding */
		EncoderState(tif)->refline = NULL;

	return (1);
}