static int GetDataBlock (MG_RWops *area, unsigned char *buf)
{
    unsigned char count;

    if (!ReadOK(area, &count, 1))
        return 0;
    ZeroDataBlock = (count == 0);

    if ((count != 0) && (!ReadOK(area, buf, count)))
        return 0;
    return count;
}
예제 #2
0
static bool ReadPalette( RageFile &f, int number, RageSurfaceColor buffer[MAXCOLORMAPSIZE] )
{
	for( int i = 0; i < number; ++i )
	{
		if( !ReadOK(f, &buffer[i].r, sizeof(buffer[i].r)) )
			return false;
		if( !ReadOK(f, &buffer[i].g, sizeof(buffer[i].g)) )
			return false;
		if( !ReadOK(f, &buffer[i].b, sizeof(buffer[i].b)) )
			return false;
		buffer[i].a = 0xFF;
	}

	return true;
}
예제 #3
0
bool LWZState::Init( RageFile &f )
{
	unsigned char input_code_size;

	/* code size: */
	if( !ReadOK(f, &input_code_size, 1) )
	{
//		RWSetMsg("EOF / read error on image data");
		return false;
	}

	set_code_size = input_code_size;
	code_size = set_code_size + 1;
	clear_code = 1 << set_code_size;
	end_code = clear_code + 1;
	max_code_size = 2 * clear_code;
	max_code = clear_code + 2;

	m_Code.Init();

	fresh = true;

	memset( table, 0, sizeof(table) );

	for( int i = 0; i < clear_code; ++i )
		table[1][i] = i;

	sp = stack;

	return true;
}
예제 #4
0
static gboolean
ReadColorMap (FILE *fd,
              gint  number,
              CMap  buffer,
              gint *format)
{
  guchar rgb[3];
  gint   flag;
  gint   i;

  flag = TRUE;

  for (i = 0; i < number; ++i)
    {
      if (! ReadOK (fd, rgb, sizeof (rgb)))
        return FALSE;

      buffer[CM_RED][i] = rgb[0];
      buffer[CM_GREEN][i] = rgb[1];
      buffer[CM_BLUE][i] = rgb[2];

      flag &= (rgb[0] == rgb[1] && rgb[1] == rgb[2]);
    }

  *format = (flag) ? GRAYSCALE : COLOR;

  return TRUE;
}
예제 #5
0
static tsize_t
TIFFReadRawStrip1(TIFF* tif,
    tstrip_t strip, tdata_t buf, tsize_t size, const char* module)
{
	TIFFDirectory *td = &tif->tif_dir;

	if (!isMapped(tif)) {
		if (!SeekOK(tif, td->td_stripoffset[strip])) {
			TIFFError(module,
			    "%s: Seek error at scanline %lu, strip %lu",
			    tif->tif_name,
			    (u_long) tif->tif_row, (u_long) strip);
			return (-1);
		}
		if (!ReadOK(tif, buf, size)) {
			TIFFError(module, "%s: Read error at scanline %lu",
			    tif->tif_name, (u_long) tif->tif_row);
			return (-1);
		}
	} else {
		if (td->td_stripoffset[strip] + size > tif->tif_size) {
			TIFFError(module,
			    "%s: Seek error at scanline %lu, strip %lu",
			    tif->tif_name,
			    (u_long) tif->tif_row, (u_long) strip);
			return (-1);
		}
		memcpy(buf, tif->tif_base + td->td_stripoffset[strip], size);
	}
	return (size);
}
static int ReadImageDesc (MG_RWops *area, IMAGEDESC* ImageDesc, GIFSCREEN* GifScreen)
{
    unsigned char buf[16];
    if (!ReadOK (area, buf, 9)) {
        _MG_PRINTF ("EX_CTRL>GIF89a: bad image size\n");
        return -1;
    }

    ImageDesc->Top = LM_to_uint (buf[0], buf[1]);
    ImageDesc->Left = LM_to_uint (buf[2], buf[3]);
    ImageDesc->Width = LM_to_uint (buf[4], buf[5]);
    ImageDesc->Height = LM_to_uint (buf[6], buf[7]);
    ImageDesc->haveColorMap = BitSet (buf[8], LOCALCOLORMAP);

    ImageDesc->bitPixel = 1 << ((buf[8] & 0x07) + 1);

    ImageDesc->interlace = BitSet(buf[8], INTERLACE);

    if (ImageDesc->haveColorMap) {
        _MG_PRINTF ("EX_CTRL>GIF89a: have local colormap\n");
        if (ReadColorMap (area, ImageDesc->bitPixel, ImageDesc->ColorMap) < 0) {
            _MG_PRINTF ("EX_CTRL>GIF89a: bad local colormap\n");
            return -1;
        }
    } else {
        memcpy (ImageDesc->ColorMap, GifScreen->ColorMap, MAXCOLORMAPSIZE*sizeof (RGB));
    }

    return 0;
}
예제 #7
0
static int
ReadColorMap(SDL_RWops *src, int number,
             unsigned char buffer[3][MAXCOLORMAPSIZE], int *gray)
{
    int i;
    unsigned char rgb[3];
    int flag;

    flag = TRUE;

    for (i = 0; i < number; ++i) {
		if (!ReadOK(src, rgb, sizeof(rgb))) {
		    IMG_SetError("bad colormap");
		    return 1;
		}
		buffer[CM_RED][i] = rgb[0];
		buffer[CM_GREEN][i] = rgb[1];
		buffer[CM_BLUE][i] = rgb[2];
		flag &= (rgb[0] == rgb[1] && rgb[1] == rgb[2]);
    }

#if 0
    if (flag)
	*gray = (number == 2) ? PBM_TYPE : PGM_TYPE;
    else
	*gray = PPM_TYPE;
#else
    *gray = 0;
#endif

    return FALSE;
}
예제 #8
0
파일: rdppm.c 프로젝트: John-He-928/krkrz
get_word_rgb_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
/* This version is for reading raw-word-format PPM files with any maxval */
{
  ppm_source_ptr source = (ppm_source_ptr) sinfo;
  register JSAMPROW ptr;
  register U_CHAR * bufferptr;
  register JSAMPLE *rescale = source->rescale;
  JDIMENSION col;

  if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
    ERREXIT(cinfo, JERR_INPUT_EOF);
  ptr = source->pub.buffer[0];
  bufferptr = source->iobuffer;
  for (col = cinfo->image_width; col > 0; col--) {
    register int temp;
    temp  = UCH(*bufferptr++) << 8;
    temp |= UCH(*bufferptr++);
    *ptr++ = rescale[temp];
    temp  = UCH(*bufferptr++) << 8;
    temp |= UCH(*bufferptr++);
    *ptr++ = rescale[temp];
    temp  = UCH(*bufferptr++) << 8;
    temp |= UCH(*bufferptr++);
    *ptr++ = rescale[temp];
  }
  return 1;
}
예제 #9
0
int
copyFaxFile(TIFF* tifin, TIFF* tifout)
{
	uint32 row;
	uint16 badrun;
	int ok;

	tifin->tif_rawdatasize = TIFFGetFileSize(tifin);
	tifin->tif_rawdata = _TIFFmalloc(tifin->tif_rawdatasize);
	if (!ReadOK(tifin, tifin->tif_rawdata, tifin->tif_rawdatasize)) {
		TIFFError(tifin->tif_name, "%s: Read error at scanline 0");
		return (0);
	}
	tifin->tif_rawcp = tifin->tif_rawdata;
	tifin->tif_rawcc = tifin->tif_rawdatasize;

	(*tifin->tif_setupdecode)(tifin);
	(*tifin->tif_predecode)(tifin, (tsample_t) 0);
	tifin->tif_row = 0;
	badfaxlines = 0;
	badfaxrun = 0;

	_TIFFmemset(refbuf, 0, sizeof (refbuf));
	row = 0;
	badrun = 0;		/* current run of bad lines */
	while (tifin->tif_rawcc > 0) {
		ok = (*tifin->tif_decoderow)(tifin, rowbuf, sizeof (rowbuf), 0);
		if (!ok) {
			badfaxlines++;
			badrun++;
			/* regenerate line from previous good line */
			_TIFFmemcpy(rowbuf, refbuf, sizeof (rowbuf));
		} else {
			if (badrun > badfaxrun)
				badfaxrun = badrun;
			badrun = 0;
			_TIFFmemcpy(refbuf, rowbuf, sizeof (rowbuf));
		}
		tifin->tif_row++;

		if (TIFFWriteScanline(tifout, rowbuf, row, 0) < 0) {
			fprintf(stderr, "%s: Write error at row %ld.\n",
			    tifout->tif_name, (long) row);
			break;
		}
		row++;
		if (stretch) {
			if (TIFFWriteScanline(tifout, rowbuf, row, 0) < 0) {
				fprintf(stderr, "%s: Write error at row %ld.\n",
				    tifout->tif_name, (long) row);
				break;
			}
			row++;
		}
	}
	if (badrun > badfaxrun)
		badfaxrun = badrun;
	_TIFFfree(tifin->tif_rawdata);
	return (row);
}
static int ReadGIFGlobal (MG_RWops *area, GIFSCREEN* GifScreen)
{
    unsigned char buf[9];
    unsigned char version[4];

    if (!ReadOK (area, buf, 6))
        return -1;                /* not gif image*/

    if (strncmp((char *) buf, "GIF", 3) != 0)
        return -1;

    strncpy ((char*)version, (char *) buf + 3, 3);
    version [3] = '\0';

    if (strcmp ((const char*)version, "87a") != 0 && strcmp ((const char*)version, "89a") != 0) {
        _MG_PRINTF ("EX_CTRL>GIF89a: GIF version number not 87a or 89a.\n");
        return -1;                /* image loading error*/
    }

    GifScreen->Background = -1;
    GifScreen->transparent = -1;
    GifScreen->delayTime = -1;
    GifScreen->inputFlag = -1;
    GifScreen->disposal = 0;

    if (!ReadOK (area, buf, 7)) {
        _MG_PRINTF ("EX_CTRL>GIF89a: bad screen descriptor\n");
        return -1;                /* image loading error*/
    }
    GifScreen->Width = LM_to_uint (buf[0], buf[1]);
    GifScreen->Height = LM_to_uint (buf[2], buf[3]);
    GifScreen->BitPixel = 2 << (buf[4] & 0x07);
    GifScreen->ColorResolution = (((buf[4] & 0x70) >> 3) + 1);
    GifScreen->Background = buf[5];
    GifScreen->AspectRatio = buf[6];

    if (BitSet(buf[4], LOCALCOLORMAP)) {        /* Global Colormap */
        _MG_PRINTF ("EX_CTRL>GIF89a: have global colormap: %d\n", 
                    GifScreen->Background);
        if (ReadColorMap (area, GifScreen->BitPixel, GifScreen->ColorMap)) {
            _MG_PRINTF ("EX_CTRL>GIF89a: bad global colormap\n");
            return -1;                /* image loading error*/
        }
    }

    return 0;
}
예제 #11
0
static int GetDataBlock( RageFile &f, unsigned char *buf )
{
	unsigned char count;

	if( !ReadOK(f, &count, 1) )
	{
		/* pm_message("error in getting DataBlock size" ); */
		return -1;
	}

	if( count != 0 && !ReadOK(f, buf, count) )
	{
		/* pm_message("error in reading DataBlock" ); */
		return -1;
	}
	return count;
}
예제 #12
0
static int
GetDataBlock(SDL_RWops *src, unsigned char *buf)
{
    unsigned char count;

    if (!ReadOK(src, &count, 1)) {
		dbgout("error in getting DataBlock size\n");
		return -1;
    }
    ZeroDataBlock = count == 0;

    if ((count != 0) && (!ReadOK(src, buf, count))) {
		dbgout("error in reading DataBlock\n");
		return -1;
    }
    return count;
}
예제 #13
0
static int GetDataBlock(FILE *fd, unsigned char  *buf){
	unsigned char	count;

	if (! ReadOK(fd,&count,1)) {
		fprintf(stderr,"error in getting DataBlock size\n" );
		return -1;
	}

	ZeroDataBlock = count == 0;

	if ((count != 0) && (! ReadOK(fd, buf, count))) {
		fprintf(stderr,"error in reading DataBlock\n" );
		return -1;
	}

	return count;
}
예제 #14
0
파일: rdppm.c 프로젝트: John-He-928/krkrz
get_raw_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
/* This version is for reading raw-byte-format files with maxval = MAXJSAMPLE.
 * In this case we just read right into the JSAMPLE buffer!
 * Note that same code works for PPM and PGM files.
 */
{
  ppm_source_ptr source = (ppm_source_ptr) sinfo;

  if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
    ERREXIT(cinfo, JERR_INPUT_EOF);
  return 1;
}
예제 #15
0
Node *Next(List *pList, Node *pNode)
{
	if (!ReadOK(&pList->lock))
	{
		FatalError("Next - Not allowed to read!");
		return NULL;
	}

	if (pNode == NULL)
		return pList->pHead;
	else
	    return pNode->pNext;
}
예제 #16
0
static gint
GetDataBlock (FILE   *fd,
              guchar *buf)
{
  guchar count;

  if (! ReadOK (fd, &count, 1))
    {
      g_message ("Error in getting DataBlock size");
      return -1;
    }

  ZeroDataBlock = count == 0;

  if ((count != 0) && (! ReadOK (fd, buf, count)))
    {
      g_message ("Error in reading DataBlock");
      return -1;
    }

  return count;
}
예제 #17
0
static int ReadColorMap(FILE *fd, int number, RGBQUAD *buffer){
	int i;
	unsigned char rgb[3];
	char *str;
	for (i = 0; i < number; ++i, buffer++) {
		if (! ReadOK(fd, rgb, sizeof(rgb))){
			strcpy(str,"bad colormap");
			pm_error(str);
		}
		buffer->rgbRed= rgb[0];
		buffer->rgbGreen= rgb[1];
		buffer->rgbBlue= rgb[2];
		buffer->rgbReserved= 0;
	}
	return 0;
}
static int ReadColorMap (MG_RWops *area, int number, RGB* ColorMap)
{
    int i;
    unsigned char rgb[3];

    for (i = 0; i < number; ++i) {
        if (!ReadOK (area, rgb, sizeof(rgb))) {
            return -1;
        }

        ColorMap [i].r = rgb[0];
        ColorMap [i].g = rgb[1];
        ColorMap [i].b = rgb[2];
    }

    return 0;
}
예제 #19
0
파일: rdppm.c 프로젝트: msabhijith/dgate
get_corr_row16 (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
/* This version is for reading raw-word-format maxval = MAXJSAMPLE, any endian */
{
  ppm_source_ptr source = (ppm_source_ptr) sinfo;
  register JSAMPROW16 ptr;
  register U_CHAR * bufferptr;
  JDIMENSION col;

  if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
    ERREXIT(cinfo, JERR_INPUT_EOF);
  ptr = (JSAMPROW16)source->pub.buffer[0];
  bufferptr = source->iobuffer;
  for (col = cinfo->image_width; col > 0; col--) {
    *ptr = UCH(*bufferptr++) << 8;
    *ptr++  |= UCH(*bufferptr++);
  }
  return 1;
}
예제 #20
0
파일: rdppm.c 프로젝트: msabhijith/dgate
get_scaled_gray_row16 (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
/* This version is for reading raw-byte-format PGM files with any maxval */
{
  ppm_source_ptr source = (ppm_source_ptr) sinfo;
  register JSAMPROW16 ptr;
  register U_CHAR * bufferptr;
  register JSAMPLE16 *rescale = (JSAMPROW16)source->rescale;
  JDIMENSION col;

  if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
    ERREXIT(cinfo, JERR_INPUT_EOF);
  ptr = (JSAMPROW16)source->pub.buffer[0];
  bufferptr = source->iobuffer;
  for (col = cinfo->image_width; col > 0; col--) {
    *ptr++ = rescale[UCH(*bufferptr++)];
  }
  return 1;
}
예제 #21
0
/*
 * Fetch a contiguous directory item.
 */
static tsize_t
TIFFFetchData(TIFF* tif, TIFFDirEntry* dir, char* cp)
{
	int w = tiffDataWidth[dir->tdir_type];
	tsize_t cc = dir->tdir_count * w;

	if (!isMapped(tif)) {
		if (!SeekOK(tif, dir->tdir_offset))
			goto bad;
		if (!ReadOK(tif, cp, cc))
			goto bad;
	} else {
		if (dir->tdir_offset + cc > tif->tif_size)
			goto bad;
		_TIFFmemcpy(cp, tif->tif_base + dir->tdir_offset, cc);
	}
	if (tif->tif_flags & TIFF_SWAB) {
		switch (dir->tdir_type) {
		case TIFF_SHORT:
		case TIFF_SSHORT:
			TIFFSwabArrayOfShort((uint16*) cp, dir->tdir_count);
			break;
		case TIFF_LONG:
		case TIFF_SLONG:
		case TIFF_FLOAT:
			TIFFSwabArrayOfLong((uint32*) cp, dir->tdir_count);
			break;
		case TIFF_RATIONAL:
		case TIFF_SRATIONAL:
			TIFFSwabArrayOfLong((uint32*) cp, 2*dir->tdir_count);
			break;
		case TIFF_DOUBLE:
			TIFFSwabArrayOfDouble((double*) cp, dir->tdir_count);
			break;
		}
	}
	return (cc);
bad:
	TIFFError(tif->tif_name, "Error fetching data for field \"%s\"",
	    _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
	return ((tsize_t) 0);
}
예제 #22
0
static void ReadImage(FILE *fd,unsigned char *data,int len, int height, RGBQUAD *cmap, int bpp, int interlace)
{
   unsigned char c;
   int v;
   int xpos = 0, ypos=0, pass=0;
   unsigned char *scanline;
   char *str;
   
   if (!ReadOK(fd,&c,1)){
       strcpy(str,"EOF / read error on image data");
       pm_error(str);
   }
   
   if (LWZReadByte(fd,TRUE,c)<0){
       strcpy(str,"error reading image");
       pm_error(str);
   }
   
   if((scanline = (unsigned char*)malloc(len)) == NULL){
       strcpy(str,"couldn't allocate space for image");
       pm_error(str);
   }
   
   while(ypos < height && (v = LWZReadByte(fd,FALSE,c)) >= 0){
       switch(bitCount){
	       case 1:
		       if (v){
			       scanline[xpos>>3] |= 128 >> (xpos&7);
			   }
			   else{
			       scanline[xpos>>3] &= 0xff7f >> (xpos&7);
			   }
			   break;
		   case 4:
		       if (xpos&1){
			       scanline[xpos>>1] |= v&15;
			   }
			   else{
예제 #23
0
static tsize_t
TIFFReadRawTile1(TIFF* tif,
    ttile_t tile, tdata_t buf, tsize_t size, const char* module)
{
	TIFFDirectory *td = &tif->tif_dir;

	if (!isMapped(tif)) {
		if (!SeekOK(tif, td->td_stripoffset[tile])) {
			TIFFError(module,
			    "%s: Seek error at row %ld, col %ld, tile %ld",
			    tif->tif_name,
			    (long) tif->tif_row,
			    (long) tif->tif_col,
			    (long) tile);
			return ((tsize_t) -1);
		}
		if (!ReadOK(tif, buf, size)) {
			TIFFError(module, "%s: Read error at row %ld, col %ld",
			    tif->tif_name,
			    (long) tif->tif_row,
			    (long) tif->tif_col);
			return ((tsize_t) -1);
		}
	} else {
		if (td->td_stripoffset[tile] + size > tif->tif_size) {
			TIFFError(module,
			    "%s: Seek error at row %ld, col %ld, tile %ld",
			    tif->tif_name,
			    (long) tif->tif_row,
			    (long) tif->tif_col,
			    (long) tile);
			return ((tsize_t) -1);
		}
		memcpy(buf, tif->tif_base + td->td_stripoffset[tile], size);
	}
	return (size);
}
예제 #24
0
/*
 * Link the current directory into the
 * directory chain for the file.
 */
static int
TIFFLinkDirectory(TIFF* tif)
{
	static const char module[] = "TIFFLinkDirectory";
	toff_t nextdir;
	toff_t diroff, off;

	tif->tif_diroff = (TIFFSeekFile(tif, (toff_t) 0, SEEK_END)+1) &~ 1;
	diroff = tif->tif_diroff;
	if (tif->tif_flags & TIFF_SWAB)
		TIFFSwabLong(&diroff);
#if SUBIFD_SUPPORT
	if (tif->tif_flags & TIFF_INSUBIFD) {
		(void) TIFFSeekFile(tif, tif->tif_subifdoff, SEEK_SET);
		if (!WriteOK(tif, &diroff, sizeof (diroff))) {
			TIFFError(module,
			    "%s: Error writing SubIFD directory link",
			    tif->tif_name);
			return (0);
		}
		/*
		 * Advance to the next SubIFD or, if this is
		 * the last one configured, revert back to the
		 * normal directory linkage.
		 */
		if (--tif->tif_nsubifd)
			tif->tif_subifdoff += sizeof (diroff);
		else
			tif->tif_flags &= ~TIFF_INSUBIFD;
		return (1);
	}
#endif
	if (tif->tif_header.tiff_diroff == 0) {
		/*
		 * First directory, overwrite offset in header.
		 */
		tif->tif_header.tiff_diroff = tif->tif_diroff;
#define	HDROFF(f)	((toff_t) &(((TIFFHeader*) 0)->f))
		(void) TIFFSeekFile(tif, HDROFF(tiff_diroff), SEEK_SET);
		if (!WriteOK(tif, &diroff, sizeof (diroff))) {
			TIFFError(tif->tif_name, "Error writing TIFF header");
			return (0);
		}
		return (1);
	}
	/*
	 * Not the first directory, search to the last and append.
	 */
	nextdir = tif->tif_header.tiff_diroff;
	do {
		uint16 dircount;

		if (!SeekOK(tif, nextdir) ||
		    !ReadOK(tif, &dircount, sizeof (dircount))) {
			TIFFError(module, "Error fetching directory count");
			return (0);
		}
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabShort(&dircount);
		(void) TIFFSeekFile(tif,
		    dircount * sizeof (TIFFDirEntry), SEEK_CUR);
		if (!ReadOK(tif, &nextdir, sizeof (nextdir))) {
			TIFFError(module, "Error fetching directory link");
			return (0);
		}
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabLong(&nextdir);
	} while (nextdir != 0);
        off = TIFFSeekFile(tif, 0, SEEK_CUR); /* get current offset */
        (void) TIFFSeekFile(tif, off - (toff_t)sizeof(nextdir), SEEK_SET);
	if (!WriteOK(tif, &diroff, sizeof (diroff))) {
		TIFFError(module, "Error writing directory link");
		return (0);
	}
	return (1);
}
예제 #25
0
int 
TIFFRewriteDirectory( TIFF *tif )
{
    static const char module[] = "TIFFRewriteDirectory";

    /* We don't need to do anything special if it hasn't been written. */
    if( tif->tif_diroff == 0 )
        return TIFFWriteDirectory( tif );

    /*
    ** Find and zero the pointer to this directory, so that TIFFLinkDirectory
    ** will cause it to be added after this directories current pre-link.
    */
    
    /* Is it the first directory in the file? */
    if (tif->tif_header.tiff_diroff == tif->tif_diroff) 
    {
        tif->tif_header.tiff_diroff = 0;
        tif->tif_diroff = 0;

#if defined(__hpux) && defined(__LP64__)
#define HDROFF(f) ((toff_t)(unsigned long) &(((TIFFHeader*) 0)->f))
#else
#define	HDROFF(f)	((toff_t) &(((TIFFHeader*) 0)->f))
#endif
        TIFFSeekFile(tif, HDROFF(tiff_diroff), SEEK_SET);
        if (!WriteOK(tif, &(tif->tif_header.tiff_diroff), 
                     sizeof (tif->tif_diroff))) 
        {
            TIFFError(tif->tif_name, "Error updating TIFF header");
            return (0);
        }
    }
    else
    {
        toff_t  nextdir, off;

	nextdir = tif->tif_header.tiff_diroff;
	do {
		uint16 dircount;

		if (!SeekOK(tif, nextdir) ||
		    !ReadOK(tif, &dircount, sizeof (dircount))) {
			TIFFError(module, "Error fetching directory count");
			return (0);
		}
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabShort(&dircount);
		(void) TIFFSeekFile(tif,
		    dircount * sizeof (TIFFDirEntry), SEEK_CUR);
		if (!ReadOK(tif, &nextdir, sizeof (nextdir))) {
			TIFFError(module, "Error fetching directory link");
			return (0);
		}
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabLong(&nextdir);
	} while (nextdir != tif->tif_diroff && nextdir != 0);
        off = TIFFSeekFile(tif, 0, SEEK_CUR); /* get current offset */
        (void) TIFFSeekFile(tif, off - (toff_t)sizeof(nextdir), SEEK_SET);
        tif->tif_diroff = 0;
	if (!WriteOK(tif, &(tif->tif_diroff), sizeof (nextdir))) {
		TIFFError(module, "Error writing directory link");
		return (0);
	}
    }

    /*
    ** Now use TIFFWriteDirectory() normally.
    */

    return TIFFWriteDirectory( tif );
}
예제 #26
0
TIFF*
TIFFClientOpen(
    const char* name, const char* mode,
    thandle_t clientdata,
    TIFFReadWriteProc readproc,
    TIFFReadWriteProc writeproc,
    TIFFSeekProc seekproc,
    TIFFCloseProc closeproc,
    TIFFSizeProc sizeproc,
    TIFFMapFileProc mapproc,
    TIFFUnmapFileProc unmapproc
)
{
    static const char module[] = "TIFFClientOpen";
    TIFF *tif;
    int m;
    const char* cp;

    /* The following are configuration checks. They should be redundant, but should not
     * compile to any actual code in an optimised release build anyway. If any of them
     * fail, (makefile-based or other) configuration is not correct */
    assert(sizeof(uint8)==1);
    assert(sizeof(int8)==1);
    assert(sizeof(uint16)==2);
    assert(sizeof(int16)==2);
    assert(sizeof(uint32)==4);
    assert(sizeof(int32)==4);
    assert(sizeof(uint64)==8);
    assert(sizeof(int64)==8);
    assert(sizeof(tmsize_t)==sizeof(void*));
    {
        union{
            uint8 a8[2];
            uint16 a16;
        } n;
        n.a8[0]=1;
        n.a8[1]=0;
        #ifdef WORDS_BIGENDIAN
        assert(n.a16==256);
        #else
        assert(n.a16==1);
        #endif
    }

    m = _TIFFgetMode(mode, module);
    if (m == -1)
        goto bad2;
    tif = (TIFF *)_TIFFmalloc((tmsize_t)(sizeof (TIFF) + strlen(name) + 1));
    if (tif == NULL) {
        TIFFErrorExt(clientdata, module, "%s: Out of memory (TIFF structure)", name);
        goto bad2;
    }
    _TIFFmemset(tif, 0, sizeof (*tif));
    tif->tif_name = (char *)tif + sizeof (TIFF);
    strcpy(tif->tif_name, name);
    tif->tif_mode = m &~ (O_CREAT|O_TRUNC);
    tif->tif_curdir = (uint16) -1;		/* non-existent directory */
    tif->tif_curoff = 0;
    tif->tif_curstrip = (uint32) -1;	/* invalid strip */
    tif->tif_row = (uint32) -1;		/* read/write pre-increment */
    tif->tif_clientdata = clientdata;
    if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc) {
        TIFFErrorExt(clientdata, module,
            "One of the client procedures is NULL pointer.");
        goto bad2;
    }
    tif->tif_readproc = readproc;
    tif->tif_writeproc = writeproc;
    tif->tif_seekproc = seekproc;
    tif->tif_closeproc = closeproc;
    tif->tif_sizeproc = sizeproc;
    if (mapproc)
        tif->tif_mapproc = mapproc;
    else
        tif->tif_mapproc = _tiffDummyMapProc;
    if (unmapproc)
        tif->tif_unmapproc = unmapproc;
    else
        tif->tif_unmapproc = _tiffDummyUnmapProc;
    _TIFFSetDefaultCompressionState(tif);    /* setup default state */
    /*
     * Default is to return data MSB2LSB and enable the
     * use of memory-mapped files and strip chopping when
     * a file is opened read-only.
     */
    tif->tif_flags = FILLORDER_MSB2LSB;
    if (m == O_RDONLY )
        tif->tif_flags |= TIFF_MAPPED;

    #ifdef STRIPCHOP_DEFAULT
    if (m == O_RDONLY || m == O_RDWR)
        tif->tif_flags |= STRIPCHOP_DEFAULT;
    #endif

    /*
     * Process library-specific flags in the open mode string.
     * The following flags may be used to control intrinsic library
     * behaviour that may or may not be desirable (usually for
     * compatibility with some application that claims to support
     * TIFF but only supports some braindead idea of what the
     * vendor thinks TIFF is):
     *
     * 'l' use little-endian byte order for creating a file
     * 'b' use big-endian byte order for creating a file
     * 'L' read/write information using LSB2MSB bit order
     * 'B' read/write information using MSB2LSB bit order
     * 'H' read/write information using host bit order
     * 'M' enable use of memory-mapped files when supported
     * 'm' disable use of memory-mapped files
     * 'C' enable strip chopping support when reading
     * 'c' disable strip chopping support
     * 'h' read TIFF header only, do not load the first IFD
     * '4' ClassicTIFF for creating a file (default)
     * '8' BigTIFF for creating a file
     *
     * The use of the 'l' and 'b' flags is strongly discouraged.
     * These flags are provided solely because numerous vendors,
     * typically on the PC, do not correctly support TIFF; they
     * only support the Intel little-endian byte order.  This
     * support is not configured by default because it supports
     * the violation of the TIFF spec that says that readers *MUST*
     * support both byte orders.  It is strongly recommended that
     * you not use this feature except to deal with busted apps
     * that write invalid TIFF.  And even in those cases you should
     * bang on the vendors to fix their software.
     *
     * The 'L', 'B', and 'H' flags are intended for applications
     * that can optimize operations on data by using a particular
     * bit order.  By default the library returns data in MSB2LSB
     * bit order for compatibiltiy with older versions of this
     * library.  Returning data in the bit order of the native cpu
     * makes the most sense but also requires applications to check
     * the value of the FillOrder tag; something they probably do
     * not do right now.
     *
     * The 'M' and 'm' flags are provided because some virtual memory
     * systems exhibit poor behaviour when large images are mapped.
     * These options permit clients to control the use of memory-mapped
     * files on a per-file basis.
     *
     * The 'C' and 'c' flags are provided because the library support
     * for chopping up large strips into multiple smaller strips is not
     * application-transparent and as such can cause problems.  The 'c'
     * option permits applications that only want to look at the tags,
     * for example, to get the unadulterated TIFF tag information.
     */
    for (cp = mode; *cp; cp++)
        switch (*cp) {
            case 'b':
                #ifndef WORDS_BIGENDIAN
                if (m&O_CREAT)
                    tif->tif_flags |= TIFF_SWAB;
                #endif
                break;
            case 'l':
                #ifdef WORDS_BIGENDIAN
                if ((m&O_CREAT))
                    tif->tif_flags |= TIFF_SWAB;
                #endif
                break;
            case 'B':
                tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
                    FILLORDER_MSB2LSB;
                break;
            case 'L':
                tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
                    FILLORDER_LSB2MSB;
                break;
            case 'H':
                tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
                    HOST_FILLORDER;
                break;
            case 'M':
                if (m == O_RDONLY)
                    tif->tif_flags |= TIFF_MAPPED;
                break;
            case 'm':
                if (m == O_RDONLY)
                    tif->tif_flags &= ~TIFF_MAPPED;
                break;
            case 'C':
                if (m == O_RDONLY)
                    tif->tif_flags |= TIFF_STRIPCHOP;
                break;
            case 'c':
                if (m == O_RDONLY)
                    tif->tif_flags &= ~TIFF_STRIPCHOP;
                break;
            case 'h':
                tif->tif_flags |= TIFF_HEADERONLY;
                break;
            case '8':
                if (m&O_CREAT)
                    tif->tif_flags |= TIFF_BIGTIFF;
                break;
        }
    /*
     * Read in TIFF header.
     */
    if ((m & O_TRUNC) ||
        !ReadOK(tif, &tif->tif_header, sizeof (TIFFHeaderClassic))) {
        if (tif->tif_mode == O_RDONLY) {
            TIFFErrorExt(tif->tif_clientdata, name,
                "Cannot read TIFF header");
            goto bad;
        }
        /*
         * Setup header and write.
         */
        #ifdef WORDS_BIGENDIAN
        tif->tif_header.common.tiff_magic = tif->tif_flags & TIFF_SWAB
            ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN;
        #else
        tif->tif_header.common.tiff_magic = tif->tif_flags & TIFF_SWAB
            ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN;
        #endif
        if (!(tif->tif_flags&TIFF_BIGTIFF))
        {
            tif->tif_header.common.tiff_version = TIFF_VERSION_CLASSIC;
            tif->tif_header.classic.tiff_diroff = 0;
            if (tif->tif_flags & TIFF_SWAB)
                TIFFSwabShort(&tif->tif_header.common.tiff_version);
            tif->tif_header_size = sizeof(TIFFHeaderClassic);
        }
        else
        {
            tif->tif_header.common.tiff_version = TIFF_VERSION_BIG;
            tif->tif_header.big.tiff_offsetsize = 8;
            tif->tif_header.big.tiff_unused = 0;
            tif->tif_header.big.tiff_diroff = 0;
            if (tif->tif_flags & TIFF_SWAB)
            {
                TIFFSwabShort(&tif->tif_header.common.tiff_version);
                TIFFSwabShort(&tif->tif_header.big.tiff_offsetsize);
            }
            tif->tif_header_size = sizeof (TIFFHeaderBig);
        }
        /*
         * The doc for "fopen" for some STD_C_LIBs says that if you
         * open a file for modify ("+"), then you must fseek (or
         * fflush?) between any freads and fwrites.  This is not
         * necessary on most systems, but has been shown to be needed
         * on Solaris.
         */
        TIFFSeekFile( tif, 0, SEEK_SET );
        if (!WriteOK(tif, &tif->tif_header, (tmsize_t)(tif->tif_header_size))) {
            TIFFErrorExt(tif->tif_clientdata, name,
                "Error writing TIFF header");
            goto bad;
        }
        /*
         * Setup the byte order handling.
         */
        if (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN) {
            #ifndef WORDS_BIGENDIAN
            tif->tif_flags |= TIFF_SWAB;
            #endif
        } else {
            #ifdef WORDS_BIGENDIAN
            tif->tif_flags |= TIFF_SWAB;
            #endif
        }
        /*
         * Setup default directory.
         */
        if (!TIFFDefaultDirectory(tif))
            goto bad;
        tif->tif_diroff = 0;
        tif->tif_dirlist = NULL;
        tif->tif_dirlistsize = 0;
        tif->tif_dirnumber = 0;
        return (tif);
    }
    /*
     * Setup the byte order handling.
     */
    if (tif->tif_header.common.tiff_magic != TIFF_BIGENDIAN &&
        tif->tif_header.common.tiff_magic != TIFF_LITTLEENDIAN
        #if MDI_SUPPORT
        &&
        #if HOST_BIGENDIAN
        tif->tif_header.common.tiff_magic != MDI_BIGENDIAN
        #else
        tif->tif_header.common.tiff_magic != MDI_LITTLEENDIAN
        #endif
        ) {
        TIFFErrorExt(tif->tif_clientdata, name,
            "Not a TIFF or MDI file, bad magic number %d (0x%x)",
        #else
        ) {
        TIFFErrorExt(tif->tif_clientdata, name,
            "Not a TIFF file, bad magic number %d (0x%x)",
        #endif
            tif->tif_header.common.tiff_magic,
            tif->tif_header.common.tiff_magic);
        goto bad;
    }
    if (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN) {
        #ifndef WORDS_BIGENDIAN
        tif->tif_flags |= TIFF_SWAB;
        #endif
    } else {
        #ifdef WORDS_BIGENDIAN
        tif->tif_flags |= TIFF_SWAB;
        #endif
    }
    if (tif->tif_flags & TIFF_SWAB)
        TIFFSwabShort(&tif->tif_header.common.tiff_version);
    if ((tif->tif_header.common.tiff_version != TIFF_VERSION_CLASSIC)&&
        (tif->tif_header.common.tiff_version != TIFF_VERSION_BIG)) {
        TIFFErrorExt(tif->tif_clientdata, name,
            "Not a TIFF file, bad version number %d (0x%x)",
            tif->tif_header.common.tiff_version,
            tif->tif_header.common.tiff_version);
        goto bad;
    }
    if (tif->tif_header.common.tiff_version == TIFF_VERSION_CLASSIC)
    {
        if (tif->tif_flags & TIFF_SWAB)
            TIFFSwabLong(&tif->tif_header.classic.tiff_diroff);
        tif->tif_header_size = sizeof(TIFFHeaderClassic);
    }
    else
    {
        if (!ReadOK(tif, ((uint8*)(&tif->tif_header) + sizeof(TIFFHeaderClassic)), (sizeof(TIFFHeaderBig)-sizeof(TIFFHeaderClassic))))
        {
            TIFFErrorExt(tif->tif_clientdata, name,
                "Cannot read TIFF header");
            goto bad;
        }
        if (tif->tif_flags & TIFF_SWAB)
        {
            TIFFSwabShort(&tif->tif_header.big.tiff_offsetsize);
            TIFFSwabLong8(&tif->tif_header.big.tiff_diroff);
        }
        if (tif->tif_header.big.tiff_offsetsize != 8)
        {
            TIFFErrorExt(tif->tif_clientdata, name,
                "Not a TIFF file, bad BigTIFF offsetsize %d (0x%x)",
                tif->tif_header.big.tiff_offsetsize,
                tif->tif_header.big.tiff_offsetsize);
            goto bad;
        }
        if (tif->tif_header.big.tiff_unused != 0)
        {
            TIFFErrorExt(tif->tif_clientdata, name,
                "Not a TIFF file, bad BigTIFF unused %d (0x%x)",
                tif->tif_header.big.tiff_unused,
                tif->tif_header.big.tiff_unused);
            goto bad;
        }
        tif->tif_header_size = sizeof(TIFFHeaderBig);
        tif->tif_flags |= TIFF_BIGTIFF;
    }
    tif->tif_flags |= TIFF_MYBUFFER;
    tif->tif_rawcp = tif->tif_rawdata = 0;
    tif->tif_rawdatasize = 0;
        tif->tif_rawdataoff = 0;
        tif->tif_rawdataloaded = 0;

    switch (mode[0]) {
        case 'r':
            if (!(tif->tif_flags&TIFF_BIGTIFF))
                tif->tif_nextdiroff = tif->tif_header.classic.tiff_diroff;
            else
                tif->tif_nextdiroff = tif->tif_header.big.tiff_diroff;
            /*
             * Try to use a memory-mapped file if the client
             * has not explicitly suppressed usage with the
             * 'm' flag in the open mode (see above).
             */
            if (tif->tif_flags & TIFF_MAPPED)
            {
                toff_t n;
                if (TIFFMapFileContents(tif,(void**)(&tif->tif_base),&n))
                {
                    tif->tif_size=(tmsize_t)n;
                    assert((toff_t)tif->tif_size==n);
                }
                else
                    tif->tif_flags &= ~TIFF_MAPPED;
            }
            /*
             * Sometimes we do not want to read the first directory (for example,
             * it may be broken) and want to proceed to other directories. I this
             * case we use the TIFF_HEADERONLY flag to open file and return
             * immediately after reading TIFF header.
             */
            if (tif->tif_flags & TIFF_HEADERONLY)
                return (tif);

            /*
             * Setup initial directory.
             */
            if (TIFFReadDirectory(tif)) {
                tif->tif_rawcc = (tmsize_t)-1;
                tif->tif_flags |= TIFF_BUFFERSETUP;
                return (tif);
            }
            break;
        case 'a':
            /*
             * New directories are automatically append
             * to the end of the directory chain when they
             * are written out (see TIFFWriteDirectory).
             */
            if (!TIFFDefaultDirectory(tif))
                goto bad;
            return (tif);
    }
bad:
    tif->tif_mode = O_RDONLY;	/* XXX avoid flush */
        TIFFCleanup(tif);
bad2:
    return ((TIFF*)0);
}
예제 #27
0
static SDL_Surface*
ReadImage(SDL_RWops * src, int len, int height, int cmapSize,
	  unsigned char cmap[3][MAXCOLORMAPSIZE],
	  int gray, int interlace, int ignore)
{
    SDL_Surface*image;
    unsigned char c;
    int i, v;
    int xpos = 0, ypos = 0, pass = 0;

    /*
    **	Initialize the compression routines
     */
    if (!ReadOK(src, &c, 1)) {
		IMG_SetError("EOF / read error on image data");
		return NULL;
    }
    if (LWZReadByte(src, TRUE, c) < 0) {
		IMG_SetError("error reading image");
		return NULL;
    }
    /*
    **	If this is an "uninteresting picture" ignore it.
     */
    if (ignore) {
		while (LWZReadByte(src, FALSE, c) >= 0)
		    ;
		return NULL;
    }
    image = ImageNewCmap(len, height, cmapSize);

    for (i = 0; i < cmapSize; i++)
		ImageSetCmap(image, i, cmap[CM_RED][i],
				cmap[CM_GREEN][i], cmap[CM_BLUE][i]);

    while ((v = LWZReadByte(src, FALSE, c)) >= 0) {

	((Uint8 *)image->pixels)[xpos + ypos * image->pitch] = v;

	++xpos;
	if (xpos == len) {
	    xpos = 0;
	    if (interlace) {
			switch (pass) {
				case 0:
				case 1:
				    ypos += 8;
				    break;
				case 2:
				    ypos += 4;
				    break;
				case 3:
				    ypos += 2;
				    break;
			}

			if (ypos >= height) {
			    ++pass;
			    switch (pass) {
				    case 1:
						ypos = 4;
						break;
				    case 2:
						ypos = 2;
						break;
				    case 3:
						ypos = 1;
						break;
				    default:
						goto fini;
			    }
			}
	    } else {
			++ypos;
	    }
	}
	if (ypos >= height)
	    break;
    }

  fini:

    return image;
}
예제 #28
0
/* TODO: (Chase) dump frames into frameset instead of combining into one frame */
int IMG_LoadGIF_RW(SDL_RWops *src, IMG_File* dst)
{
    int start;
    unsigned char buf[16];
    unsigned char c;
    unsigned char localColorMap[3][MAXCOLORMAPSIZE];
    int grayScale;
    int useGlobalColormap;
    int bitPixel;
    int imageCount = 0;
    char version[4];
    int imageNumber = 1; /*<-- I believe this is what we want to control in order to change what frame to grab*/
    int successCount = 0;
	int w = 0;
	int i = 0;
	Uint32 color = 0; 
	SDL_Surface*image = NULL;
	SDL_Surface*nextImage = NULL;
	GifFrame frame;
	GifFrame* frames;
	
    if ( src == NULL ) {
		return 0;
    }
    start = SDL_RWtell(src);

    if (!ReadOK(src, buf, 6)) {
		IMG_SetError("error reading magic number");
        goto done;
    }
    if (strncmp((char *) buf, "GIF", 3) != 0) {
		IMG_SetError("not a GIF file");
        goto done;
    }
    strncpy(version, (char *) buf + 3, 3);
    version[3] = '\0';

    if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0)) {
		IMG_SetError("bad version number, not '87a' or '89a'");
        goto done;
    }
    frame.transparent = -1;
    frame.delayMs = -1;
    frame.inputFlag = -1;
    frame.disposal = 0;

    if (!ReadOK(src, buf, 7)) {
		IMG_SetError("failed to read screen descriptor");
        goto done;
    }
    GifScreen.Width = LM_to_uint(buf[0], buf[1]);
    GifScreen.Height = LM_to_uint(buf[2], buf[3]);
    GifScreen.BitPixel = 2 << (buf[4] & 0x07);
    GifScreen.ColorResolution = (((buf[4] & 0x70) >> 3) + 1);
    GifScreen.Background = buf[5];
    GifScreen.AspectRatio = buf[6];

    if (BitSet(buf[4], LOCALCOLORMAP)) {	/* Global Colormap */
		if (ReadColorMap(src, GifScreen.BitPixel, GifScreen.ColorMap,
			&GifScreen.GrayScale)) {
			IMG_SetError("error reading global colormap");
	        goto done;
		}
    }
	    
    dbgout("GLOBAL BG COLOR: Index:%i RGB:%i,%i,%i\n", GifScreen.Background,
			GifScreen.ColorMap[CM_RED][GifScreen.Background],
			GifScreen.ColorMap[CM_GREEN][GifScreen.Background], 
			GifScreen.ColorMap[CM_BLUE][GifScreen.Background]);
	
	
	frames = (GifFrame*)malloc(sizeof(GifFrame));
	if (!frames) {
		IMG_SetError("Malloc Failed");
		goto done;
	}
	
    do { /* This loop goes through and reads every image and sends its data to ReadImage, if its the one we want (index 1) it'll output SDL_Surface*/
		/*
			What this SHOULD do...
			METHOD 1 (Lazy):
				Read every image, output an SDL_Surface into a vector
				After loop, count vector images, make a new image which has a w equal to the vector.size() * image width
				Render each image from the vector onto the new image, each one with an x offset of image width * index
				Free all surfaces in the vector, return the new combined one.
			METHOD 2 (hardcore):
				Read every image, count the number of images we get.
				Create a surface with a w equal to count * width
				Go back and read every images data, writing their pixels, leftmost to images x * index
			GENERAL PROBLEM:
				We have no delay info. We'd have to manually set the frame delay... However, this isn't a problem. =3
			Looks like we can have local layer color maps.. of course being able to do this in imageready is a whole other issue.
				But as far as we know.. maybe?
		*/
		
		if (!ReadOK(src, &c, 1)) {
		    IMG_SetError("EOF / read error on image data");
	        goto done;
		} else
			dbgout("%c", c);
			
		if (c == ';') {		/* GIF terminator -0x3b */
		    /*if (imageCount < imageNumber) {
				IMG_SetError("only %d image%s found in file",
					imageCount, imageCount > 1 ? "s" : "");
	            goto done;
		    }*/
		    break;
		}
		if (c == '!') {		/* Extension 0x21 */
		    if (!ReadOK(src, &c, 1)) {
				IMG_SetError("EOF / read error on extention function code");
	            goto done;
		    }
		    DoExtension(&frame, src, c);
		    continue;
		}
		if (c != ',') {		/* Image seperator - 0x2c */
		    continue;
		}
		++imageCount;

		if (!ReadOK(src, buf, 9)) {
		    IMG_SetError("couldn't read left/top/width/height");
			goto done;
		}
/*
Offset   Length   Contents
  0      1 byte   Image Separator (0x2c)
  1      2 bytes  Image Left Position
  3      2 bytes  Image Top Position
  5      2 bytes  Image Width
  7      2 bytes  Image Height
  8      1 byte   bit 0:    Local Color Table Flag (LCTF)
                  bit 1:    Interlace Flag
                  bit 2:    Sort Flag
                  bit 2..3: Reserved
                  bit 4..7: Size of Local Color Table: 2^(1+n)
         ? bytes  Local Color Table(0..255 x 3 bytes) if LCTF is one
         1 byte   LZW Minimum Code Size
[ // Blocks
         1 byte   Block Size (s)
œSx    (s)bytes  Image Data
]*
         1 byte   Block Terminator(0x00)
*/

		useGlobalColormap = !BitSet(buf[8], LOCALCOLORMAP);

		frame.x = LM_to_uint(buf[0], buf[1]);
		frame.y = LM_to_uint(buf[2], buf[3]);
		
		dbgout("X:%i, Y:%i\n", frame.x, frame.y);

		bitPixel = 1 << ((buf[8] & 0x07) + 1);
		dbgout("Checkpoint\n");
		if (!useGlobalColormap) {
		    if (ReadColorMap(src, bitPixel, localColorMap, &grayScale)) {
				IMG_SetError("error reading local colormap");
	            goto done;
		    }
		    image = ReadImage(src, LM_to_uint(buf[4], buf[5]),
				      LM_to_uint(buf[6], buf[7]),
				      bitPixel, localColorMap, grayScale,
				      BitSet(buf[8], INTERLACE),
				      0);
			if (image) color = SDL_MapRGB(image->format,
										localColorMap[CM_RED][frame.transparent], 
										localColorMap[CM_GREEN][frame.transparent], 
										localColorMap[CM_BLUE][frame.transparent]);
		} else {
		    image = ReadImage(src, LM_to_uint(buf[4], buf[5]),
				      LM_to_uint(buf[6], buf[7]),
				      GifScreen.BitPixel, GifScreen.ColorMap,
				      GifScreen.GrayScale, BitSet(buf[8], INTERLACE),
				      0); 
			if (image) color = SDL_MapRGB(image->format,
										GifScreen.ColorMap[CM_RED][frame.transparent], 
										GifScreen.ColorMap[CM_GREEN][frame.transparent], 
										GifScreen.ColorMap[CM_BLUE][frame.transparent]);
		}
		dbgout("Image: %p\n", image);
		if (image) {
			++successCount;
			/*image = convertTo32bit(image); */ /* transform to a 32 bit surface because I HATE palettes*/
			dbgout("Converted Image: %ix%i [%p]\n", image->w, image->h, image);
			if (image) {
			    if ( frame.transparent >= 0 ) {
			        SDL_SetColorKey(image, SDL_SRCCOLORKEY, frame.transparent);
			    }
			    /*if ( frame.transparent >= 0 ) {
			        SDL_SetColorKey(image, SDL_SRCCOLORKEY, color);
			        Uint8 r, g, b;
					SDL_GetRGB(color, image->format, &r, &g, &b);
					dbgout("Local Transparency: %i,%i,%i\n", r, g, b);
			    }*/
				/*Reallocate room for another image in the list*/
				frames = (GifFrame*)realloc(frames, successCount * sizeof(GifFrame));
				if (!frames) { /*realloc failed*/
					IMG_SetError("Realloc Failed");
			        goto done;
				}
				frame.surf = image;
				/* Copy the current state of the GifFrame before the next read loop */
				frames[successCount-1] = frame;
				/*int i = 0;
				while (i < successCount) {
					dbgout("Frames[%i]: %p\n", i, frames[i]);	
					i++;
				}*/
				
				image = NULL;
			}
		}
		
    } while (1); /*let the above ... goto's... handle it*/
    
    SDL_Frame* framesArray;
	if (successCount > 0) 
	{
		dbgout("Mallocing Frames %i\n", successCount);fflush(stdout);
		
		framesArray = IMG_MallocFrames(successCount);

		i = 0;
		
		//first frame
		image = SDL_CreateRGBSurface(SDL_SWSURFACE, GifScreen.Width, 
										GifScreen.Height, 
										32, RMASK, GMASK, BMASK, 0);
				
		color = SDL_MapRGB(image->format,
							GifScreen.ColorMap[CM_RED][frames[0].transparent], 
							GifScreen.ColorMap[CM_GREEN][frames[0].transparent], 
							GifScreen.ColorMap[CM_BLUE][frames[0].transparent]);
		Uint8 r, g, b;
		SDL_GetRGB(color, image->format, &r, &g, &b);
		dbgout("Final Transparency: %i,%i,%i\n", r, g, b);fflush(stdout);
		if (color != 0) /* Ignore 0,0,0 as the transparent color */
		{ 
			SDL_FillRect(image, NULL, color);
			SDL_SetColorKey(image, SDL_SRCCOLORKEY, color); /* use the first frames trans color */
		}

		while (i < successCount) /* render our surfs and clear */
		{
			if (image)
			{
				dbgout("Dimensions: %ix%i: %p\n", image->w, image->h, image);fflush(stdout);

				w = 0;

				SDL_Rect r2, r3; 
				
				dbgout("Adding Frames[%i]: %p Disposal:%i TransIndex: %i Delay: %i Input:%i\n", i, 
						frames[i].surf, frames[i].disposal, frames[i].transparent, frames[i].delayMs,
						frames[i].inputFlag);	fflush(stdout);
						
				/* Print out the overlay at its offset coordinates */
				r2.x = frames[i].x;
				r2.y = frames[i].y; 
				r2.w = frames[i].surf->w;
				r2.h = frames[i].surf->h;
				
				dbgout("Drawing at: %i,%i\n", r2.x, r2.y);fflush(stdout);
				if (SDL_BlitSurface(frames[i].surf, NULL, image, &r2)) 
				{
					/*something bad happened but ignore it for now. */
					dbgout("Drawing Failed: %s\n", IMG_GetError());fflush(stdout);
				}
				dbgout("Setting Crap\n");fflush(stdout);
				//add image to our frames list
				framesArray[i].surf = image;
				framesArray[i].delay = frames[i].delayMs * 10; //HACK: All observed gifs have a delay of say.. 7, which means 70ms.
				framesArray[i].key = NULL;
				
				dbgout("i+1 crap\n");fflush(stdout);
				/*what to do in frame[i+1] before rendering*/
				if (i + 1 < successCount)
				{
					//create next frame so we can do something to it
					nextImage = SDL_CreateRGBSurface(SDL_SWSURFACE, GifScreen.Width, 
										GifScreen.Height, 
										32, RMASK, GMASK, BMASK, 0);
									
					color = SDL_MapRGB(nextImage->format,
										GifScreen.ColorMap[CM_RED][frames[0].transparent], 
										GifScreen.ColorMap[CM_GREEN][frames[0].transparent], 
										GifScreen.ColorMap[CM_BLUE][frames[0].transparent]);
					Uint8 r, g, b;
					SDL_GetRGB(color, nextImage->format, &r, &g, &b);
					dbgout("Final Transparency: %i,%i,%i\n", r, g, b);fflush(stdout);
					if (color != 0) /* Ignore 0,0,0 as the transparent color */
					{ 
						SDL_FillRect(nextImage, NULL, color);
						SDL_SetColorKey(nextImage, SDL_SRCCOLORKEY, color); /* use the first frames trans color */
					}
				
					dbgout("Disposal crap\n");fflush(stdout);
					switch (frames[i].disposal)
					{
						case DISPOSAL_PREVIOUSFRAME: /* 04h - Overwrite graphic with previous graphic */
							dbgout("Doing previous frame\n");fflush(stdout);
							r2.x = 0;
							r2.y = 0;
							r2.w = GifScreen.Width;
							r2.h = GifScreen.Height;
							SDL_BlitSurface(frames[0].surf, NULL, nextImage, &r2); //Since I'm lazy, and haven't seen many gifs use this, it'll just render the original frame
							break;
						case DISPOSAL_UNSPECIFIED: /* DISPOSAL_UNSPECIFIED 00h - Let the viewer decide */
							/*Drop down to donotdispose */
						case DISPOSAL_DONOTDISPOSE: /* 01h - Leave graphic there */
							dbgout("Doing nondispose\n");fflush(stdout);
							/*render a copy of the previous i-1 into i */
							
							r2.w = GifScreen.Width;
							r2.h = GifScreen.Height;
							r2.x = 0;
							r2.y = 0;
							/* r3 = src, r2 = dst */
							r3.w = GifScreen.Width;
							r3.h = GifScreen.Height;
							r3.x = 0;
							r3.y = 0;
							dbgout("r3:(%i,%i)%ix%i r2:(%i,%i)%ix%i\n", r3.x, r3.y, r3.w, r3.h, 
																	  r2.x, r2.y, r2.w, r2.h);fflush(stdout);

							if (SDL_BlitSurface(image, &r3, nextImage, &r2)) {
								dbgout("Drawing Failed: %s\n", IMG_GetError());fflush(stdout);
							}
							break;	
						default: /* This'll default to DISPOSAL_BGCOLORWIPE 
									02h - Overwrite graphic with background color 
									do nothing, next rect is empty already*/
							dbgout("Doing default %i\n", frames[i].disposal);fflush(stdout);
							break;
					}
					image = nextImage;
				}
			}
			i++;
		}
		
		i = 0;
		while (i < successCount) {
			SDL_FreeSurface(frames[i].surf);
			i++;
		}
		free(frames);
		frames = NULL;
	} else {
		image = NULL;
	}
	
done:
	if (frames) { /* We didn't complete successfully, handle any leaks */
		i = 0;
		while (i < successCount) {
			SDL_FreeSurface(frames[i].surf);
			i++;
		}
		free(frames);
		/*if (image) {
			SDL_FreeSurface(image);
			image = NULL; 
		}*/
	}
	
	/*if ( image == NULL ) {
        SDL_RWseek(src, start, SEEK_SET);
    }   */
		
	if (successCount > 0)
	{
		dst->frames = framesArray;
		dst->count = successCount;
		dst->format = IMG_FORMAT_GIF;
		return 1;
	}
	return 0;
		
    //return IMG_SurfaceToFrameset(image, sdlFrames, sdlFrameCount);
}
예제 #29
0
파일: tif_open.c 프로젝트: xharbour/core
TIFF*
TIFFClientOpen(
	const char* name, const char* mode,
	void* clientdata,
	TIFFReadWriteProc readproc,
	TIFFReadWriteProc writeproc,
	TIFFSeekProc seekproc,
	TIFFCloseProc closeproc,
	TIFFSizeProc sizeproc,
	TIFFMapFileProc mapproc,
        TIFFUnmapFileProc unmapproc,
        void* pdflib_opaque,
        TIFFmallocHandler malloc_h,
        TIFFreallocHandler realloc_h,
        TIFFfreeHandler free_h,
        TIFFErrorHandler error_h,
        TIFFErrorHandler warn_h
)
{
	static const char module[] = "TIFFClientOpen";
	TIFF pdftiff;
        TIFF *tif = &pdftiff;
	int m;
	int bigendian;
	const char* cp;

	(void) mapproc;
        (void) unmapproc;

	{ union { int32 i; char c[4]; } u; u.i = 1; bigendian = u.c[0] == 0; }
	m = _TIFFgetMode(mode, module);
	if (m == -1)
		goto bad2;
        /* PDFlib: preset tiff structure so that the first malloc works */
        tif->pdflib_opaque = pdflib_opaque;
        tif->pdflib_malloc = malloc_h;
        tif->pdflib_realloc = realloc_h;
        tif->pdflib_free = free_h;
        tif->pdflib_error = error_h;
        tif->pdflib_warn = warn_h;

	tif = (TIFF *)_TIFFmalloc(sizeof (TIFF) + (tsize_t) strlen(name) + 1);
	if (tif == NULL) {
		_TIFFError(tif, module,
			"%s: Out of memory (TIFF structure)", name);
		goto bad2;
	}
	_TIFFmemset(tif, 0, sizeof (*tif));

        /* PDFlib: add own mallochandling */
        tif->pdflib_opaque = pdflib_opaque;
        tif->pdflib_malloc = malloc_h;
        tif->pdflib_realloc = realloc_h;
        tif->pdflib_free = free_h;
        tif->pdflib_error = error_h;
        tif->pdflib_warn = warn_h;

	tif->tif_name = (char *)tif + sizeof (TIFF);
	strcpy(tif->tif_name, name);
	tif->tif_mode = m &~ (O_CREAT|O_TRUNC);
	tif->tif_curdir = (tdir_t) -1;		/* non-existent directory */
	tif->tif_curoff = 0;
	tif->tif_curstrip = (tstrip_t) -1;	/* invalid strip */
	tif->tif_row = (uint32) -1;		/* read/write pre-increment */
	tif->tif_clientdata = clientdata;
#ifdef PDFlib_NOT_USED
	if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc) {
		_TIFFError(tif, module,
			  "One of the client procedures is NULL pointer.");
		goto bad2;
	}
#endif /* PDFLIB_TIFFWRITE_SUPPORT */
	tif->tif_readproc = readproc;
	tif->tif_writeproc = writeproc;
	tif->tif_seekproc = seekproc;
	tif->tif_closeproc = closeproc;
	tif->tif_sizeproc = sizeproc;
#ifdef HAVE_MMAP
        if (mapproc)
		tif->tif_mapproc = mapproc;
	else
		tif->tif_mapproc = _tiffDummyMapProc;
	if (unmapproc)
		tif->tif_unmapproc = unmapproc;
	else
		tif->tif_unmapproc = _tiffDummyUnmapProc;
#endif
	_TIFFSetDefaultCompressionState(tif);	/* setup default state */
	/*
	 * Default is to return data MSB2LSB and enable the
	 * use of memory-mapped files and strip chopping when
	 * a file is opened read-only.
	 */
	tif->tif_flags = FILLORDER_MSB2LSB;
#ifdef HAVE_MMAP
	if (m == O_RDONLY )
            tif->tif_flags |= TIFF_MAPPED;
#endif

#ifdef STRIPCHOP_DEFAULT
	if (m == O_RDONLY || m == O_RDWR)
		tif->tif_flags |= STRIPCHOP_DEFAULT;
#endif

	/*
	 * Process library-specific flags in the open mode string.
	 * The following flags may be used to control intrinsic library
	 * behaviour that may or may not be desirable (usually for
	 * compatibility with some application that claims to support
	 * TIFF but only supports some braindead idea of what the
	 * vendor thinks TIFF is):
	 *
	 * 'l'		use little-endian byte order for creating a file
	 * 'b'		use big-endian byte order for creating a file
	 * 'L'		read/write information using LSB2MSB bit order
	 * 'B'		read/write information using MSB2LSB bit order
	 * 'H'		read/write information using host bit order
	 * 'M'		enable use of memory-mapped files when supported
	 * 'm'		disable use of memory-mapped files
	 * 'C'		enable strip chopping support when reading
	 * 'c'		disable strip chopping support
	 * 'h'		read TIFF header only, do not load the first IFD
	 *
	 * The use of the 'l' and 'b' flags is strongly discouraged.
	 * These flags are provided solely because numerous vendors,
	 * typically on the PC, do not correctly support TIFF; they
	 * only support the Intel little-endian byte order.  This
	 * support is not configured by default because it supports
	 * the violation of the TIFF spec that says that readers *MUST*
	 * support both byte orders.  It is strongly recommended that
	 * you not use this feature except to deal with busted apps
	 * that write invalid TIFF.  And even in those cases you should
	 * bang on the vendors to fix their software.
	 *
	 * The 'L', 'B', and 'H' flags are intended for applications
	 * that can optimize operations on data by using a particular
	 * bit order.  By default the library returns data in MSB2LSB
	 * bit order for compatibiltiy with older versions of this
	 * library.  Returning data in the bit order of the native cpu
	 * makes the most sense but also requires applications to check
	 * the value of the FillOrder tag; something they probably do
	 * not do right now.
	 *
	 * The 'M' and 'm' flags are provided because some virtual memory
	 * systems exhibit poor behaviour when large images are mapped.
	 * These options permit clients to control the use of memory-mapped
	 * files on a per-file basis.
	 *
	 * The 'C' and 'c' flags are provided because the library support
	 * for chopping up large strips into multiple smaller strips is not
	 * application-transparent and as such can cause problems.  The 'c'
	 * option permits applications that only want to look at the tags,
	 * for example, to get the unadulterated TIFF tag information.
	 */
	for (cp = mode; *cp; cp++)
		switch (*cp) {
		case 'b':
		    if ((m&O_CREAT) && !bigendian)
				tif->tif_flags |= TIFF_SWAB;
			break;
		case 'l':
			if ((m&O_CREAT) && bigendian)
				tif->tif_flags |= TIFF_SWAB;
			break;
		case 'B':
			tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
			    FILLORDER_MSB2LSB;
			break;
		case 'L':
			tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
			    FILLORDER_LSB2MSB;
			break;
#ifdef PDFlib_NOT_USED       /* PDFlib GmbH */
		case 'H':
			tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
			    HOST_FILLORDER;
			break;
#endif
#ifdef HAVE_MMAP
		case 'M':
			if (m == O_RDONLY)
				tif->tif_flags |= TIFF_MAPPED;
			break;
		case 'm':
			if (m == O_RDONLY)
				tif->tif_flags &= ~TIFF_MAPPED;
			break;
#endif
		case 'C':
			if (m == O_RDONLY)
				tif->tif_flags |= TIFF_STRIPCHOP;
			break;
		case 'c':
			if (m == O_RDONLY)
				tif->tif_flags &= ~TIFF_STRIPCHOP;
			break;
		case 'h':
			tif->tif_flags |= TIFF_HEADERONLY;
			break;
		}
	/*
	 * Read in TIFF header.
	 */
	if (tif->tif_mode & O_TRUNC ||
	    !ReadOK(tif, &tif->tif_header, sizeof (TIFFHeader))) {
		if (tif->tif_mode == O_RDONLY) {
			_TIFFError(tif, name, "Cannot read TIFF header");
			goto bad;
		}
		/*
		 * Setup header and write.
		 */
		tif->tif_header.tiff_magic = tif->tif_flags & TIFF_SWAB
                   ? (bigendian ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN)
                   : (bigendian ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN);

		tif->tif_header.tiff_version = TIFF_VERSION;
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabShort(&tif->tif_header.tiff_version);
		tif->tif_header.tiff_diroff = 0;	/* filled in later */


                /*
                 * The doc for "fopen" for some STD_C_LIBs says that if you 
                 * open a file for modify ("+"), then you must fseek (or 
                 * fflush?) between any freads and fwrites.  This is not
                 * necessary on most systems, but has been shown to be needed
                 * on Solaris. 
                 */
                TIFFSeekFile( tif, 0, SEEK_SET );
               
		if (!WriteOK(tif, &tif->tif_header, sizeof (TIFFHeader))) {
			_TIFFError(tif, name, "Error writing TIFF header");
			goto bad;
		}
		/*
		 * Setup the byte order handling.
		 */
		TIFFInitOrder(tif, tif->tif_header.tiff_magic, bigendian);
		/*
		 * Setup default directory.
		 */
		if (!TIFFDefaultDirectory(tif))
			goto bad;
		tif->tif_diroff = 0;
		tif->tif_dirlist = NULL;
		tif->tif_dirnumber = 0;
		return (tif);
	}
	/*
	 * Setup the byte order handling.
	 */
	if (tif->tif_header.tiff_magic != TIFF_BIGENDIAN &&
	    tif->tif_header.tiff_magic != TIFF_LITTLEENDIAN) {
		_TIFFError(tif, name,
			"Not a TIFF file, bad magic number %d (0x%x)",
		    tif->tif_header.tiff_magic,
		    tif->tif_header.tiff_magic);
		goto bad;
	}
	TIFFInitOrder(tif, tif->tif_header.tiff_magic, bigendian);
	/*
	 * Swap header if required.
	 */
	if (tif->tif_flags & TIFF_SWAB) {
		TIFFSwabShort(&tif->tif_header.tiff_version);
		TIFFSwabLong(&tif->tif_header.tiff_diroff);
	}
	/*
	 * Now check version (if needed, it's been byte-swapped).
	 * Note that this isn't actually a version number, it's a
	 * magic number that doesn't change (stupid).
	 */
	if (tif->tif_header.tiff_version == TIFF_BIGTIFF_VERSION) {
		_TIFFError(tif, name,
                          "This is a BigTIFF file.  This format not supported\n"
                          "by this version of libtiff." );
		goto bad;
	}
	if (tif->tif_header.tiff_version != TIFF_VERSION) {
		_TIFFError(tif, name,
		    "Not a TIFF file, bad version number %d (0x%x)",
		    tif->tif_header.tiff_version,
		    tif->tif_header.tiff_version);
		goto bad;
	}
	tif->tif_flags |= TIFF_MYBUFFER;
	tif->tif_rawcp = tif->tif_rawdata = 0;
	tif->tif_rawdatasize = 0;

	/*
	 * Sometimes we do not want to read the first directory (for example,
	 * it may be broken) and want to proceed to other directories. I this
	 * case we use the TIFF_HEADERONLY flag to open file and return
	 * immediately after reading TIFF header.
	 */
	if (tif->tif_flags & TIFF_HEADERONLY)
		return (tif);

	/*
	 * Setup initial directory.
	 */
	switch (mode[0]) {
	case 'r':
		tif->tif_nextdiroff = tif->tif_header.tiff_diroff;
#ifdef HAVE_MMAP
		/*
		 * Try to use a memory-mapped file if the client
		 * has not explicitly suppressed usage with the
		 * 'm' flag in the open mode (see above).
		 */
		if ((tif->tif_flags & TIFF_MAPPED) &&
	!TIFFMapFileContents(tif, (tdata_t*) &tif->tif_base, &tif->tif_size))
			tif->tif_flags &= ~TIFF_MAPPED;
#endif
		if (TIFFReadDirectory(tif)) {
			tif->tif_rawcc = -1;
			tif->tif_flags |= TIFF_BUFFERSETUP;
			return (tif);
		}
		break;
	case 'a':
		/*
		 * New directories are automatically append
		 * to the end of the directory chain when they
		 * are written out (see TIFFWriteDirectory).
		 */
		if (!TIFFDefaultDirectory(tif))
			goto bad;
		return (tif);
	}
bad:
	tif->tif_mode = O_RDONLY;	/* XXX avoid flush */
        TIFFCleanup(tif);
bad2:
	return ((TIFF*)0);
}
예제 #30
0
start_input_tga (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
{
  tga_source_ptr source = (tga_source_ptr) sinfo;
  U_CHAR targaheader[18];
  int idlen, cmaptype, subtype, flags, interlace_type, components;
  unsigned int width, height, maplen;
  boolean is_bottom_up;

#define GET_2B(offset)	((unsigned int) UCH(targaheader[offset]) + \
			 (((unsigned int) UCH(targaheader[offset+1])) << 8))

  if (! ReadOK(source->pub.input_file, targaheader, 18))
    ERREXIT(cinfo, JERR_INPUT_EOF);

  /* Pretend "15-bit" pixels are 16-bit --- we ignore attribute bit anyway */
  if (targaheader[16] == 15)
    targaheader[16] = 16;

  idlen = UCH(targaheader[0]);
  cmaptype = UCH(targaheader[1]);
  subtype = UCH(targaheader[2]);
  maplen = GET_2B(5);
  width = GET_2B(12);
  height = GET_2B(14);
  source->pixel_size = UCH(targaheader[16]) >> 3;
  flags = UCH(targaheader[17]);	/* Image Descriptor byte */

  is_bottom_up = ((flags & 0x20) == 0);	/* bit 5 set => top-down */
  interlace_type = flags >> 6;	/* bits 6/7 are interlace code */

  if (cmaptype > 1 ||		/* cmaptype must be 0 or 1 */
      source->pixel_size < 1 || source->pixel_size > 4 ||
      (UCH(targaheader[16]) & 7) != 0 || /* bits/pixel must be multiple of 8 */
      interlace_type != 0)	/* currently don't allow interlaced image */
    ERREXIT(cinfo, JERR_TGA_BADPARMS);
  
  if (subtype > 8) {
    /* It's an RLE-coded file */
    source->read_pixel = read_rle_pixel;
    source->block_count = source->dup_pixel_count = 0;
    subtype -= 8;
  } else {
    /* Non-RLE file */
    source->read_pixel = read_non_rle_pixel;
  }

  /* Now should have subtype 1, 2, or 3 */
  components = 3;		/* until proven different */
  cinfo->in_color_space = JCS_RGB;

  switch (subtype) {
  case 1:			/* Colormapped image */
    if (source->pixel_size == 1 && cmaptype == 1)
      source->get_pixel_rows = get_8bit_row;
    else
      ERREXIT(cinfo, JERR_TGA_BADPARMS);
    TRACEMS2(cinfo, 1, JTRC_TGA_MAPPED, width, height);
    break;
  case 2:			/* RGB image */
    switch (source->pixel_size) {
    case 2:
      source->get_pixel_rows = get_16bit_row;
      break;
    case 3:
      source->get_pixel_rows = get_24bit_row;
      break;
    case 4:
      source->get_pixel_rows = get_32bit_row;
      break;
    default:
      ERREXIT(cinfo, JERR_TGA_BADPARMS);
      break;
    }
    TRACEMS2(cinfo, 1, JTRC_TGA, width, height);
    break;
  case 3:			/* Grayscale image */
    components = 1;
    cinfo->in_color_space = JCS_GRAYSCALE;
    if (source->pixel_size == 1)
      source->get_pixel_rows = get_8bit_gray_row;
    else
      ERREXIT(cinfo, JERR_TGA_BADPARMS);
    TRACEMS2(cinfo, 1, JTRC_TGA_GRAY, width, height);
    break;
  default:
    ERREXIT(cinfo, JERR_TGA_BADPARMS);
    break;
  }

  if (is_bottom_up) {
    /* Create a virtual array to buffer the upside-down image. */
    source->whole_image = (*cinfo->mem->request_virt_sarray)
      ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
       (JDIMENSION) width * components, (JDIMENSION) height, (JDIMENSION) 1);
    if (cinfo->progress != NULL) {
      cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
      progress->total_extra_passes++; /* count file input as separate pass */
    }
    /* source->pub.buffer will point to the virtual array. */
    source->pub.buffer_height = 1; /* in case anyone looks at it */
    source->pub.get_pixel_rows = preload_image;
  } else {
    /* Don't need a virtual array, but do need a one-row input buffer. */
    source->whole_image = NULL;
    source->pub.buffer = (*cinfo->mem->alloc_sarray)
      ((j_common_ptr) cinfo, JPOOL_IMAGE,
       (JDIMENSION) width * components, (JDIMENSION) 1);
    source->pub.buffer_height = 1;
    source->pub.get_pixel_rows = source->get_pixel_rows;
  }
  
  while (idlen--)		/* Throw away ID field */
    (void) read_byte(source);

  if (maplen > 0) {
    if (maplen > 256 || GET_2B(3) != 0)
      ERREXIT(cinfo, JERR_TGA_BADCMAP);
    /* Allocate space to store the colormap */
    source->colormap = (*cinfo->mem->alloc_sarray)
      ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) maplen, (JDIMENSION) 3);
    /* and read it from the file */
    read_colormap(source, (int) maplen, UCH(targaheader[7]));
  } else {
    if (cmaptype)		/* but you promised a cmap! */
      ERREXIT(cinfo, JERR_TGA_BADPARMS);
    source->colormap = NULL;
  }

  cinfo->input_components = components;
  cinfo->data_precision = 8;
  cinfo->image_width = width;
  cinfo->image_height = height;
}