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/libhtmlw/HTMLimages.c

1056 lines
25 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 <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "HTMLP.h"
#include "NoImage.c"
#include "DelayedImage.c"
#include "AnchoredImage.c"
/* SWP -- Now use eptr->bwidth -- 02/08/96
#define IMAGE_BORDER 2 */
#define IMAGE_DEFAULT_BORDER 2
ImageInfo no_image;
ImageInfo delayed_image;
ImageInfo anchored_image;
static int allocation_index[256];
#ifndef DISABLE_TRACE
extern int htmlwTrace;
#endif
extern int installed_colormap;
extern Colormap installed_cmap;
void CreateOrNotGC(HTMLWidget w);
/*
* Free all the colors in the default colormap that we have allocated so far.
*/
void
FreeColors(dsp, colormap)
Display *dsp;
Colormap colormap;
{
int i, j;
unsigned long pix;
for (i=0; i<256; i++)
{
if (allocation_index[i])
{
pix = (unsigned long)i;
/*
* Because X is stupid, we have to Free the color
* once for each time we've allocated it.
*/
for (j=0; j<allocation_index[i]; j++)
{
XFreeColors(dsp, colormap, &pix, 1, 0L);
}
}
allocation_index[i] = 0;
}
}
void
FreeBodyImages(hw)
HTMLWidget hw;
{
if (hw->html.bgmap_SAVE!=None) {
XFreePixmap(XtDisplay(hw),
hw->html.bgmap_SAVE);
hw->html.bgmap_SAVE=None;
}
if (hw->html.bgclip_SAVE!=None) {
XFreePixmap(XtDisplay(hw),
hw->html.bgclip_SAVE);
hw->html.bgclip_SAVE=None;
}
return;
}
/*
* Free up all the pixmaps allocated for this document.
*/
void
FreeImages(hw)
HTMLWidget hw;
{
struct ele_rec *eptr;
eptr = hw->html.formatted_elements;
while (eptr != NULL)
{
if ((eptr->type == E_IMAGE)&&(eptr->pic_data != NULL))
{
/*
* Don't free the no_image default image
*/
if ((eptr->pic_data->image != None)&&
(eptr->pic_data->image != delayed_image.image)&&
(eptr->pic_data->image != anchored_image.image)&&
(eptr->pic_data->image != no_image.image))
{
/*
* Don't free internal images
*/
if ((eptr->edata != NULL)&&
(strncmp(eptr->edata, INTERNAL_IMAGE,
strlen(INTERNAL_IMAGE)) == 0))
{
}
else
{
if (eptr->pic_data->image!=None) {
XFreePixmap(XtDisplay(hw),
eptr->pic_data->image);
eptr->pic_data->image = None;
}
if (eptr->pic_data->transparent && eptr->pic_data->clip!=None) {
XFreePixmap(XtDisplay(hw),
eptr->pic_data->clip);
eptr->pic_data->clip = None;
}
}
}
}
eptr = eptr->next;
}
/* Now take care of the background image! -- SWP */
if (hw->html.bgmap_SAVE!=None) {
XFreePixmap(XtDisplay(hw),
hw->html.bgmap_SAVE);
hw->html.bgmap_SAVE=None;
}
if (hw->html.bgclip_SAVE!=None) {
XFreePixmap(XtDisplay(hw),
hw->html.bgclip_SAVE);
hw->html.bgclip_SAVE=None;
}
}
/*
* Find the closest color by allocating it, or picking an already allocated
* color
*/
void
FindColor(dsp, colormap, colr)
Display *dsp;
Colormap colormap;
XColor *colr;
{
int i, match;
#ifdef MORE_ACCURATE
double rd, gd, bd, dist, mindist;
#else
int rd, gd, bd, dist, mindist;
#endif /* MORE_ACCURATE */
int cindx;
XColor tempcolr;
static XColor def_colrs[256];
static int have_colors = 0;
int NumCells;
tempcolr.pixel=colr->pixel;
tempcolr.red=colr->red;
tempcolr.green=colr->green;
tempcolr.blue=colr->blue;
tempcolr.flags=colr->flags;
tempcolr.pad=colr->pad;
match = XAllocColor(dsp, colormap, colr);
if (match == 0)
{
colr->pixel=tempcolr.pixel;
colr->red=tempcolr.red;
colr->green=tempcolr.green;
colr->blue=tempcolr.blue;
colr->flags=tempcolr.flags;
colr->pad=tempcolr.pad;
NumCells = DisplayCells(dsp, DefaultScreen(dsp));
if (!have_colors)
{
for (i=0; i<NumCells; i++)
{
def_colrs[i].pixel = i;
}
XQueryColors(dsp, colormap, def_colrs, NumCells);
have_colors = 1;
}
#ifdef MORE_ACCURATE
mindist = 196608.0; /* 256.0 * 256.0 * 3.0 */
cindx = (-1);
for (i=0; i<NumCells; i++)
{
rd = (def_colrs[i].red - colr->red) / 256.0;
gd = (def_colrs[i].green - colr->green) / 256.0;
bd = (def_colrs[i].blue - colr->blue) / 256.0;
dist = (rd * rd) +
(gd * gd) +
(bd * bd);
if (dist < mindist)
{
mindist = dist;
cindx = def_colrs[i].pixel;
if (dist == 0.0)
{
break;
}
}
}
#else
mindist = 196608; /* 256 * 256 * 3 */
cindx = (-1);
for (i=0; i<NumCells; i++)
{
rd = ((int)(def_colrs[i].red >> 8) -
(int)(colr->red >> 8));
gd = ((int)(def_colrs[i].green >> 8) -
(int)(colr->green >> 8));
bd = ((int)(def_colrs[i].blue >> 8) -
(int)(colr->blue >> 8));
dist = (rd * rd) +
(gd * gd) +
(bd * bd);
if (dist < mindist)
{
mindist = dist;
cindx = def_colrs[i].pixel;
if (dist == 0)
{
break;
}
}
}
#endif /* MORE_ACCURATE */
if (cindx==(-1)) {
colr->pixel=BlackPixel(dsp,
DefaultScreen(dsp));
colr->red = colr->green = colr->blue = 0;
}
else {
colr->pixel = cindx;
colr->red = def_colrs[cindx].red;
colr->green = def_colrs[cindx].green;
colr->blue = def_colrs[cindx].blue;
}
}
else
{
/*
* Keep a count of how many times we have allocated the
* same color, so we can properly free them later.
*/
allocation_index[colr->pixel]++;
/*
* If this is a new color, we've actually changed the default
* colormap, and may have to re-query it later.
*/
if (allocation_index[colr->pixel] == 1)
{
have_colors = 0;
}
}
}
static int
highbit(ul)
unsigned long ul;
{
/*
* returns position of highest set bit in 'ul' as an integer (0-31),
* or -1 if none.
*/
int i;
for (i=31; ((ul&0x80000000) == 0) && i>=0; i--, ul<<=1);
return i;
}
/*
#ifndef NEW
#define NEW
#endif
*/
#ifdef NEW
extern int bits_per_pixel(int dpy, int depth); /*this is in ../src/pixmaps.c*/
#endif
/*
* Make am image of appropriate depth for display from image data.
*/
XImage *
MakeImage(dsp, data, width, height, depth, img_info, clip)
Display *dsp;
unsigned char *data;
int width, height;
int depth;
ImageInfo *img_info;
int clip;
{
int linepad, shiftnum;
int shiftstart, shiftstop, shiftinc;
int bytesperline,bpp;
int temp;
int w, h;
XImage *newimage;
unsigned char *bit_data, *bitp, *datap;
Visual *theVisual;
int bmap_order;
unsigned long c;
int rshift, gshift, bshift;
#ifdef NEW
switch(bpp=bits_per_pixel(dsp,depth))
#else
switch(depth)
#endif
{
case 6:
case 8:
bit_data = (unsigned char *)malloc(width * height);
/*
bcopy(data, bit_data, (width * height));
*/
memcpy(bit_data, data, (width * height));
bytesperline = width;
if (clip) {
depth = 1;
}
newimage = XCreateImage(dsp,
DefaultVisual(dsp, DefaultScreen(dsp)),
depth, ZPixmap, 0, (char *)bit_data,
width, height, 8, bytesperline);
break;
case 1:
case 2:
case 4:
if (BitmapBitOrder(dsp) == LSBFirst)
{
shiftstart = 0;
shiftstop = 8;
#ifndef NEW
shiftinc = depth;
#else
shiftinc = bpp;
#endif
}
else
{
#ifndef NEW
shiftstart = 8 - depth;
shiftstop = -depth;
shiftinc = -depth;
#else
shiftstart = 8 - bpp;
shiftstop = -bpp;
shiftinc = -bpp;
#endif
}
linepad = 8 - (width % 8);
bit_data = (unsigned char *)malloc(((width + linepad) * height)
+ 1);
bitp = bit_data;
datap = data;
*bitp = 0;
shiftnum = shiftstart;
for (h=0; h<height; h++)
{
for (w=0; w<width; w++)
{
temp = *datap++ << shiftnum;
*bitp = *bitp | temp;
shiftnum = shiftnum + shiftinc;
if (shiftnum == shiftstop)
{
shiftnum = shiftstart;
bitp++;
*bitp = 0;
}
}
for (w=0; w<linepad; w++)
{
shiftnum = shiftnum + shiftinc;
if (shiftnum == shiftstop)
{
shiftnum = shiftstart;
bitp++;
*bitp = 0;
}
}
}
#ifndef NEW
bytesperline = (width + linepad) * depth / 8;
#else
bytesperline = (width + linepad) * bpp / 8;
#endif
newimage = XCreateImage(dsp,
DefaultVisual(dsp, DefaultScreen(dsp)),
depth, ZPixmap, 0, (char *)bit_data,
(width + linepad), height, 8, bytesperline);
break;
/*
* WARNING: This depth 16 code is donated code for 16 but
* TrueColor displays. I have no access to such displays, so I
* can't really test it.
* Donated by - nosmo@ximage.com
*/
case 16:
bit_data = (unsigned char *)malloc(width * height * 2);
bitp = bit_data;
datap = data;
theVisual = DefaultVisual(dsp, DefaultScreen(dsp));
rshift = 15 - highbit(theVisual->red_mask);
gshift = 15 - highbit(theVisual->green_mask);
bshift = 15 - highbit(theVisual->blue_mask);
bmap_order = BitmapBitOrder(dsp);
for (w = (width * height); w > 0; w--)
{
temp = (((img_info->reds[(int)*datap] >> rshift) &
theVisual->red_mask) |
((img_info->greens[(int)*datap] >> gshift) &
theVisual->green_mask) |
((img_info->blues[(int)*datap] >> bshift) &
theVisual->blue_mask));
if (bmap_order == MSBFirst)
{
*bitp++ = (temp >> 8) & 0xff;
*bitp++ = temp & 0xff;
}
else
{
*bitp++ = temp & 0xff;
*bitp++ = (temp >> 8) & 0xff;
}
datap++;
}
newimage = XCreateImage(dsp,
DefaultVisual(dsp, DefaultScreen(dsp)),
depth, ZPixmap, 0, (char *)bit_data,
width, height, 16, 0);
break;
case 24:
#ifdef NEW
case 32:
#endif
bit_data = (unsigned char *)malloc(width * height * 4);
theVisual = DefaultVisual(dsp, DefaultScreen(dsp));
rshift = highbit(theVisual->red_mask) - 7;
gshift = highbit(theVisual->green_mask) - 7;
bshift = highbit(theVisual->blue_mask) - 7;
bmap_order = BitmapBitOrder(dsp);
bitp = bit_data;
datap = data;
for (w = (width * height); w > 0; w--)
{
c =
(((img_info->reds[(int)*datap] >> 8) & 0xff) << rshift) |
(((img_info->greens[(int)*datap] >> 8) & 0xff) << gshift) |
(((img_info->blues[(int)*datap] >> 8) & 0xff) << bshift);
datap++;
if (bmap_order == MSBFirst)
{
*bitp++ = (unsigned char)((c >> 24) & 0xff);
*bitp++ = (unsigned char)((c >> 16) & 0xff);
*bitp++ = (unsigned char)((c >> 8) & 0xff);
*bitp++ = (unsigned char)(c & 0xff);
}
else
{
*bitp++ = (unsigned char)(c & 0xff);
*bitp++ = (unsigned char)((c >> 8) & 0xff);
*bitp++ = (unsigned char)((c >> 16) & 0xff);
*bitp++ = (unsigned char)((c >> 24) & 0xff);
}
}
newimage = XCreateImage(dsp,
DefaultVisual(dsp, DefaultScreen(dsp)),
depth, ZPixmap, 0, (char *)bit_data,
width, height, 32, 0);
break;
default:
#ifndef DISABLE_TRACE
if (htmlwTrace) {
fprintf(stderr, "Don't know how to format image for display of depth %d\n", depth);
}
#endif
return(NULL);
}
return(newimage);
}
int
AnchoredHeight(hw)
HTMLWidget hw;
{
return((int)(AnchoredImage_height + IMAGE_DEFAULT_BORDER));
}
char *
IsMapForm(hw)
HTMLWidget hw;
{
char *str;
str = (char *)malloc(strlen("ISMAP Form") + 1);
if (str != NULL)
{
strcpy(str, "ISMAP Form");
}
return(str);
}
int
IsIsMapForm(hw, href)
HTMLWidget hw;
char *href;
{
if ((href != NULL)&&(strcmp(href, "ISMAP Form") == 0))
{
return(1);
}
else
{
return(0);
}
}
char *
DelayedHRef(hw)
HTMLWidget hw;
{
char *str;
str = (char *)malloc(strlen("Delayed Image") + 1);
if (str != NULL)
{
strcpy(str, "Delayed Image");
}
return(str);
}
int
IsDelayedHRef(hw, href)
HTMLWidget hw;
char *href;
{
if ((href != NULL)&&(strcmp(href, "Delayed Image") == 0))
{
return(1);
}
else
{
return(0);
}
}
Pixmap
DelayedImage(hw, anchored)
HTMLWidget hw;
Boolean anchored;
{
if (delayed_image.image == None)
{
delayed_image.transparent=0;
delayed_image.image = XCreatePixmapFromBitmapData(
XtDisplay(hw->html.view),
XtWindow(hw->html.view), DelayedImage_bits,
DelayedImage_width, DelayedImage_height,
/*
* Without motif we use our own foreground resource instead of
* using the manager's
*/
#ifdef MOTIF
hw->manager.foreground,
#else
hw->html.foreground,
#endif /* MOTIF */
hw->core.background_pixel,
DefaultDepthOfScreen(XtScreen(hw)));
}
if ((anchored == True)&&(anchored_image.image == None))
{
Pixmap pix;
anchored_image.transparent=0;
anchored_image.image = XCreatePixmapFromBitmapData(
XtDisplay(hw->html.view),
XtWindow(hw->html.view), AnchoredImage_bits,
AnchoredImage_width, AnchoredImage_height,
/*
* Without motif we use our own foreground resource instead of
* using the manager's
*/
#ifdef MOTIF
hw->manager.foreground,
#else
hw->html.foreground,
#endif /* MOTIF */
hw->core.background_pixel,
DefaultDepthOfScreen(XtScreen(hw)));
pix = XCreatePixmap(
XtDisplay(hw->html.view),
XtWindow(hw->html.view),
DelayedImage_width,
(DelayedImage_height + AnchoredImage_height +
IMAGE_DEFAULT_BORDER),
DefaultDepthOfScreen(XtScreen(hw)));
XSetForeground(XtDisplay(hw), hw->html.drawGC,
hw->core.background_pixel);
XFillRectangle(XtDisplay(hw->html.view), pix,
hw->html.drawGC, 0, 0,
DelayedImage_width,
(DelayedImage_height + AnchoredImage_height +
IMAGE_DEFAULT_BORDER));
XCopyArea(XtDisplay(hw->html.view),
anchored_image.image, pix, hw->html.drawGC,
0, 0, AnchoredImage_width, AnchoredImage_height,
0, 0);
XCopyArea(XtDisplay(hw->html.view),
delayed_image.image, pix, hw->html.drawGC,
0, 0, DelayedImage_width, DelayedImage_height,
0, (AnchoredImage_height + IMAGE_DEFAULT_BORDER));
XFreePixmap(XtDisplay(hw->html.view), anchored_image.image);
anchored_image.image = pix;
return(anchored_image.image);
}
return(delayed_image.image);
}
ImageInfo *
DelayedImageData(hw, anchored)
HTMLWidget hw;
Boolean anchored;
{
delayed_image.delayed = 1;
delayed_image.internal = 0;
delayed_image.fetched = 0;
delayed_image.width = DelayedImage_width;
delayed_image.height = DelayedImage_height;
delayed_image.num_colors = 0;
delayed_image.reds = NULL;
delayed_image.greens = NULL;
delayed_image.blues = NULL;
delayed_image.image_data = NULL;
delayed_image.clip_data = NULL;
delayed_image.image = None;
delayed_image.clip = None;
delayed_image.transparent = 0;
if (anchored == True)
{
anchored_image.delayed = 0;
anchored_image.internal = 0;
anchored_image.fetched = 0;
anchored_image.width = DelayedImage_width;
anchored_image.height = DelayedImage_height +
AnchoredImage_height + IMAGE_DEFAULT_BORDER;
anchored_image.num_colors = 0;
anchored_image.reds = NULL;
anchored_image.greens = NULL;
anchored_image.blues = NULL;
anchored_image.image_data = NULL;
anchored_image.image = None;
anchored_image.clip_data = NULL;
anchored_image.clip = None;
anchored_image.transparent = 0;
return(&anchored_image);
}
return(&delayed_image);
}
Pixmap
NoImage(hw)
HTMLWidget hw;
{
if (no_image.image == None)
{
no_image.transparent=0;
no_image.image = XCreatePixmapFromBitmapData(
XtDisplay(hw),
XtWindow(hw->html.view), NoImage_bits,
NoImage_width, NoImage_height,
/*
* Without motif we use our own foreground resource instead of
* using the manager's
*/
#ifdef MOTIF
hw->manager.foreground,
#else
hw->html.foreground,
#endif /* MOTIF */
hw->core.background_pixel,
DefaultDepthOfScreen(XtScreen(hw)));
}
return(no_image.image);
}
ImageInfo *
NoImageData(hw)
HTMLWidget hw;
{
no_image.delayed = 0;
no_image.internal = 0;
no_image.fetched = 0;
no_image.width = NoImage_width;
no_image.height = NoImage_height;
no_image.num_colors = 0;
no_image.reds = NULL;
no_image.greens = NULL;
no_image.blues = NULL;
no_image.image_data = NULL;
no_image.clip_data = NULL;
no_image.image = None;
no_image.clip = None;
no_image.transparent=0;
return(&no_image);
}
Pixmap
InfoToImage(hw, img_info, clip)
HTMLWidget hw;
ImageInfo *img_info;
int clip;
{
int i, size;
int delta, not_right_col, not_last_row;
Pixmap Img;
XImage *tmpimage;
XColor tmpcolr;
int *Mapping;
unsigned char *tmpdata;
unsigned char *ptr;
unsigned char *ptr2;
int Vclass;
XVisualInfo vinfo, *vptr;
Boolean need_to_dither;
unsigned long black_pixel;
unsigned long white_pixel;
int depth;
CreateOrNotGC(hw);
/* find the visual class. */
vinfo.visualid = XVisualIDFromVisual(DefaultVisual(XtDisplay(hw),
DefaultScreen(XtDisplay(hw))));
vptr = XGetVisualInfo(XtDisplay(hw), VisualIDMask, &vinfo, &i);
Vclass = vptr->class;
depth=vptr->depth;
if (clip) {
need_to_dither = False;
}
else if (vptr->depth == 1)
{
need_to_dither = True;
black_pixel = BlackPixel(XtDisplay(hw),
DefaultScreen(XtDisplay(hw)));
white_pixel = WhitePixel(XtDisplay(hw),
DefaultScreen(XtDisplay(hw)));
}
else
{
need_to_dither = False;
}
XFree((char *)vptr);
Mapping = (int *)malloc(img_info->num_colors * sizeof(int));
if (!clip) {
for (i=0; i < img_info->num_colors; i++)
{
tmpcolr.red = img_info->reds[i];
tmpcolr.green = img_info->greens[i];
tmpcolr.blue = img_info->blues[i];
tmpcolr.flags = DoRed|DoGreen|DoBlue;
if ((Vclass == TrueColor) || (Vclass == DirectColor))
{
Mapping[i] = i;
}
else if (need_to_dither == True)
{
Mapping[i] = ((tmpcolr.red>>5)*11 +
(tmpcolr.green>>5)*16 +
(tmpcolr.blue>>5)*5) / (65504/64);
}
else
{
FindColor(XtDisplay(hw),
(installed_colormap ?
installed_cmap :
DefaultColormapOfScreen(XtScreen(hw))),
&tmpcolr);
Mapping[i] = tmpcolr.pixel;
}
}
}
/*
* Special case: For 2 color non-black&white images, instead
* of 2 dither patterns, we will always drop them to be
* black on white.
*/
if ((need_to_dither == True)&&(img_info->num_colors == 2))
{
if (Mapping[0] < Mapping[1])
{
Mapping[0] = 0;
Mapping[1] = 64;
}
else
{
Mapping[0] = 64;
Mapping[1] = 0;
}
}
size = img_info->width * img_info->height;
if (size == 0)
{
tmpdata = NULL;
}
else
{
tmpdata = (unsigned char *)malloc(size);
}
if (tmpdata == NULL)
{
tmpimage = NULL;
Img = None;
}
else
{
if (clip) {
ptr = img_info->clip_data;
}
else {
ptr = img_info->image_data;
}
ptr2 = tmpdata;
if (need_to_dither == True)
{
int cx, cy;
if (clip) {
for (ptr2 = tmpdata, ptr = img_info->clip_data;
ptr2 < tmpdata+(size-1); ptr2++, ptr++) {
*ptr2 = Mapping[(int)*ptr];
}
}
else {
for (ptr2 = tmpdata, ptr = img_info->image_data;
ptr2 < tmpdata+(size-1); ptr2++, ptr++) {
*ptr2 = Mapping[(int)*ptr];
}
}
ptr2 = tmpdata;
for (cy=0; cy < img_info->height; cy++)
{
for (cx=0; cx < img_info->width; cx++)
{
/*
* Assume high numbers are
* really negative.
*/
if (*ptr2 > 128)
{
*ptr2 = 0;
}
if (*ptr2 > 64)
{
*ptr2 = 64;
}
/*
* Traditional Floyd-Steinberg
*/
if (*ptr2 < 32)
{
delta = *ptr2;
*ptr2 = black_pixel;
}
else
{
delta = *ptr2 - 64;
*ptr2 = white_pixel;
}
if (not_right_col =
(cx < (img_info->width-1)))
{
*(ptr2+1) += delta*7 >> 4;
}
if (not_last_row =
(cy < (img_info->height-1)))
{
(*(ptr2+img_info->width)) +=
delta*5 >> 4;
}
if (not_right_col && not_last_row)
{
(*(ptr2+img_info->width+1)) +=
delta >> 4;
}
if (cx && not_last_row)
{
(*(ptr2+img_info->width-1)) +=
delta*3 >> 4;
}
ptr2++;
}
}
} /* end if (need_to_dither==True) */
else
{
for (i=0; i < size; i++)
{
if (clip) {
*ptr2++ = *ptr;
}
else {
*ptr2++ = (unsigned char)Mapping[(int)*ptr];
}
ptr++;
}
}
depth=DefaultDepthOfScreen(XtScreen(hw));
tmpimage = MakeImage(XtDisplay(hw), tmpdata,
img_info->width, img_info->height,
depth, img_info, clip);
/* Caught by Purify; should be OK. */
free (tmpdata);
Img = XCreatePixmap(XtDisplay(hw),
XtWindow(hw->html.view),
img_info->width, img_info->height,
depth);
}
if ((tmpimage == NULL)||(Img == None))
{
if (tmpimage != NULL)
{
XDestroyImage(tmpimage);
}
if (Img != None)
{
XFreePixmap(XtDisplay(hw), Img);
}
img_info->width = NoImage_width;
img_info->height = NoImage_height;
Img = NoImage(hw);
}
else
{
XPutImage(XtDisplay(hw), Img, hw->html.drawGC, tmpimage, 0, 0,
0, 0, img_info->width, img_info->height);
XDestroyImage(tmpimage);
}
/* Caught by Purify; should be OK. */
free((char *)Mapping);
return(Img);
}