Blame libtiff/tif_jbig.c

Packit 994f1a
/* $Id: tif_jbig.c,v 1.2.2.3 2010-06-08 18:50:42 bfriesen Exp $ */
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * Copyright (c) 1988-1997 Sam Leffler
Packit 994f1a
 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
Packit 994f1a
 *
Packit 994f1a
 * Permission to use, copy, modify, distribute, and sell this software and 
Packit 994f1a
 * its documentation for any purpose is hereby granted without fee, provided
Packit 994f1a
 * that (i) the above copyright notices and this permission notice appear in
Packit 994f1a
 * all copies of the software and related documentation, and (ii) the names of
Packit 994f1a
 * Sam Leffler and Silicon Graphics may not be used in any advertising or
Packit 994f1a
 * publicity relating to the software without the specific, prior written
Packit 994f1a
 * permission of Sam Leffler and Silicon Graphics.
Packit 994f1a
 * 
Packit 994f1a
 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
Packit 994f1a
 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
Packit 994f1a
 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
Packit 994f1a
 * 
Packit 994f1a
 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
Packit 994f1a
 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
Packit 994f1a
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
Packit 994f1a
 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
Packit 994f1a
 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
Packit 994f1a
 * OF THIS SOFTWARE.
Packit 994f1a
 */
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * TIFF Library.
Packit 994f1a
 *
Packit 994f1a
 * JBIG Compression Algorithm Support.
Packit 994f1a
 * Contributed by Lee Howard <faxguy@deanox.com>
Packit 994f1a
 * 
Packit 994f1a
 */
Packit 994f1a
Packit 994f1a
#include "tiffiop.h"
Packit 994f1a
Packit 994f1a
#ifdef JBIG_SUPPORT
Packit 994f1a
#include "jbig.h"
Packit 994f1a
Packit 994f1a
typedef struct
Packit 994f1a
{
Packit 994f1a
        uint32  recvparams;     /* encoded Class 2 session params             */
Packit 994f1a
        char*   subaddress;     /* subaddress string                          */
Packit 994f1a
        uint32  recvtime;       /* time spend receiving in seconds            */
Packit 994f1a
        char*   faxdcs;         /* encoded fax parameters (DCS, Table 2/T.30) */
Packit 994f1a
Packit 994f1a
        TIFFVGetMethod vgetparent;
Packit 994f1a
        TIFFVSetMethod vsetparent;
Packit 994f1a
} JBIGState;
Packit 994f1a
Packit 994f1a
#define GetJBIGState(tif) ((JBIGState*)(tif)->tif_data)
Packit 994f1a
Packit 994f1a
#define FIELD_RECVPARAMS        (FIELD_CODEC+0)
Packit 994f1a
#define FIELD_SUBADDRESS        (FIELD_CODEC+1)
Packit 994f1a
#define FIELD_RECVTIME          (FIELD_CODEC+2)
Packit 994f1a
#define FIELD_FAXDCS            (FIELD_CODEC+3)
Packit 994f1a
Packit 994f1a
static const TIFFFieldInfo jbigFieldInfo[] = 
Packit 994f1a
{
Packit 994f1a
        {TIFFTAG_FAXRECVPARAMS,  1,  1, TIFF_LONG,  FIELD_RECVPARAMS, TRUE, FALSE, "FaxRecvParams"},
Packit 994f1a
        {TIFFTAG_FAXSUBADDRESS, -1, -1, TIFF_ASCII, FIELD_SUBADDRESS, TRUE, FALSE, "FaxSubAddress"},
Packit 994f1a
        {TIFFTAG_FAXRECVTIME,    1,  1, TIFF_LONG,  FIELD_RECVTIME,   TRUE, FALSE, "FaxRecvTime"},
Packit 994f1a
        {TIFFTAG_FAXDCS,        -1, -1, TIFF_ASCII, FIELD_FAXDCS,     TRUE, FALSE, "FaxDcs"},
Packit 994f1a
};
Packit 994f1a
Packit 994f1a
static int JBIGSetupDecode(TIFF* tif)
Packit 994f1a
{
Packit 994f1a
        if (TIFFNumberOfStrips(tif) != 1)
Packit 994f1a
        {
Packit 994f1a
                TIFFError("JBIG", "Multistrip images not supported in decoder");
Packit 994f1a
                return 0;
Packit 994f1a
        }
Packit 994f1a
Packit 994f1a
        return 1;
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
static int JBIGDecode(TIFF* tif, tidata_t buffer, tsize_t size, tsample_t s)
Packit 994f1a
{
Packit 994f1a
        struct jbg_dec_state decoder;
Packit 994f1a
        int decodeStatus = 0;
Packit 994f1a
        unsigned char* pImage = NULL;
Packit 994f1a
	(void) size, (void) s;
Packit 994f1a
Packit 994f1a
        if (isFillOrder(tif, tif->tif_dir.td_fillorder))
Packit 994f1a
        {
Packit 994f1a
                TIFFReverseBits(tif->tif_rawdata, tif->tif_rawdatasize);
Packit 994f1a
        }
Packit 994f1a
Packit 994f1a
        jbg_dec_init(&decoder);
Packit 994f1a
Packit 994f1a
#if defined(HAVE_JBG_NEWLEN)
Packit 994f1a
        jbg_newlen(tif->tif_rawdata, tif->tif_rawdatasize);
Packit 994f1a
        /*
Packit 994f1a
         * I do not check the return status of jbg_newlen because even if this
Packit 994f1a
         * function fails it does not necessarily mean that decoding the image
Packit 994f1a
         * will fail.  It is generally only needed for received fax images
Packit 994f1a
         * that do not contain the actual length of the image in the BIE
Packit 994f1a
         * header.  I do not log when an error occurs because that will cause
Packit 994f1a
         * problems when converting JBIG encoded TIFF's to 
Packit 994f1a
         * PostScript.  As long as the actual image length is contained in the
Packit 994f1a
         * BIE header jbg_dec_in should succeed.
Packit 994f1a
         */
Packit 994f1a
#endif /* HAVE_JBG_NEWLEN */
Packit 994f1a
Packit 994f1a
        decodeStatus = jbg_dec_in(&decoder, tif->tif_rawdata,
Packit 994f1a
                                  tif->tif_rawdatasize, NULL);
Packit 994f1a
        if (JBG_EOK != decodeStatus)
Packit 994f1a
        {
Packit 994f1a
		/*
Packit 994f1a
		 * XXX: JBG_EN constant was defined in pre-2.0 releases of the
Packit 994f1a
		 * JBIG-KIT. Since the 2.0 the error reporting functions were
Packit 994f1a
		 * changed. We will handle both cases here.
Packit 994f1a
		 */
Packit 994f1a
                TIFFError("JBIG", "Error (%d) decoding: %s", decodeStatus,
Packit 994f1a
#if defined(JBG_EN)
Packit 994f1a
			  jbg_strerror(decodeStatus, JBG_EN)
Packit 994f1a
#else
Packit 994f1a
                          jbg_strerror(decodeStatus)
Packit 994f1a
#endif
Packit 994f1a
			 );
Packit 994f1a
                return 0;
Packit 994f1a
        }
Packit 994f1a
        
Packit 994f1a
        pImage = jbg_dec_getimage(&decoder, 0);
Packit 994f1a
        _TIFFmemcpy(buffer, pImage, jbg_dec_getsize(&decoder));
Packit 994f1a
        jbg_dec_free(&decoder);
Packit 994f1a
        return 1;
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
static int JBIGSetupEncode(TIFF* tif)
Packit 994f1a
{
Packit 994f1a
        if (TIFFNumberOfStrips(tif) != 1)
Packit 994f1a
        {
Packit 994f1a
                TIFFError("JBIG", "Multistrip images not supported in encoder");
Packit 994f1a
                return 0;
Packit 994f1a
        }
Packit 994f1a
Packit 994f1a
        return 1;
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
static int JBIGCopyEncodedData(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s)
Packit 994f1a
{
Packit 994f1a
        (void) s;
Packit 994f1a
        while (cc > 0) 
Packit 994f1a
        {
Packit 994f1a
                tsize_t n = cc;
Packit 994f1a
Packit 994f1a
                if (tif->tif_rawcc + n > tif->tif_rawdatasize)
Packit 994f1a
                {
Packit 994f1a
                        n = tif->tif_rawdatasize - tif->tif_rawcc;
Packit 994f1a
                }
Packit 994f1a
Packit 994f1a
                assert(n > 0);
Packit 994f1a
                _TIFFmemcpy(tif->tif_rawcp, pp, n);
Packit 994f1a
                tif->tif_rawcp += n;
Packit 994f1a
                tif->tif_rawcc += n;
Packit 994f1a
                pp += n;
Packit 994f1a
                cc -= n;
Packit 994f1a
                if (tif->tif_rawcc >= tif->tif_rawdatasize &&
Packit 994f1a
                    !TIFFFlushData1(tif))
Packit 994f1a
                {
Packit 994f1a
                        return (-1);
Packit 994f1a
                }
Packit 994f1a
        }
Packit 994f1a
Packit 994f1a
        return (1);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
static void JBIGOutputBie(unsigned char* buffer, size_t len, void *userData)
Packit 994f1a
{
Packit 994f1a
        TIFF* tif = (TIFF*)userData;
Packit 994f1a
Packit 994f1a
        if (isFillOrder(tif, tif->tif_dir.td_fillorder))
Packit 994f1a
        {
Packit 994f1a
                TIFFReverseBits(buffer, len);
Packit 994f1a
        }
Packit 994f1a
Packit 994f1a
        JBIGCopyEncodedData(tif, buffer, len, 0);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
static int JBIGEncode(TIFF* tif, tidata_t buffer, tsize_t size, tsample_t s)
Packit 994f1a
{
Packit 994f1a
        TIFFDirectory* dir = &tif->tif_dir;
Packit 994f1a
        struct jbg_enc_state encoder;
Packit 994f1a
Packit 994f1a
	(void) size, (void) s;
Packit 994f1a
Packit 994f1a
        jbg_enc_init(&encoder, 
Packit 994f1a
                     dir->td_imagewidth, 
Packit 994f1a
                     dir->td_imagelength, 
Packit 994f1a
                     1, 
Packit 994f1a
                     &buffer,
Packit 994f1a
                     JBIGOutputBie,
Packit 994f1a
                     tif);
Packit 994f1a
        /* 
Packit 994f1a
         * jbg_enc_out does the "real" encoding.  As data is encoded,
Packit 994f1a
         * JBIGOutputBie is called, which writes the data to the directory.
Packit 994f1a
         */
Packit 994f1a
        jbg_enc_out(&encoder);
Packit 994f1a
        jbg_enc_free(&encoder);
Packit 994f1a
Packit 994f1a
        return 1;
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
static void JBIGCleanup(TIFF* tif)
Packit 994f1a
{
Packit 994f1a
        JBIGState *sp = GetJBIGState(tif);
Packit 994f1a
Packit 994f1a
        assert(sp != 0);
Packit 994f1a
Packit 994f1a
        tif->tif_tagmethods.vgetfield = sp->vgetparent;
Packit 994f1a
        tif->tif_tagmethods.vsetfield = sp->vsetparent;
Packit 994f1a
Packit 994f1a
	_TIFFfree(tif->tif_data);
Packit 994f1a
	tif->tif_data = NULL;
Packit 994f1a
Packit 994f1a
	_TIFFSetDefaultCompressionState(tif);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
static void JBIGPrintDir(TIFF* tif, FILE* fd, long flags)
Packit 994f1a
{
Packit 994f1a
        JBIGState* codec = GetJBIGState(tif);
Packit 994f1a
        (void)flags;
Packit 994f1a
Packit 994f1a
        if (TIFFFieldSet(tif, FIELD_RECVPARAMS))
Packit 994f1a
        {
Packit 994f1a
                fprintf(fd, 
Packit 994f1a
                        "  Fax Receive Parameters: %08lx\n",
Packit 994f1a
                        (unsigned long)codec->recvparams);
Packit 994f1a
        }
Packit 994f1a
Packit 994f1a
        if (TIFFFieldSet(tif, FIELD_SUBADDRESS))
Packit 994f1a
        {
Packit 994f1a
                fprintf(fd, 
Packit 994f1a
                        "  Fax SubAddress: %s\n", 
Packit 994f1a
                        codec->subaddress);
Packit 994f1a
        }
Packit 994f1a
Packit 994f1a
        if (TIFFFieldSet(tif, FIELD_RECVTIME))
Packit 994f1a
        {
Packit 994f1a
                fprintf(fd, 
Packit 994f1a
                        "  Fax Receive Time: %lu secs\n",
Packit 994f1a
                        (unsigned long)codec->recvtime);
Packit 994f1a
        }
Packit 994f1a
Packit 994f1a
        if (TIFFFieldSet(tif, FIELD_FAXDCS))
Packit 994f1a
        {
Packit 994f1a
                fprintf(fd, 
Packit 994f1a
                        "  Fax DCS: %s\n", 
Packit 994f1a
                        codec->faxdcs);
Packit 994f1a
        }
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
static int JBIGVGetField(TIFF* tif, ttag_t tag, va_list ap)
Packit 994f1a
{
Packit 994f1a
        JBIGState* codec = GetJBIGState(tif);
Packit 994f1a
Packit 994f1a
        switch (tag)
Packit 994f1a
        {
Packit 994f1a
                case TIFFTAG_FAXRECVPARAMS:
Packit 994f1a
                        *va_arg(ap, uint32*) = codec->recvparams;
Packit 994f1a
                        break;
Packit 994f1a
                
Packit 994f1a
                case TIFFTAG_FAXSUBADDRESS:
Packit 994f1a
                        *va_arg(ap, char**) = codec->subaddress;
Packit 994f1a
                        break;
Packit 994f1a
Packit 994f1a
                case TIFFTAG_FAXRECVTIME:
Packit 994f1a
                        *va_arg(ap, uint32*) = codec->recvtime;
Packit 994f1a
                        break;
Packit 994f1a
Packit 994f1a
                case TIFFTAG_FAXDCS:
Packit 994f1a
                        *va_arg(ap, char**) = codec->faxdcs;
Packit 994f1a
                        break;
Packit 994f1a
Packit 994f1a
                default:
Packit 994f1a
                        return (*codec->vgetparent)(tif, tag, ap);
Packit 994f1a
        }
Packit 994f1a
Packit 994f1a
        return 1;
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
static int JBIGVSetField(TIFF* tif, ttag_t tag, va_list ap)
Packit 994f1a
{
Packit 994f1a
        JBIGState* codec = GetJBIGState(tif);
Packit 994f1a
Packit 994f1a
        switch (tag)
Packit 994f1a
        {
Packit 994f1a
                case TIFFTAG_FAXRECVPARAMS:
Packit 994f1a
                        codec->recvparams = va_arg(ap, uint32);
Packit 994f1a
                        break;
Packit 994f1a
Packit 994f1a
                case TIFFTAG_FAXSUBADDRESS:
Packit 994f1a
                        _TIFFsetString(&codec->subaddress, va_arg(ap, char*));
Packit 994f1a
                        break;
Packit 994f1a
Packit 994f1a
                case TIFFTAG_FAXRECVTIME:
Packit 994f1a
                        codec->recvtime = va_arg(ap, uint32);
Packit 994f1a
                        break;
Packit 994f1a
Packit 994f1a
                case TIFFTAG_FAXDCS:
Packit 994f1a
                        _TIFFsetString(&codec->faxdcs, va_arg(ap, char*));
Packit 994f1a
                        break;
Packit 994f1a
Packit 994f1a
                default:
Packit 994f1a
                        return (*codec->vsetparent)(tif, tag, ap);
Packit 994f1a
        }
Packit 994f1a
Packit 994f1a
        TIFFSetFieldBit(tif, _TIFFFieldWithTag(tif, tag)->field_bit);
Packit 994f1a
        tif->tif_flags |= TIFF_DIRTYDIRECT;
Packit 994f1a
        return 1;
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
int TIFFInitJBIG(TIFF* tif, int scheme)
Packit 994f1a
{
Packit 994f1a
        JBIGState* codec = NULL;
Packit 994f1a
Packit 994f1a
	assert(scheme == COMPRESSION_JBIG);
Packit 994f1a
Packit 994f1a
	/*
Packit 994f1a
	 * Merge codec-specific tag information.
Packit 994f1a
	 */
Packit 994f1a
	if (!_TIFFMergeFieldInfo(tif, jbigFieldInfo,
Packit 994f1a
				 TIFFArrayCount(jbigFieldInfo))) {
Packit 994f1a
		TIFFErrorExt(tif->tif_clientdata, "TIFFInitJBIG",
Packit 994f1a
			     "Merging JBIG codec-specific tags failed");
Packit 994f1a
		return 0;
Packit 994f1a
	}
Packit 994f1a
Packit 994f1a
        /* Allocate memory for the JBIGState structure.*/
Packit 994f1a
        tif->tif_data = (tdata_t)_TIFFmalloc(sizeof(JBIGState));
Packit 994f1a
        if (tif->tif_data == NULL)
Packit 994f1a
        {
Packit 994f1a
                TIFFError("TIFFInitJBIG", "Not enough memory for JBIGState");
Packit 994f1a
                return 0;
Packit 994f1a
        }
Packit 994f1a
        _TIFFmemset(tif->tif_data, 0, sizeof(JBIGState));
Packit 994f1a
        codec = GetJBIGState(tif);
Packit 994f1a
Packit 994f1a
        /* Initialize codec private fields */
Packit 994f1a
        codec->recvparams = 0;
Packit 994f1a
        codec->subaddress = NULL;
Packit 994f1a
        codec->faxdcs = NULL;
Packit 994f1a
        codec->recvtime = 0;
Packit 994f1a
Packit 994f1a
	/* 
Packit 994f1a
	 * Override parent get/set field methods.
Packit 994f1a
	 */
Packit 994f1a
        codec->vgetparent = tif->tif_tagmethods.vgetfield;
Packit 994f1a
        codec->vsetparent = tif->tif_tagmethods.vsetfield;
Packit 994f1a
        tif->tif_tagmethods.vgetfield = JBIGVGetField;
Packit 994f1a
        tif->tif_tagmethods.vsetfield = JBIGVSetField;
Packit 994f1a
        tif->tif_tagmethods.printdir = JBIGPrintDir;
Packit 994f1a
Packit 994f1a
        /*
Packit 994f1a
         * These flags are set so the JBIG Codec can control when to reverse
Packit 994f1a
         * bits and when not to and to allow the jbig decoder and bit reverser
Packit 994f1a
         * to write to memory when necessary.
Packit 994f1a
         */
Packit 994f1a
        tif->tif_flags |= TIFF_NOBITREV;
Packit 994f1a
        tif->tif_flags &= ~TIFF_MAPPED;
Packit 994f1a
Packit 994f1a
        /* Setup the function pointers for encode, decode, and cleanup. */
Packit 994f1a
        tif->tif_setupdecode = JBIGSetupDecode;
Packit 994f1a
        tif->tif_decodestrip = JBIGDecode;
Packit 994f1a
Packit 994f1a
        tif->tif_setupencode = JBIGSetupEncode;
Packit 994f1a
        tif->tif_encodestrip = JBIGEncode;
Packit 994f1a
        
Packit 994f1a
        tif->tif_cleanup = JBIGCleanup;
Packit 994f1a
Packit 994f1a
        return 1;
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
#endif /* JBIG_SUPPORT */
Packit 994f1a
Packit 994f1a
/* vim: set ts=8 sts=8 sw=8 noet: */
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * Local Variables:
Packit 994f1a
 * mode: c
Packit 994f1a
 * c-basic-offset: 8
Packit 994f1a
 * fill-column: 78
Packit 994f1a
 * End:
Packit 994f1a
 */