/* Initialize png_ptr structure, and allocate any memory needed */
png_structp
png_create_write_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_write_struct_2(user_png_ver, error_ptr, error_fn,
      warn_fn, NULL, NULL, NULL));
}
Exemple #2
0
static int png_save(BPGDecoderContext *img, mem_encode * mempng, int bit_depth)
{
	BPGImageInfo img_info_s, *img_info = &img_info_s;
	FILE *f;
	png_structp png_ptr;
	png_infop info_ptr;
	png_bytep row_pointer;
	int y, color_type, bpp;
	BPGDecoderOutputFormat out_fmt;


	mempng->buffer = 0;
	mempng->size = 0;

	if (bit_depth != 8 && bit_depth != 16) {
		fprintf(stderr, "Only bit_depth = 8 or 16 are supported for PNG output\n");
		return -1;
	}

	bpg_decoder_get_info(img, img_info);

	png_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING,
		NULL,
		NULL,  /* error */
		NULL, /* warning */
		NULL,
		NULL,
		NULL);
	info_ptr = png_create_info_struct(png_ptr);

	png_set_write_fn(png_ptr, (png_voidp)mempng, &png_write_data_buffer, NULL);

	if (setjmp(png_jmpbuf(png_ptr)) != 0) {
		fprintf(stderr, "PNG write error\n");
		return -1;
	}

	if (img_info->has_alpha)
		color_type = PNG_COLOR_TYPE_RGB_ALPHA;
	else
		color_type = PNG_COLOR_TYPE_RGB;

	png_set_IHDR(png_ptr, info_ptr, img_info->width, img_info->height,
		bit_depth, color_type, PNG_INTERLACE_NONE,
		PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

	png_write_info(png_ptr, info_ptr);

#if __BYTE_ORDER__ != __ORDER_BIG_ENDIAN__
	if (bit_depth == 16) {
		png_set_swap(png_ptr);
	}
#endif

	if (bit_depth == 16) {
		if (img_info->has_alpha)
			out_fmt = BPG_OUTPUT_FORMAT_RGBA64;
		else
			out_fmt = BPG_OUTPUT_FORMAT_RGB48;
	}
	else {
		if (img_info->has_alpha)
			out_fmt = BPG_OUTPUT_FORMAT_RGBA32;
		else
			out_fmt = BPG_OUTPUT_FORMAT_RGB24;
	}

	bpg_decoder_start(img, out_fmt);

	bpp = (3 + img_info->has_alpha) * (bit_depth / 8);
	row_pointer = (png_bytep)png_malloc(png_ptr, img_info->width * bpp);
	for (y = 0; y < img_info->height; y++) {
		bpg_decoder_get_line(img, row_pointer);
		png_write_row(png_ptr, row_pointer);
	}
	png_free(png_ptr, row_pointer);

	png_write_end(png_ptr, NULL);

	png_destroy_write_struct(&png_ptr, &info_ptr);

	return 0;
}
Exemple #3
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
      }
   }
Exemple #4
0
BOOL OutputPNG::OutputPNGHeader(CCLexFile *File, LPBITMAPINFOHEADER pInfo,
                                BOOL InterlaceState, INT32 TransparentColour,
                                LPLOGPALETTE pPalette, LPRGBQUAD pQuadPalette)
{
    ERROR2IF(File==NULL,FALSE,"OutputPNG::OutputPNGHeader File pointer is null");
    if (pInfo == NULL)
        pInfo = &(DestBitmapInfo->bmiHeader);
    ERROR2IF(pInfo==NULL,FALSE,"OutputPNG::OutputPNGHeader BitmapInfo pointer is null");
    //ERROR2IF(pPalette==NULL && pQuadPalette==NULL,FALSE,"OutputPNG::OutputPNGHeader Bitmap palette pointer is null");

    TRACEUSER( "Jonathan", _T("PNG write: Interlace: %s\n"), InterlaceState ? _T("Yes") : _T("No"));

    // Note file in our class variable as used by all the low level routines
    OutputFile = File;

    // Note the specified transparency and interlace states in our class variables
    Interlace = InterlaceState;
    if (TransparentColour != -1)
        Transparent = TRUE;
    else
        Transparent = FALSE;

    // We are just about to start so set the PNG exception handling up with our CCFile pointer
    PNGUtil::SetCCFilePointer(File);

    // Must set the exception throwing flag to True and force reporting of errors to False.
    // This means that the caller must report an error if the function returns False.
    // Any calls to CCFile::GotError will now throw a file exception and should fall into
    // the catch handler at the end of the function.
    // Replaces the goto's that handled this before.
    BOOL OldThrowingState = File->SetThrowExceptions( TRUE );
    BOOL OldReportingState = File->SetReportErrors( FALSE );

    // PNG related items (NOTE: p at end means pointer and hence implied *)
    png_ptr		= NULL;
    info_ptr	= NULL;

    palette = NULL;

    try
    {
        // Work out the palette size
        INT32 PalSize = pInfo->biClrUsed;		// How many entries in palette
        TRACEUSER( "Jonathan", _T("PNG write: PalSize = %d\n"),PalSize);

        // Set up the class variables
        // First the width/height of the bitmap
        Width = pInfo->biWidth;
        Height = pInfo->biHeight;
        TRACEUSER( "Jonathan", _T("PNG write: Width = %d Height = %d\n"),Width,Height);

        BitsPerPixel = pInfo->biBitCount;

        // Start up the PNG writing code

        // allocate the necessary structures
        // Use the default handlers
        png_ptr = png_create_write_struct_2(
                      PNG_LIBPNG_VER_STRING,	// libpng version
                      0,						// Optional pointer to be sent with errors
                      camelot_png_error,		// Function called in case of error
                      camelot_png_warning,	// Function called for warnings
                      0,						// Optional pointer to be sent with mem ops
                      camelot_png_malloc,		// Function called to alloc memory
                      camelot_png_free		// Function called to free memory
                  );

        if (!png_ptr)
            File->GotError( _R(IDS_OUT_OF_MEMORY) );

        info_ptr = png_create_info_struct(png_ptr);
        if (!info_ptr)
        {
            png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
            File->GotError( _R(IDS_OUT_OF_MEMORY) );
        }

        // set up the input control to the fstream class
        // If not a disk file then panic for the present moment
        // Could use the memfile functions for reading and writing as they give us what
        // we want. Use the io_ptr and
        iostream* pFStream = File->GetIOFile();
        if (pFStream == NULL)
        {
            TRACEUSER( "Jonathan", _T("PNG write: OutputPNG::OutputPNGHeader No access to IOStream!"));
            File->GotError( _R(IDS_UNKNOWN_PNG_ERROR) );
        }

        // Should use our own function
        png_set_write_fn(png_ptr, pFStream, camelot_png_write_data, camelot_png_flush_data);
        // png_init_io(png_ptr, pFStream);

        // You now have the option of modifying how the compression library
        // will run.  The following functions are mainly for testing, but
        // may be useful in certain special cases, like if you need to
        // write png files extremely fast and are willing to give up some
        // compression, or if you want to get the maximum possible compression
        // at the expense of slower writing.  If you have no special needs
        // in this area, let the library do what it wants, as it has been
        // carefully tuned to deliver the best speed/compression ratio.
        // See the compression library for more details.

        // turn on or off filtering (1 or 0)
        //png_set_filtering(png_ptr, 1);

        // compression level (0 - none, 6 - default, 9 - maximum)
        //png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
        //png_set_compression_mem_level(png_ptr, 8);
        //png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY);
        //png_set_compression_window_bits(png_ptr, 15);
        //png_set_compression_method(png_ptr, 8);

        // - this describes which optional chunks to write to the
        // file.  Note that if you are writing a
        // PNG_COLOR_TYPE_PALETTE file, the PLTE chunk is not
        // optional, but must still be marked for writing.  To
        // mark chunks for writing, OR valid with the
        // appropriate PNG_INFO_<chunk name> define.
        png_get_valid(png_ptr, info_ptr, 0);

        // resolution of image
        png_set_invalid(png_ptr, info_ptr, PNG_INFO_pHYs);
        png_set_pHYs(png_ptr, info_ptr,
                     pInfo->biXPelsPerMeter,
                     pInfo->biYPelsPerMeter,
                     1); //meter
        TRACEUSER( "Jonathan", _T("PNG write: x,y px per cm = %d %d\n"),
                   png_get_x_pixels_per_meter(png_ptr, info_ptr) / 1000,
                   png_get_y_pixels_per_meter(png_ptr, info_ptr) / 1000);

        BitsPerPixel				= pInfo->biBitCount;
        TRACEUSER( "Jonathan", _T("PNG write: Bitdepth = %d\n"), BitsPerPixel);
        palette		= NULL;
        num_palette	= 0;
        trans		= NULL;	// - array of transparent entries for paletted images
        num_trans	= 0;	// - number of transparent entries
        TRACEUSER( "Jonathan", _T("PNG write: TransColour = %d\n"), TransparentColour);
        if ( BitsPerPixel <= 8 )
        {
            png_set_IHDR(png_ptr, info_ptr,
                         Width,
                         Height,
                         BitsPerPixel,
                         PNG_COLOR_TYPE_PALETTE,
                         PNG_INTERLACE_NONE,
                         PNG_COMPRESSION_TYPE_BASE,
                         PNG_FILTER_TYPE_BASE);

            // set the palette if there is one
            png_set_invalid(png_ptr, info_ptr, PNG_INFO_PLTE);
            INT32 PaletteEntries = pInfo->biClrUsed;

            palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH * sizeof (png_color));
            if (palette == NULL)
                File->GotError( _R(IDS_OUT_OF_MEMORY) );

            png_set_PLTE(png_ptr, info_ptr, palette, num_palette);
            png_color_struct * pPNGPalette = palette;
            // ... set palette colors ...
            if (pQuadPalette && PaletteEntries > 0)
            {
                // Palette supplied in RGBQUAD form
                for (INT32 i = 0; i < PaletteEntries; i++)
                {
                    pPNGPalette->red 	= pQuadPalette->rgbRed;
                    pPNGPalette->green 	= pQuadPalette->rgbGreen;
                    pPNGPalette->blue 	= pQuadPalette->rgbBlue;
                    // skip to the next palette entry
                    pQuadPalette++;
                    pPNGPalette++;
                }
            }
            else if (pPalette && PaletteEntries > 0)
            {
                // Palette supplied in LOGPALETTE form
                for (INT32 i = 0; i < PaletteEntries; i++)
                {
                    pPNGPalette->red  	= pPalette->palPalEntry[i].peRed;
                    pPNGPalette->green 	= pPalette->palPalEntry[i].peGreen;
                    pPNGPalette->blue 	= pPalette->palPalEntry[i].peBlue;
                    pPNGPalette++;
                }
            }
            else
                File->GotError(_R(IDS_PNG_ERR_WRITE_PALETTE));

            // Now check to see if transparency is present or not
            if (TransparentColour >= 0 && TransparentColour <= PaletteEntries )
            {
                // Create the array of transparent entries for this palette
                // 0 is fully transparent, 255 is fully opaque, regardless of image bit depth
                // We will only create as many as we require, i.e. up to the transparent colour entry
                // rather a full palettes worth
                INT32 NumEntries = TransparentColour + 1;
                trans = (png_byte*)png_malloc(png_ptr, NumEntries * sizeof (png_byte));
                if (trans)
                {
                    // Set the number of transparent entries
                    num_trans			= NumEntries;
                    png_byte * pTransEntry		= trans;
                    png_set_invalid(png_ptr, info_ptr, PNG_INFO_tRNS);
                    for (INT32 i = 0; i < TransparentColour; i++)
                    {
                        *pTransEntry = 255;	// set it fully opaque
                        pTransEntry++;
                    }
                    // We should now be at the transparent entry so set it fully transparent
                    *pTransEntry = 0;
                }
            }
        }
        else if (BitsPerPixel == 24)
        {
            png_set_IHDR(png_ptr, info_ptr,
                         Width,
                         Height,
                         8, /* bit_depth */
                         PNG_COLOR_TYPE_RGB,
                         PNG_INTERLACE_NONE,
                         PNG_COMPRESSION_TYPE_BASE,
                         PNG_FILTER_TYPE_BASE);
        }
        else if (BitsPerPixel == 32)
        {
            png_set_IHDR(png_ptr, info_ptr,
                         Width,
                         Height,
                         8, /* bit_depth */
                         PNG_COLOR_TYPE_RGB_ALPHA,
                         PNG_INTERLACE_NONE,
                         PNG_COMPRESSION_TYPE_BASE,
                         PNG_FILTER_TYPE_BASE);
        }
        else
            ERROR2(FALSE,"OutputPNG::OutputPNGHeader Unknown bit depth");

        TRACEUSER( "Jonathan", _T("PNG write: bit_depth = %d color_type = %d\n"),
                   png_get_bit_depth(png_ptr, info_ptr),
                   png_get_color_type(png_ptr, info_ptr));

        // Could use:-
        // if we are dealing with a grayscale image then
        //info_ptr->sig_bit.gray = true_bit_depth;

        png_set_hIST(png_ptr, info_ptr, NULL);
        png_set_text(png_ptr, info_ptr, NULL, 0);


        // write the file information
        png_write_info(png_ptr, info_ptr);

        TRACEUSER( "Jonathan", _T("PNG write: pixel_depth %d channels %d\n"),
                   png_get_bit_depth(png_ptr, info_ptr),
                   png_get_channels(png_ptr, info_ptr));
        TRACEUSER( "Jonathan", _T("PNG write: rowbytes %d color_type %d\n"),
                   png_get_rowbytes(png_ptr, info_ptr),
                   png_get_color_type(png_ptr, info_ptr));
        // Set up the transformations you want.
        // Note: that these are all optional.  Only call them if you want them

        // invert monocrome pixels
        //png_set_invert(png_ptr);

        // shift the pixels up to a legal bit depth and fill in as appropriate
        // to correctly scale the image
        //png_set_shift(png_ptr, &(info_ptr->sig_bit));

        // pack pixels into bytes
        //png_set_packing(png_ptr);

        png_set_bgr(png_ptr);

        // swap bytes of 16 bit files to most significant bit first
        png_set_swap(png_ptr);

        // Must set the exception throwing and reporting flags back to their entry states
        File->SetThrowExceptions( OldThrowingState );
        File->SetReportErrors( OldReportingState );

        // er, we seem to have finished OK so say so
        return TRUE;
    }

    catch (...)
    {
        // catch our form of a file exception
        TRACE( _T("OutputPNG::OutputPNGHeader CC catch handler\n"));

        // Call up function to clean up the png structures
        CleanUpPngStructures();

        // Must set the exception throwing and reporting flags back to their entry states
        File->SetThrowExceptions( OldThrowingState );
        File->SetReportErrors( OldReportingState );

        // We have finished so reset the PNG exception handling
        PNGUtil::SetCCFilePointer(NULL);

        return FALSE;
    }

    ERROR2( FALSE, "Escaped exception clause somehow" );
}
Exemple #5
0
RADRT_API bool RADRT_CALL Encode(const Image &in, const Mipmap &mip, bool interlaced, void *&outData, AddrSize &outSize)
{
	RAD_ASSERT(in.format == Format_A8 || in.format == Format_RGB888 || in.format == Format_RGBA8888);

	if (in.format != Format_A8 &&
		in.format != Format_RGB888 &&
		in.format != Format_RGBA8888) return false;

	png_structp png;
	png_infop   info;

	png = png_create_write_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_write_struct(&png, 0);
		return false;
	}

	stream::DynamicMemOutputBuffer ob(ZImageCodec);
	stream::OutputStream os(ob);

	png_set_write_fn(png, &os, PNGWrite, PNGFlush);
	png_set_IHDR(png, info, mip.width, mip.height, 8,
		(in.format == Format_A8) ? PNG_COLOR_TYPE_GRAY :
		(in.format == Format_RGB888) ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGBA,
		interlaced ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE,
		PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

	png_color_8 sig;
	memset(&sig, 0, sizeof(sig));
	
	if (in.format == Format_A8)
	{
		sig.gray = 8;
	}
	else
	{
		sig.red = 8;
		sig.green = 8;
		sig.blue = 8;
		sig.alpha = (in.format == Format_RGBA8888) ? 8 : 0;
	}

	png_set_sBIT(png, info, &sig);

	try
	{
		png_write_info(png, info);
	}
	catch (PNGException&)
	{
		png_destroy_write_struct(&png, &info);
		return false;
	}

	png_set_shift(png, &sig);

	int passes = 1;

	if (interlaced)
	{
		passes = png_set_interlace_handling(png);
	}

	for (int pass = 0; pass < passes; ++pass)
	{
		png_bytep src = (png_bytep)mip.data;

		for (int y = 0; y < mip.height; ++y)
		{
			png_write_rows(png, (png_bytepp)&src, 1);
			src += mip.stride;
		}
	}

	png_write_end(png, info);
	png_destroy_write_struct(&png, &info);

	outData = ob.OutputBuffer().Ptr();
	outSize = ob.OutputBuffer().Size();
	ob.OutputBuffer().Set(0, 0); // don't let the output buffer release the memory.

	return true;

}
Exemple #6
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
      }
   }
bool DeferredPNGWriter::begin( GFXFormat format, S32 width, S32 height, Stream &stream, U32 compressionLevel )
{   
   // ONLY RGB bitmap writing supported at this time!
   AssertFatal(   format == GFXFormatR8G8B8 || 
                  format == GFXFormatR8G8B8A8 || 
                  format == GFXFormatR8G8B8X8 || 
                  format == GFXFormatA8 ||
                  format == GFXFormatR5G6B5, "_writePNG: ONLY RGB bitmap writing supported at this time.");

   if (  format != GFXFormatR8G8B8 && 
         format != GFXFormatR8G8B8A8 && 
         format != GFXFormatR8G8B8X8 && 
         format != GFXFormatA8 &&
         format != GFXFormatR5G6B5 )
      return false;

   mData->png_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING,
      NULL,
      pngFatalErrorFn,
      pngWarningFn,
      NULL,
      pngRealMallocFn,
      pngRealFreeFn);
   if (mData->png_ptr == NULL)
      return (false);

   mData->info_ptr = png_create_info_struct(mData->png_ptr);
   if (mData->info_ptr == NULL)
   {
      png_destroy_write_struct(&mData->png_ptr, (png_infopp)NULL);
      return false;
   }

   png_set_write_fn(mData->png_ptr, &stream, pngWriteDataFn, pngFlushDataFn);

   // Set the compression level and image filters
   png_set_compression_window_bits(mData->png_ptr, 15);
   png_set_compression_level(mData->png_ptr, compressionLevel);
   png_set_filter(mData->png_ptr, 0, PNG_ALL_FILTERS);

   // Set the image information here.  Width and height are up to 2^31,
   // bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
   // the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
   // PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
   // or PNG_COLOR_TYPE_RGB_ALPHA.  interlace is either PNG_INTERLACE_NONE or
   // PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
   // currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
   
   if (format == GFXFormatR8G8B8)
   {
      png_set_IHDR(mData->png_ptr, mData->info_ptr,
         width, height,               // the width & height
         8, PNG_COLOR_TYPE_RGB,       // bit_depth, color_type,
         NULL,                        // no interlace
         NULL,                        // compression type
         NULL);                       // filter type
   }
   else if (format == GFXFormatR8G8B8A8 || format == GFXFormatR8G8B8X8)
   {
      png_set_IHDR(mData->png_ptr, mData->info_ptr,
         width, height,               // the width & height
         8, PNG_COLOR_TYPE_RGB_ALPHA, // bit_depth, color_type,
         NULL,                        // no interlace
         NULL,                        // compression type
         NULL);                       // filter type
   }
   else if (format == GFXFormatA8)
   {
      png_set_IHDR(mData->png_ptr, mData->info_ptr,
         width, height,               // the width & height
         8, PNG_COLOR_TYPE_GRAY,      // bit_depth, color_type,
         NULL,                        // no interlace
         NULL,                        // compression type
         NULL);                       // filter type
   }
   else if (format == GFXFormatR5G6B5) 
   {
      png_set_IHDR(mData->png_ptr, mData->info_ptr,
         width, height,               // the width & height
         16, PNG_COLOR_TYPE_GRAY,     // bit_depth, color_type,
         PNG_INTERLACE_NONE,          // no interlace
         PNG_COMPRESSION_TYPE_DEFAULT,   // compression type
         PNG_FILTER_TYPE_DEFAULT);       // filter type
      
      png_color_8_struct sigBit = { 0 };
      sigBit.gray = 16;
      png_set_sBIT(mData->png_ptr, mData->info_ptr, &sigBit );

      png_set_swap( mData->png_ptr );
   }

   png_write_info(mData->png_ptr, mData->info_ptr);
   
   mActive = true;

   return true;
}
//--------------------------------------------------------------------------
static bool _writePNG(GBitmap *bitmap, Stream &stream, U32 compressionLevel, U32 strategy, U32 filter)
{
   GFXFormat   format = bitmap->getFormat();

   // ONLY RGB bitmap writing supported at this time!
   AssertFatal(   format == GFXFormatR8G8B8 || 
                  format == GFXFormatR8G8B8A8 || 
                  format == GFXFormatR8G8B8X8 || 
                  format == GFXFormatA8 ||
                  format == GFXFormatR5G6B5, "_writePNG: ONLY RGB bitmap writing supported at this time.");

   if (  format != GFXFormatR8G8B8 && 
         format != GFXFormatR8G8B8A8 && 
         format != GFXFormatR8G8B8X8 && 
         format != GFXFormatA8 &&
         format != GFXFormatR5G6B5 )
      return false;

   png_structp png_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING,
      NULL,
      pngFatalErrorFn,
      pngWarningFn,
      NULL,
      pngMallocFn,
      pngFreeFn);
   if (png_ptr == NULL)
      return (false);

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

   png_set_write_fn(png_ptr, &stream, pngWriteDataFn, pngFlushDataFn);

   // Set the compression level and image filters
   png_set_compression_window_bits(png_ptr, 15);
   png_set_compression_level(png_ptr, compressionLevel);
   png_set_filter(png_ptr, 0, filter);

   // Set the image information here.  Width and height are up to 2^31,
   // bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
   // the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
   // PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
   // or PNG_COLOR_TYPE_RGB_ALPHA.  interlace is either PNG_INTERLACE_NONE or
   // PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
   // currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED

   U32   width = bitmap->getWidth();
   U32   height = bitmap->getHeight();

   if (format == GFXFormatR8G8B8)
   {
      png_set_IHDR(png_ptr, info_ptr,
         width, height,               // the width & height
         8, PNG_COLOR_TYPE_RGB,       // bit_depth, color_type,
         NULL,                        // no interlace
         NULL,                        // compression type
         NULL);                       // filter type
   }
   else if (format == GFXFormatR8G8B8A8 || format == GFXFormatR8G8B8X8)
   {
      png_set_IHDR(png_ptr, info_ptr,
         width, height,               // the width & height
         8, PNG_COLOR_TYPE_RGB_ALPHA, // bit_depth, color_type,
         NULL,                        // no interlace
         NULL,                        // compression type
         NULL);                       // filter type
   }
   else if (format == GFXFormatA8)
   {
      png_set_IHDR(png_ptr, info_ptr,
         width, height,               // the width & height
         8, PNG_COLOR_TYPE_GRAY,      // bit_depth, color_type,
         NULL,                        // no interlace
         NULL,                        // compression type
         NULL);                       // filter type
   }
   else if (format == GFXFormatR5G6B5) 
   {
      png_set_IHDR(png_ptr, info_ptr,
         width, height,               // the width & height
         16, PNG_COLOR_TYPE_GRAY,     // bit_depth, color_type,
         PNG_INTERLACE_NONE,          // no interlace
         PNG_COMPRESSION_TYPE_DEFAULT,   // compression type
         PNG_FILTER_TYPE_DEFAULT);       // filter type
      
      png_color_8_struct sigBit = { 0 };
      sigBit.gray = 16;
      png_set_sBIT(png_ptr, info_ptr, &sigBit );

      png_set_swap( png_ptr );
   }

   png_write_info(png_ptr, info_ptr);
   FrameAllocatorMarker marker;
   png_bytep* row_pointers = (png_bytep*)marker.alloc( height * sizeof( png_bytep ) );
   for (U32 i=0; i<height; i++)
      row_pointers[i] = const_cast<png_bytep>(bitmap->getAddress(0, i));

   png_write_image(png_ptr, row_pointers);

   // Write S3TC data if present...
   // Write FXT1 data if present...

   png_write_end(png_ptr, info_ptr);
   png_destroy_write_struct(&png_ptr, (png_infopp)NULL);

   return true;
}
Exemple #9
0
//==============================================================
void PngWrite(char *file, int w, int h, u_char *ptr)
//--------------------------------------------------------------
// データ出力
// 32bit → 32bit
//--------------------------------------------------------------
// in:	file = ファイル名
//		w, h = データサイズ
//		ptr  = データポインタ
//--------------------------------------------------------------
// out:	なし
//==============================================================
{
	sFILE *fp;
	png_structp png_ptr;
	png_infop info_ptr;
	png_color_8 sig_bit;
	png_text text_ptr[1];
	png_bytep *row_pointers;
	int k;

#ifdef USE_USER_MEMORY
	png_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL, NULL, libpng_Malloc, libpng_Free);
#else
	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
#endif
	if(!png_ptr)
	{
		return;
	}

	info_ptr = png_create_info_struct(png_ptr);
	if(!info_ptr)
	{
		png_destroy_write_struct(&png_ptr, png_infopp_NULL);
		return;
	}

	// ファイルの新規作成
	//--------------------
	fp = FsCreate(file);
	ASSERT(fp);

	png_set_write_fn(png_ptr, (png_voidp)fp, writeFunc, flushFunc);
	png_set_IHDR(png_ptr, info_ptr, w, h, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_BASE);

	sig_bit.red = 8;
	sig_bit.green = 8;
	sig_bit.blue = 8;
	sig_bit.alpha = 0;
	png_set_sBIT(png_ptr, info_ptr, &sig_bit);

	text_ptr[0].key = "Description";
	text_ptr[0].text = "ktcDIB::Save() Data";
	text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
	png_set_text(png_ptr, info_ptr, text_ptr, 1);

	png_write_info(png_ptr, info_ptr);
	png_set_bgr(png_ptr);

	row_pointers = (png_bytep *)fsMalloc(sizeof(png_bytep *) * h, "png_bytep");
	ASSERT(row_pointers);
	for(k = 0; k < h; ++k)
	{
		png_byte *p;

		p = (png_byte *)fsMalloc(sizeof(png_byte) * w * 3, "png_byte");
		ASSERT(p);
		row_pointers[k] = (png_bytep)p;
		memcpy(p, ptr, w * 3);
		ptr += w * 3;
	}

	png_write_image(png_ptr, row_pointers);
	png_write_end(png_ptr, info_ptr);

	for(k = 0; k < h; ++k)
	{
		Free(row_pointers[k]);
	}
	Free(row_pointers);

	png_destroy_write_struct(&png_ptr, &info_ptr);
	FsClose(fp);
}
Exemple #10
0
bool R9_ImgWritePNG( F9FILE file, r9Img* img )
{
	
	const int32 compressionlevel = 6;
	const int32 strategy = 0;
	const int32 filter = PNG_ALL_FILTERS;
	
	if(img->m_pf!=R9_PF_RGB && img->m_pf!=R9_PF_ARGB && img->m_pf!=R9_PF_BGR && img->m_pf!=R9_PF_ABGR )
	{
		elog::rnd() << "png format not supported" << std::endl; return false;
	}

	png_structp png_ptr = png_create_write_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_write_struct(&png_ptr, (png_infopp)NULL);
		return false;
	}

	r9_imgpng_file = file;
	png_set_write_fn(png_ptr, NULL, R9_ImgPNG_WriteData, NULL); // last one was imgpng_flush (fflush) that did nothing

	// set the compression level, image filters, and compression strategy...
	png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY;
	png_ptr->zlib_strategy = strategy;
	png_set_compression_window_bits(png_ptr, 15);
	png_set_compression_level(png_ptr, compressionlevel);
	png_set_filter(png_ptr, 0, filter);

	// flip rgb temporary, if necessarily - png likes BGR!
	if(img->m_pf==R9_PF_ARGB || img->m_pf==R9_PF_RGB) R9_ImgFlipRGB(img);

	// Set the image information here.  Width and height are up to 2^31,
	// bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
	// the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
	// PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
	// or PNG_COLOR_TYPE_RGB_ALPHA.  interlace is either PNG_INTERLACE_NONE or
	// PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
	// currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
	
	if(img->m_pf==R9_PF_RGB || img->m_pf==R9_PF_BGR)
	{
		png_set_IHDR(png_ptr, info_ptr, 
				   img->m_width, img->m_height,	// the width & height
				   8, PNG_COLOR_TYPE_RGB,       // bit_depth, color_type,
				   NULL,                        // no interlace
				   NULL,                        // compression type
				   NULL);                       // filter type
	}
	else 
	if(img->m_pf==R9_PF_ARGB || img->m_pf==R9_PF_ABGR)
	{
		png_set_IHDR(png_ptr, info_ptr, 
				   img->m_width, img->m_height, // the width & height
				   8, PNG_COLOR_TYPE_RGB_ALPHA, // bit_depth, color_type,
				   NULL,                        // no interlace
				   NULL,                        // compression type
				   NULL);                       // filter type
	}

	png_write_info(png_ptr, info_ptr);
	png_bytep* rowpointers = new png_bytep[img->m_height];
	for(int i=0; i<img->m_height; i++)
		rowpointers[i] = (png_bytep)(img->m_data+(i*img->lineSize()));

	png_write_image(png_ptr, rowpointers);

	// release
	png_write_end(png_ptr, info_ptr);
	png_destroy_write_struct(&png_ptr, &info_ptr);
	delete [] rowpointers;
	r9_imgpng_file = NULL;

	// flip rgb back, if necessarily
	if(img->m_pf==R9_PF_ARGB || img->m_pf==R9_PF_RGB) R9_ImgFlipRGB(img);

	return true;
}
Exemple #11
0
//---------------------------------------------------------------------------
void __fastcall TDeePNG::SaveToStream(Classes::TStream * Stream)
{
	// SaveToStream method
	// warning: this method would change the pixelformat to pf24bit
	// if the pixelformat is pfDevice, pf15bit, pf16bit, or pfCustom.


	png_structp png_ptr = NULL;
	png_infop info_ptr = NULL;
	png_bytep row_buffer = NULL;

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


		// create png_info
		info_ptr = png_create_info_struct(png_ptr);

		// set write function
		png_set_write_fn(png_ptr, (png_voidp)Stream,
			DeePNG_write_data, DeePNG_flush);


		// set IHDR
		if(PixelFormat == pfDevice || PixelFormat == pf15bit ||
			PixelFormat == pf16bit || PixelFormat == pfCustom)
			PixelFormat = pf24bit;

		bool grayscale = IsGrayscaleBitmap(this);
		int colordepth = GetBitmapColorDepth(this);

		int w = Width;
		int h = Height;

		int color_type;
		if(grayscale)
			color_type = PNG_COLOR_TYPE_GRAY;
		else if(colordepth <= 8)
			color_type = PNG_COLOR_TYPE_PALETTE;
		else if(colordepth == 32)
			color_type = PNG_COLOR_TYPE_RGB_ALPHA;
		else
			color_type = PNG_COLOR_TYPE_RGB;

		png_set_IHDR(png_ptr, info_ptr, w, h,
			colordepth < 8 ? colordepth : 8,
			color_type, PNG_INTERLACE_NONE,
			PNG_COMPRESSION_TYPE_DEFAULT,
			PNG_FILTER_TYPE_DEFAULT);

		// set oFFs
		if(ofs_set)
			png_set_oFFs(png_ptr, info_ptr, ofs_x, ofs_y, ofs_unit);

		// set palette
		if(color_type == PNG_COLOR_TYPE_PALETTE)
		{
			png_color *palette = (png_colorp)png_malloc(png_ptr, 256 * sizeof(png_color));
			PALETTEENTRY palentry[256];
			int num_palette = GetPaletteEntries(Palette, 0, (1<<colordepth), palentry);
			for(int i = 0; i < num_palette; i++)
			{
				palette[i].red = palentry[i].peRed;
				palette[i].green = palentry[i].peGreen;
				palette[i].blue = palentry[i].peBlue;
			}
			png_set_PLTE(png_ptr, info_ptr, palette, num_palette);
		}

		// write info
		png_write_info(png_ptr, info_ptr);

		// write vpAg private chunk
		if(vpag_set)
		{
			png_byte png_vpAg[5] = {118, 112,  65, 103, '\0'};
			unsigned char vpag_chunk_data[9];
		#define PNG_write_be32(p, a) (\
			((unsigned char *)(p))[0] = (unsigned char)(((a) >>24) & 0xff), \
			((unsigned char *)(p))[1] = (unsigned char)(((a) >>16) & 0xff), \
			((unsigned char *)(p))[2] = (unsigned char)(((a) >> 8) & 0xff), \
			((unsigned char *)(p))[3] = (unsigned char)(((a)     ) & 0xff)  )
			PNG_write_be32(vpag_chunk_data,     vpag_w);
			PNG_write_be32(vpag_chunk_data + 4, vpag_h);
			vpag_chunk_data[8] = (unsigned char)vpag_unit;
			png_write_chunk(png_ptr, png_vpAg, vpag_chunk_data, 9);
		}

/*
		// change RGB order
		if(color_type = PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA)
		   png_set_bgr(png_ptr);
		// ???? why this does not work ?
*/
		// write image
		if(color_type == PNG_COLOR_TYPE_RGB)
		{
			row_buffer = (png_bytep)png_malloc(png_ptr, 3 * w + 6);
			try
			{
				png_bytep row_pointer = row_buffer;

				for(int i = 0; i < h; i++)
				{
					png_bytep in = (png_bytep)ScanLine[i];
					png_bytep out = row_buffer;
					for(int x = 0; x < w; x++)
					{
						out[2] = in[0];
						out[1] = in[1];
						out[0] = in[2];
						out += 3;
						in += 3;
					}
					png_write_row(png_ptr, row_pointer);
				}
			}
			catch(...)
			{
				png_free(png_ptr, row_buffer);
				throw;
			}
			png_free(png_ptr, row_buffer);
		}
		else if(color_type == PNG_COLOR_TYPE_RGB_ALPHA)
		{
			row_buffer = (png_bytep)png_malloc(png_ptr, 4 * w + 6);
			try
			{
				png_bytep row_pointer = row_buffer;

				for(int i = 0; i < h; i++)
				{
					png_bytep in = (png_bytep)ScanLine[i];
					png_bytep out = row_buffer;
					for(int x = 0; x < w; x++)
					{
						out[2] = in[0];
						out[1] = in[1];
						out[0] = in[2];
						out[3] = in[3];
						out += 4;
						in += 4;
					}
					png_write_row(png_ptr, row_pointer);
				}
			}
			catch(...)
			{
				png_free(png_ptr, row_buffer);
				throw;
			}
			png_free(png_ptr, row_buffer);
		}
		else
		{
			for(int i = 0; i < h; i++)
			{
				png_bytep row_pointer = (png_bytep)ScanLine[i];
				png_write_row(png_ptr, row_pointer);
			}
		}


		// finish writing
		png_write_end(png_ptr, info_ptr);

	}
	catch(...)
	{
		png_destroy_write_struct(&png_ptr, &info_ptr);
		throw;
	}

	png_destroy_write_struct(&png_ptr, &info_ptr);
}