home *** CD-ROM | disk | FTP | other *** search
- /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
- /**********************************************************************
- mkanim.c
- By Daniel Malmer
-
- This code was mostly taken from mkicons.c.
-
- Given a list of filenames, creates a datafile that is read in by the
- browser at run-time. The images in the datafile will be used as the
- custom animation.
-
- Usage:
-
- mkanim large-file1 large-file2... large-filen small-file1 small-file2...
- small-filen
-
- **********************************************************************/
-
- /*
- mkicons.c --- converting transparent GIFs to embeddable XImage data.
- Created: Jamie Zawinski <jwz@netscape.com>, 17-Aug-95.
- (Danger. Here be monsters.)
- */
-
- #define MAX_ANIM_FRAMES 50
-
- #ifdef sgi
- #include <bstring.h>
- #else
- #include <string.h>
- #endif
-
- #ifdef _HPUX_SOURCE
- typedef unsigned char uchar_t;
- #endif
-
- #include "if.h"
- #include "prtypes.h"
- #include <plevent.h>
- #include <prtypes.h>
- #include "libevent.h"
-
- extern void append_to_output_file(char* data, int len);
-
- /* =========================================================================
- All this junk is just to get it to link.
- =========================================================================
- */
-
- void * FE_SetTimeout(TimeoutCallbackFunction func, void * closure,
- uint32 msecs) { return 0; }
- void FE_ClearTimeout(void *timer_id) {}
- void XP_Trace(const char * format, ...) {}
- void FE_ImageDelete(IL_Image *portableImage) {}
- int32 NET_GetMemoryCacheSize(void) { return 1000000; }
- int32 NET_GetMaxMemoryCacheSize(void) { return 1000000; }
- void NET_FreeURLStruct(URL_Struct * URL_s) {}
- int NET_InterruptWindow(MWContext * window_id) {return 0;}
- URL_Struct *NET_CreateURLStruct(const char *url, NET_ReloadMethod reload) { return 0; }
- History_entry * SHIST_GetCurrent(History * hist) { return 0; }
- int NET_GetURL (URL_Struct * URL_s, FO_Present_Types output_format,
- MWContext * context, Net_GetUrlExitFunc* exit_routine)
- { return -1; }
- Bool LO_BlockedOnImage(MWContext *c, LO_ImageStruct *image) { return FALSE; }
- Bool NET_IsURLInDiskCache(URL_Struct *URL_s) {return TRUE;}
- XP_Bool NET_IsLocalFileURL(char *address) {return TRUE;}
-
- NET_StreamClass * NET_StreamBuilder (FO_Present_Types format_out,
- URL_Struct *anchor, MWContext *window_id)
- { return 0; }
-
- Bool NET_AreThereActiveConnectionsForWindow(MWContext * window_id)
- { return FALSE; }
- Bool NET_AreThereStoppableConnectionsForWindow(MWContext * window_id)
- { return FALSE; }
- void LO_RefreshAnchors(MWContext *context) { }
- void GH_UpdateGlobalHistory(URL_Struct * URL_s) { }
- char * NET_EscapeHTML(const char * string) { return (char *)string; }
- Bool LO_LocateNamedAnchor(MWContext *context, URL_Struct *url_struct,
- int32 *xpos, int32 *ypos) { return FALSE; }
- Bool LO_HasBGImage(MWContext *context) {return FALSE; }
-
- void FE_UpdateStopState(MWContext *context) {}
-
- void
- FE_Alert (MWContext *context, const char *message) {}
-
- void ET_RemoveWindowContext(MWContext *context, ETVoidPtrFunc fn,
- void *data) { }
-
- extern int il_first_write(NET_StreamClass *stream, const unsigned char *str, int32 len);
-
- void fe_ReLayout (MWContext *context, NET_ReloadMethod force_reload) {}
-
- char *XP_GetBuiltinString(int16 i);
-
- char *
- XP_GetString(int16 i)
- {
- return XP_GetBuiltinString(i);
- }
-
- Bool
- NET_IsURLInMemCache(URL_Struct *URL_s)
- {
- return FALSE;
- }
-
-
-
- /* =========================================================================
- Now it gets REALLY nasty.
- =========================================================================
- */
-
- struct image {
- int width, height;
- char *color_bits;
- char *mono_bits;
- char *mask_bits;
- };
-
- int total_images = 0;
- struct image images[500] = { { 0, }, };
-
- int total_colors;
- IL_IRGB cmap[256];
-
- char* current_file = NULL;
-
- int num_frames_small = 0;
- int width_small = 0;
- int height_small = 0;
-
- int num_frames_large = 0;
- int width_large = 0;
- int height_large = 0;
-
- int in_anim = 0;
- int inactive_icon_p = 0;
- int anim_frames[100] = { 0, };
-
- XP_Bool sgi_p = FALSE;
-
- static unsigned char *bitrev = 0;
-
-
- /*
- * warn
- */
- void
- warn(char* msg)
- {
- fprintf(stderr, "Warning: %s: %s\n", current_file, msg);
- }
-
-
- /*
- * error
- */
- void
- error(char* msg)
- {
- fprintf(stderr, "Error: %s: %s\n", current_file, msg);
-
- exit(1);
- }
-
-
- /*
- * init_reverse_bits
- */
- static void
- init_reverse_bits(void)
- {
- if(!bitrev)
- {
- int i, x, br;
- bitrev = (unsigned char *)XP_ALLOC(256);
- for(i=0; i<256; i++)
- {
- br = 0;
- for(x=0; x<8; x++)
- {
- br = br<<1;
- if(i&(1<<x))
- br |= 1;
- }
- bitrev[i] = br;
- }
- }
- }
-
-
- typedef enum {INITIAL_STATE, LARGE_STATE, SMALL_STATE, ERROR_STATE} image_state;
-
-
- /*
- * image_size
- * This routine is registered with the image library to be invoked
- * when it has determined the size of the image that it is processing.
- * Sets the size of the image, and allocates the appropriate memory.
- */
- int
- image_size (MWContext *context, IL_ImageStatus message,
- IL_Image *il_image, void *data)
- {
- static image_state state = INITIAL_STATE;
-
- switch ( state ) {
- case INITIAL_STATE:
- printf("First large frame is %s.\n", current_file);
- printf("Size is %d by %d pixels.\n", il_image->width, il_image->height);
- num_frames_large++;
- width_large = il_image->width;
- height_large = il_image->height;
- state = LARGE_STATE;
- break;
- case LARGE_STATE:
- if ( il_image->width == width_large &&
- il_image->height == height_large ) {
- if ( num_frames_large < MAX_ANIM_FRAMES ) {
- num_frames_large++;
- printf("Reading large frame %d...\n", num_frames_large);
- } else {
- warn("Ignoring. Too many frames for animation.");
- }
- } else {
- printf("First small frame is %s.\n", current_file);
- printf("Size is %d by %d pixels.\n", il_image->width, il_image->height);
- num_frames_small++;
- width_small = il_image->width;
- height_small = il_image->height;
- state = SMALL_STATE;
- }
- break;
- case SMALL_STATE:
- if ( il_image->width == width_small &&
- il_image->height == height_small ) {
- if ( num_frames_small < MAX_ANIM_FRAMES ) {
- num_frames_small++;
- printf("Reading small frame %d...\n", num_frames_small);
- } else {
- warn("Ignoring. Too many frames for animation.");
- }
- } else {
- error("Bad size. Animation frames must have the same size.\n");
- state = ERROR_STATE;
- }
- break;
- case ERROR_STATE:
- break;
- default:
- error("Unexpected error. Reached bad switch.\n");
- break;
- }
-
- if (il_image->bits)
- free (il_image->bits);
-
- il_image->bits = malloc (il_image->widthBytes * il_image->height);
- memset (il_image->bits, ~0, (il_image->widthBytes * il_image->height));
- if (!il_image->mask && il_image->transparent)
- {
- int size = il_image->maskWidthBytes * il_image->height;
- il_image->mask = malloc (size);
- memset (il_image->mask, ~0, size);
- }
-
- return 0;
- }
-
-
- /*
- * print_image
- */
- void
- print_image(IL_Image* il_image)
- {
- printf("---------------------------------------------\n");
- printf("il_image->width = %d\n", il_image->width);
- printf("il_image->height = %d\n", il_image->height);
- printf("il_image->widthBytes = %d\n", il_image->widthBytes);
- printf("il_image->maskWidthBytes = %d\n", il_image->maskWidthBytes);
- printf("il_image->depth = %d\n", il_image->depth);
- printf("il_image->bytesPerPixel = %d\n", il_image->bytesPerPixel);
- printf("il_image->colors = %d\n", il_image->colors);
- printf("il_image->unique_colors = %d\n", il_image->unique_colors);
- printf("il_image->validHeight = %d\n", il_image->validHeight);
- printf("il_image->lastValidHeight = %d\n", il_image->lastValidHeight);
- printf("il_image->has_mask = %s\n", il_image->has_mask ?
- "True" : "False");
- printf("il_image->hasUniqueColormap = %s\n", il_image->hasUniqueColormap ?
- "True" : "False");
- }
-
-
- /*
- * get_color
- */
- int
- get_color(uchar_t r, uchar_t g, uchar_t b)
- {
- int i;
-
- #ifdef DEBUG_username
- printf("Trying to find %d %d %d... ", r, g, b);
- #endif
-
- for ( i = 0; i < total_colors; i++ ) {
- if ( cmap[i].red == r &&
- cmap[i].green == g &&
- cmap[i].blue == b ) {
- return i;
- }
- }
-
- if ( total_colors > 64 ) {
- error("Animations can contain no more than 64 colors.\n");
- }
-
- cmap[total_colors].red = r;
- cmap[total_colors].green = g;
- cmap[total_colors].blue = b;
-
- total_colors++;
-
- return (total_colors-1);
- }
-
-
- /*
- * image_data
- * This routine is registered with the image library. It is invoked
- * when the image library has image data to be processed. The mono
- * bits, mask bits and color bits are written to the output buffer.
- */
- void
- image_data (MWContext *context, IL_ImageStatus message, IL_Image *il_image,
- void *data)
- {
- int row_parity;
- unsigned char *s, *m, *scanline, *mask_scanline, *end;
-
- #ifdef DEBUG_username
- print_image(il_image);
- #endif
-
- if (message != ilComplete) abort ();
- images[total_images].width = il_image->width;
- images[total_images].height = il_image->height;
- if (il_image->depth == 1)
- images[total_images].mono_bits = il_image->bits;
- else
- images[total_images].color_bits = il_image->bits;
- if (il_image->mask)
- images[total_images].mask_bits = il_image->mask;
-
- if (il_image->depth == 1)
- return;
- if (il_image->depth != 32) {
- error("Color image depth not 32.\n");
- }
-
- /* Generate monochrome icon from color data. */
- scanline = il_image->bits;
- mask_scanline = il_image->mask;
- end = scanline + (il_image->widthBytes * il_image->height);
- row_parity = 0;
-
- while (scanline < end)
- {
- unsigned char *scanline_end = scanline + (il_image->width * 4);
- int luminance, pixel;
- int bit = 0;
- uchar_t byte = 0;
-
- row_parity ^= 1;
- for (m = mask_scanline, s = scanline; s < scanline_end; s += 4)
- {
- unsigned char r = s[3];
- unsigned char g = s[2];
- unsigned char b = s[1];
-
- luminance = (0.299 * r) + (0.587 * g) + (0.114 * b);
-
- pixel =
- ((luminance < 128)) ||
- ((r == 66) && (g == 154) && (b == 167)); /* Magic: blue */
- byte |= pixel << bit++;
-
- if ((bit == 8) || ((s + 4) >= scanline_end)) {
- /* Handle transparent areas of the icon */
- if (il_image->mask)
- byte &= bitrev[*m++];
-
- append_to_output_file((char*) &byte, 1);
-
- bit = 0;
- byte = 0;
- }
- }
- scanline += il_image->widthBytes;
- mask_scanline += il_image->maskWidthBytes;
- }
-
- /* Mask data */
- if (il_image->mask)
- {
- scanline = il_image->mask;
- end = scanline + (il_image->maskWidthBytes * il_image->height);
- for (;scanline < end; scanline += il_image->maskWidthBytes)
- {
- unsigned char *scanline_end = scanline + ((il_image->width + 7) / 8);
- for (s = scanline; s < scanline_end; s++)
- {
- append_to_output_file((char*) &(bitrev[*s]), 1);
- }
- }
- }
- else
- {
- append_to_output_file(0, (il_image->width+7)/8*(il_image->height));
- }
-
- /* Color icon */
-
- scanline = il_image->bits;
- end = scanline + (il_image->widthBytes * il_image->height);
- for (;scanline < end; scanline += il_image->widthBytes)
- {
- unsigned char *scanline_end = scanline + (il_image->width * 4);
- for (s = scanline; s < scanline_end; s += 4)
- {
- unsigned char r = s[3];
- unsigned char g = s[2];
- unsigned char b = s[1];
- int j;
- uchar_t byte;
- j = get_color(r, g, b);
- byte = (uchar_t) j;
- append_to_output_file((char*) &byte, 1);
-
- #ifdef DEBUG_username
- for (j = 0; j < total_colors; j++)
- if (r == cmap[j].red &&
- g == cmap[j].green &&
- b == cmap[j].blue)
- {
- byte = (uchar_t) j;
- append_to_output_file((char*) &byte, 1);
- goto DONE;
- }
- error("Error allocated colors.\n");
- DONE:
- ;
- #endif
- }
- }
-
- if (il_image->bits) free (il_image->bits);
- il_image->bits = 0;
- if (il_image->mask) free (il_image->mask);
- il_image->mask = 0;
- }
-
-
- /*
- * set_title
- * A no-op.
- */
- void
- set_title (MWContext *context, char *title)
- {
- }
-
-
- /*
- * do_file
- * Process an image file.
- */
- void
- do_file (char *file)
- {
- static int counter = 0;
- FILE *fp;
- char *data;
- int size;
- NET_StreamClass *stream;
- struct stat st;
- char *s;
-
- URL_Struct *url;
- il_container *ic;
- il_process *proc;
- MWContext cx;
- ContextFuncs fns;
- IL_IRGB trans;
-
- memset (&cx, 0, sizeof(cx));
- memset (&fns, 0, sizeof(fns));
-
- url = XP_NEW_ZAP (URL_Struct);
- proc = XP_NEW_ZAP (il_process);
-
- url->address = strdup("\000\000");
- cx.funcs = &fns;
-
- fns.ImageSize = image_size;
- fns.ImageData = image_data;
- fns.SetDocTitle = set_title;
-
- {
- /* make a container */
- ic = XP_NEW_ZAP(il_container);
- ic->hash = 0;
- ic->urlhash = 0;
- ic->cx = &cx;
- ic->forced = 0;
-
- ic->image = XP_NEW_ZAP(IL_Image);
-
- ic->next = 0;
- ic->ip = proc;
- cx.imageProcess = proc;
-
- ic->state = IC_START;
- }
-
- url->fe_data = ic;
-
- ic->clients = XP_NEW_ZAP(il_client);
- ic->clients->cx = &cx;
-
- if ( stat (file, &st) ) {
- perror(file);
- exit(errno);
- }
-
- if ( !S_ISREG(st.st_mode) ) {
- fprintf(stderr, "%s: Not a plain file.\n", file);
- exit(1);
- }
-
- size = st.st_size;
-
- data = (char *) malloc (size + 1);
- fp = fopen (file, "r");
- fread (data, 1, size, fp);
- fclose (fp);
-
- current_file = strdup(file);
-
- s = strrchr (file, '.');
- if (s) *s = 0;
- s = strrchr (file, '/');
- if (s)
- s++;
- else
- s = file;
-
- if (in_anim && strncmp (s, "Anim", 4))
- /* once you've started anim frames, don't stop. */
- abort ();
-
- if ((!strcmp (s, "AnimSm00") || !strcmp (s, "AnimHuge00")) ||
- ((!strcmp (s, "AnimSm01") || !strcmp (s, "AnimHuge01")) &&
- (!in_anim ||
- anim_frames[in_anim-1] > 1)))
- {
- char *s2;
-
- s2 = s - 2;
- while (s2 > file && *s2 != '/')
- s2--;
- s[-1] = 0;
- if (*s2 == '/')
- s2++;
-
- in_anim++;
- }
-
- if (in_anim)
- {
- if (strncmp (s, "Anim", 4)) abort ();
- anim_frames[in_anim-1]++;
- }
- else
- {
- char *s2 = s;
- while (*s2)
- {
- if (*s2 == '.') *s2 = '_';
- s2++;
- }
- }
-
- trans.red = trans.green = trans.blue = 0xC0;
-
- cx.colorSpace = NULL;
-
- IL_EnableTrueColor (&cx, 32,
- #if defined(IS_LITTLE_ENDIAN)
- 24, 16, 8,
- #elif defined(IS_BIG_ENDIAN)
- 0, 8, 16,
- #else
- ERROR! Endianness unknown.
- #endif
- 8, 8, 8,
- &trans, FALSE);
-
- ic->cs = cx.colorSpace;
- /*IL_SetPreferences (&cx, FALSE, ilClosestColor);*/
- IL_SetPreferences (&cx, FALSE, ilDither);/* XXXM12N Replace with
- IL_SetDisplayMode. */
- url->address[0] = counter++;
- stream = IL_NewStream (FO_PRESENT,
- (strstr (current_file, ".gif") ? (void *) IL_GIF :
- strstr (current_file, ".jpg") ? (void *) IL_JPEG :
- strstr (current_file, ".jpeg") ? (void *) IL_JPEG :
- strstr (current_file, ".xbm") ? (void *) IL_XBM :
- (void *) IL_GIF),
- url, &cx);
- if ( stream->put_block (stream, data, size) < 0 ) {
- error("Couldn't decode file.\n");
- }
-
- stream->complete (stream);
-
- free(current_file);
- free (data);
-
- total_images++;
- }
-
-
- uchar_t* output_buf = NULL;
- int output_max_len = 0;
- int output_len = 0;
-
-
- /*
- * CHUNKSIZE should be 1024 or something, but make
- * it small to make sure it works.
- */
- #define CHUNKSIZE 64
-
-
- /*
- * append_to_output_file
- * Append the given data to the output buffer. If the resulting data
- * is too large for the currently allocated output buffer, first allocate
- * additional space.
- */
- void
- append_to_output_file(char* data, int len)
- {
- while ( output_buf == NULL || output_len + len >= output_max_len ) {
- output_max_len+= CHUNKSIZE;
- output_buf = (char*) realloc(output_buf, output_max_len);
- }
-
- if ( data ) {
- memcpy(output_buf+output_len, data, len);
- } else {
- memset(output_buf+output_len, 0xff, len);
- }
-
- output_len+= len;
- }
-
-
- #define ANIMATION_FILENAME "animation.dat"
-
-
- /*
- * usage
- */
- void
- usage(char* progname)
- {
- fprintf(stderr, "Usage: %s large-animation-files small-animation-files\n",
- progname);
- }
-
-
- /*
- * main
- * Process each file given on the command line.
- */
- int
- main (int argc, char* argv[])
- {
- int i;
- FILE* anim_file;
-
- init_reverse_bits();
-
- if ( argc < 2 ) {
- usage(argv[0]);
- exit(1);
- }
-
- for (i = 1; i < argc; i++) {
- char *filename = argv[i];
- inactive_icon_p = (strstr(filename, ".i.gif") != NULL);
- do_file (filename);
- }
-
- if ( (anim_file = fopen(ANIMATION_FILENAME, "w")) == NULL ) {
- perror(ANIMATION_FILENAME);
- exit(errno);
- }
-
- fprintf(anim_file, "%d %d %d\n", num_frames_large, width_large, height_large);
- fprintf(anim_file, "%d %d %d\n", num_frames_small, width_small, height_small);
- fprintf(anim_file, "%d\n", total_colors);
-
- for ( i = 0; i < total_colors; i++ ) {
- fprintf(anim_file, "%x %x %x\n", cmap[i].red * 257,
- cmap[i].green * 257,
- cmap[i].blue * 257);
- }
-
- if ( output_buf == NULL ) {
- error("No image data to write.\n");
- }
-
- if ( fwrite(output_buf, sizeof(uchar_t), output_len, anim_file) !=
- output_len) {
- perror(ANIMATION_FILENAME);
- exit(errno);
- }
-
- if ( fclose(anim_file) != 0 ) {
- perror(ANIMATION_FILENAME);
- exit(errno);
- }
-
- printf("Wrote %d large frames, %d small frames.\n", num_frames_large,
- num_frames_small);
-
- printf("%d colors\n", total_colors);
-
- fprintf(stderr, "Successfully wrote '%s'\n", ANIMATION_FILENAME);
-
- return 0;
- }
-
-
-