User:AtteSmythe/yppRAW/yppRAWrd.c
From YPPedia
< User:AtteSmythe | yppRAW
/* 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; }