From YPPedia
/* bmpread.c reads any bitmap I could get for testing */
/* Alexander.Schulz@stud.uni-karlsruhe.de */
/*
* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* ----------------------------------------------------------------------------
* Modified - atteSmythe@atteSmythe.com - 10 Aug 05
*/
#include "config.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
#include <libgimp/gimp.h>
#include "yppRAW.h"
#include "libgimp/stdplugins-intl.h"
#if !defined(WIN32) || defined(__MINGW32__)
#define BI_RGB 0
#define BI_RLE8 1
#define BI_RLE4 2
#define BI_BITFIELDS 3
#else
#include <windows.h>
#endif
static gint32 ReadImage (
FILE *fd,
guint width,
guint height,
guchar *alpha,
guchar **palette,
guint colors
);
static gint32
ToL (const guchar *puffer)
{
return (puffer[3] | puffer[2] << 8 | puffer[1] << 16 | puffer[0] << 24);
}
static gint16
ToS (const guchar *puffer)
{
return (puffer[1] | puffer[0] << 8);
}
static gboolean
ReadPalette(FILE *fd, guchar *alpha, guchar **colors, guint entries) {
guint i;
guchar ABGR[4];
for (i=0; i < entries; ++i) {
if (!ReadOK (fd, ABGR, sizeof(ABGR))) {
g_message(_("Palette Incomplete"));
return FALSE;
}
// Since we want to do A(RGB), not A(BGR), we'll have to swap here,
// so as only to swap once.
alpha[i] = ABGR[0];
colors[0][i] = ABGR[1];
colors[1][i] = ABGR[2];
colors[2][i] = ABGR[3];
}
return TRUE;
}
/*
static gboolean
ReadColorMap (FILE *fd,
guchar buffer[256][3],
gint number,
gint size,
gboolean *grey)
{
gint i;
guchar rgb[4];
*grey = (number > 2);
for (i = 0; i < number ; i++)
{
if (!ReadOK (fd, rgb, size))
{
g_message (_("Bad colormap"));
return FALSE;
}
// Bitmap save the colors in another order! But change only once!
buffer[i][0] = rgb[2];
buffer[i][1] = rgb[1];
buffer[i][2] = rgb[0];
*grey = ((*grey) && (rgb[0]==rgb[1]) && (rgb[1]==rgb[2]));
}
return TRUE;
}
static gboolean
ReadChannelMasks (FILE *fd, Bitmap_Channel *masks, guint channels)
{
guint32 tmp[3];
guint32 mask;
gint nbits, offset, bit;
guint i;
if (!ReadOK (fd, tmp, 3 * sizeof (guint32)))
return FALSE;
for (i = 0; i < channels; i++)
{
mask = ToL ((guchar*) &tmp[i]);
masks[i].mask = mask;
nbits = 0;
offset = -1;
for (bit = 0; bit < 32; bit++)
{
if (mask & 1)
{
nbits++;
if (offset == -1)
offset = bit;
}
mask = mask >> 1;
}
masks[i].shiftin = offset;
masks[i].shiftout = 8 - nbits;
#ifdef DEBUG
g_print ("Channel %d mask %08x in %d out %d\n", i, masks[i].mask, masks[i].shiftin, masks[i].shiftout);
#endif
}
return TRUE;
}
*/
gint32
ReadRAW (const gchar *name)
{
FILE *fd;
gchar *temp_buf;
struct RAW_File_Head_Struct {
_int32 Xsize;
_int32 Ysize;
_int32 PaletteUsed;
_int32 PaletteSize;
} RAW_File_Head;
guchar *palAlpha;
guchar **palColors;
gint32 image_ID;
gint i;
filename = name;
fd = fopen (filename, "rb");
if (!fd) {
g_message (_("Could not open '%s' for reading: %s"),
gimp_filename_to_utf8 (filename), g_strerror (errno));
return -1;
}
temp_buf = g_strdup_printf (_("Opening '%s'..."),
gimp_filename_to_utf8 (name));
gimp_progress_init (temp_buf);
g_free (temp_buf);
// It is a File. Now is it a valid RAWfile? Read the shortest possible header
if (!ReadOK (fd, &RAW_File_Head, sizeof(RAW_File_Head))) {
g_message (_("Could not read file header in '%s'"),
gimp_filename_to_utf8 (filename));
return -1;
}
RAW_File_Head.Xsize = ToL((unsigned char*)&RAW_File_Head.Xsize);
RAW_File_Head.Ysize = ToL((unsigned char*)&RAW_File_Head.Ysize);
RAW_File_Head.PaletteUsed = ToL((unsigned char *)&RAW_File_Head.PaletteUsed);
RAW_File_Head.PaletteSize = ToL((unsigned char *)&RAW_File_Head.PaletteSize);
if (RAW_File_Head.PaletteSize < RAW_File_Head.PaletteUsed) {
g_message (_("'%s' is not a valid Y!PP RAW file"),
gimp_filename_to_utf8 (filename));
return -1;
}
// How about a palette? I'd like a palette. And an alpha palette!
// First check for no colors...
if (RAW_File_Head.PaletteSize == 0 ||
RAW_File_Head.Xsize == 0 ||
RAW_File_Head.Ysize == 0) {
g_message (_("Error reading Y!PP RAW file header from '%s'"),
gimp_filename_to_utf8(filename));
return -1;
}
palAlpha = (guchar*)g_malloc(RAW_File_Head.PaletteSize);
palColors = (guchar**)g_malloc(sizeof(unsigned char*[3]));
for (i=0; i<3; ++i) {
palColors[i] = (guchar*)g_malloc(RAW_File_Head.PaletteSize);
}
if (!ReadPalette(fd, palAlpha, palColors, RAW_File_Head.PaletteSize)) {
g_message (_("'%s' is not a valid Y!PP RAW file"),
gimp_filename_to_utf8 (filename));
return -1;
}
// Get the Image and return the ID or -1 on error
image_ID = ReadImage (fd,
RAW_File_Head.Xsize,
RAW_File_Head.Ysize,
palAlpha,
palColors,
RAW_File_Head.PaletteSize
);
g_free(palAlpha);
for (i=0; i<3; ++i) {
g_free(palColors[i]);
}
g_free(palColors);
return image_ID;
}
static gint32
ReadImage (
FILE *fd,
guint width,
guint height,
guchar *alpha,
guchar **palette,
guint colors
)
{
/*
guchar v, n;
guchar *dest, *temp, *buffer;
guchar gimp_cmap[768];
gushort rgb;
glong rowstride, channels;
*/
gint32 image;
gint32 layer;
glong rowstride, channels;
GimpPixelRgn pixel_rgn;
GimpDrawable *drawable;
guchar *dest, *temp, *buffer;
gint cur_progress, max_progress;
guint xpos, ypos;
guint cidx;
// Create an image in the GIMP
image = gimp_image_new (width, height, GIMP_RGB);
layer = gimp_layer_new (image, _("Background"),
width, height,
GIMP_RGBA_IMAGE, 100, GIMP_NORMAL_MODE);
channels = 4; // RGB+A
gimp_image_set_filename (image, filename);
gimp_image_add_layer (image, layer, 0);
drawable = gimp_drawable_get (layer);
// create a temporary, uncompressed version from which to transfer to GIMP
dest = g_malloc (drawable->width * drawable->height * channels);
// read buffer - size = 1 row of _source_
buffer = g_malloc (drawable->width);
// how far to advance the pointer into the dest array each iteration
rowstride = drawable->width * channels;
cur_progress = 0;
max_progress = height;
for (ypos=0; ypos < height; ++ypos) {
if (!ReadOK(fd,buffer,drawable->width)) { break; }
temp = dest + ypos*rowstride;
for (xpos=0; xpos < width; ++xpos) {
cidx = buffer[xpos];
*(temp++)=palette[0][cidx]; // R
*(temp++)=palette[1][cidx]; // G
*(temp++)=palette[2][cidx]; // B
*(temp++)=alpha[cidx]; // A
}
++cur_progress;
if ((cur_progress %5) == 0) {
gimp_progress_update((gdouble) cur_progress / (gdouble)max_progress);
}
}
fclose (fd);
gimp_progress_update (1);
gimp_pixel_rgn_init (&pixel_rgn, drawable,
0, 0, drawable->width, drawable->height, TRUE, FALSE);
gimp_pixel_rgn_set_rect (&pixel_rgn, dest,
0, 0, drawable->width, drawable->height);
gimp_drawable_flush (drawable);
gimp_drawable_detach (drawable);
g_free (dest);
g_free (buffer);
return image;
}