PCX support for gdk-pixbuf
- From: "Terry 'Mongoose' Hendrix II" <stu7440 westga edu>
- To: gtk-devel-list gnome org
- Subject: PCX support for gdk-pixbuf
- Date: 10 May 2001 01:57:25 -0500
Well, I figured I'd dump the PCX loader on you guys too - I'll be moving
these to tmp file less progressive loaders this week as I port my
modeler to gnome. This prob isn't useful as the TGA, unless you do a
lot of quakeforge development. =)
cheers,
Terry
--
---------------------------------------------------
| GooseEgg http://gooseegg.sourceforge.net |
| QuakeForge http://www.quakeforge.net |
| Personal http://www.westga.edu/~stu7440 |
| |
| Death is running Debian GNU/Linux |
---------------------------------------------------
/* -*- Mode: C; tab-width: 3; indent-tabs-mode: t; c-basic-offset: 3 -*- */
/* GdkPixbuf library - PCX image loader
*
* Copyright (C) 2001 Mongoose
*
* Authors: Terry 'Mongoose' Hendrix II <stu7440 westga edu>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <config.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
#include "gdk-pixbuf-private.h"
#include "gdk-pixbuf-io.h"
#define MONGOOSE_PCX
#ifdef MONGOOSE_PCX
#define PCX_FATAL_ERR -1
#define PCX_SUSPEND 0
#define PCX_OK 1
typedef struct pcx_header_s
{
guchar signature;
guchar version;
guchar encoding;
guchar bytes_per_pixel;
gushort xmin;
gushort ymin;
gushort xmax;
gushort ymax;
gushort vres;
gushort hres;
guchar palette[48];
guchar reserved;
guchar color_layers;
gushort bytes_per_line;
gushort palette_type;
guchar unused[58];
} pcx_header_t;
typedef struct _PcxData PcxData;
struct _PcxData
{
ModulePreparedNotifyFunc prepare_func;
ModuleUpdatedNotifyFunc update_func;
gpointer user_data;
gchar *tempname;
FILE *file;
gboolean all_okay;
};
GdkPixbuf *gdk_pixbuf__pcx_image_load (FILE *f);
gpointer gdk_pixbuf__pcx_image_begin_load (ModulePreparedNotifyFunc func,
ModuleUpdatedNotifyFunc func2,
ModuleFrameDoneNotifyFunc frame_done_func,
ModuleAnimationDoneNotifyFunc anim_done_func,
gpointer user_data);
void gdk_pixbuf__pcx_image_stop_load (gpointer context);
gboolean gdk_pixbuf__pcx_image_load_increment (gpointer context, guchar *buf, guint size);
/* Destroy notification function for the pixbuf */
static void
free_buffer (guchar *pixels, gpointer data)
{
g_free (pixels);
}
/* Shared library entry point */
GdkPixbuf *
gdk_pixbuf__pcx_image_load (FILE *f)
{
guint size, i, index, width, height;
guchar *indexed_image = NULL;
guchar *palette = NULL;
guchar *image = NULL;
pcx_header_t header;
guchar buf;
guint counter;
if (!f)
return NULL;
fseek(f, 0, SEEK_SET);
if (fread(&header, sizeof(pcx_header_t), 1, f) < 1)
{
perror("gdk_pixbuf__pcx_image_load> Failed to read file.\n");
return NULL;
}
if ((header.signature != 0x0a) || (header.version != 5))
{
fprintf(stderr, "gdk_pixbuf__pcx_image_load> Unknown PCX format.\n");
return NULL;
}
/* Get height and length */
width = header.xmax + 1 - header.xmin;
height = header.ymax + 1 - header.ymin;
size = width * height;
if (!size)
{
fprintf(stderr, "gdk_pixbuf__pcx_image_load> Will not allocate 0bytes.\n");
return NULL;
}
printf("PCX [%ix%i 8bpp]\n", width, height);
/* Allocate indexed palette, indexed image, and rgb image */
palette = g_malloc(768);
indexed_image = g_malloc(size);
image = g_malloc(size * 3);
if (!indexed_image || !palette || !image)
{
if (image)
g_free(image);
if (indexed_image)
g_free(indexed_image);
if (palette)
g_free(palette);
fprintf(stderr, "gdk_pixbuf__pcx_image_load> Malloc failed.\n");
return NULL;
}
/* Read the indexed image from file */
for (i = 0; i <= size;)
{
/* Get one byte */
fread(&buf, 1, 1, f);
/* Check the 2 most significant bits */
if ((buf & 192) == 192)
{
/* We have 11xxxxxx */
counter = (buf & 63); /* Number of times to repeat next byte */
fread(&buf, 1, 1, f); /* Get next byte */
for(; counter > 0; counter--) /* and copy it counter times */
{
indexed_image[i++] = buf;
}
}
else
{
/* Just copy the byte */
indexed_image[i++] = buf;
}
}
/* Read the palette index */
fseek(f, -768, SEEK_END);
fread(palette, 1, 768, f);
/* Convert to RGB image */
for (i = 0; i < size; i++)
{
index = indexed_image[i];
if (index * 3 + 2 > 768)
printf("gdk_pixbuf::pcx_load> Corupt image index.\n");
else
{
image[i*3] = palette[index*3];
image[i*3+1] = palette[index*3+1];
image[i*3+2] = palette[index*3+2];
}
}
if (indexed_image)
g_free(indexed_image);
if (palette)
g_free(palette);
return gdk_pixbuf_new_from_data(image, GDK_COLORSPACE_RGB, FALSE, 8,
width, height,
width * 3, free_buffer, NULL);
}
/* Progressive loader, barrowed file cache to disk hack from tiff for now */
gpointer
gdk_pixbuf__pcx_image_begin_load (ModulePreparedNotifyFunc prepare_func,
ModuleUpdatedNotifyFunc update_func,
ModuleFrameDoneNotifyFunc frame_done_func,
ModuleAnimationDoneNotifyFunc anim_done_func,
gpointer user_data)
{
PcxData *context;
gint fd;
context = g_new (PcxData, 1);
context->prepare_func = prepare_func;
context->update_func = update_func;
context->user_data = user_data;
context->all_okay = TRUE;
context->tempname = g_strdup ("/tmp/gdkpixbuf-pcx-tmp.XXXXXX");
fd = mkstemp (context->tempname);
if (fd < 0) {
g_free (context->tempname);
g_free (context);
return NULL;
}
context->file = fdopen (fd, "w");
if (context->file == NULL) {
g_free (context->tempname);
g_free (context);
return NULL;
}
return context;
}
void
gdk_pixbuf__pcx_image_stop_load (gpointer data)
{
PcxData *context = (PcxData*) data;
GdkPixbuf *pixbuf;
g_return_if_fail (data != NULL);
fflush (context->file);
rewind (context->file);
// KAOS!!!! SHONOVEATA!!!
if (context->all_okay)
{
pixbuf = gdk_pixbuf__pcx_image_load(fopen(context->tempname, "rb"));
//context->file);
(* context->prepare_func) (pixbuf, context->user_data);
(* context->update_func)(pixbuf, 0, 0,
gdk_pixbuf_get_width(pixbuf),
gdk_pixbuf_get_height(pixbuf),
context->user_data);
gdk_pixbuf_unref(pixbuf);
}
fclose (context->file);
unlink (context->tempname);
g_free (context->tempname);
g_free ((PcxData *) context);
}
gboolean
gdk_pixbuf__pcx_image_load_increment (gpointer data, guchar *buf, guint size)
{
PcxData *context = (PcxData *) data;
g_return_val_if_fail (data != NULL, FALSE);
if (fwrite (buf, sizeof (guchar), size, context->file) != size) {
context->all_okay = FALSE;
return FALSE;
}
return TRUE;
}
#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]