This repository has been archived on 2024-01-04. You can view files and clone it, but cannot push or open issues or pull requests.
ncsa-mosaic/src/picread.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);
}