TIFF support
This commit is contained in:
		
							parent
							
								
									36bd67f197
								
							
						
					
					
						commit
						7db03f7aab
					
				@ -461,10 +461,10 @@ endif
 | 
				
			|||||||
      LOPT += -lSDLmain -lSDL $(shell $(CROSS_SDLCONFIG) --libs) -lSDL_image
 | 
					      LOPT += -lSDLmain -lSDL $(shell $(CROSS_SDLCONFIG) --libs) -lSDL_image
 | 
				
			||||||
      endif
 | 
					      endif
 | 
				
			||||||
      ifeq (,$(CROSS_PKGCONFIG))
 | 
					      ifeq (,$(CROSS_PKGCONFIG))
 | 
				
			||||||
      COPT += -D__no_pnglib__
 | 
					      COPT += -D__no_pnglib__ -D__no_tifflib__
 | 
				
			||||||
      else
 | 
					      else
 | 
				
			||||||
      COPT += $(shell PKG_CONFIG_LIBDIR=$(CROSS_PKG_CONFIG_PATH) $(CROSS_PKGCONFIG) --cflags libpng || echo "-D__no_pnglib__" )
 | 
					      COPT += $(shell PKG_CONFIG_LIBDIR=$(CROSS_PKG_CONFIG_PATH) $(CROSS_PKGCONFIG) --cflags libpng || echo "-D__no_pnglib__" )
 | 
				
			||||||
      LOPT += $(shell PKG_CONFIG_LIBDIR=$(CROSS_PKG_CONFIG_PATH) $(CROSS_PKGCONFIG) --libs libpng)
 | 
					      LOPT += $(shell PKG_CONFIG_LIBDIR=$(CROSS_PKG_CONFIG_PATH) $(CROSS_PKGCONFIG) --libs libpng libtiff-4)
 | 
				
			||||||
      endif
 | 
					      endif
 | 
				
			||||||
      LUALOPT = -llua
 | 
					      LUALOPT = -llua
 | 
				
			||||||
      COPT += $(LUACOPT)
 | 
					      COPT += $(LUACOPT)
 | 
				
			||||||
@ -576,7 +576,7 @@ endif
 | 
				
			|||||||
          COPT += -DNO_X11
 | 
					          COPT += -DNO_X11
 | 
				
			||||||
        endif
 | 
					        endif
 | 
				
			||||||
        LOPT += $(TTFLOPT)
 | 
					        LOPT += $(TTFLOPT)
 | 
				
			||||||
        LOPT += $(shell pkg-config --libs libpng)
 | 
					        LOPT += $(shell pkg-config --libs libpng libtiff-4)
 | 
				
			||||||
        LOPT += $(LUALOPT)
 | 
					        LOPT += $(LUALOPT)
 | 
				
			||||||
        OBJDIR = ../obj/unix
 | 
					        OBJDIR = ../obj/unix
 | 
				
			||||||
        FCLOPT = -lfontconfig
 | 
					        FCLOPT = -lfontconfig
 | 
				
			||||||
@ -705,7 +705,7 @@ OBJS = main.o init.o graph.o $(APIOBJ) misc.o special.o \
 | 
				
			|||||||
       fileformats.o miscfileformats.o libraw2crtc.o \
 | 
					       fileformats.o miscfileformats.o libraw2crtc.o \
 | 
				
			||||||
       brush_ops.o buttons_effects.o layers.o \
 | 
					       brush_ops.o buttons_effects.o layers.o \
 | 
				
			||||||
       oldies.o tiles.o colorred.o unicode.o gfx2surface.o \
 | 
					       oldies.o tiles.o colorred.o unicode.o gfx2surface.o \
 | 
				
			||||||
       gfx2log.o
 | 
					       gfx2log.o tifformat.o
 | 
				
			||||||
ifndef NORECOIL
 | 
					ifndef NORECOIL
 | 
				
			||||||
OBJS += loadrecoil.o recoil.o
 | 
					OBJS += loadrecoil.o recoil.o
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
				
			|||||||
@ -153,6 +153,7 @@ enum FILE_FORMATS
 | 
				
			|||||||
  FORMAT_FLI,  ///< Autodesk Animator FLI/FLC
 | 
					  FORMAT_FLI,  ///< Autodesk Animator FLI/FLC
 | 
				
			||||||
  FORMAT_MOTO, ///< Thomson MO/TO computers pictures
 | 
					  FORMAT_MOTO, ///< Thomson MO/TO computers pictures
 | 
				
			||||||
  FORMAT_HGR,  ///< Apple II HGR and DHGR
 | 
					  FORMAT_HGR,  ///< Apple II HGR and DHGR
 | 
				
			||||||
 | 
					  FORMAT_TIFF, ///< Tagged Image File Format
 | 
				
			||||||
  FORMAT_MISC, ///< Must be last of enum: others formats recognized by SDL_image (or recoil)
 | 
					  FORMAT_MISC, ///< Must be last of enum: others formats recognized by SDL_image (or recoil)
 | 
				
			||||||
  FORMAT_CLIPBOARD  ///< To load/save from/to Clipboard
 | 
					  FORMAT_CLIPBOARD  ///< To load/save from/to Clipboard
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -162,5 +162,12 @@ void Test_HGR(T_IO_Context *, FILE *);
 | 
				
			|||||||
void Load_HGR(T_IO_Context *);
 | 
					void Load_HGR(T_IO_Context *);
 | 
				
			||||||
void Save_HGR(T_IO_Context *);
 | 
					void Save_HGR(T_IO_Context *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// -- TIFF ------------------------------------------------------------------
 | 
				
			||||||
 | 
					#ifndef __no_tifflib__
 | 
				
			||||||
 | 
					void Test_TIFF(T_IO_Context *, FILE *);
 | 
				
			||||||
 | 
					void Load_TIFF(T_IO_Context *);
 | 
				
			||||||
 | 
					void Save_TIFF(T_IO_Context *);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// @}
 | 
					/// @}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,7 @@
 | 
				
			|||||||
*/
 | 
					*/
 | 
				
			||||||
/*  Grafx2 - The Ultimate 256-color bitmap paint program
 | 
					/*  Grafx2 - The Ultimate 256-color bitmap paint program
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Copyright 2018 Thomas Bernard
 | 
				
			||||||
    Copyright 2011 Pawel Góralski
 | 
					    Copyright 2011 Pawel Góralski
 | 
				
			||||||
    Copyright 2010 Alexander Filyanov
 | 
					    Copyright 2010 Alexander Filyanov
 | 
				
			||||||
    Copyright 2009 Petter Lindquist
 | 
					    Copyright 2009 Petter Lindquist
 | 
				
			||||||
@ -143,6 +144,9 @@ const T_Format File_formats[] = {
 | 
				
			|||||||
  {FORMAT_FLI, " flc", Test_FLI, Load_FLI, NULL,     0, 0, 0, "flc", "flc;fli;dat"},
 | 
					  {FORMAT_FLI, " flc", Test_FLI, Load_FLI, NULL,     0, 0, 0, "flc", "flc;fli;dat"},
 | 
				
			||||||
  {FORMAT_MOTO," moto",Test_MOTO,Load_MOTO,Save_MOTO,0, 1, 0, "bin", "bin;map"},
 | 
					  {FORMAT_MOTO," moto",Test_MOTO,Load_MOTO,Save_MOTO,0, 1, 0, "bin", "bin;map"},
 | 
				
			||||||
  {FORMAT_HGR, " hgr", Test_HGR, Load_HGR, Save_HGR, 0, 0, 1, "hgr", "hgr;dhgr;bin"},
 | 
					  {FORMAT_HGR, " hgr", Test_HGR, Load_HGR, Save_HGR, 0, 0, 1, "hgr", "hgr;dhgr;bin"},
 | 
				
			||||||
 | 
					#ifndef __no_tifflib__
 | 
				
			||||||
 | 
					  {FORMAT_TIFF," tiff",Test_TIFF,Load_TIFF,Save_TIFF,0, 1, 1, "tif", "tif;tiff"},
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
  {FORMAT_MISC,"misc.",NULL,     NULL,     NULL,     0, 0, 0, "",    "tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff"},
 | 
					  {FORMAT_MISC,"misc.",NULL,     NULL,     NULL,     0, 0, 0, "",    "tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff"},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										464
									
								
								src/tifformat.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										464
									
								
								src/tifformat.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,464 @@
 | 
				
			|||||||
 | 
					/* vim:expandtab:ts=2 sw=2:
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					/*  Grafx2 - The Ultimate 256-color bitmap paint program
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Copyright 2018 Thomas Bernard
 | 
				
			||||||
 | 
					    Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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/>
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					///@file tifformat.c
 | 
				
			||||||
 | 
					/// Support of TIFF
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// @todo use TIFFSetErrorHandler() and TIFFSetWarningHandler() to
 | 
				
			||||||
 | 
					///       redirect warning/error output to our own functions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __no_tifflib__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <tiffio.h>
 | 
				
			||||||
 | 
					#include "global.h"
 | 
				
			||||||
 | 
					#include "io.h"
 | 
				
			||||||
 | 
					#include "loadsave.h"
 | 
				
			||||||
 | 
					#include "gfx2log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern char Program_version[]; // generated in pversion.c
 | 
				
			||||||
 | 
					extern const char SVN_revision[]; // generated in version.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// test for a valid TIFF
 | 
				
			||||||
 | 
					void Test_TIFF(T_IO_Context * context, FILE * file)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  char buffer[4];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  File_error = 1;
 | 
				
			||||||
 | 
					  if (!Read_bytes(file, buffer, 4))
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  if (0 == memcmp(buffer, "MM\0*", 4) || 0 == memcmp(buffer, "II*\0", 4))
 | 
				
			||||||
 | 
					    File_error = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Load current image in TIFF
 | 
				
			||||||
 | 
					static void Load_TIFF_image(T_IO_Context * context, TIFF * tif, word spp, word bps)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  tsize_t size;
 | 
				
			||||||
 | 
					  int x, y;
 | 
				
			||||||
 | 
					  unsigned int i, j;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (TIFFIsTiled(tif))
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    // Tiled image
 | 
				
			||||||
 | 
					    dword tile_width, tile_height;
 | 
				
			||||||
 | 
					    if (!TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tile_width) || !TIFFGetField(tif, TIFFTAG_TILELENGTH, &tile_height))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      File_error = 2;
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (spp > 1 || bps > 8)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      dword * buffer;
 | 
				
			||||||
 | 
					      dword x2, y2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      buffer = malloc(sizeof(dword) * tile_width * tile_height);
 | 
				
			||||||
 | 
					      for (y = 0; y < context->Height; y += tile_height)
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        for (x = 0; x < context->Width; x += tile_width)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          if (!TIFFReadRGBATile(tif, x, y, buffer))
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            free(buffer);
 | 
				
			||||||
 | 
					            File_error = 2;
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          j = 0;
 | 
				
			||||||
 | 
					          // Note that the raster is assume to be organized such that the pixel at
 | 
				
			||||||
 | 
					          // location (x,y) is raster[y*width+x]; with the raster origin in the
 | 
				
			||||||
 | 
					          // lower-left hand corner of the tile. That is bottom to top organization.
 | 
				
			||||||
 | 
					          // Edge tiles which partly fall off the image will be filled out with
 | 
				
			||||||
 | 
					          // appropriate zeroed areas.
 | 
				
			||||||
 | 
					          for (y2 = 0; y2 < tile_height; y2++)
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            int y_pos = y + tile_height - 1 - y2;
 | 
				
			||||||
 | 
					            for (x2 = 0; x2 < tile_width ; x2++)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					              Set_pixel_24b(context, x + x2, y_pos, TIFFGetR(buffer[j]), TIFFGetG(buffer[j]), TIFFGetB(buffer[j]));
 | 
				
			||||||
 | 
					              j++;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      free(buffer);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      byte * buffer;
 | 
				
			||||||
 | 
					      //ttile_t tile;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      size = TIFFTileSize(tif);
 | 
				
			||||||
 | 
					      buffer = malloc(size);
 | 
				
			||||||
 | 
					      for (y = 0; y < context->Height; y += tile_height)
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        for (x = 0; x < context->Width; x += tile_width)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          dword x2, y2;
 | 
				
			||||||
 | 
					          if (TIFFReadTile(tif, buffer, x, y, 0, 0) == -1)
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            free(buffer);
 | 
				
			||||||
 | 
					            File_error = 2;
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          j = 0;
 | 
				
			||||||
 | 
					          for (y2 = 0; y2 < tile_height; y2++)
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            for (x2 = 0; x2 < tile_width ; x2++)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					              Set_pixel(context, x + x2, y + y2, buffer[j]);
 | 
				
			||||||
 | 
					              j++;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      free(buffer);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    dword rows_per_strip = 0;
 | 
				
			||||||
 | 
					    tstrip_t strip, strip_count;
 | 
				
			||||||
 | 
					    // "Striped" image
 | 
				
			||||||
 | 
					    TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rows_per_strip);
 | 
				
			||||||
 | 
					    if (rows_per_strip == 0)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      File_error = 2;
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (spp > 1 || bps > 8)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      // if not 8bit with colormap, use TIFFReadRGBAStrip
 | 
				
			||||||
 | 
					      dword * buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      strip_count = (context->Height + rows_per_strip - 1) / rows_per_strip;
 | 
				
			||||||
 | 
					      buffer = malloc(sizeof(dword) * rows_per_strip * context->Width);
 | 
				
			||||||
 | 
					      for (strip = 0, y = 0; strip < strip_count; strip++)
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        if (!TIFFReadRGBAStrip(tif, strip * rows_per_strip, buffer))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          free(buffer);
 | 
				
			||||||
 | 
					          File_error = 2;
 | 
				
			||||||
 | 
					          return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // 	Note that the raster is assume to be organized such that the
 | 
				
			||||||
 | 
					        // pixel at location (x,y) is raster[y*width+x]; with the raster
 | 
				
			||||||
 | 
					        // origin in the lower-left hand corner of the strip. That is bottom
 | 
				
			||||||
 | 
					        // to top organization. When reading a partial last strip in the
 | 
				
			||||||
 | 
					        // file the last line of the image will begin at the beginning of
 | 
				
			||||||
 | 
					        // the buffer.
 | 
				
			||||||
 | 
					        y = (strip + 1) * rows_per_strip - 1;
 | 
				
			||||||
 | 
					        if (y >= context->Height)
 | 
				
			||||||
 | 
					          y = context->Height - 1;
 | 
				
			||||||
 | 
					        for (i = 0, j = 0;
 | 
				
			||||||
 | 
					             i < rows_per_strip && y >= (int)(strip * rows_per_strip);
 | 
				
			||||||
 | 
					             i++, y--)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          for (x = 0; x < context->Width; x++)
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            Set_pixel_24b(context, x, y, TIFFGetR(buffer[j]), TIFFGetG(buffer[j]), TIFFGetB(buffer[j]));
 | 
				
			||||||
 | 
					            j++;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      free(buffer);
 | 
				
			||||||
 | 
					      return; // ignore next image for now...
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      byte * buffer = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      strip_count = TIFFNumberOfStrips(tif);
 | 
				
			||||||
 | 
					      size = TIFFStripSize(tif);
 | 
				
			||||||
 | 
					      GFX2_Log(GFX2_DEBUG, "TIFF %u strips of %u bytes\n", strip_count, size);
 | 
				
			||||||
 | 
					      buffer = malloc(size);
 | 
				
			||||||
 | 
					      for (strip = 0, y = 0; strip < strip_count; strip++)
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        tsize_t r = TIFFReadEncodedStrip(tif, strip, buffer, size);
 | 
				
			||||||
 | 
					        if (r == -1)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          free(buffer);
 | 
				
			||||||
 | 
					          File_error = 2;
 | 
				
			||||||
 | 
					          return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        for (i = 0, j = 0; i < rows_per_strip && y < context->Height; i++, y++)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          for (x = 0; x < context->Width; x++)
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            switch (bps)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					              case 8:
 | 
				
			||||||
 | 
					                Set_pixel(context, x, y, buffer[j++]);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					              case 6: // 3 bytes => 4 pixels
 | 
				
			||||||
 | 
					                Set_pixel(context, x++, y, buffer[j] >> 2);
 | 
				
			||||||
 | 
					                if (x < context->Width)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                  Set_pixel(context, x++, y, (buffer[j] & 3) << 4 | (buffer[j+1] & 0xf0) >> 4);
 | 
				
			||||||
 | 
					                  j++;
 | 
				
			||||||
 | 
					                  if (x < context->Width)
 | 
				
			||||||
 | 
					                  {
 | 
				
			||||||
 | 
					                    Set_pixel(context, x++, y, (buffer[j] & 0x0f) << 2 | (buffer[j+1] & 0xc0) >> 6);
 | 
				
			||||||
 | 
					                    j++;
 | 
				
			||||||
 | 
					                    Set_pixel(context, x, y, buffer[j] & 0x3f);
 | 
				
			||||||
 | 
					                  }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                j++;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					              case 4:
 | 
				
			||||||
 | 
					                Set_pixel(context, x++, y, buffer[j] >> 4);
 | 
				
			||||||
 | 
					                Set_pixel(context, x, y, buffer[j++] & 0x0f);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					              case 2:
 | 
				
			||||||
 | 
					                Set_pixel(context, x++, y, buffer[j] >> 6);
 | 
				
			||||||
 | 
					                Set_pixel(context, x++, y, (buffer[j] >> 4) & 3);
 | 
				
			||||||
 | 
					                Set_pixel(context, x++, y, (buffer[j] >> 2) & 3);
 | 
				
			||||||
 | 
					                Set_pixel(context, x, y, buffer[j++] & 3);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					              case 1:
 | 
				
			||||||
 | 
					                Set_pixel(context, x++, y, (buffer[j] >> 7) & 1);
 | 
				
			||||||
 | 
					                Set_pixel(context, x++, y, (buffer[j] >> 6) & 1);
 | 
				
			||||||
 | 
					                Set_pixel(context, x++, y, (buffer[j] >> 5) & 1);
 | 
				
			||||||
 | 
					                Set_pixel(context, x++, y, (buffer[j] >> 4) & 1);
 | 
				
			||||||
 | 
					                Set_pixel(context, x++, y, (buffer[j] >> 3) & 1);
 | 
				
			||||||
 | 
					                Set_pixel(context, x++, y, (buffer[j] >> 2) & 1);
 | 
				
			||||||
 | 
					                Set_pixel(context, x++, y, (buffer[j] >> 1) & 1);
 | 
				
			||||||
 | 
					                Set_pixel(context, x, y, buffer[j++] & 1);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					              default:
 | 
				
			||||||
 | 
					                File_error = 2;
 | 
				
			||||||
 | 
					                GFX2_Log(GFX2_ERROR, "TIFF : %u bps unsupported\n", bps);
 | 
				
			||||||
 | 
					                free(buffer);
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      free(buffer);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Load TIFF
 | 
				
			||||||
 | 
					void Load_TIFF_Sub(T_IO_Context * context, TIFF * tif, unsigned long file_size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int layer = 0;
 | 
				
			||||||
 | 
					  enum PIXEL_RATIO ratio = PIXEL_SIMPLE;
 | 
				
			||||||
 | 
					  dword width, height;
 | 
				
			||||||
 | 
					  word bps, spp;
 | 
				
			||||||
 | 
					  word photometric = PHOTOMETRIC_RGB;
 | 
				
			||||||
 | 
					  char * desc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  TIFFPrintDirectory(tif, stdout, TIFFPRINT_NONE);
 | 
				
			||||||
 | 
					  if (!TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width) || !TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height))
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  if (!TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bps) || !TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &spp))
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  GFX2_Log(GFX2_DEBUG, "TIFF #0 : %ux%u %ux%ubps\n", width, height, spp, bps);
 | 
				
			||||||
 | 
					  if (TIFFGetField(tif, TIFFTAG_IMAGEDESCRIPTION, &desc))
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    size_t len = strlen(desc);
 | 
				
			||||||
 | 
					    if (len <= COMMENT_SIZE)
 | 
				
			||||||
 | 
					      memcpy(context->Comment, desc, len + 1);
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      memcpy(context->Comment, desc, COMMENT_SIZE);
 | 
				
			||||||
 | 
					      context->Comment[COMMENT_SIZE] = '\0';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric);
 | 
				
			||||||
 | 
					  File_error = 0;
 | 
				
			||||||
 | 
					  Pre_load(context, width, height, file_size, FORMAT_TIFF, ratio, bps * spp);
 | 
				
			||||||
 | 
					  if (File_error != 0)
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  if (spp == 1)
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    struct {
 | 
				
			||||||
 | 
					      word * r;
 | 
				
			||||||
 | 
					      word * g;
 | 
				
			||||||
 | 
					      word * b;
 | 
				
			||||||
 | 
					    } colormap;
 | 
				
			||||||
 | 
					    unsigned i, count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    count = (bps <= 8) ? 1 << bps : 256;
 | 
				
			||||||
 | 
					    if (TIFFGetField(tif, TIFFTAG_COLORMAP, &colormap.r, &colormap.g, &colormap.b))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      for (i = 0; i < count; i++)
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        context->Palette[i].R = colormap.r[i] >> 8;
 | 
				
			||||||
 | 
					        context->Palette[i].G = colormap.g[i] >> 8;
 | 
				
			||||||
 | 
					        context->Palette[i].B = colormap.b[i] >> 8;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      // Grayscale palette
 | 
				
			||||||
 | 
					      for (i = 0; i < count; i++)
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        unsigned int value = 255
 | 
				
			||||||
 | 
					          * (photometric == PHOTOMETRIC_MINISWHITE ? (count - 1 - i) : i)
 | 
				
			||||||
 | 
					          / (count - 1);
 | 
				
			||||||
 | 
					        context->Palette[i].R = value;
 | 
				
			||||||
 | 
					        context->Palette[i].G = value;
 | 
				
			||||||
 | 
					        context->Palette[i].B = value;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (;;)
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    Load_TIFF_image(context, tif, spp, bps);
 | 
				
			||||||
 | 
					    if (File_error != 0)
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (context->Type != CONTEXT_MAIN_IMAGE)
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    if (!TIFFReadDirectory(tif))
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    if (!TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width) || !TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height))
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    if (!TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bps) || !TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &spp))
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    layer++;
 | 
				
			||||||
 | 
					    GFX2_Log(GFX2_DEBUG, "TIFF #%d : %ux%u %ux%ubps\n", layer, width, height, spp, bps);
 | 
				
			||||||
 | 
					    if ((int)width != context->Width || (int)height != context->Height)
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    if (context->bpp != (spp * bps))
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    Set_loading_layer(context, layer);
 | 
				
			||||||
 | 
					    TIFFPrintDirectory(tif, stdout, TIFFPRINT_NONE);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Load TIFF from file
 | 
				
			||||||
 | 
					void Load_TIFF(T_IO_Context * context)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  FILE * file;
 | 
				
			||||||
 | 
					  TIFF * tif;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  File_error = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  file = Open_file_read(context);
 | 
				
			||||||
 | 
					  if (file != NULL)
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    tif = TIFFFdOpen(fileno(file), context->File_name, "r");
 | 
				
			||||||
 | 
					    if (tif != NULL)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      Load_TIFF_Sub(context, tif, File_length_file(file));
 | 
				
			||||||
 | 
					      TIFFClose(tif);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    fclose(file);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Save_TIFF_Sub(T_IO_Context * context, TIFF * tif)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  char version[64];
 | 
				
			||||||
 | 
					  int i;
 | 
				
			||||||
 | 
					  int layer = 0;
 | 
				
			||||||
 | 
					  dword width, height;
 | 
				
			||||||
 | 
					  dword y;
 | 
				
			||||||
 | 
					  tstrip_t strip;
 | 
				
			||||||
 | 
					  struct {
 | 
				
			||||||
 | 
					    word r[256];
 | 
				
			||||||
 | 
					    word g[256];
 | 
				
			||||||
 | 
					    word b[256];
 | 
				
			||||||
 | 
					  } colormap;
 | 
				
			||||||
 | 
					  const word bps = 8;
 | 
				
			||||||
 | 
					  const word spp = 1;
 | 
				
			||||||
 | 
					  const dword rowsperstrip = 64;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  snprintf(version, sizeof(version), "GrafX2 %s.%s", Program_version, SVN_revision);
 | 
				
			||||||
 | 
					  width = context->Width;
 | 
				
			||||||
 | 
					  height = context->Height;
 | 
				
			||||||
 | 
					  for (i = 0; i < 256; i++)
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    colormap.r[i] = 0x101 * context->Palette[i].R;
 | 
				
			||||||
 | 
					    colormap.g[i] = 0x101 * context->Palette[i].G;
 | 
				
			||||||
 | 
					    colormap.b[i] = 0x101 * context->Palette[i].B;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (;;)
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    GFX2_Log(GFX2_DEBUG, "TIFF save layer #%d\n", layer);
 | 
				
			||||||
 | 
					    TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width);
 | 
				
			||||||
 | 
					    TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height);
 | 
				
			||||||
 | 
					    TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
 | 
				
			||||||
 | 
					    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps);
 | 
				
			||||||
 | 
					    TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, spp);
 | 
				
			||||||
 | 
					    TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
 | 
				
			||||||
 | 
					    TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
 | 
				
			||||||
 | 
					    //TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); // not relevant if SAMPLESPERPIXEL == 1
 | 
				
			||||||
 | 
					    TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
 | 
				
			||||||
 | 
					    if (context->Comment[0] != '\0')
 | 
				
			||||||
 | 
					      TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION, context->Comment);
 | 
				
			||||||
 | 
					    TIFFSetField(tif, TIFFTAG_SOFTWARE, version);
 | 
				
			||||||
 | 
					    TIFFSetField(tif, TIFFTAG_COLORMAP, colormap.r, colormap.g, colormap.b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
 | 
					    for (y = 0; y < height; y++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      if (TIFFWriteScanline(tif, context->Target_address + y*context->Pitch, y, 0) < 0)
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    for (y = 0, strip = 0; y < height; y += rowsperstrip, strip++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      if (TIFFWriteEncodedStrip(tif, strip, context->Target_address + y*context->Pitch, rowsperstrip * context->Pitch) < 0)
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    layer++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (layer >= context->Nb_layers)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      TIFFFlushData(tif);
 | 
				
			||||||
 | 
					      File_error = 0; // everything was fine
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    Set_saving_layer(context, layer);
 | 
				
			||||||
 | 
					    if (!TIFFWriteDirectory(tif))
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    TIFFFlushData(tif);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Save TIFF
 | 
				
			||||||
 | 
					void Save_TIFF(T_IO_Context * context)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  TIFF * tif;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  File_error = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(WIN32)
 | 
				
			||||||
 | 
					  if (context->File_name_unicode != NULL && context->File_name_unicode[0] != 0)
 | 
				
			||||||
 | 
					    tif = TIFFOpenW(context->File_name_unicode, "w");
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    tif = TIFFOpen(context->File_name, "w");
 | 
				
			||||||
 | 
					  if (tif != NULL)
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    Save_TIFF_Sub(context, tif);
 | 
				
			||||||
 | 
					    TIFFClose(tif);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user