Esempio n. 1
0
bool FPngImageWrapper::LoadPNGHeader()
{
	check(CompressedData.Num());

	// Test whether the data this PNGLoader is pointing at is a PNG or not.
	if (IsPNG())
	{
		// thread safety
		FScopeLock PNGLock(&GPNGSection);

		png_structp png_ptr = png_create_read_struct_2( PNG_LIBPNG_VER_STRING, this, FPngImageWrapper::user_error_fn, FPngImageWrapper::user_warning_fn, NULL, FPngImageWrapper::user_malloc, FPngImageWrapper::user_free );
		check(png_ptr);

		png_infop info_ptr = png_create_info_struct( png_ptr );
		check(info_ptr);

		PNGReadGuard PNGGuard(&png_ptr, &info_ptr);
		{
			png_set_read_fn(png_ptr, this, FPngImageWrapper::user_read_compressed);

			png_read_info(png_ptr, info_ptr);

			Width = info_ptr->width;
			Height = info_ptr->height;
			ColorType = info_ptr->color_type;
			BitDepth = info_ptr->bit_depth;
			Channels = info_ptr->channels;
			Format = (ColorType & PNG_COLOR_MASK_COLOR) ? ERGBFormat::RGBA : ERGBFormat::Gray;
		}

		return true;
	}

	return false;
}
/* Create a PNG structure for reading, and allocate any memory needed. */
png_structp PNGAPI
png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr,
   png_error_ptr error_fn, png_error_ptr warn_fn)
{

#ifdef PNG_USER_MEM_SUPPORTED
   return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn,
      warn_fn, NULL, NULL, NULL));
}
Esempio n. 3
0
void TextureReader::initialisePNGReader(FileReader reader)
{
    _png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, handlePNGError, handlePNGWarning, NULL,
                                    allocatePNGMemory, deallocatePNGMemory);

    //CHECK_ERROR(_png == NULL, "Graphics::TextureReader", "Failed to initialise the PNG reader");
    png_set_read_fn(_png, &reader, readPNGData);
    png_set_sig_bytes(_png, 8);
    _pngInfo = png_create_info_struct(_png);
    //CHECK_ERROR(_pngInfo == NULL, "Graphics::TextureReader", "Failed to initialise the PNG reader info");
}
Esempio n. 4
0
    PNGImageReader(PNGImageDecoder* decoder)
        : m_readOffset(0)
        , m_currentBufferSize(0)
        , m_decodingSizeOnly(false)
        , m_hasAlpha(false)
        , m_interlaceBuffer(0)
#if USE(QCMSLIB)
        , m_transform(0)
        , m_rowBuffer()
#endif
    {
#if PLATFORM(HP)
        m_png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, 0, decodingFailed, decodingWarning, 0, (png_malloc_ptr) pngMalloc, pngFree);
#else
        m_png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, decodingFailed, decodingWarning);
#endif
        m_info = png_create_info_struct(m_png);
        png_set_progressive_read_fn(m_png, decoder, headerAvailable, rowAvailable, pngComplete);
    }
Esempio n. 5
0
void png_start(struct cached_image *cimg)
{
	png_structp png_ptr;
	png_infop info_ptr;
	struct png_decoder *decoder;

	retry1:
#ifdef PNG_USER_MEM_SUPPORTED
	png_ptr=png_create_read_struct_2(PNG_LIBPNG_VER_STRING,
			NULL, img_my_png_error, img_my_png_warning,
			NULL, my_png_alloc, my_png_free);
#else
	png_ptr=png_create_read_struct(PNG_LIBPNG_VER_STRING,
			NULL, img_my_png_error, img_my_png_warning);
#endif
	if (!png_ptr) {
		if (out_of_memory(0, NULL, 0)) goto retry1;
		fatal_exit("png_create_read_struct failed");
	}
	retry2:
	info_ptr=png_create_info_struct(png_ptr);
	if (!info_ptr) {
		if (out_of_memory(0, NULL, 0)) goto retry2;
		fatal_exit("png_create_info_struct failed");
	}
	if (setjmp(png_jmpbuf(png_ptr))){
error:
		png_destroy_read_struct(&png_ptr, &info_ptr,
			(png_infopp)NULL);
		img_end(cimg);
		return;
	}
	png_set_progressive_read_fn(png_ptr, NULL,
				    png_info_callback, &png_row_callback,
				    png_end_callback);
   	if (setjmp(png_jmpbuf(png_ptr))) goto error;
	decoder=mem_alloc(sizeof(*decoder));
	decoder->png_ptr=png_ptr;
	decoder->info_ptr=info_ptr;
	cimg->decoder=decoder;
}
Esempio n. 6
0
/* Shared library entry point */
static GdkPixbuf *
gdk_pixbuf__png_image_load (FILE *f, GError **error)
{
        GdkPixbuf * volatile pixbuf = NULL;
	png_structp png_ptr;
	png_infop info_ptr;
        png_textp text_ptr;
	gint i, ctype;
	png_uint_32 w, h;
	png_bytepp volatile rows = NULL;
        gint    num_texts;
        gchar *key;
        gchar *value;
        gchar *icc_profile_base64;
        const gchar *icc_profile_title;
        const gchar *icc_profile;
        png_uint_32 icc_profile_size;
        guint32 retval;
        gint compression_type;

#ifdef PNG_USER_MEM_SUPPORTED
	png_ptr = png_create_read_struct_2 (PNG_LIBPNG_VER_STRING,
                                            error,
                                            png_simple_error_callback,
                                            png_simple_warning_callback,
                                            NULL, 
                                            png_malloc_callback, 
                                            png_free_callback);
#else
	png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,
                                          error,
                                          png_simple_error_callback,
                                          png_simple_warning_callback);
#endif
	if (!png_ptr)
		return NULL;

	info_ptr = png_create_info_struct (png_ptr);
	if (!info_ptr) {
		png_destroy_read_struct (&png_ptr, NULL, NULL);
		return NULL;
	}

	if (setjmp (png_jmpbuf(png_ptr))) {
	    	g_free (rows);

		if (pixbuf)
			g_object_unref (pixbuf);

		png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
		return NULL;
	}

	png_init_io (png_ptr, f);
	png_read_info (png_ptr, info_ptr);

        if (!setup_png_transformations(png_ptr, info_ptr, error, &w, &h, &ctype)) {
                png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
                return NULL;
        }
        
        pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, ctype & PNG_COLOR_MASK_ALPHA, 8, w, h);

	if (!pixbuf) {
                if (error && *error == NULL) {
                        g_set_error_literal (error,
                                             GDK_PIXBUF_ERROR,
                                             GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
                                             _("Insufficient memory to load PNG file"));
                }
                

		png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
		return NULL;
	}

	rows = g_new (png_bytep, h);

	for (i = 0; i < h; i++)
		rows[i] = pixbuf->pixels + i * pixbuf->rowstride;

	png_read_image (png_ptr, rows);
        png_read_end (png_ptr, info_ptr);

        if (png_get_text (png_ptr, info_ptr, &text_ptr, &num_texts)) {
                for (i = 0; i < num_texts; i++) {
                        png_text_to_pixbuf_option (text_ptr[i], &key, &value);
                        gdk_pixbuf_set_option (pixbuf, key, value);
                        g_free (key);
                        g_free (value);
                }
        }

#if defined(PNG_cHRM_SUPPORTED)
        /* Extract embedded ICC profile */
        retval = png_get_iCCP (png_ptr, info_ptr,
                               (png_charpp) &icc_profile_title, &compression_type,
                               (png_bytepp) &icc_profile, (png_uint_32*) &icc_profile_size);
        if (retval != 0) {
                icc_profile_base64 = g_base64_encode ((const guchar *) icc_profile, (gsize)icc_profile_size);
                gdk_pixbuf_set_option (pixbuf, "icc-profile", icc_profile_base64);
                g_free (icc_profile_base64);
        }
#endif

	g_free (rows);
	png_destroy_read_struct (&png_ptr, &info_ptr, NULL);

        return pixbuf;
}
Esempio n. 7
0
/* Test one file */
int
test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
{
   static FILE *fpin, *fpout;  /* "static" prevents setjmp corruption */
   png_structp read_ptr, write_ptr;
   png_infop read_info_ptr, write_info_ptr, end_info_ptr, write_end_info_ptr;
   png_bytep row_buf;
   png_uint_32 y;
   png_uint_32 width, height;
   int num_pass, pass;
   int bit_depth, color_type;
#ifdef PNG_SETJMP_SUPPORTED
#ifdef USE_FAR_KEYWORD
   jmp_buf jmp_env;
#endif
#endif

   char inbuf[256], outbuf[256];

   row_buf = (png_bytep)NULL;

   if ((fpin = fopen(inname, "rb")) == NULL)
   {
      fprintf(STDERR, "Could not find input file %s\n", inname);
      return (1);
   }

   if ((fpout = fopen(outname, "wb")) == NULL)
   {
      fprintf(STDERR, "Could not open output file %s\n", outname);
      fclose(fpin);
      return (1);
   }

   png_debug(0, "Allocating read and write structures\n");
#ifdef PNG_USER_MEM_SUPPORTED
   read_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
      (png_error_ptr)NULL, (png_error_ptr)NULL, (png_voidp)NULL,
      (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free);
#else
   read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
      (png_error_ptr)NULL, (png_error_ptr)NULL);
#endif
#if defined(PNG_NO_STDIO)
   png_set_error_fn(read_ptr, (png_voidp)inname, png_default_error,
       png_default_warning);
#endif
#ifdef PNG_USER_MEM_SUPPORTED
   write_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
      (png_error_ptr)NULL, (png_error_ptr)NULL, (png_voidp)NULL,
      (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free);
#else
   write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
      (png_error_ptr)NULL, (png_error_ptr)NULL);
#endif
#if defined(PNG_NO_STDIO)
   png_set_error_fn(write_ptr, (png_voidp)inname, png_default_error,
       png_default_warning);
#endif
   png_debug(0, "Allocating read_info, write_info and end_info structures\n");
   read_info_ptr = png_create_info_struct(read_ptr);
   write_info_ptr = png_create_info_struct(write_ptr);
   end_info_ptr = png_create_info_struct(read_ptr);
   write_end_info_ptr = png_create_info_struct(write_ptr);
#ifdef PNG_USER_MEM_SUPPORTED
#endif

#ifdef PNG_SETJMP_SUPPORTED
   png_debug(0, "Setting jmp_env for read struct\n");
#ifdef USE_FAR_KEYWORD
   if (setjmp(jmp_env))
#else
   if (setjmp(png_jmp_env(read_ptr)))
#endif
   {
      fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname);
      png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
      png_destroy_info_struct(write_ptr, &write_end_info_ptr);
      png_destroy_write_struct(&write_ptr, &write_info_ptr);
      fclose(fpin);
      fclose(fpout);
      return (1);
   }
#ifdef USE_FAR_KEYWORD
   png_memcpy(png_jmp_env(read_ptr),jmp_env,sizeof(jmp_buf));
#endif

   png_debug(0, "Setting jmp_env for write struct\n");
#ifdef USE_FAR_KEYWORD
   if (setjmp(jmp_env))
#else
   if (setjmp(png_jmp_env(write_ptr)))
#endif
   {
      fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname);
      png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
      png_destroy_info_struct(write_ptr, &write_end_info_ptr);
      png_destroy_write_struct(&write_ptr, &write_info_ptr);
      fclose(fpin);
      fclose(fpout);
      return (1);
   }
#ifdef USE_FAR_KEYWORD
   png_memcpy(png_jmp_env(write_ptr),jmp_env,sizeof(jmp_buf));
#endif
#endif

   png_debug(0, "Initializing input and output streams\n");
#if !defined(PNG_NO_STDIO)
   png_init_io(read_ptr, fpin);
   png_init_io(write_ptr, fpout);
#else
   png_set_read_fn(read_ptr, (png_voidp)fpin, png_default_read_data);
   png_set_write_fn(write_ptr, (png_voidp)fpout,  png_default_write_data,
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
      png_default_flush);
#else
      NULL);
#endif
#endif
   if(status_dots_requested == 1)
   {
      png_set_write_status_fn(write_ptr, write_row_callback);
      png_set_read_status_fn(read_ptr, read_row_callback);
   }
   else
   {
      png_set_write_status_fn(write_ptr, NULL);
      png_set_read_status_fn(read_ptr, NULL);
   }

#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
   {
     int i;
     for(i=0; i<256; i++)
        filters_used[i]=0;
     png_set_read_user_transform_fn(read_ptr, count_filters);
   }
#endif
#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
   zero_samples=0;
   png_set_write_user_transform_fn(write_ptr, count_zero_samples);
#endif

#define HANDLE_CHUNK_IF_SAFE      2
#define HANDLE_CHUNK_ALWAYS       3
#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
   png_set_keep_unknown_chunks(read_ptr, HANDLE_CHUNK_ALWAYS, NULL, 0);
#endif
#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
   png_set_keep_unknown_chunks(write_ptr, HANDLE_CHUNK_IF_SAFE, NULL, 0);
#endif

   png_debug(0, "Reading info struct\n");
   png_read_info(read_ptr, read_info_ptr);

   png_debug(0, "Transferring info struct\n");
   {
      int interlace_type, compression_type, filter_type;

      if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth,
          &color_type, &interlace_type, &compression_type, &filter_type))
      {
         png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth,
#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
            color_type, interlace_type, compression_type, filter_type);
#else
            color_type, PNG_INTERLACE_NONE, compression_type, filter_type);
#endif
      }
   }
Esempio n. 8
0
/* This only determines if we have an alpha value */
int
xps_png_has_alpha(xps_context_t *ctx, byte *rbuf, int rlen)
{
    png_structp png;
    png_infop info;
    struct xps_png_io_s io;
    int has_alpha;

    /*
     * Set up PNG structs and input source
     */

    io.ptr = rbuf;
    io.lim = rbuf + rlen;

    png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING,
            NULL, NULL, NULL,
            ctx->memory, xps_png_malloc, xps_png_free);
    if (!png) {
        gs_warn("png_create_read_struct");
        return 0;
    }

    info = png_create_info_struct(png);
    if (!info) {
        gs_warn("png_create_info_struct");
        return 0;
    }

    png_set_read_fn(png, &io, xps_png_read);
    png_set_crc_action(png, PNG_CRC_WARN_USE, PNG_CRC_WARN_USE);

    /*
     * Jump to here on errors.
     */

    if (setjmp(png_jmpbuf(png)))
    {
        png_destroy_read_struct(&png, &info, NULL);
        gs_warn("png reading failed");
        return 0;
    }

    /*
     * Read PNG header
     */

    png_read_info(png, info);

    switch (png_get_color_type(png, info))
    {
    case PNG_COLOR_TYPE_PALETTE:
    case PNG_COLOR_TYPE_GRAY:
    case PNG_COLOR_TYPE_RGB:
        has_alpha = 0;
        break;

    case PNG_COLOR_TYPE_GRAY_ALPHA:
    case PNG_COLOR_TYPE_RGB_ALPHA:
        has_alpha = 1;
        break;

    default:
        gs_warn("cannot handle this png color type");
        has_alpha = 0;
        break;
    }

    /*
     * Clean up memory.
     */

    png_destroy_read_struct(&png, &info, NULL);

    return has_alpha;
}
Esempio n. 9
0
bool R9_ImgReadPNG( F9FILE file, r9Img* img )
{
	if(file==NULL || img==NULL) return false;
	R9_ImgDestroy(img);
	
	// check png sig
	const int headersize = 8;
	byte header[headersize];
	if(file->Read( header, headersize) != headersize) return false;

	BOOL ispng = png_check_sig(header, headersize) != 0;
	if(!ispng) { elog::rnd() << "png sig failed" << std::endl; return false; }

	// create png structures
	png_structp png_ptr = png_create_read_struct_2( PNG_LIBPNG_VER_STRING,
												NULL,
												R9_ImgPNG_FatalError,
												R9_ImgPNG_Warning,
												NULL,
												R9_ImgPNG_Malloc,
												R9_ImgPNG_Free );

	if(png_ptr==NULL) return false;

	png_infop info_ptr = png_create_info_struct(png_ptr);
	if(info_ptr == NULL) 
	{
		png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
		return false;
	}

	png_infop end_info = png_create_info_struct(png_ptr);
	if(end_info == NULL) 
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
		return false;
	}

	// set global file
	r9_imgpng_file = file;
	png_set_read_fn(png_ptr, NULL, R9_ImgPNG_ReadData);

	// read off the info on the image
	png_set_sig_bytes(png_ptr, headersize);
	png_read_info(png_ptr, info_ptr);

	png_uint_32 pngwidth;
	png_uint_32 pngheight;	
	int32 pngbits;
	int32 pngpf;

	png_get_IHDR(png_ptr, info_ptr,
				&pngwidth, &pngheight,
				&pngbits, &pngpf,
				NULL,                        // interlace
				NULL,                        // compression_type
				NULL);                       // filter_type

	BOOL alpha = FALSE;
	img->m_width = pngwidth;
	img->m_height = pngheight;
	img->m_pf = R9_PF_RGB;
	assert(img->m_width!=0 && img->m_height!=0);

	// Strip off any 16 bit info
	if(pngbits==16) png_set_strip_16(png_ptr);

	// Expand a transparency channel into a full alpha channel...
	if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) 
	{
		png_set_expand(png_ptr);
		alpha = TRUE;
	}

	if( pngpf == PNG_COLOR_TYPE_RGB) 
	{
		png_set_expand(png_ptr);
		img->m_pf = alpha ? R9_PF_ARGB : R9_PF_RGB;
	} 
	else 
	if( pngpf == PNG_COLOR_TYPE_RGB_ALPHA) 
	{
		png_set_expand(png_ptr);
		img->m_pf = R9_PF_ARGB;
	}
	else
	{
		elog::rnd() << "png wrong color format" << std::endl;
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		return false;
	}

	// Update the info pointer with the result of the transformations above...
	png_read_update_info(png_ptr, info_ptr);

	png_uint_32 rowbytes = png_get_rowbytes(png_ptr, info_ptr);
	if(img->m_pf==R9_PF_RGB) assert(rowbytes==img->m_width*3);
	else
	if(img->m_pf==R9_PF_RGB) assert(rowbytes==img->m_width*4);

	// create image
	R9_ImgCreate(img);

	// set up the row pointers...
	png_bytep* rowpointers = new png_bytep[img->m_height];
	for(int i=0; i<img->m_height; i++)
	  rowpointers[i] = img->m_data + (i*rowbytes);

	// read image
	png_read_image(png_ptr, rowpointers);

	// release
	png_read_end(png_ptr, NULL);
	png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
	delete [] rowpointers;
	r9_imgpng_file = NULL;

	R9_ImgFlipRGB(img); // it was BGR, we want it RGB !
	return true;
}
Esempio n. 10
0
//
// In order to avoid CRT mismatches, we override all CRT functions libpng uses
// with our own. The alternative, using fopen and fread in our code and then
// passing a FILE* into libpng, isn't reliable because it crashes if libpng was
// compiled with a different CRT than lsapi.dll
//
HBITMAP LoadFromPNG(LPCSTR pszFilename)
{
    HBITMAP hDibSection = NULL;
    
    if (pszFilename != NULL)
    {
        FILE * hFile = fopen(pszFilename, "rb");
        
        if (hFile)
        {
            const size_t num_sig_bytes = 8;
            unsigned char sig[num_sig_bytes];
            
            fread(sig, 1, num_sig_bytes, hFile);
            
            if (png_check_sig(sig, num_sig_bytes))
            {
                PNGERROR PngError = { 0 };
                
                PngError.Wnd = GetForegroundWindow();
                
                png_structp Read = png_create_read_struct_2(
                    PNG_LIBPNG_VER_STRING, &PngError, PNGErrorHandler, NULL,
                    NULL, ls_png_malloc, ls_png_free);
                
                if (Read)
                {
                    png_infop Info = png_create_info_struct(Read);
                    
                    if (Info)
                    {
                        if (!setjmp(PngError.ErrorJump))
                        {
                            png_set_read_fn(Read, hFile, ls_png_read_data);
                            png_set_sig_bytes(Read, num_sig_bytes);
                            png_read_info(Read, Info);
                            
                            const unsigned char bit_depth = png_get_bit_depth(Read, Info);
                            const unsigned char color_type = png_get_color_type(Read, Info);
                            
                            if (color_type == PNG_COLOR_TYPE_PALETTE)
                            {
                                png_set_palette_to_rgb(Read);
                            }
                            
                            if ((color_type == PNG_COLOR_TYPE_GRAY) ||
                                (color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
                            {
                                if (bit_depth < 8)
                                {
                                    png_set_gray_1_2_4_to_8(Read);
                                }
                                png_set_gray_to_rgb(Read);
                            }
                            
                            if (png_get_valid(Read, Info, PNG_INFO_tRNS))
                            {
                                png_set_tRNS_to_alpha(Read);
                            }
                            
                            if (color_type & PNG_COLOR_MASK_COLOR)
                            {
                                png_set_bgr(Read);
                            }
                            
                            if (bit_depth == 16)
                            {
                                png_set_strip_16(Read);
                            }
                            
                            double image_gamma = 1 / 2.2;
                            png_get_gAMA(Read, Info, &image_gamma);
                            png_set_gamma(Read, 2.2, image_gamma);
                            
                            const int num_passes = png_set_interlace_handling(Read);
                            
                            png_read_update_info(Read, Info);
                            
                            BITMAPINFO bmi = { {0} };
                            bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
                            bmi.bmiHeader.biWidth = (LONG)png_get_image_width(Read, Info);
                            bmi.bmiHeader.biHeight = -(LONG)png_get_image_height(Read, Info);
                            bmi.bmiHeader.biBitCount = (WORD)(png_get_channels(Read, Info) * png_get_bit_depth(Read, Info));
                            bmi.bmiHeader.biPlanes = 1;
                            bmi.bmiHeader.biCompression = BI_RGB;
                            
                            unsigned char* bits;
                            hDibSection = CreateDIBSection(NULL, &bmi, 0,
                                reinterpret_cast<LPVOID*>(&bits), NULL, 0);
                            
                            if (!bits)
                            {
                                longjmp(PngError.ErrorJump, 1);
                            }
                            
                            unsigned int dib_bytes_per_scanline = \
                                (((bmi.bmiHeader.biWidth * bmi.bmiHeader.biBitCount) + 31) & ~31) >> 3;
                            
                            for (int Pass = 0; Pass < num_passes; ++Pass)
                            {
                                for (int y = 0; y < -bmi.bmiHeader.biHeight; ++y)
                                {
                                    unsigned char* Scanline = \
                                        reinterpret_cast<unsigned char*>(bits + (y * dib_bytes_per_scanline));
                                    
                                    png_read_row(Read, Scanline, NULL);
                                }
                            }
                            
                            png_read_end(Read, Info);
                            png_destroy_read_struct(&Read, &Info, NULL);
                        }
                        else
                        {
                            png_destroy_read_struct(&Read, &Info, NULL);
                        }
                    }
                    else
                    {
                        png_destroy_read_struct(&Read, NULL, NULL);
                    }
                }
Esempio n. 11
0
void FPngImageWrapper::UncompressPNGData( const ERGBFormat::Type InFormat, const int32 InBitDepth )
{
	// thread safety
	FScopeLock PNGLock(&GPNGSection);

	check( CompressedData.Num() );
	check( Width > 0 );
	check( Height > 0 );

	// Note that PNGs on PC tend to be BGR
	check( InFormat == ERGBFormat::BGRA || InFormat == ERGBFormat::RGBA || InFormat == ERGBFormat::Gray )	// Other formats unsupported at present
	check( InBitDepth == 8 || InBitDepth == 16 )	// Other formats unsupported at present

	// Reset to the beginning of file so we can use png_read_png(), which expects to start at the beginning.
	ReadOffset = 0;
		
	png_structp png_ptr	= png_create_read_struct_2( PNG_LIBPNG_VER_STRING, this, FPngImageWrapper::user_error_fn, FPngImageWrapper::user_warning_fn, NULL, FPngImageWrapper::user_malloc, FPngImageWrapper::user_free);
	check( png_ptr );

	png_infop info_ptr	= png_create_info_struct( png_ptr );
	check( info_ptr );
	PNGReadGuard PNGGuard( &png_ptr, &info_ptr );
	{
		if (ColorType == PNG_COLOR_TYPE_PALETTE)
		{
			png_set_palette_to_rgb(png_ptr);
		}

		if ((ColorType & PNG_COLOR_MASK_COLOR) == 0 && BitDepth < 8)
		{
			png_set_expand_gray_1_2_4_to_8(png_ptr);
		}

		// Insert alpha channel with full opacity for RGB images without alpha
		if ((ColorType & PNG_COLOR_MASK_ALPHA) == 0 && (InFormat == ERGBFormat::BGRA || InFormat == ERGBFormat::RGBA))
		{
			// png images don't set PNG_COLOR_MASK_ALPHA if they have alpha from a tRNS chunk, but png_set_add_alpha seems to be safe regardless
			if ((ColorType & PNG_COLOR_MASK_COLOR) == 0)
			{
				png_set_tRNS_to_alpha(png_ptr);
			}
			else if (ColorType == PNG_COLOR_TYPE_PALETTE)
			{
				png_set_tRNS_to_alpha(png_ptr);
			}
			if (InBitDepth == 8)
			{
				png_set_add_alpha(png_ptr, 0xff , PNG_FILLER_AFTER);
			}
			else if (InBitDepth == 16)
			{
				png_set_add_alpha(png_ptr, 0xffff , PNG_FILLER_AFTER);
			}
		}

		// Calculate Pixel Depth
		const uint32 PixelChannels = (InFormat == ERGBFormat::Gray) ? 1 : 4;
		const uint32 BytesPerPixel = (InBitDepth * PixelChannels) / 8;
		const uint32 BytesPerRow = BytesPerPixel * Width;
		RawData.Empty(Height * BytesPerRow);
		RawData.AddUninitialized(Height * BytesPerRow);

		png_set_read_fn( png_ptr, this, FPngImageWrapper::user_read_compressed );

		png_bytep* row_pointers = (png_bytep*) png_malloc( png_ptr, Height*sizeof(png_bytep) );
		PNGGuard.SetRowPointers(&row_pointers);
		for (int32 i = 0; i < Height; i++)
		{
			row_pointers[i]= &RawData[i * BytesPerRow];
		}
		png_set_rows(png_ptr, info_ptr, row_pointers);

		uint32 Transform = (InFormat == ERGBFormat::BGRA) ? PNG_TRANSFORM_BGR : PNG_TRANSFORM_IDENTITY;
			
		// PNG files store 16-bit pixels in network byte order (big-endian, ie. most significant bits first).
#if PLATFORM_LITTLE_ENDIAN
		// We're little endian so we need to swap
		if (BitDepth == 16)
		{
			Transform |= PNG_TRANSFORM_SWAP_ENDIAN;
		}
#endif

		// Convert grayscale png to RGB if requested
		if ((ColorType & PNG_COLOR_MASK_COLOR) == 0 &&
			(InFormat == ERGBFormat::RGBA || InFormat == ERGBFormat::BGRA))
		{
			Transform |= PNG_TRANSFORM_GRAY_TO_RGB;
		}

		// Convert RGB png to grayscale if requested
		if ((ColorType & PNG_COLOR_MASK_COLOR) != 0 && InFormat == ERGBFormat::Gray)
		{
			png_set_rgb_to_gray_fixed(png_ptr, 2 /* warn if image is in color */, -1, -1);
		}

		// Strip alpha channel if requested output is grayscale
		if (InFormat == ERGBFormat::Gray)
		{
			// this is not necessarily the best option, instead perhaps:
			// png_color background = {0,0,0};
			// png_set_background(png_ptr, &background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
			Transform |= PNG_TRANSFORM_STRIP_ALPHA;
		}

		// Reduce 16-bit to 8-bit if requested
		if (BitDepth == 16 && InBitDepth == 8)
		{
#if PNG_LIBPNG_VER >= 10504
			check(0); // Needs testing
			Transform |= PNG_TRANSFORM_SCALE_16;
#else
			Transform |= PNG_TRANSFORM_STRIP_16;
#endif
		}

		// Increase 8-bit to 16-bit if requested
		if (BitDepth <= 8 && InBitDepth == 16)
		{
#if PNG_LIBPNG_VER >= 10504
			check(0); // Needs testing
			Transform |= PNG_TRANSFORM_EXPAND_16
#else
			// Expanding 8-bit images to 16-bit via transform needs a libpng update
			check(0);
#endif
		}

		png_read_png(png_ptr, info_ptr, Transform, NULL);
	}

	RawFormat = InFormat;
	RawBitDepth = InBitDepth;
}
Esempio n. 12
0
//--------------------------------------
static bool sReadPNG(Stream &stream, GBitmap *bitmap)
{
   static const U32 cs_headerBytesChecked = 8;

   U8 header[cs_headerBytesChecked];
   stream.read(cs_headerBytesChecked, header);

   bool isPng = png_check_sig(header, cs_headerBytesChecked) != 0;
   if (isPng == false) 
   {
      AssertWarn(false, "GBitmap::readPNG: stream doesn't contain a PNG");
      return false;
   }

   U32 prevWaterMark = FrameAllocator::getWaterMark();
   png_structp png_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING,
      NULL,
      pngFatalErrorFn,
      pngWarningFn,
      NULL,
      pngRealMallocFn,
      pngRealFreeFn);

   if (png_ptr == NULL) 
   {
      FrameAllocator::setWaterMark(prevWaterMark);
      return false;
   }

   png_infop info_ptr = png_create_info_struct(png_ptr);
   if (info_ptr == NULL) 
   {
      png_destroy_read_struct(&png_ptr,
         (png_infopp)NULL,
         (png_infopp)NULL);

      FrameAllocator::setWaterMark(prevWaterMark);
      return false;
   }

   png_infop end_info = png_create_info_struct(png_ptr);
   if (end_info == NULL) 
   {
      png_destroy_read_struct(&png_ptr,
         &info_ptr,
         (png_infopp)NULL);

      FrameAllocator::setWaterMark(prevWaterMark);
      return false;
   }

   png_set_read_fn(png_ptr, &stream, pngReadDataFn);

   // Read off the info on the image.
   png_set_sig_bytes(png_ptr, cs_headerBytesChecked);
   png_read_info(png_ptr, info_ptr);

   // OK, at this point, if we have reached it ok, then we can reset the
   //  image to accept the new data...
   //
   bitmap->deleteImage();

   png_uint_32 width;
   png_uint_32 height;
   S32 bit_depth;
   S32 color_type;

   png_get_IHDR(png_ptr, info_ptr,
      &width, &height,             // obv.
      &bit_depth, &color_type,     // obv.
      NULL,                        // interlace
      NULL,                        // compression_type
      NULL);                       // filter_type

   // First, handle the color transformations.  We need this to read in the
   //  data as RGB or RGBA, _always_, with a maximal channel width of 8 bits.
   //
   bool transAlpha     = false;
   GFXFormat format = GFXFormatR8G8B8;

   // Strip off any 16 bit info
   //
   if (bit_depth == 16 && color_type != PNG_COLOR_TYPE_GRAY) 
   {
      png_set_strip_16(png_ptr);
   }

   // Expand a transparency channel into a full alpha channel...
   //
   if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) 
   {
      png_set_expand(png_ptr);
      transAlpha = true;
   }

   if (color_type == PNG_COLOR_TYPE_PALETTE) 
   {
      png_set_expand(png_ptr);
      format = transAlpha ? GFXFormatR8G8B8A8 : GFXFormatR8G8B8;
   }
   else if (color_type == PNG_COLOR_TYPE_GRAY) 
   {
      png_set_expand(png_ptr);

      if (bit_depth == 16)
         format = GFXFormatR5G6B5;
      else
         format = GFXFormatA8;
   }
   else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 
   {
      png_set_expand(png_ptr);
      png_set_gray_to_rgb(png_ptr);
      format = GFXFormatR8G8B8A8;
   }
   else if (color_type == PNG_COLOR_TYPE_RGB) 
   {
      format = transAlpha ? GFXFormatR8G8B8A8 : GFXFormatR8G8B8;
      png_set_expand(png_ptr);
   }
   else if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) 
   {
      png_set_expand(png_ptr);
      format = GFXFormatR8G8B8A8;
   }

   // Update the info pointer with the result of the transformations
   //  above...
   png_read_update_info(png_ptr, info_ptr);

   const png_size_t rowBytes = png_get_rowbytes(png_ptr, info_ptr);
   if (format == GFXFormatR8G8B8) 
   {
      AssertFatal(rowBytes == width * 3,
         "Error, our rowbytes are incorrect for this transform... (3)");
   }
   else if (format == GFXFormatR8G8B8A8) 
   {
      AssertFatal(rowBytes == width * 4,
         "Error, our rowbytes are incorrect for this transform... (4)");
   }
   else if (format == GFXFormatR5G6B5) 
   {
      AssertFatal(rowBytes == width * 2,
         "Error, our rowbytes are incorrect for this transform... (2)");
   }

   // actually allocate the bitmap space...
   bitmap->allocateBitmap(width, height,
      false,            // don't extrude miplevels...
      format);          // use determined format...

   // Set up the row pointers...
   png_bytep* rowPointers = new png_bytep[ height ];
   U8* pBase = (U8*)bitmap->getBits();
   
   for (U32 i = 0; i < height; i++)
      rowPointers[i] = pBase + (i * rowBytes);

   // And actually read the image!
   png_read_image(png_ptr, rowPointers);

   // We're outta here, destroy the png structs, and release the lock
   //  as quickly as possible...
   //png_read_end(png_ptr, end_info);
   delete [] rowPointers;
   png_read_end(png_ptr, NULL);
   png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);

   // Ok, the image is read in, now we need to finish up the initialization,
   //  which means: setting up the detailing members, init'ing the palette
   //  key, etc...
   //
   // actually, all of that was handled by allocateBitmap, so we're outta here
   //

   // Check this bitmap for transparency
   bitmap->checkForTransparency();

   FrameAllocator::setWaterMark(prevWaterMark);

   return true;
}
Esempio n. 13
0
uint8_t *PNG_unpack(SYS_FILEHANDLE infile, uint32_t *LX, uint32_t *LY, int *dwBitsPerPixel, rgb24_t *pClut, int options)
{
    uint8_t *out_buffer;
	uint32_t i;
	unsigned char sig[8];
	png_structp png_ptr;
	png_infop info_ptr;

	FIO_cur->fread(sig, 1, 8, infile);
	if (!png_check_sig(sig, 8))
	{
		return NULL;	/* bad signature */
	}
	png_ptr = png_create_read_struct_2(

	PNG_LIBPNG_VER_STRING,
	(png_voidp)NULL,
	(png_error_ptr)pngx_error,
	(png_error_ptr)pngx_warning,
	(png_voidp)NULL,
	(png_malloc_ptr)pngx_malloc,
	(png_free_ptr)pngx_free);

	png_init_io(png_ptr, (FILE*)infile);
	png_set_sig_bytes(png_ptr, 8);	/* we already read the 8 signature bytes */
	png_set_read_fn(png_ptr, (FILE*)infile, pngx_readm_pData);

if (!pClut)
		pClut = (rgb24_t*)MM_heap.malloc(3*256);

	info_ptr = png_create_info_struct(png_ptr);
	png_read_info(png_ptr, info_ptr);  /* read all PNG info up to image data */

	if (setjmp(png_jmpbuf(png_ptr)))
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		return NULL;
	}

	out_buffer = 0;

	if (png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE))
	{
		png_colorp palette;
		int num_palette;
		png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
		if (palette)
			sysMemCpy(pClut, palette, num_palette * 3);
	}
	else
	{
		for (i=0;i<256;i++)
			pClut[i].r = pClut[i].g = pClut[i].b = (uint8_t)i;
	}

	if (png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA))
	{
		double gamma;
		png_get_gAMA(png_ptr, info_ptr, &gamma);
	}

	if (options & 1)
	{
		png_uint_32 width, height;
		int bit_depth, rowbytes;
		int color_type;
		uint8_t **row_pointers = NULL;

		png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);

		if (bit_depth<8)
			png_set_packing(png_ptr);

		if ((color_type == PNG_COLOR_TYPE_RGB_ALPHA && bit_depth>8))
			png_set_bgr(png_ptr);

		png_read_update_info(png_ptr, info_ptr);
		rowbytes = png_get_rowbytes(png_ptr, info_ptr);

		out_buffer	 = (uint8_t*) MM_heap.malloc(height * rowbytes);
		row_pointers = (uint8_t**) MM_std.malloc(sizeof(char*)*height);
		SYS_ASSERT(row_pointers!=0);
		for (i=0;i<height;i++)
			row_pointers[i] = out_buffer + i * rowbytes;
		png_read_image(png_ptr, row_pointers);
		MM_std.free(row_pointers);
		png_read_end(png_ptr, NULL);

		*LX  = width;
		*LY  = height;
		*dwBitsPerPixel = (rowbytes<<3) / width;
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
	}
	return out_buffer;
}
Esempio n. 14
0
/*
 * @brief Reads header information from the PNG file into the bitmap pointer
 *
 * @param [in]  filename  name of the PNG bitmap file
 * @param [out] w         width of the bitmap
 * @param [out] h         height of the bitmap
 * @param [out] bpp       bits per pixel of the bitmap
 * @param [out] palette
 *
 * @retval PNG_ERROR_NONE if successful, otherwise error code
 */
int png_read_header(const char *real_filename, CFILE *img_cfp, int *w, int *h, int *bpp, ubyte *palette)
{
	char filename[MAX_FILENAME_LEN];
	png_infop info_ptr;
	png_structp png_ptr;

	png_read_status status;
	status.reading_header = true;
	status.filename = real_filename;

	if (img_cfp == NULL) {
		strcpy_s( filename, real_filename );

		char *p = strchr( filename, '.' );

		if ( p )
			*p = 0;
		strcat_s( filename, ".png" );

		status.cfp = cfopen( filename , "rb" );

		if ( !status.cfp ) {
			return PNG_ERROR_READING;
		}
	} else {
		status.cfp = img_cfp;
	}

	Assert( status.cfp != NULL );

	if (status.cfp == NULL)
		return PNG_ERROR_READING;

	/* Create and initialize the png_struct with the desired error handler
	* functions.  If you want to use the default stderr and longjump method,
	* you can supply NULL for the last three parameters.  We also supply the
	* the compiler header file version, so that we know if the application
	* was compiled with a compatible version of the library.  REQUIRED
	*/
	png_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, &status, png_error_fn, png_warning_fn, &status, png_malloc_fn, png_free_fn);

	if (png_ptr == NULL)
	{
		mprintf(("png_read_header: error creating read struct\n"));
		cfclose(status.cfp);
		return PNG_ERROR_READING;
	}

	/* Allocate/initialize the memory for image information.  REQUIRED. */
	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL)
	{
		mprintf(("png_read_header: error creating info struct\n"));
		cfclose(status.cfp);
		png_destroy_read_struct(&png_ptr, NULL, NULL);
		return PNG_ERROR_READING;
	}

	if (setjmp(png_jmpbuf(png_ptr)))
	{
		mprintf(("png_read_header: something went wrong\n"));
		/* Free all of the memory associated with the png_ptr and info_ptr */
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		cfclose(status.cfp);
		/* If we get here, we had a problem reading the file */
		return PNG_ERROR_READING;
	}

	png_set_read_fn(png_ptr, &status, png_scp_read_data);

	png_read_info(png_ptr, info_ptr);

	if (w) *w = png_get_image_width(png_ptr, info_ptr);
	if (h) *h = png_get_image_height(png_ptr, info_ptr);
	// this turns out to be near useless, but meh
	if (bpp) *bpp = (png_get_channels(png_ptr, info_ptr) * png_get_bit_depth(png_ptr, info_ptr));

	if (img_cfp == NULL) {
		cfclose(status.cfp);
		status.cfp = NULL;
	}

	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

	return PNG_ERROR_NONE;
}
Esempio n. 15
0
/*
 * Loads a PNG image
 *
 * @param [in]  real_filename  name of the png file to load
 * @param [out] image_data     allocated storage for the bitmap
 * @param [in]  bpp
 * @param [in]  dest_size
 * @param [in]  cf_type
 *
 * @retval true if succesful, false otherwise
 */
int png_read_bitmap(const char *real_filename, ubyte *image_data, int *bpp, int dest_size, int cf_type)
{
	char filename[MAX_FILENAME_LEN];
	png_infop info_ptr;
	png_structp png_ptr;
	png_bytepp row_pointers;
	unsigned int i;

	png_read_status status;
	status.reading_header = false;
	status.filename = real_filename;

	strcpy_s( filename, real_filename );
	char *p = strchr( filename, '.' );
	if ( p ) *p = 0;
	strcat_s( filename, ".png" );

	status.cfp = cfopen(filename, "rb", CFILE_NORMAL, cf_type);

	if (status.cfp == NULL)
		return PNG_ERROR_READING;

	/* Create and initialize the png_struct with the desired error handler
	* functions.  If you want to use the default stderr and longjump method,
	* you can supply NULL for the last three parameters.  We also supply the
	* the compiler header file version, so that we know if the application
	* was compiled with a compatible version of the library.  REQUIRED
	*/
	png_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, &status, png_error_fn, png_warning_fn, NULL, NULL, NULL);

	if (png_ptr == NULL)
	{
		mprintf(("png_read_bitmap: png_ptr went wrong\n"));
		cfclose(status.cfp);
		return PNG_ERROR_READING;
	}

	/* Allocate/initialize the memory for image information.  REQUIRED. */
	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL)
	{
		mprintf(("png_read_bitmap: info_ptr went wrong\n"));
		cfclose(status.cfp);
		png_destroy_read_struct(&png_ptr, NULL, NULL);
		return PNG_ERROR_READING;
	}

	if (setjmp(png_jmpbuf(png_ptr)))
	{
		mprintf(("png_read_bitmap: something went wrong\n"));
		/* Free all of the memory associated with the png_ptr and info_ptr */
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		cfclose(status.cfp);
		/* If we get here, we had a problem reading the file */
		return PNG_ERROR_READING;
	}

	png_set_read_fn(png_ptr, &status, png_scp_read_data);

	png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_BGR | PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_STRIP_16, NULL);
	auto len = png_get_rowbytes(png_ptr, info_ptr);

	row_pointers = png_get_rows(png_ptr, info_ptr);

	if(bpp)
		*bpp = (ubyte)(len / png_get_image_width(png_ptr, info_ptr)) << 3;

	//copy row data to image
	unsigned int height = png_get_image_height(png_ptr, info_ptr);
	for (i = 0; i < height; i++) {
		memcpy(&image_data[i * len], row_pointers[i], len);
	}

	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
	cfclose(status.cfp);

	return PNG_ERROR_NONE;
}
Esempio n. 16
0
//==============================================================
sPNG *PngRead(void *ptr, size_t size)
//--------------------------------------------------------------
// データ読み込み
//--------------------------------------------------------------
// in:	ptr  = データポインタ
//		size = データサイズ
//--------------------------------------------------------------
// out:	アクセスハンドル(NULL = 失敗)
//==============================================================
{
	png_struct *hdl;
	png_info *info;
	u_char *filepos;
	png_uint_32 width, height;
	int depth, type;
	u_char **image;
	int num_palette;
	png_colorp palette;
	sPalette *pal;
	size_t w_size;

	int trans_ex;
	png_bytep trans;
	png_color_16p trans_16;
	int trans_num;

	int i;
	unsigned int h;
	sPNG *hdr;

	// ヘッダチェック
	//----------------
	if(!png_check_sig((png_bytep)ptr, size))
		return NULL;

	// 基本構造体の初期化
	//--------------------
#ifdef USE_USER_MEMORY
	hdl = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL, NULL, libpng_Malloc, libpng_Free);
#else
	hdl = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
#endif
	if(!hdl)
		return NULL;
	info = png_create_info_struct(hdl);
	if(!info)
	{
		png_destroy_read_struct(&hdl, NULL, NULL);
		return NULL;
	}

	filepos = (u_char *)ptr;
	png_set_read_fn(hdl, (png_voidp)&filepos, (png_rw_ptr)readFunc);

	png_read_info(hdl, info);

	png_get_IHDR(hdl, info, &width, &height, &depth, &type, NULL, NULL, NULL);

	if(depth == 16)
	{
		png_set_strip_16(hdl);					// 16bit -> 8bit
	}
	else
	if(depth == 4)
	{
		png_set_packing(hdl);					// 4bit -> 8bit
	}
	else
	if(depth != 8)
	{
		PRINTF("Format error(%d)\n", depth);
		return NULL;
	}

#if 0
	if(type != PNG_COLOR_TYPE_PALETTE)
	{
		PRINTF("Format error(not palette type)\n");
		return NULL;
	}
#endif

#if 0											// OpenGLで使う場合は不要
	// アルファ付きPNG
	//-----------------
	if(type & PNG_COLOR_MASK_ALPHA)
		png_set_bgr(hdl);
#endif

	// 透明色情報取得
	//----------------
	trans_ex = png_get_tRNS(hdl, info, &trans, &trans_num, &trans_16);

	// 設定を反映
	//------------
	png_read_update_info(hdl, info);

	// パレットを取得
	//----------------
	if(png_get_PLTE(hdl, info, &palette, &num_palette))
	{
//		PRINTF("palette: %d\n", num_palette);

		pal = (sPalette *)pngMalloc(sizeof(sPalette) * num_palette, "sPalette");
		ASSERT(pal);

		for(i = 0; i < num_palette; ++i)
		{
			pal[i].red   = palette[i].red;
			pal[i].green = palette[i].green;
			pal[i].blue  = palette[i].blue;
			if(trans_ex && trans_num)
			{
				// 取得した情報に従って設定
				//--------------------------
				pal[i].alpha = *trans;
				++trans;
				--trans_num;
			}
			else
			{
				// 不透明
				//--------
				pal[i].alpha = 255;
			}
		}
	}
	else
	{
		pal = NULL;
	}

	// データ格納領域を確保
	//----------------------
	image = (u_char **)pngMalloc(sizeof(u_char *) * height, "png"); 
	ASSERT(image);
	w_size = png_get_rowbytes(hdl, info);
	for(h = 0; h < height; ++h)
	{
		image[h] = (u_char *)pngMalloc(w_size, "png");
		ASSERT(image[h]);
	}

	// データを読み込む
	//------------------
	png_read_image(hdl, image);

	// 読み込み終了処理
	//------------------
	png_read_end(hdl, info);

	// 後始末
	//--------
	png_destroy_read_struct(&hdl, &info, NULL);

	// アクセスハンドルを作成
	//------------------------
	hdr = (sPNG *)pngMalloc(sizeof(sPNG), "sPNG");
	ASSERT(hdr);

	hdr->type = type;
	hdr->width = width;
	hdr->height = height;
	hdr->image = (u_char *)pngMalloc(w_size * height, "sPNG image");
	hdr->palnum = num_palette;
	hdr->pal = pal;

	// イメージをコピー
	//------------------
	for(h = 0; h < height; ++h)
	{
		memcpy(&hdr->image[w_size * h], image[h], w_size);
		Free(image[h]);
	}
	Free(image);

	return hdr;
}
Esempio n. 17
0
static gpointer
gdk_pixbuf__png_image_begin_load (GdkPixbufModuleSizeFunc size_func,
                                  GdkPixbufModulePreparedFunc prepare_func,
				  GdkPixbufModuleUpdatedFunc update_func,
				  gpointer user_data,
                                  GError **error)
{
        LoadContext* lc;
        
        lc = g_new0(LoadContext, 1);
        
        lc->fatal_error_occurred = FALSE;

        lc->size_func = size_func;
        lc->prepare_func = prepare_func;
        lc->update_func = update_func;
        lc->notify_user_data = user_data;

        lc->first_row_seen_in_chunk = -1;
        lc->last_row_seen_in_chunk = -1;
        lc->first_pass_seen_in_chunk = -1;
        lc->last_pass_seen_in_chunk = -1;
        lc->max_row_seen_in_chunk = -1;
        lc->error = error;
        
        /* Create the main PNG context struct */

#ifdef PNG_USER_MEM_SUPPORTED
        lc->png_read_ptr = png_create_read_struct_2 (PNG_LIBPNG_VER_STRING,
                                                     lc, /* error/warning callback data */
                                                     png_error_callback,
                                                     png_warning_callback,
                                                     NULL,
                                                     png_malloc_callback,
                                                     png_free_callback);
#else
        lc->png_read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
                                                  lc, /* error/warning callback data */
                                                  png_error_callback,
                                                  png_warning_callback);
#endif
        if (lc->png_read_ptr == NULL) {
                g_free(lc);
                /* error callback should have set the error */
                return NULL;
        }
        
	if (setjmp (png_jmpbuf(lc->png_read_ptr))) {
		if (lc->png_info_ptr)
			png_destroy_read_struct(&lc->png_read_ptr, NULL, NULL);
                g_free(lc);
                /* error callback should have set the error */
                return NULL;
	}

        /* Create the auxiliary context struct */

        lc->png_info_ptr = png_create_info_struct(lc->png_read_ptr);

        if (lc->png_info_ptr == NULL) {
                png_destroy_read_struct(&lc->png_read_ptr, NULL, NULL);
                g_free(lc);
                /* error callback should have set the error */
                return NULL;
        }

        png_set_progressive_read_fn(lc->png_read_ptr,
                                    lc, /* callback data */
                                    png_info_callback,
                                    png_row_callback,
                                    png_end_callback);
        

        /* We don't want to keep modifying error after returning here,
         * it may no longer be valid.
         */
        lc->error = NULL;
        
        return lc;
}
Esempio n. 18
0
Error ImageLoaderPNG::_load_image(void *rf_up,png_rw_ptr p_func,Image *p_image) {



	png_structp png;
	png_infop info;

	//png = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL);

	png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,_png_error_function,_png_warn_function,(png_voidp)NULL,
				 _png_malloc_fn,_png_free_fn );

	ERR_FAIL_COND_V(!png, ERR_OUT_OF_MEMORY);

	info = png_create_info_struct(png);
	if (!info) {
		png_destroy_read_struct(&png,NULL,NULL);
		ERR_PRINT("Out of Memory");
		return ERR_OUT_OF_MEMORY;
	}

	if (setjmp(png_jmpbuf(png))) {

	      png_destroy_read_struct(&png,NULL,NULL);
	      ERR_PRINT("PNG Corrupted");
	      return ERR_FILE_CORRUPT;
	}

	png_set_read_fn(png,(void*)rf_up,p_func);

	png_uint_32 width, height;
	int depth, color;


	png_read_info(png, info);
	png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL);

	png_textp t;
	//https://svn.gov.pt/projects/ccidadao/repository/middleware-offline/trunk/_src/eidmw/FreeImagePTEiD/Source/FreeImage/PluginPNG.cpp
	//png_get_text(png,info,)
	/*
	printf("Image width:%i\n", width);
	printf("Image Height:%i\n", height);
	printf("Bit depth:%i\n", depth);
	printf("Color type:%i\n", color);
	*/

	if (depth<8) { //only bit dept 8 per channel is handled

		png_set_packing(png);
	};

	if (depth > 8) {
		png_set_strip_16(png);
		png_read_update_info(png, info);
	}

	int palette_colors = 0;
	int palette_components = 0;
	int components = 0;

	Image::Format fmt;
	switch(color) {


		case PNG_COLOR_TYPE_GRAY: {

			fmt=Image::FORMAT_GRAYSCALE;
			components=1;
		} break;
		case PNG_COLOR_TYPE_GRAY_ALPHA: {

			fmt=Image::FORMAT_GRAYSCALE_ALPHA;
			components=2;
		} break;
		case PNG_COLOR_TYPE_RGB: {

			fmt=Image::FORMAT_RGB;
			components=3;
		} break;
		case PNG_COLOR_TYPE_RGB_ALPHA: {

			fmt=Image::FORMAT_RGBA;
			components=4;
		} break;
		case PNG_COLOR_TYPE_PALETTE: {

			int ntrans = 0;
			png_get_tRNS(png, info, NULL, &ntrans, NULL);
			//printf("transparent colors %i\n", ntrans);

			fmt = ntrans > 0 ? Image::FORMAT_INDEXED_ALPHA : Image::FORMAT_INDEXED;
			palette_components = ntrans > 0 ? 4 : 3;
			components = 1;

			png_colorp colors;
			png_get_PLTE(png, info, &colors, &palette_colors);

		} break;
		default: {

			ERR_PRINT("INVALID PNG TYPE");
			png_destroy_read_struct(&png, &info, NULL);
			return ERR_UNAVAILABLE;
		} break;
	}

	//int rowsize = png_get_rowbytes(png, info);
	int rowsize = components * width;

	DVector<uint8_t> dstbuff;

	dstbuff.resize( rowsize * height + palette_components * 256 ); // alloc the entire palette? - yes always

	DVector<uint8_t>::Write dstbuff_write = dstbuff.write();

	uint8_t* data = dstbuff_write.ptr();

	uint8_t **row_p = memnew_arr( uint8_t*, height );

	for (unsigned int i = 0; i < height; i++) {
		row_p[i] = &data[components*width*i];
	}

	png_read_image(png, (png_bytep*)row_p);

	if (palette_colors) {

		uint8_t *r_pal = &data[components*width*height]; // end of the array
		png_colorp colors;
		int num;
		png_get_PLTE(png, info, &colors, &num);

		int ofs = 0;
		for (int i=0; i < palette_colors; i++) {

			r_pal[ofs + 0] = colors[i].red;
			r_pal[ofs + 1] = colors[i].green;
			r_pal[ofs + 2] = colors[i].blue;
			if (palette_components == 4) {
				r_pal[ofs + 3] = 255;
			};
			ofs += palette_components;
		};

		if (fmt == Image::FORMAT_INDEXED_ALPHA) {
			png_color_16p alphas;
			png_bytep alpha_idx;
			int count;
			png_get_tRNS(png, info, &alpha_idx, &count, &alphas);
			for (int i=0; i<count; i++) {

				//printf("%i: loading alpha fron transparent color %i, values %i, %i, %i, %i, %i\n", i, (int)alpha_idx[i], (int)alphas[i].index, (int)alphas[i].red, (int)alphas[i].green, (int)alphas[i].blue, (int)alphas[i].gray);
				//r_pal[alpha_idx[i]] = alphas[i].gray >> 8;
				r_pal[i*4+3] = alpha_idx[i];
			};
		};
	};

	memdelete_arr( row_p );

	p_image->create( width, height, 0,fmt, dstbuff );

	png_destroy_read_struct(&png, &info, NULL );

	return OK;
}
Esempio n. 19
0
void printImage(size_t center, size_t middle, void const * imgStart, void const * imgEnd)
{
   PSEUDO_FILE *fp;
   png_bytep *row_pointers;
   int width, height;

   if( (fp = pseudo_fopen((char const *)imgStart, (long)imgEnd-(long)imgStart )) == NULL )
   {
      debug("Pseudo open failed");
      return;
   }

   png_structp png_ptr = png_create_read_struct_2(
      PNG_LIBPNG_VER_STRING,
      (png_voidp)NULL,
      NULL,
      NULL,
      NULL,
      my_malloc,
      my_free);
   if ( !png_ptr )
   {
      debug("Got no png ptr");
      return;
   }

   png_infop info_ptr = png_create_info_struct(png_ptr);
   if ( !info_ptr )
   {
       png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
       debug("Got no info struct");
       return;
   }

   /* read file */
   if (setjmp(png_jmpbuf(png_ptr)))
   {
      debug("[read_png_file] Error");
      png_destroy_read_struct(&png_ptr, &info_ptr, 0);
      return;
   }

   /* Pass file 'handle' and function address to png_set_read_fn() */
   png_set_read_fn(png_ptr, (void *)fp, my_fread);
   png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_SWAP_ALPHA, NULL);

   width = png_get_image_width(png_ptr, info_ptr);
   height = png_get_image_height(png_ptr, info_ptr);

   row_pointers = png_get_rows(png_ptr, info_ptr);
   int left = center-width/2;
   int top = middle+height/2;
   for( int x = 0; x < width; ++x )
   {
      for( int y = 0; y < height; ++y )
      {  
         if(sizeof(color) != 4)
         {
            debug("Color size: %d", sizeof(color));
         }
         color * screenpxp = (color*)&SCREEN[top-y][left+x];
         color * imagepxp = (color*)&((uint32_t *)row_pointers[y])[x];
         color imagepx = *imagepxp;
         color screenpx = *screenpxp;

         screenpx.r = imagepx.a * imagepx.r / 255 + (255 - imagepx.a) * screenpx.r / 255;
         screenpx.g = imagepx.a * imagepx.g / 255 + (255 - imagepx.a) * screenpx.g / 255;
         screenpx.b = imagepx.a * imagepx.b / 255 + (255 - imagepx.a) * screenpx.b / 255;

         setPixel(left+x,top-y,*(uint32_t *)&screenpx);
      }
   }

   png_destroy_read_struct(&png_ptr, &info_ptr, 0);
   pseudo_fclose(fp);

   return;
}
Esempio n. 20
0
Error ImageLoaderPNG::_load_image(void *rf_up, png_rw_ptr p_func, Ref<Image> p_image) {

	png_structp png;
	png_infop info;

	//png = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL);

	png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, _png_error_function, _png_warn_function, (png_voidp)NULL,
			_png_malloc_fn, _png_free_fn);

	ERR_FAIL_COND_V(!png, ERR_OUT_OF_MEMORY);

	info = png_create_info_struct(png);
	if (!info) {
		png_destroy_read_struct(&png, NULL, NULL);
		ERR_PRINT("Out of Memory");
		return ERR_OUT_OF_MEMORY;
	}

	if (setjmp(png_jmpbuf(png))) {

		png_destroy_read_struct(&png, NULL, NULL);
		ERR_PRINT("PNG Corrupted");
		return ERR_FILE_CORRUPT;
	}

	png_set_read_fn(png, (void *)rf_up, p_func);

	png_uint_32 width, height;
	int depth, color;

	png_read_info(png, info);
	png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL);

	//https://svn.gov.pt/projects/ccidadao/repository/middleware-offline/trunk/_src/eidmw/FreeImagePTEiD/Source/FreeImage/PluginPNG.cpp
	//png_get_text(png,info,)
	/*
	printf("Image width:%i\n", width);
	printf("Image Height:%i\n", height);
	printf("Bit depth:%i\n", depth);
	printf("Color type:%i\n", color);
	*/

	bool update_info = false;

	if (depth < 8) { //only bit dept 8 per channel is handled

		png_set_packing(png);
		update_info = true;
	};

	if (png_get_color_type(png, info) == PNG_COLOR_TYPE_PALETTE) {
		png_set_palette_to_rgb(png);
		update_info = true;
	}

	if (depth > 8) {
		png_set_strip_16(png);
		update_info = true;
	}

	if (png_get_valid(png, info, PNG_INFO_tRNS)) {
		//png_set_expand_gray_1_2_4_to_8(png);
		png_set_tRNS_to_alpha(png);
		update_info = true;
	}

	if (update_info) {
		png_read_update_info(png, info);
		png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL);
	}

	int components = 0;

	Image::Format fmt;
	switch (color) {

		case PNG_COLOR_TYPE_GRAY: {

			fmt = Image::FORMAT_L8;
			components = 1;
		} break;
		case PNG_COLOR_TYPE_GRAY_ALPHA: {

			fmt = Image::FORMAT_LA8;
			components = 2;
		} break;
		case PNG_COLOR_TYPE_RGB: {

			fmt = Image::FORMAT_RGB8;
			components = 3;
		} break;
		case PNG_COLOR_TYPE_RGB_ALPHA: {

			fmt = Image::FORMAT_RGBA8;
			components = 4;
		} break;
		default: {

			ERR_PRINT("INVALID PNG TYPE");
			png_destroy_read_struct(&png, &info, NULL);
			return ERR_UNAVAILABLE;
		} break;
	}

	//int rowsize = png_get_rowbytes(png, info);
	int rowsize = components * width;

	PoolVector<uint8_t> dstbuff;

	dstbuff.resize(rowsize * height);

	PoolVector<uint8_t>::Write dstbuff_write = dstbuff.write();

	uint8_t *data = dstbuff_write.ptr();

	uint8_t **row_p = memnew_arr(uint8_t *, height);

	for (unsigned int i = 0; i < height; i++) {
		row_p[i] = &data[components * width * i];
	}

	png_read_image(png, (png_bytep *)row_p);

	memdelete_arr(row_p);

	p_image->create(width, height, 0, fmt, dstbuff);

	png_destroy_read_struct(&png, &info, NULL);

	return OK;
}
Esempio n. 21
0
RADRT_API bool RADRT_CALL DecodeHeader(const void *buff, AddrSize buffLength, Image &out)
{
	RAD_ASSERT(buff&&buffLength);
	RAD_ASSERT(buffLength <= std::numeric_limits<stream::SPos>::max());

	out.Free();
	
	stream::MemInputBuffer ib(buff, (stream::SPos)buffLength);
	stream::InputStream is(ib);

	{
		char sig[SigSize];
		if (is.Read(sig, SigSize, 0) != SigSize) 
			return false;
		// NOTE: png_sig_cmp() returns 0 if the sig matches the PNG sig.
		if (png_sig_cmp((png_bytep)sig, 0, SigSize)) 
			return false;
	}

	png_structp png;
	png_infop   info;
	
	png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, 0, PNGErrorHandler, PNGWarningHandler, 0, PNGMalloc, PNGFree);
	if (!png) return false;

	info = png_create_info_struct(png);
	if (!info) 
	{
		png_destroy_read_struct(&png, 0, 0);
		return false;
	}

	png_set_read_fn(png, &is, PNGRead);	
	png_set_sig_bytes(png, SigSize);
	
	try
	{
		png_uint_32 w, h;
		int bd, color, interlace;

		png_read_info(png, info);
		png_get_IHDR(png, info, &w, &h, &bd, &color, &interlace, 0, 0);
		if (!out.AllocateFrames(1)||!out.AllocateMipmaps(0, 1)) 
			return false;
		
		Mipmap &m = out.frames[0].mipmaps[0];

		out.format = Format(png, info, bd, color);

		if (out.format == InvalidFormat)
		{
			out.Free();
			png_destroy_read_struct(&png, &info, 0);
			return false;
		}

		out.bpp = FormatBPP(out.format);

		m.width = w;
		m.height = h;
		m.stride = w * out.bpp;
	}
	catch (PNGException&)
	{
		out.Free();
		png_destroy_read_struct(&png, &info, 0);
		return false;
	}

	png_destroy_read_struct(&png, &info, 0);
	return true;
}
Esempio n. 22
0
bool R9_ImgReadHeaderPNG( F9FILE file, r9Img* img )
{
	if(file==NULL || img==NULL) return false;
	R9_ImgDestroy(img);
	
	// check png sig
	const int headersize = 8;
	byte header[headersize];
	if(file->Read( header, headersize)!=headersize) return false;

	BOOL ispng = png_check_sig(header, headersize) != 0;
	if(!ispng) { elog::rnd() << "png sig failed" << std::endl; return false; }

	// create png structures
	png_structp png_ptr = png_create_read_struct_2( PNG_LIBPNG_VER_STRING,
												NULL,
												R9_ImgPNG_FatalError,
												R9_ImgPNG_Warning,
												NULL,
												R9_ImgPNG_Malloc,
												R9_ImgPNG_Free );

	if(png_ptr==NULL) return false;

	png_infop info_ptr = png_create_info_struct(png_ptr);
	if(info_ptr == NULL) 
	{
		png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
		return false;
	}

	png_infop end_info = png_create_info_struct(png_ptr);
	if(end_info == NULL) 
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
		return false;
	}

	// set global file
	r9_imgpng_file = file;
	png_set_read_fn(png_ptr, NULL, R9_ImgPNG_ReadData);

	// read off the info on the image
	png_set_sig_bytes(png_ptr, headersize);
	png_read_info(png_ptr, info_ptr);

	png_uint_32 pngwidth;
	png_uint_32 pngheight;	
	int32 pngbits;
	int32 pngpf;

	png_get_IHDR(png_ptr, info_ptr,
				&pngwidth, &pngheight,
				&pngbits, &pngpf,
				NULL,                        // interlace
				NULL,                        // compression_type
				NULL);                       // filter_type

	BOOL alpha = FALSE;
	img->m_width = pngwidth;
	img->m_height = pngheight;
	img->m_pf = R9_PF_RGB;

	// release
	png_read_end(png_ptr, NULL);
	png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
	r9_imgpng_file = NULL;

	return true;
}
Esempio n. 23
0
/* Test one file */
int
test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
{
   static png_FILE_p fpin;
   static png_FILE_p fpout;  /* "static" prevents setjmp corruption */
   png_structp read_ptr;
   png_infop read_info_ptr, end_info_ptr;
#ifdef PNG_WRITE_SUPPORTED
   png_structp write_ptr;
   png_infop write_info_ptr;
   png_infop write_end_info_ptr;
#else
   png_structp write_ptr = NULL;
   png_infop write_info_ptr = NULL;
   png_infop write_end_info_ptr = NULL;
#endif
   png_bytep row_buf;
   png_uint_32 y;
   png_uint_32 width, height;
   int num_pass, pass;
   int bit_depth, color_type;
#ifdef PNG_SETJMP_SUPPORTED
#ifdef USE_FAR_KEYWORD
   jmp_buf jmpbuf;
#endif
#endif

#if defined(_WIN32_WCE)
   TCHAR path[MAX_PATH];
#endif
   char inbuf[256], outbuf[256];

   row_buf = NULL;

#if defined(_WIN32_WCE)
   MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH);
   if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
#else
   if ((fpin = fopen(inname, "rb")) == NULL)
#endif
   {
      fprintf(STDERR, "Could not find input file %s\n", inname);
      return (1);
   }

#if defined(_WIN32_WCE)
   MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH);
   if ((fpout = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL)) == INVALID_HANDLE_VALUE)
#else
   if ((fpout = fopen(outname, "wb")) == NULL)
#endif
   {
      fprintf(STDERR, "Could not open output file %s\n", outname);
      FCLOSE(fpin);
      return (1);
   }

   png_debug(0, "Allocating read and write structures\n");
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
   read_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, png_voidp_NULL,
      png_error_ptr_NULL, png_error_ptr_NULL, png_voidp_NULL,
      (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free);
#else
   read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL,
      png_error_ptr_NULL, png_error_ptr_NULL);
#endif
#if defined(PNG_NO_STDIO)
   png_set_error_fn(read_ptr, (png_voidp)inname, pngtest_error,
       pngtest_warning);
#endif
#ifdef PNG_WRITE_SUPPORTED
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
   write_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, png_voidp_NULL,
      png_error_ptr_NULL, png_error_ptr_NULL, png_voidp_NULL,
      (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free);
#else
   write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL,
      png_error_ptr_NULL, png_error_ptr_NULL);
#endif
#if defined(PNG_NO_STDIO)
   png_set_error_fn(write_ptr, (png_voidp)inname, pngtest_error,
       pngtest_warning);
#endif
#endif
   png_debug(0, "Allocating read_info, write_info and end_info structures\n");
   read_info_ptr = png_create_info_struct(read_ptr);
   end_info_ptr = png_create_info_struct(read_ptr);
#ifdef PNG_WRITE_SUPPORTED
   write_info_ptr = png_create_info_struct(write_ptr);
   write_end_info_ptr = png_create_info_struct(write_ptr);
#endif

#ifdef PNG_SETJMP_SUPPORTED
   png_debug(0, "Setting jmpbuf for read struct\n");
#ifdef USE_FAR_KEYWORD
   if (setjmp(jmpbuf))
#else
   if (setjmp(png_jmpbuf(read_ptr)))
#endif
   {
      fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname);
      if (row_buf)
         png_free(read_ptr, row_buf);
      png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
#ifdef PNG_WRITE_SUPPORTED
      png_destroy_info_struct(write_ptr, &write_end_info_ptr);
      png_destroy_write_struct(&write_ptr, &write_info_ptr);
#endif
      FCLOSE(fpin);
      FCLOSE(fpout);
      return (1);
   }
#ifdef USE_FAR_KEYWORD
   png_memcpy(png_jmpbuf(read_ptr),jmpbuf,png_sizeof(jmp_buf));
#endif

#ifdef PNG_WRITE_SUPPORTED
   png_debug(0, "Setting jmpbuf for write struct\n");
#ifdef USE_FAR_KEYWORD
   if (setjmp(jmpbuf))
#else
   if (setjmp(png_jmpbuf(write_ptr)))
#endif
   {
      fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname);
      png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
      png_destroy_info_struct(write_ptr, &write_end_info_ptr);
#ifdef PNG_WRITE_SUPPORTED
      png_destroy_write_struct(&write_ptr, &write_info_ptr);
#endif
      FCLOSE(fpin);
      FCLOSE(fpout);
      return (1);
   }
#ifdef USE_FAR_KEYWORD
   png_memcpy(png_jmpbuf(write_ptr),jmpbuf,png_sizeof(jmp_buf));
#endif
#endif
#endif

   png_debug(0, "Initializing input and output streams\n");
#if !defined(PNG_NO_STDIO)
   png_init_io(read_ptr, fpin);
#  ifdef PNG_WRITE_SUPPORTED
   png_init_io(write_ptr, fpout);
#  endif
#else
   png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data);
#  ifdef PNG_WRITE_SUPPORTED
   png_set_write_fn(write_ptr, (png_voidp)fpout,  pngtest_write_data,
#    if defined(PNG_WRITE_FLUSH_SUPPORTED)
      pngtest_flush);
#    else
      NULL);
#    endif
#  endif
#endif
   if(status_dots_requested == 1)
   {
#ifdef PNG_WRITE_SUPPORTED
      png_set_write_status_fn(write_ptr, write_row_callback);
#endif
      png_set_read_status_fn(read_ptr, read_row_callback);
   }
   else
   {
#ifdef PNG_WRITE_SUPPORTED
      png_set_write_status_fn(write_ptr, png_write_status_ptr_NULL);
#endif
      png_set_read_status_fn(read_ptr, png_read_status_ptr_NULL);
   }

#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
   {
     int i;
     for(i=0; i<256; i++)
        filters_used[i]=0;
     png_set_read_user_transform_fn(read_ptr, count_filters);
   }
#endif
#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
   zero_samples=0;
   png_set_write_user_transform_fn(write_ptr, count_zero_samples);
#endif

#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
#  ifndef PNG_HANDLE_CHUNK_ALWAYS
#    define PNG_HANDLE_CHUNK_ALWAYS       3
#  endif
   png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS,
      png_bytep_NULL, 0);
#endif
#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
#  ifndef PNG_HANDLE_CHUNK_IF_SAFE
#    define PNG_HANDLE_CHUNK_IF_SAFE      2
#  endif
   png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_IF_SAFE,
      png_bytep_NULL, 0);
#endif

   png_debug(0, "Reading info struct\n");
   png_read_info(read_ptr, read_info_ptr);

   png_debug(0, "Transferring info struct\n");
   {
      int interlace_type, compression_type, filter_type;

      if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth,
          &color_type, &interlace_type, &compression_type, &filter_type))
      {
         png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth,
#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
            color_type, interlace_type, compression_type, filter_type);
#else
            color_type, PNG_INTERLACE_NONE, compression_type, filter_type);
#endif
      }
   }
Esempio n. 24
0
RADRT_API bool RADRT_CALL Decode(const void *buff, AddrSize buffLength, Image &out)
{
	RAD_ASSERT(buff&&buffLength);
	RAD_ASSERT(buffLength <= std::numeric_limits<stream::SPos>::max());

	out.Free();

	stream::MemInputBuffer ib(buff, (stream::SPos)buffLength);
	stream::InputStream is(ib);

	{
		char sig[SigSize];
		if (is.Read(sig, SigSize, 0) != SigSize)
			return false;
		// NOTE: png_sig_cmp() returns 0 if the sig matches the PNG sig.
		if (png_sig_cmp((png_bytep)sig, 0, SigSize))
			return false;
	}

	png_structp png;
	png_infop   info;
	
	png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, 0, PNGErrorHandler, PNGWarningHandler, 0, PNGMalloc, PNGFree);
	if (!png)
		return false;

	info = png_create_info_struct(png);
	if (!info) 
	{
		png_destroy_read_struct(&png, 0, 0);
		return false;
	}
	
	png_set_read_fn(png, &is, PNGRead);	
	png_set_sig_bytes(png, SigSize);
	
	try
	{
		png_uint_32 w, h;
		int bd, color, interlace;

		png_read_info(png, info);
		png_get_IHDR(png, info, &w, &h, &bd, &color, &interlace, 0, 0);
		if (!out.AllocateFrames(1)||!out.AllocateMipmaps(0, 1)) 
		{
			png_destroy_read_struct(&png, &info, 0);
			return false;
		}
		
		Mipmap &m = out.frames[0].mipmaps[0];
				
		out.format = Format(png, info, bd, color);

		if (out.format == InvalidFormat)
		{
			out.Free();
			png_destroy_read_struct(&png, &info, 0);
			return false;
		}

		out.bpp = FormatBPP(out.format);

		if (!out.AllocateMipmap(0, 0, w, h, w * out.bpp, w * h * out.bpp))
		{
			out.Free();
			png_destroy_read_struct(&png, &info, 0);
			return false;
		}

		png_set_strip_16(png);

		if (color == PNG_COLOR_TYPE_PALETTE)
		{
			png_set_palette_to_rgb(png);
		}

		if (color == PNG_COLOR_TYPE_GRAY && bd < 8)
		{
			png_set_expand_gray_1_2_4_to_8(png);
		}

		if (png_get_valid(png, info, PNG_INFO_tRNS))
		{
			png_set_tRNS_to_alpha(png);
		}

		png_set_swap(png);
		int passes = png_set_interlace_handling(png);

		png_bytep dstRow = 0;
		png_bytep imgRow = 0;
		png_uint_32 stride = (png_uint_32)png_get_rowbytes(png, info);

		RAD_ASSERT(stride >= m.stride);
		if (stride != m.stride) 
		{
			dstRow = (png_bytep)safe_zone_malloc(ZImageCodec, stride, 0);
		}
		
		for (int pass = 0; pass < passes; ++pass)
		{
			if (stride == m.stride)
			{
				dstRow = (png_bytep)m.data; // reset.
			}

			imgRow = (png_bytep)m.data;

			for (png_uint_32 y = 0; y < h; ++y)
			{
				if (pass > 0 && stride != m.stride)
				{
					RAD_ASSERT(imgRow != dstRow);
					// interlaced image, copy the result of the last pass.
					memcpy(dstRow, imgRow, m.stride);
				}

				png_read_rows(png, &dstRow, 0, 1);

				if (stride != m.stride)
				{
					// imgRow/dstRow are correct, we are copying from dstRow to imgRow.
					memcpy(imgRow, dstRow, m.stride);
				}
				else
				{
					dstRow += m.stride;
				}

				imgRow += m.stride;
			}
		}

		if (stride != m.stride) 
		{
			RAD_ASSERT(dstRow);
			zone_free(dstRow);
		}

		png_read_end(png, info);
	}
	catch (PNGException&)
	{
		out.Free();
		png_destroy_read_struct(&png, &info, 0);
		return false;
	}

	png_destroy_read_struct(&png, &info, 0);
	return true;
}
Esempio n. 25
0
int ReadPNG(const uint8_t* const data, size_t data_size,
            struct WebPPicture* const pic,
            int keep_alpha, struct Metadata* const metadata) {
  volatile png_structp png = NULL;
  volatile png_infop info = NULL;
  volatile png_infop end_info = NULL;
  PNGReadContext context = { NULL, 0, 0 };
  int color_type, bit_depth, interlaced;
  int has_alpha;
  int num_passes;
  int p;
  volatile int ok = 0;
  png_uint_32 width, height, y;
  int64_t stride;
  uint8_t* volatile rgb = NULL;

  if (data == NULL || data_size == 0 || pic == NULL) return 0;

  context.data = data;
  context.data_size = data_size;

  png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL,
                                 NULL, MallocFunc, FreeFunc);
  if (png == NULL) goto End;

  png_set_error_fn(png, 0, error_function, NULL);
  if (setjmp(png_jmpbuf(png))) {
 Error:
    MetadataFree(metadata);
    goto End;
  }

  info = png_create_info_struct(png);
  if (info == NULL) goto Error;
  end_info = png_create_info_struct(png);
  if (end_info == NULL) goto Error;

  png_set_read_fn(png, &context, ReadFunc);
  png_read_info(png, info);
  if (!png_get_IHDR(png, info,
                    &width, &height, &bit_depth, &color_type, &interlaced,
                    NULL, NULL)) goto Error;

  png_set_strip_16(png);
  png_set_packing(png);
  if (color_type == PNG_COLOR_TYPE_PALETTE) {
    png_set_palette_to_rgb(png);
  }
  if (color_type == PNG_COLOR_TYPE_GRAY ||
      color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
    if (bit_depth < 8) {
      png_set_expand_gray_1_2_4_to_8(png);
    }
    png_set_gray_to_rgb(png);
  }
  if (png_get_valid(png, info, PNG_INFO_tRNS)) {
    png_set_tRNS_to_alpha(png);
    has_alpha = 1;
  } else {
    has_alpha = !!(color_type & PNG_COLOR_MASK_ALPHA);
  }

  // Apply gamma correction if needed.
  {
    double image_gamma = 1 / 2.2, screen_gamma = 2.2;
    int srgb_intent;
    if (png_get_sRGB(png, info, &srgb_intent) ||
        png_get_gAMA(png, info, &image_gamma)) {
      png_set_gamma(png, screen_gamma, image_gamma);
    }
  }

  if (!keep_alpha) {
    png_set_strip_alpha(png);
    has_alpha = 0;
  }

  num_passes = png_set_interlace_handling(png);
  png_read_update_info(png, info);

  stride = (int64_t)(has_alpha ? 4 : 3) * width * sizeof(*rgb);
  if (stride != (int)stride ||
      !ImgIoUtilCheckSizeArgumentsOverflow(stride, height)) {
    goto Error;
  }

  rgb = (uint8_t*)malloc((size_t)stride * height);
  if (rgb == NULL) goto Error;
  for (p = 0; p < num_passes; ++p) {
    png_bytep row = rgb;
    for (y = 0; y < height; ++y) {
      png_read_rows(png, &row, NULL, 1);
      row += stride;
    }
  }
  png_read_end(png, end_info);

  if (metadata != NULL &&
      !ExtractMetadataFromPNG(png, info, end_info, metadata)) {
    fprintf(stderr, "Error extracting PNG metadata!\n");
    goto Error;
  }

  pic->width = (int)width;
  pic->height = (int)height;
  ok = has_alpha ? WebPPictureImportRGBA(pic, rgb, (int)stride)
                 : WebPPictureImportRGB(pic, rgb, (int)stride);

  if (!ok) {
    goto Error;
  }

 End:
  if (png != NULL) {
    png_destroy_read_struct((png_structpp)&png,
                            (png_infopp)&info, (png_infopp)&end_info);
  }
  free(rgb);
  return ok;
}
Esempio n. 26
0
static ImgloadErrorCode IMGLOAD_CALLBACK png_init_image(ImgloadPlugin plugin, ImgloadImage img)
{
    png_structp png_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, plugin, png_error_fn, png_warning_fn, plugin, png_malloc_fn, png_free_fn);
    if (png_ptr == NULL)
    {
        return IMGLOAD_ERR_PLUGIN_ERROR;
    }

    png_infop png_info = png_create_info_struct(png_ptr);
    if (png_info == NULL)
    {
        png_destroy_read_struct(&png_ptr, NULL, NULL);
        return IMGLOAD_ERR_PLUGIN_ERROR;
    }

    if (png_error_occured(png_ptr))
    {
        // libPNG has caused an error, free memory and return
        png_destroy_read_struct(&png_ptr, &png_info, NULL);
        return IMGLOAD_ERR_PLUGIN_ERROR;
    }

    png_set_read_fn(png_ptr, img, png_user_read_data);

    png_set_sig_bytes(png_ptr, PNGSIGSIZE);

    png_read_info(png_ptr, png_info);

    // Info has been read
    png_uint_32 img_width = png_get_image_width(png_ptr, png_info);
    png_uint_32 img_height = png_get_image_height(png_ptr, png_info);

    png_uint_32 bitdepth = png_get_bit_depth(png_ptr, png_info);
    png_uint_32 color_type = png_get_color_type(png_ptr, png_info);

    if (bitdepth == 16)
    {
        png_set_strip_16(png_ptr);
    }

    switch (color_type) {
    case PNG_COLOR_TYPE_PALETTE:
        // Expand palette to rgb
        png_set_palette_to_rgb(png_ptr);
        break;
    case PNG_COLOR_TYPE_GRAY:
        if (bitdepth < 8)
            png_set_expand_gray_1_2_4_to_8(png_ptr);
        break;
    }

    // if the image has a transperancy set.. convert it to a full Alpha channel..
    // Also make sure that is was RGB before
    if (png_get_valid(png_ptr, png_info, PNG_INFO_tRNS))
    {
        png_set_tRNS_to_alpha(png_ptr);
    }

    // Update the structure so we can use it later
    png_read_update_info(png_ptr, png_info);

    bitdepth = png_get_bit_depth(png_ptr, png_info);
    uint32_t channels = png_get_channels(png_ptr, png_info);
    color_type = png_get_color_type(png_ptr, png_info);

    if (bitdepth != 8)
    {
        // Any bitdepth != 8 is not supported
        png_destroy_read_struct(&png_ptr, &png_info, NULL);

        imgload_plugin_log(plugin, IMGLOAD_LOG_ERROR, "PNG has a bitdepth of %"PRIu32" but only a bitdepth of 8 is supported by this plugin!", bitdepth);

        return IMGLOAD_ERR_UNSUPPORTED_FORMAT;
    }

    // Convert PNG format to imageloader. Also validates channel number
    ImgloadFormat format;
    if (color_type == PNG_COLOR_TYPE_RGB && channels == 3)
    {
        format = IMGLOAD_FORMAT_R8G8B8;
    } else if (color_type == PNG_COLOR_TYPE_RGBA && channels == 4)
    {
        format = IMGLOAD_FORMAT_R8G8B8A8;
    } else if (color_type == PNG_COLOR_TYPE_GRAY && channels == 1)
    {
        format = IMGLOAD_FORMAT_GRAY8;
    } else
    {
        // Currently no other format is supported
        png_destroy_read_struct(&png_ptr, &png_info, NULL);

        imgload_plugin_log(plugin, IMGLOAD_LOG_ERROR, "PNG has an unsupported data format!");

        return IMGLOAD_ERR_UNSUPPORTED_FORMAT;
    }

    // Everything seems to be alright, set imageloader properties
    imgload_plugin_image_set_data_type(img, format, IMGLOAD_COMPRESSION_NONE);
    imgload_plugin_image_set_num_frames(img, 1);
    imgload_plugin_image_set_num_mipmaps(img, 0, 1);

    imgload_plugin_image_set_property(img, 0, IMGLOAD_PROPERTY_WIDTH, IMGLOAD_PROPERTY_TYPE_UINT32, &img_width);
    imgload_plugin_image_set_property(img, 0, IMGLOAD_PROPERTY_HEIGHT, IMGLOAD_PROPERTY_TYPE_UINT32, &img_height);

    // PNGs are always 2D so set depth to 1
    uint32_t one = 1;
    imgload_plugin_image_set_property(img, 0, IMGLOAD_PROPERTY_DEPTH, IMGLOAD_PROPERTY_TYPE_UINT32, &one);

    PNGPointers* pointers = (PNGPointers*)imgload_plugin_realloc(plugin, NULL, sizeof(PNGPointers));
    if (pointers == NULL)
    {
        // Currently no other format is supported
        png_destroy_read_struct(&png_ptr, &png_info, NULL);
        return IMGLOAD_ERR_OUT_OF_MEMORY;
    }

    pointers->png_ptr = png_ptr;
    pointers->info_ptr = png_info;

    imgload_plugin_image_set_data(img, pointers);
    return IMGLOAD_ERR_NO_ERROR;
}
Esempio n. 27
0
int
xps_decode_png(xps_context_t *ctx, byte *rbuf, int rlen, xps_image_t *image)
{
    png_structp png;
    png_infop info;
    struct xps_png_io_s io;
    int npasses;
    int pass;
    int y;

    /*
     * Set up PNG structs and input source
     */

    io.ptr = rbuf;
    io.lim = rbuf + rlen;

    png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING,
            NULL, NULL, NULL,
            ctx->memory, xps_png_malloc, xps_png_free);
    if (!png)
        return gs_throw(-1, "png_create_read_struct");

    info = png_create_info_struct(png);
    if (!info)
        return gs_throw(-1, "png_create_info_struct");

    png_set_read_fn(png, &io, xps_png_read);
    png_set_crc_action(png, PNG_CRC_WARN_USE, PNG_CRC_WARN_USE);

    /*
     * Jump to here on errors.
     */

    if (setjmp(png_jmpbuf(png)))
    {
        png_destroy_read_struct(&png, &info, NULL);
        return gs_throw(-1, "png reading failed");
    }

    /*
     * Read PNG header
     */

    png_read_info(png, info);

    if (png_get_interlace_type(png, info) == PNG_INTERLACE_ADAM7)
    {
        npasses = png_set_interlace_handling(png);
    }
    else
    {
        npasses = 1;
    }

    if (png_get_color_type(png, info) == PNG_COLOR_TYPE_PALETTE)
    {
        png_set_palette_to_rgb(png);
    }

    if (png_get_valid(png, info, PNG_INFO_tRNS))
    {
        /* this will also expand the depth to 8-bits */
        png_set_tRNS_to_alpha(png);
    }

    png_read_update_info(png, info);

    image->width = png_get_image_width(png, info);
    image->height = png_get_image_height(png, info);
    image->comps = png_get_channels(png, info);
    image->bits = png_get_bit_depth(png, info);

    /* See if we have an icc profile */
    if (info->iccp_profile != NULL)
    {
        image->profilesize = info->iccp_proflen;
        image->profile = xps_alloc(ctx, info->iccp_proflen);
        if (image->profile)
        {
            /* If we can't create it, just ignore */
            memcpy(image->profile, info->iccp_profile, info->iccp_proflen);
        }
    }

    switch (png_get_color_type(png, info))
    {
    case PNG_COLOR_TYPE_GRAY:
        image->colorspace = ctx->gray;
        image->hasalpha = 0;
        break;

    case PNG_COLOR_TYPE_RGB:
        image->colorspace = ctx->srgb;
        image->hasalpha = 0;
        break;

    case PNG_COLOR_TYPE_GRAY_ALPHA:
        image->colorspace = ctx->gray;
        image->hasalpha = 1;
        break;

    case PNG_COLOR_TYPE_RGB_ALPHA:
        image->colorspace = ctx->srgb;
        image->hasalpha = 1;
        break;

    default:
        return gs_throw(-1, "cannot handle this png color type");
    }

    /*
     * Extract DPI, default to 96 dpi
     */

    image->xres = 96;
    image->yres = 96;

    if (info->valid & PNG_INFO_pHYs)
    {
        png_uint_32 xres, yres;
        int unit;
        png_get_pHYs(png, info, &xres, &yres, &unit);
        if (unit == PNG_RESOLUTION_METER)
        {
            image->xres = xres * 0.0254 + 0.5;
            image->yres = yres * 0.0254 + 0.5;
        }
    }

    /*
     * Read rows, filling transformed output into image buffer.
     */

    image->stride = (image->width * image->comps * image->bits + 7) / 8;

    image->samples = xps_alloc(ctx, image->stride * image->height);

    for (pass = 0; pass < npasses; pass++)
    {
        for (y = 0; y < image->height; y++)
        {
            png_read_row(png, image->samples + (y * image->stride), NULL);
        }
    }

    /*
     * Clean up memory.
     */

    png_destroy_read_struct(&png, &info, NULL);

    return gs_okay;
}
Esempio n. 28
0
//---------------------------------------------------------------------------
void __fastcall TDeePNG::LoadFromStream(Classes::TStream * Stream)
{
	// LoadFromStream

	png_structp png_ptr = NULL;
	png_infop info_ptr = NULL;
	png_infop end_info = NULL;

	png_bytep *row_pointers = NULL;
	BYTE *image = NULL;

	png_uint_32 i;

	try
	{
		// create png_struct
		png_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING,
			(png_voidp)this, DeePNG_error, DeePNG_warning,
			(png_voidp)this, DeePNG_malloc, DeePNG_free);

		// set read_chunk_callback
		png_set_read_user_chunk_fn(png_ptr,
			reinterpret_cast<void*>(this),
			PNG_read_chunk_callback);
		png_set_keep_unknown_chunks(png_ptr, 2, NULL, 0);
			// keep only if safe-to-copy chunks, for all unknown chunks

		// create png_info
		info_ptr = png_create_info_struct(png_ptr);

		// create end_info
		end_info = png_create_info_struct(png_ptr);

		// set stream input functions
		png_set_read_fn(png_ptr, (voidp)Stream, DeePNG_read_data);

		// set read_row_callback
		png_set_read_status_fn(png_ptr, DeePNG_read_row_callback);

		// call png_read_info
		png_read_info(png_ptr, info_ptr);

		// retrieve IHDR
		png_uint_32 width, height;
		int bit_depth, color_type, interlace_type, compression_type, filter_type;
		png_get_IHDR(png_ptr,info_ptr, &width, &height, &bit_depth, &color_type,
			&interlace_type, &compression_type, &filter_type);

		// expand palletted image which has transparent color, to 32bpp
		if (png_get_valid(png_ptr, info_ptr,PNG_INFO_tRNS))
		{
			png_set_expand(png_ptr);
			color_type=PNG_COLOR_TYPE_RGB_ALPHA;
		}

		// analyse IHDR ( color_type )
		switch(color_type)
		{
		case PNG_COLOR_TYPE_GRAY_ALPHA:
			PixelFormat=pf32bit;
			break;
		case PNG_COLOR_TYPE_GRAY:
			// w/b
			SetGrayscalePalette(this,bit_depth);
			break;
		case PNG_COLOR_TYPE_PALETTE:
			SetColorDepth(this,bit_depth);
			break;
		case PNG_COLOR_TYPE_RGB_ALPHA:
			PixelFormat=pf32bit;
			break;
		case PNG_COLOR_TYPE_RGB:
			PixelFormat=pf24bit;
			break;
		default:
			throw EDeePNG("EDeePNG : Non-supported color type.");
		}

		// retrieve offset information
		png_int_32 offset_x, offset_y;
		int offset_unit_type;
		if(png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, &offset_unit_type))
		{
			ofs_x = offset_x;
			ofs_y = offset_y;
			ofs_unit = offset_unit_type;
			ofs_set = true;
		}
		else
		{
			ofs_set = false;
		}

		// check size
		if(width>=65536 || height>=65536)
		{
			throw EDeePNG("EDeePNG : Too large image size.");
		}


		// retrieve palette
		if(color_type == PNG_COLOR_TYPE_PALETTE)
		{
			int num_palette;
			png_color *palette = NULL;
			png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);

			int i;
		#pragma pack(push, 1)
			struct
			{
				WORD	palVersion;
				WORD	palNumEntries;
				PALETTEENTRY entry[256];
			} pal;
		#pragma pack(pop)
			pal.palVersion = 0x300;
			pal.palNumEntries = num_palette;
			for(i = 0; i < num_palette; i++)
			{
				pal.entry[i].peRed = palette[i].red;
				pal.entry[i].peGreen = palette[i].green;
				pal.entry[i].peBlue = palette[i].blue;
				pal.entry[i].peFlags = 0;
			}
			Palette = CreatePalette((const LOGPALETTE*)&pal);
		}

		// collapse 16bit precision data to 8bit
		if(bit_depth == 16) png_set_strip_16(png_ptr);

		// change color component order
		if (color_type == PNG_COLOR_TYPE_RGB ||
			color_type == PNG_COLOR_TYPE_RGB_ALPHA)
				png_set_bgr(png_ptr);

		// call png_read_update_info ...
		png_read_update_info(png_ptr, info_ptr);

		// set size
		Width=width, Height=height;

		// allocate memory for row_pointers
		row_pointers = new png_bytep[height];
		png_uint_32 rowbytes = png_get_rowbytes(png_ptr, info_ptr);
		image = new BYTE[rowbytes*height];
		for(i = 0;i < height; i++)
		{
			row_pointers[i] = image + i*rowbytes;
		}

		// load image
		png_read_image(png_ptr, row_pointers);

		// finish loading image
		png_read_end(png_ptr, info_ptr);

		// set image to ScanLines

		BYTE *imageptr = image;
		if(color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
		{
			// IA IA IA ....

			for(i = 0; i < height; i++)
			{
				BYTE *scanptr = (BYTE*)ScanLine[i];
				png_uint_32 j;
				for(j = 0; j < width; j++)
				{
					BYTE i = *(imageptr++);
					scanptr[0] = i;
					scanptr[1] = i;
					scanptr[2] = i;
					scanptr[3] = *(imageptr++);
					scanptr += 4;
				}
			}
		}
		else
		{
			// intact copy

			for(i = 0; i < height; i++)
			{
				BYTE *scanptr = (BYTE*)ScanLine[i];
				memcpy(scanptr, imageptr, rowbytes);
				imageptr += rowbytes;
			}


		}
	}
	catch(...)
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		if(row_pointers) delete [] row_pointers;
		if(image) delete [] image;
		throw;
	}

	png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
	if(row_pointers) delete [] row_pointers;
	if(image) delete [] image;
}