712 lines
17 KiB
C
712 lines
17 KiB
C
/****************************************************************************
|
|
* NCSA Mosaic for the X Window System *
|
|
* Software Development Group *
|
|
* National Center for Supercomputing Applications *
|
|
* University of Illinois at Urbana-Champaign *
|
|
* 605 E. Springfield, Champaign IL 61820 *
|
|
* mosaic@ncsa.uiuc.edu *
|
|
* *
|
|
* Copyright (C) 1993, Board of Trustees of the University of Illinois *
|
|
* *
|
|
* NCSA Mosaic software, both binary and source (hereafter, Software) is *
|
|
* copyrighted by The Board of Trustees of the University of Illinois *
|
|
* (UI), and ownership remains with the UI. *
|
|
* *
|
|
* The UI grants you (hereafter, Licensee) a license to use the Software *
|
|
* for academic, research and internal business purposes only, without a *
|
|
* fee. Licensee may distribute the binary and source code (if released) *
|
|
* to third parties provided that the copyright notice and this statement *
|
|
* appears on all copies and that no charge is associated with such *
|
|
* copies. *
|
|
* *
|
|
* Licensee may make derivative works. However, if Licensee distributes *
|
|
* any derivative work based on or derived from the Software, then *
|
|
* Licensee will (1) notify NCSA regarding its distribution of the *
|
|
* derivative work, and (2) clearly notify users that such derivative *
|
|
* work is a modified version and not the original NCSA Mosaic *
|
|
* distributed by the UI. *
|
|
* *
|
|
* Any Licensee wishing to make commercial use of the Software should *
|
|
* contact the UI, c/o NCSA, to negotiate an appropriate license for such *
|
|
* commercial use. Commercial use includes (1) integration of all or *
|
|
* part of the source code into a product for sale or license by or on *
|
|
* behalf of Licensee to third parties, or (2) distribution of the binary *
|
|
* code or source code to third parties that need it to utilize a *
|
|
* commercial product sold or licensed by or on behalf of Licensee. *
|
|
* *
|
|
* UI MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR *
|
|
* ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED *
|
|
* WARRANTY. THE UI SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY THE *
|
|
* USERS OF THIS SOFTWARE. *
|
|
* *
|
|
* By using or copying this Software, Licensee agrees to abide by the *
|
|
* copyright law and all other applicable laws of the U.S. including, but *
|
|
* not limited to, export control laws, and the terms of this license. *
|
|
* UI shall have the right to terminate this license immediately by *
|
|
* written notice upon Licensee's breach of, or non-compliance with, any *
|
|
* of its terms. Licensee may be held legally responsible for any *
|
|
* copyright infringement that is caused or encouraged by Licensee's *
|
|
* failure to abide by the terms of this license. *
|
|
* *
|
|
* Comments and questions are welcome and can be sent to *
|
|
* mosaic-x@ncsa.uiuc.edu. *
|
|
****************************************************************************/
|
|
#include "../config.h"
|
|
#include "mosaic.h"
|
|
#include "picread.h"
|
|
#include "gifread.h"
|
|
#include "xpmread.h"
|
|
|
|
#ifdef HAVE_JPEG
|
|
#include "readJPEG.h"
|
|
#endif
|
|
|
|
#ifdef HAVE_PNG
|
|
#include "readPNG.h"
|
|
#endif
|
|
|
|
#include <X11/Xos.h>
|
|
|
|
#define DEF_BLACK BlackPixel(dsp, DefaultScreen(dsp))
|
|
#define DEF_WHITE WhitePixel(dsp, DefaultScreen(dsp))
|
|
#define MAX_LINE 81
|
|
|
|
|
|
/*extern unsigned char *ReadGIF();
|
|
extern unsigned char *ReadXpm3Pixmap();
|
|
extern unsigned char *ReadJPEG();*/
|
|
|
|
|
|
extern Display *dsp;
|
|
|
|
extern int installed_colormap;
|
|
extern Colormap installed_cmap;
|
|
|
|
#ifndef DISABLE_TRACE
|
|
extern int srcTrace;
|
|
#endif
|
|
|
|
char nibMask[8] = {
|
|
1, 2, 4, 8, 16, 32, 64, 128
|
|
};
|
|
|
|
|
|
|
|
unsigned char *ReadXpmPixmap(fp, datafile, w, h, colrs, Colors, CharsPP)
|
|
FILE *fp;
|
|
char *datafile;
|
|
int *w, *h;
|
|
XColor *colrs;
|
|
int Colors, CharsPP;
|
|
{
|
|
unsigned char *pixels;
|
|
char **Color_Vals;
|
|
XColor tmpcolr;
|
|
int i, j, k;
|
|
int /*value,*/ found;
|
|
char line[BUFSIZ], name_and_type[MAX_LINE];
|
|
unsigned char *dataP;
|
|
unsigned char *bitp;
|
|
int tchar;
|
|
char *t;
|
|
char *t2;
|
|
|
|
if (Colors == 0)
|
|
{
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace) {
|
|
fprintf(stderr, "Can't find Colors.\n");
|
|
}
|
|
#endif
|
|
|
|
return((unsigned char *)NULL);
|
|
}
|
|
if (*w == 0)
|
|
{
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace) {
|
|
fprintf(stderr, "Can't read image.\n");
|
|
}
|
|
#endif
|
|
|
|
return((unsigned char *)NULL);
|
|
}
|
|
if (*h == 0)
|
|
{
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace) {
|
|
fprintf(stderr, "Can't read image.\n");
|
|
}
|
|
#endif
|
|
|
|
return((unsigned char *)NULL);
|
|
}
|
|
|
|
Color_Vals = (char **)malloc(sizeof(char *) * Colors);
|
|
for (i=0; i<Colors; i++)
|
|
{
|
|
tchar = getc(fp);
|
|
while ((tchar != '"')&&(tchar != EOF))
|
|
{
|
|
tchar = getc(fp);
|
|
}
|
|
Color_Vals[i] = (char *)malloc(sizeof(char) * (CharsPP + 1));
|
|
j = 0;
|
|
tchar = getc(fp);
|
|
while ((tchar != '"')&&(tchar != EOF)&&(j < CharsPP))
|
|
{
|
|
Color_Vals[i][j] = (char)tchar;
|
|
tchar = getc(fp);
|
|
j++;
|
|
}
|
|
Color_Vals[i][j] = '\0';
|
|
if (tchar != '"')
|
|
{
|
|
tchar = getc(fp);
|
|
while ((tchar != '"')&&(tchar != EOF))
|
|
{
|
|
tchar = getc(fp);
|
|
}
|
|
}
|
|
tchar = getc(fp);
|
|
while ((tchar != '"')&&(tchar != EOF))
|
|
{
|
|
tchar = getc(fp);
|
|
}
|
|
j = 0;
|
|
tchar = getc(fp);
|
|
while ((tchar != '"')&&(tchar != EOF))
|
|
{
|
|
line[j] = (char)tchar;
|
|
tchar = getc(fp);
|
|
j++;
|
|
}
|
|
line[j] = '\0';
|
|
XParseColor(dsp, (installed_colormap ?
|
|
installed_cmap :
|
|
DefaultColormap(dsp, DefaultScreen(dsp))),
|
|
line, &tmpcolr);
|
|
colrs[i].red = tmpcolr.red;
|
|
colrs[i].green = tmpcolr.green;
|
|
colrs[i].blue = tmpcolr.blue;
|
|
colrs[i].pixel = i;
|
|
colrs[i].flags = DoRed|DoGreen|DoBlue;
|
|
}
|
|
for (i=Colors; i<256; i++)
|
|
{
|
|
colrs[i].red = 0;
|
|
colrs[i].green = 0;
|
|
colrs[i].blue = 0;
|
|
colrs[i].pixel = i;
|
|
colrs[i].flags = DoRed|DoGreen|DoBlue;
|
|
}
|
|
tchar = getc(fp);
|
|
while ((tchar != ';')&&(tchar != EOF))
|
|
{
|
|
tchar = getc(fp);
|
|
}
|
|
|
|
for ( ; ; )
|
|
{
|
|
if (!(fgets(line, MAX_LINE, fp)))
|
|
{
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace) {
|
|
fprintf(stderr, "Can't find Pixels\n");
|
|
}
|
|
#endif
|
|
|
|
return((unsigned char *)NULL);
|
|
}
|
|
else if (sscanf(line,"static char * %s = {",name_and_type) == 1)
|
|
{
|
|
if ((t = strrchr(name_and_type, '_')) == NULL)
|
|
{
|
|
t = name_and_type;
|
|
}
|
|
else
|
|
{
|
|
t++;
|
|
}
|
|
if ((t2 = strchr(name_and_type, '[')) != NULL)
|
|
{
|
|
*t2 = '\0';
|
|
}
|
|
if (!strcmp("pixels", t))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
pixels = (unsigned char *)malloc((*w) * (*h));
|
|
if (pixels == NULL)
|
|
{
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace) {
|
|
fprintf(stderr, "Not enough memory for data.\n");
|
|
}
|
|
#endif
|
|
|
|
return((unsigned char *)NULL);
|
|
}
|
|
|
|
line[0] = '\0';
|
|
t = line;
|
|
dataP = pixels;
|
|
tchar = getc(fp);
|
|
while ((tchar != '"')&&(tchar != EOF))
|
|
{
|
|
tchar = getc(fp);
|
|
}
|
|
tchar = getc(fp);
|
|
for (j=0; j<(*h); j++)
|
|
{
|
|
for (i=0; i<(*w); i++)
|
|
{
|
|
k = 0;
|
|
while ((tchar != '"')&&(tchar != EOF)&&(k < CharsPP))
|
|
{
|
|
line[k] = (char)tchar;
|
|
tchar = getc(fp);
|
|
k++;
|
|
}
|
|
if ((k == 0)&&(tchar == '"'))
|
|
{
|
|
tchar = getc(fp);
|
|
while ((tchar != '"')&&(tchar != EOF))
|
|
{
|
|
tchar = getc(fp);
|
|
}
|
|
k = 0;
|
|
tchar = getc(fp);
|
|
while ((tchar != '"')&&(tchar != EOF)&&
|
|
(k < CharsPP))
|
|
{
|
|
line[k] = (char)tchar;
|
|
tchar = getc(fp);
|
|
k++;
|
|
}
|
|
}
|
|
line[k] = '\0';
|
|
found = 0;
|
|
for (k=0; k<Colors; k++)
|
|
{
|
|
if (strncmp(Color_Vals[k], line, CharsPP) == 0)
|
|
{
|
|
*dataP++ = (unsigned char)k;
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
if (found == 0)
|
|
{
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace) {
|
|
fprintf(stderr, "Invalid Pixel (%2s) in file %s\n", line, datafile);
|
|
}
|
|
#endif
|
|
|
|
*dataP++ = (unsigned char)0;
|
|
}
|
|
}
|
|
}
|
|
|
|
bitp = pixels;
|
|
for (i=0; i<((*w) * (*h)); i++)
|
|
{
|
|
if ((int)*bitp > (256 - 1))
|
|
*bitp = (unsigned char)0;
|
|
bitp++;
|
|
}
|
|
|
|
for (i=0; i<Colors; i++)
|
|
{
|
|
free((char *)Color_Vals[i]);
|
|
}
|
|
free((char *)Color_Vals);
|
|
return(pixels);
|
|
}
|
|
|
|
|
|
unsigned char *ReadXbmBitmap(fp, datafile, w, h, colrs)
|
|
FILE *fp;
|
|
char *datafile;
|
|
int *w, *h;
|
|
XColor *colrs;
|
|
{
|
|
char line[MAX_LINE], name_and_type[MAX_LINE];
|
|
char *t;
|
|
char *t2;
|
|
unsigned char *ptr, *dataP;
|
|
int bytes_per_line, version10p, raster_length, padding;
|
|
int i, bytes, temp, value;
|
|
int Ncolors, charspp, xpmformat;
|
|
static unsigned long fg_pixel, bg_pixel;
|
|
static int done_fetch_colors = 0;
|
|
extern XColor fg_color, bg_color;
|
|
extern Widget view;
|
|
extern int Vclass;
|
|
int blackbit;
|
|
int whitebit;
|
|
|
|
if (!done_fetch_colors)
|
|
{
|
|
/* First, go fetch the pixels. */
|
|
XtVaGetValues (view, XtNforeground, &fg_pixel,
|
|
XtNbackground, &bg_pixel, NULL);
|
|
|
|
/* Now, load up fg_color and bg_color. */
|
|
fg_color.pixel = fg_pixel;
|
|
bg_color.pixel = bg_pixel;
|
|
|
|
/* Now query for the full color info. */
|
|
XQueryColor
|
|
(XtDisplay (view),
|
|
(installed_colormap ?
|
|
installed_cmap :
|
|
DefaultColormap (XtDisplay (view),
|
|
DefaultScreen (XtDisplay (view)))),
|
|
&fg_color);
|
|
XQueryColor
|
|
(XtDisplay (view),
|
|
(installed_colormap ?
|
|
installed_cmap :
|
|
DefaultColormap (XtDisplay (view),
|
|
DefaultScreen (XtDisplay (view)))),
|
|
&bg_color);
|
|
|
|
done_fetch_colors = 1;
|
|
|
|
/*
|
|
* For a TrueColor visual, we can't use the pixel value as
|
|
* the color index because it is > 255. Arbitrarily assign
|
|
* 0 to foreground, and 1 to background.
|
|
*/
|
|
if ((Vclass == TrueColor) ||(Vclass == DirectColor))
|
|
{
|
|
fg_color.pixel = 0;
|
|
bg_color.pixel = 1;
|
|
}
|
|
|
|
}
|
|
|
|
if (get_pref_boolean(eREVERSE_INLINED_BITMAP_COLORS))
|
|
{
|
|
blackbit = bg_color.pixel;
|
|
whitebit = fg_color.pixel;
|
|
}
|
|
else
|
|
{
|
|
blackbit = fg_color.pixel;
|
|
whitebit = bg_color.pixel;
|
|
}
|
|
|
|
/*
|
|
* Error out here on visuals we can't handle so we won't core dump
|
|
* later.
|
|
*/
|
|
if (((blackbit > 255)||(whitebit > 255))&&(Vclass != TrueColor))
|
|
{
|
|
fprintf(stderr, "Error: cannot deal with default colormap that is deeper than 8, and not TrueColor\n");
|
|
fprintf(stderr, " If you actually have such a system, please notify mosaic-x@ncsa.uiuc.edu.\n");
|
|
fprintf(stderr, " We thank you for your support.\n");
|
|
exit(1);
|
|
}
|
|
|
|
if (get_pref_boolean(eREVERSE_INLINED_BITMAP_COLORS))
|
|
{
|
|
colrs[blackbit].red = bg_color.red;
|
|
colrs[blackbit].green = bg_color.green;
|
|
colrs[blackbit].blue = bg_color.blue;
|
|
colrs[blackbit].pixel = bg_color.pixel;
|
|
colrs[blackbit].flags = DoRed|DoGreen|DoBlue;
|
|
|
|
colrs[whitebit].red = fg_color.red;
|
|
colrs[whitebit].green = fg_color.green;
|
|
colrs[whitebit].blue = fg_color.blue;
|
|
colrs[whitebit].pixel = fg_color.pixel;
|
|
colrs[whitebit].flags = DoRed|DoGreen|DoBlue;
|
|
}
|
|
else
|
|
{
|
|
colrs[blackbit].red = fg_color.red;
|
|
colrs[blackbit].green = fg_color.green;
|
|
colrs[blackbit].blue = fg_color.blue;
|
|
colrs[blackbit].pixel = fg_color.pixel;
|
|
colrs[blackbit].flags = DoRed|DoGreen|DoBlue;
|
|
|
|
colrs[whitebit].red = bg_color.red;
|
|
colrs[whitebit].green = bg_color.green;
|
|
colrs[whitebit].blue = bg_color.blue;
|
|
colrs[whitebit].pixel = bg_color.pixel;
|
|
colrs[whitebit].flags = DoRed|DoGreen|DoBlue;
|
|
}
|
|
|
|
*w = 0;
|
|
*h = 0;
|
|
Ncolors = 0;
|
|
charspp = 0;
|
|
xpmformat = 0;
|
|
for ( ; ; )
|
|
{
|
|
if (!(fgets(line, MAX_LINE, fp)))
|
|
break;
|
|
if (strlen(line) == (MAX_LINE - 1))
|
|
{
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace) {
|
|
fprintf(stderr, "Line too long.\n");
|
|
}
|
|
#endif
|
|
|
|
return((unsigned char *)NULL);
|
|
}
|
|
if (sscanf(line, "#define %s %d", name_and_type, &value) == 2)
|
|
{
|
|
if (!(t = strrchr(name_and_type, '_')))
|
|
t = name_and_type;
|
|
else
|
|
t++;
|
|
if (!strcmp("width", t))
|
|
*w= value;
|
|
if (!strcmp("height", t))
|
|
*h= value;
|
|
if (!strcmp("ncolors", t))
|
|
Ncolors = value;
|
|
if (!strcmp("pixel", t))
|
|
charspp = value;
|
|
continue;
|
|
}
|
|
if (sscanf(line, "static short %s = {", name_and_type) == 1)
|
|
{
|
|
version10p = 1;
|
|
break;
|
|
}
|
|
else if (sscanf(line,"static char * %s = {",name_and_type) == 1)
|
|
{
|
|
xpmformat = 1;
|
|
if (!(t = strrchr(name_and_type, '_')))
|
|
t = name_and_type;
|
|
else
|
|
t++;
|
|
if ((t2 = strchr(name_and_type, '[')) != NULL)
|
|
*t2 = '\0';
|
|
if (!strcmp("mono", t))
|
|
continue;
|
|
else
|
|
break;
|
|
}
|
|
else if (sscanf(line, "static char %s = {", name_and_type) == 1)
|
|
{
|
|
version10p = 0;
|
|
break;
|
|
}
|
|
else if (sscanf(line, "static unsigned char %s = {", name_and_type) == 1)
|
|
{
|
|
version10p = 0;
|
|
break;
|
|
}
|
|
else
|
|
continue;
|
|
}
|
|
if (xpmformat)
|
|
{
|
|
dataP = ReadXpmPixmap(fp, datafile, w, h, colrs, Ncolors, charspp);
|
|
return(dataP);
|
|
}
|
|
if (*w == 0)
|
|
{
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace) {
|
|
fprintf(stderr, "Can't read image.\n");
|
|
}
|
|
#endif
|
|
|
|
return((unsigned char *)NULL);
|
|
}
|
|
if (*h == 0)
|
|
{
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace) {
|
|
fprintf(stderr, "Can't read image.\n");
|
|
}
|
|
#endif
|
|
|
|
return((unsigned char *)NULL);
|
|
}
|
|
padding = 0;
|
|
if (((*w % 16) >= 1)&&((*w % 16) <= 8)&&version10p)
|
|
{
|
|
padding = 1;
|
|
}
|
|
bytes_per_line = ((*w + 7) / 8) + padding;
|
|
raster_length = bytes_per_line * *h;
|
|
dataP = (unsigned char *)malloc((*w) * (*h));
|
|
if (dataP == NULL)
|
|
{
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace) {
|
|
fprintf(stderr, "Not enough memory.\n");
|
|
}
|
|
#endif
|
|
|
|
return((unsigned char *)NULL);
|
|
}
|
|
ptr = dataP;
|
|
if (version10p)
|
|
{
|
|
int cnt = 0;
|
|
int lim = (bytes_per_line - padding) * 8;
|
|
for (bytes = 0; bytes < raster_length; bytes += 2)
|
|
{
|
|
if (fscanf(fp, " 0x%x%*[,}]%*[ \r\n]", &value) != 1)
|
|
{
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace) {
|
|
fprintf(stderr, "Error scanning bits item.\n");
|
|
}
|
|
#endif
|
|
|
|
return((unsigned char *)NULL);
|
|
}
|
|
temp = value;
|
|
value = temp & 0xff;
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
if (cnt < (*w))
|
|
{
|
|
if (value & nibMask[i])
|
|
*ptr++ = blackbit;
|
|
else
|
|
*ptr++ = whitebit;
|
|
}
|
|
if (++cnt >= lim)
|
|
cnt = 0;
|
|
}
|
|
if ((!padding)||((bytes+2) % bytes_per_line))
|
|
{
|
|
value = temp >> 8;
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
if (cnt < (*w))
|
|
{
|
|
if (value & nibMask[i])
|
|
*ptr++ = blackbit;
|
|
else
|
|
*ptr++ = whitebit;
|
|
}
|
|
if (++cnt >= lim)
|
|
cnt = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int cnt = 0;
|
|
int lim = bytes_per_line * 8;
|
|
for (bytes = 0; bytes < raster_length; bytes++)
|
|
{
|
|
if (fscanf(fp, " 0x%x%*[,}]%*[ \r\n]", &value) != 1)
|
|
{
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace) {
|
|
fprintf(stderr, "Error scanning bits item.\n");
|
|
}
|
|
#endif
|
|
|
|
return((unsigned char *)NULL);
|
|
}
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
if (cnt < (*w))
|
|
{
|
|
if (value & nibMask[i])
|
|
*ptr++ = blackbit;
|
|
else
|
|
*ptr++ = whitebit;
|
|
}
|
|
if (++cnt >= lim)
|
|
cnt = 0;
|
|
}
|
|
}
|
|
}
|
|
return(dataP);
|
|
}
|
|
|
|
|
|
unsigned char *ReadBitmap(datafile, w, h, colrs, bg)
|
|
char *datafile;
|
|
int *w, *h;
|
|
XColor *colrs;
|
|
int *bg;
|
|
{
|
|
unsigned char *bit_data;
|
|
FILE *fp;
|
|
|
|
*bg = -1;
|
|
|
|
/* Obviously this isn't going to work. */
|
|
if ((datafile == NULL)||(datafile[0] == '\0'))
|
|
{
|
|
fp = NULL;
|
|
}
|
|
else
|
|
{
|
|
fp = fopen(datafile, "r");
|
|
}
|
|
|
|
if (fp != NULL)
|
|
{
|
|
|
|
bit_data = ReadGIF(fp, w, h, colrs, bg);
|
|
if (bit_data != NULL)
|
|
{
|
|
if (fp != stdin) fclose(fp);
|
|
return(bit_data);
|
|
}
|
|
rewind(fp);
|
|
|
|
bit_data = ReadXbmBitmap(fp, datafile, w, h, colrs);
|
|
if (bit_data != NULL)
|
|
{
|
|
if (fp != stdin) fclose(fp);
|
|
return(bit_data);
|
|
}
|
|
rewind(fp);
|
|
|
|
bit_data = ReadXpm3Pixmap(fp, datafile, w, h, colrs, bg);
|
|
if (bit_data != NULL)
|
|
{
|
|
if (fp != stdin) fclose(fp);
|
|
return(bit_data);
|
|
}
|
|
rewind(fp);
|
|
|
|
#ifdef HAVE_PNG
|
|
/* I can't believe Mosaic works this way... - DXP */
|
|
/* I have to put this BEFORE ReadJPEG, because that code
|
|
screws up the file pointer by closing it if there is an error - go fig. */
|
|
bit_data = ReadPNG(fp, w, h, colrs);
|
|
if (bit_data != NULL) /* ie. it was able to read the image */
|
|
{
|
|
if (fp != stdin) fclose(fp);
|
|
return(bit_data);
|
|
}
|
|
rewind(fp);
|
|
#endif
|
|
#ifdef HAVE_JPEG
|
|
bit_data = ReadJPEG(fp, w, h, colrs);
|
|
if (bit_data != NULL)
|
|
{
|
|
if (fp != stdin) fclose(fp);
|
|
return(bit_data);
|
|
}
|
|
#endif
|
|
|
|
}
|
|
if ((fp != NULL) && (fp != stdin)) fclose(fp);
|
|
return((unsigned char *)NULL);
|
|
}
|
|
|