211 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			211 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* vim:expandtab:ts=2 sw=2:
 | 
						|
*/
 | 
						|
/*  Grafx2 - The Ultimate 256-color bitmap paint program
 | 
						|
 | 
						|
    Copyright 2018 Thomas Bernard
 | 
						|
 | 
						|
    Grafx2 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; version 2
 | 
						|
    of the License.
 | 
						|
 | 
						|
    Grafx2 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 Grafx2; if not, see <http://www.gnu.org/licenses/>
 | 
						|
*/
 | 
						|
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
#ifdef _MSC_VER
 | 
						|
#include <stdio.h>
 | 
						|
#if _MSC_VER < 1900
 | 
						|
#define snprintf _snprintf
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
#include "struct.h"
 | 
						|
#include "global.h"
 | 
						|
#include "loadsave.h"
 | 
						|
#include "io.h"
 | 
						|
#include "errors.h"
 | 
						|
 | 
						|
#include "recoil.h"
 | 
						|
 | 
						|
// RECOIL Vtable with our private data added
 | 
						|
typedef struct {
 | 
						|
	int (*readFile)(RECOIL *, const char *filename, unsigned char *content, int content_length);
 | 
						|
  T_IO_Context *context;
 | 
						|
}
 | 
						|
RECOILVtbl;
 | 
						|
 | 
						|
static int RECOIL_ReadFile(RECOIL * recoil, const char * filename, unsigned char * content, int content_length)
 | 
						|
{
 | 
						|
  FILE * f;
 | 
						|
  const char * ext;
 | 
						|
 | 
						|
  ext = strrchr(filename, '.');   // extract back extension from filename
 | 
						|
  if (ext == NULL)
 | 
						|
    return -1;
 | 
						|
  ext++;
 | 
						|
  f = Open_file_read_with_alternate_ext((*((const RECOILVtbl **)recoil))->context, ext);
 | 
						|
  if (f == NULL)
 | 
						|
    return -1;
 | 
						|
  content_length = fread(content, 1, content_length, f);
 | 
						|
  fclose(f);
 | 
						|
  return content_length;
 | 
						|
}
 | 
						|
 | 
						|
void Load_Recoil_Image(T_IO_Context *context)
 | 
						|
{
 | 
						|
  RECOILVtbl vtbl = { RECOIL_ReadFile, context };
 | 
						|
  RECOIL *recoil;
 | 
						|
  byte * file_content;
 | 
						|
  unsigned long file_length;
 | 
						|
  FILE * f;
 | 
						|
 | 
						|
  f = Open_file_read(context);
 | 
						|
  if (f == NULL)
 | 
						|
  {
 | 
						|
    File_error = 1;
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  file_length = File_length_file(f);
 | 
						|
  if (file_length == 0)
 | 
						|
  {
 | 
						|
    fclose(f);
 | 
						|
    File_error = 1;
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  file_content = malloc(file_length);
 | 
						|
  if (file_content == NULL)
 | 
						|
  {
 | 
						|
    Warning("Memory allocation error");
 | 
						|
    fclose(f);
 | 
						|
    File_error = 1;
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  if (!Read_bytes(f, file_content, file_length))
 | 
						|
  {
 | 
						|
    Warning("Read error");
 | 
						|
    fclose(f);
 | 
						|
    free(file_content);
 | 
						|
    File_error = 1;
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  fclose(f);
 | 
						|
 | 
						|
  recoil = RECOIL_New();
 | 
						|
  if (recoil)
 | 
						|
  {
 | 
						|
#ifdef WIN32
 | 
						|
    char tempfilename[MAX_PATH_CHARACTERS];
 | 
						|
#endif
 | 
						|
    const char * filename = context->File_name;
 | 
						|
    *(const RECOILVtbl **)recoil = &vtbl; // set Vtable
 | 
						|
#ifdef WIN32
 | 
						|
    if (context->File_name_unicode != NULL && context->File_name_unicode[0] != 0)
 | 
						|
    {
 | 
						|
      // get the full file extension from the long filename (unicode)
 | 
						|
      // RECOIL doesn't recognize file if the "short" extension is passed,
 | 
						|
      // ie .DEE instead of .deep
 | 
						|
      int i;
 | 
						|
      for (i = 0; context->File_name_unicode[i] != 0 && i < (int)sizeof(tempfilename) - 1; i++)
 | 
						|
        tempfilename[i] = (context->File_name_unicode[i] < 256) ? (char)context->File_name_unicode[i] : '_';
 | 
						|
      tempfilename[i] = '\0';
 | 
						|
      filename = tempfilename;
 | 
						|
    }
 | 
						|
#endif
 | 
						|
    if (RECOIL_Decode(recoil, filename, file_content, file_length))
 | 
						|
    {
 | 
						|
      int width, height;
 | 
						|
      int original_width, original_height;
 | 
						|
      int x, y;
 | 
						|
      int x_ratio, y_ratio;
 | 
						|
      byte * pixels;
 | 
						|
      const int *palette;
 | 
						|
      enum PIXEL_RATIO ratio = PIXEL_SIMPLE;
 | 
						|
 | 
						|
      width = RECOIL_GetWidth(recoil);
 | 
						|
      height = RECOIL_GetHeight(recoil);
 | 
						|
      original_width = RECOIL_GetOriginalWidth(recoil);
 | 
						|
      original_height = RECOIL_GetOriginalHeight(recoil);
 | 
						|
      x_ratio = width / original_width;
 | 
						|
      y_ratio = height / original_height;
 | 
						|
      if (x_ratio > 1 && y_ratio == 1)
 | 
						|
        ratio = PIXEL_WIDE;
 | 
						|
      else if(x_ratio == 1 && y_ratio > 1)
 | 
						|
        ratio = PIXEL_TALL;
 | 
						|
      pixels = malloc(width * height);
 | 
						|
      if (pixels == NULL)
 | 
						|
      {
 | 
						|
        Warning("Memory allocation error");
 | 
						|
        File_error = 1;
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        // try to convert to 8bpp image
 | 
						|
        File_error = 0;
 | 
						|
        palette = RECOIL_ToPalette(recoil, pixels);
 | 
						|
        if (palette == NULL)
 | 
						|
        {
 | 
						|
          // 24bits
 | 
						|
          const int * tc_pixels;
 | 
						|
 | 
						|
          Pre_load(context, original_width, original_height, file_length, FORMAT_MISC, ratio, 24);
 | 
						|
          tc_pixels = RECOIL_GetPixels(recoil);
 | 
						|
          for (y = 0; y < original_height; y++)
 | 
						|
          {
 | 
						|
            for (x = 0; x < original_width; x++)
 | 
						|
            {
 | 
						|
              Set_pixel_24b(context, x, y, *tc_pixels >> 16, *tc_pixels >> 8, *tc_pixels);
 | 
						|
              tc_pixels += x_ratio;
 | 
						|
            }
 | 
						|
            tc_pixels += width * (y_ratio - 1);
 | 
						|
          }
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
          // 8bits
 | 
						|
          int i;
 | 
						|
          int bpp;
 | 
						|
          int ncolors = RECOIL_GetColors(recoil);
 | 
						|
          const byte * p = pixels;
 | 
						|
 | 
						|
          bpp = 8;
 | 
						|
          while (ncolors <= (1 << (bpp - 1)))
 | 
						|
            bpp--;
 | 
						|
          if (Config.Clear_palette)
 | 
						|
            memset(context->Palette,0,sizeof(T_Palette));
 | 
						|
          for (i = 0; i < ncolors; i++)
 | 
						|
          {
 | 
						|
            context->Palette[i].R = (byte)(palette[i] >> 16);
 | 
						|
            context->Palette[i].G = (byte)(palette[i] >> 8);
 | 
						|
            context->Palette[i].B = (byte)(palette[i]);
 | 
						|
          }
 | 
						|
          Pre_load(context, original_width, original_height, file_length, FORMAT_MISC, ratio, bpp);
 | 
						|
          for (y = 0; y < original_height; y++)
 | 
						|
          {
 | 
						|
            for (x = 0; x < original_width; x++)
 | 
						|
            {
 | 
						|
              Set_pixel(context, x, y, *p);
 | 
						|
              p += x_ratio;
 | 
						|
            }
 | 
						|
            p += width * (y_ratio - 1);
 | 
						|
          }
 | 
						|
        }
 | 
						|
        free(pixels);
 | 
						|
        if (!File_error)
 | 
						|
        {
 | 
						|
          snprintf(context->Comment, COMMENT_SIZE + 1, "RECOIL: %s %d colors", RECOIL_GetPlatform(recoil), RECOIL_GetColors(recoil));
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    RECOIL_Delete(recoil);
 | 
						|
  }
 | 
						|
  free(file_content);
 | 
						|
}
 |