/* save rgb888 to png format in fp */
int save_png(const char* path, const char* data, int width, int height)
{
    FILE *fp;
    png_byte **volatile rows;
    png_struct *png;
    png_info *info;

    fp = fopen(path, "w");
    if (!fp) {
        E("Cannot open file %s for write\n", path);
        return -ENONET;
    }

    rows = malloc(height * sizeof rows[0]);
    if (!rows) goto oops;

    int i;
    for (i = 0; i < height; i++)
        rows[i] = (png_byte *) data + i * width * 3 /*fb.stride*/;

    png = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL,
                               png_simple_error_callback,
                               png_simple_warning_callback);
    if (!png)
        E("png_create_write_struct failed\n");

    info = png_create_info_struct (png);
    if (!info)
        E("png_create_info_struct failed\n");

    png_set_write_fn (png, fp, stdio_write_func, png_simple_output_flush_fn);
    png_set_IHDR (png, info,
            width,
            height,
#define DEPTH 8
            DEPTH,
        PNG_COLOR_TYPE_RGB,
        PNG_INTERLACE_NONE,
        PNG_COMPRESSION_TYPE_DEFAULT,
        PNG_FILTER_TYPE_DEFAULT);

    png_color_16 white;

    white.gray = (1 << DEPTH) - 1;
    white.red = white.blue = white.green = white.gray;

    png_set_bKGD (png, info, &white);
    png_write_info (png, info);

    png_write_image (png, rows);
    png_write_end (png, info);

    png_destroy_write_struct (&png, &info);

    free (rows);
    return 0;

oops:
    return -1;
}
void writeSetup2(png_structp png_ptr_write, png_infop info_ptr_write,
                 png_structp png_ptr_read, png_infop info_ptr_read)
{
    /* IHDR */
    png_uint_32 width;
    png_uint_32 height;
    int bit_depth;
    int colour_type;
    int interlace_method;
    int compression_method;
    int filter_method;
    
    /* PLTE */
    png_colorp palette = NULL;
    int palette_size = 0;
    
    /* gAMA */
    double gamma;
    
    /* tRNS */
    png_bytep trans;
    int num_trans;
    png_color_16p trans_values;
    
    /* bKGD */
    png_color_16p background;
    
    png_get_IHDR(png_ptr_read, info_ptr_read, &width, &height,
                 &bit_depth, &colour_type, &interlace_method,
                 &compression_method, &filter_method);
    png_set_IHDR(png_ptr_write, info_ptr_write,  width, height,
                 bit_depth, colour_type, interlace_method,
                 compression_method, filter_method);
    
    if(png_get_valid(png_ptr_read, info_ptr_read, PNG_INFO_PLTE))
    {
        png_get_PLTE(png_ptr_read, info_ptr_read, &palette, &palette_size);
        png_set_PLTE(png_ptr_write, info_ptr_write, palette, palette_size);
    }
    
    if(png_get_valid(png_ptr_read, info_ptr_read, PNG_INFO_gAMA))
    {
        png_get_gAMA(png_ptr_read, info_ptr_read, &gamma);
        png_set_gAMA(png_ptr_write, info_ptr_write, gamma);
    }
    
    if(png_get_valid(png_ptr_read, info_ptr_read, PNG_INFO_tRNS))
    {
        png_get_tRNS(png_ptr_read, info_ptr_read, &trans, &num_trans, &trans_values);
        png_set_tRNS(png_ptr_write, info_ptr_write, trans, num_trans, trans_values);
    }
    
    if(png_get_valid(png_ptr_read, info_ptr_read, PNG_INFO_bKGD))
    {
        png_get_bKGD(png_ptr_read, info_ptr_read, &background);
        png_set_bKGD(png_ptr_write, info_ptr_write, background);
    }
}
Esempio n. 3
0
    void write_header( const View& view )
    {
        using png_rw_info_t = detail::png_write_support
            <
                typename channel_type<typename get_pixel_type<View>::type>::type,
                typename color_space_type<View>::type
            >;

        // 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
        png_set_IHDR( get_struct()
                    , get_info()
                    , static_cast< png_image_width::type  >( view.width()  )
                    , static_cast< png_image_height::type >( view.height() )
                    , static_cast< png_bitdepth::type     >( png_rw_info_t::_bit_depth )
                    , static_cast< png_color_type::type   >( png_rw_info_t::_color_type )
                    , _info._interlace_method
                    , _info._compression_type
                    , _info._filter_method
                    );

#ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
        if( _info._valid_cie_colors )
        {
            png_set_cHRM( get_struct()
                        , get_info()
                        , _info._white_x
                        , _info._white_y
                        , _info._red_x
                        , _info._red_y
                        , _info._green_x
                        , _info._green_y
                        , _info._blue_x
                        , _info._blue_y
                        );
        }

        if( _info._valid_file_gamma )
        {
            png_set_gAMA( get_struct()
                        , get_info()
                        , _info._file_gamma
                        );
        }
#else
        if( _info._valid_cie_colors )
        {
            png_set_cHRM_fixed( get_struct()
                              , get_info()
                              , _info._white_x
                              , _info._white_y
                              , _info._red_x
                              , _info._red_y
                              , _info._green_x
                              , _info._green_y
                              , _info._blue_x
                              , _info._blue_y
                              );
        }

        if( _info._valid_file_gamma )
        {
            png_set_gAMA_fixed( get_struct()
                              , get_info()
                              , _info._file_gamma
                              );
        }
#endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED

        if( _info._valid_icc_profile )
        {
#if PNG_LIBPNG_VER_MINOR >= 5
            png_set_iCCP( get_struct()
                        , get_info()
                        , const_cast< png_charp >( _info._icc_name.c_str() )
                        , _info._iccp_compression_type
                        , reinterpret_cast< png_const_bytep >( & (_info._profile.front ()) )
                        , _info._profile_length
                        );
#else
            png_set_iCCP( get_struct()
                        , get_info()
                        , const_cast< png_charp >( _info._icc_name.c_str() )
                        , _info._iccp_compression_type
                        , const_cast< png_charp >( & (_info._profile.front()) )
                        , _info._profile_length
                        );
#endif
        }

        if( _info._valid_intent )
        {
            png_set_sRGB( get_struct()
                        , get_info()
                        , _info._intent
                        );
        }

        if( _info._valid_palette )
        {
            png_set_PLTE( get_struct()
                        , get_info()
                        , const_cast< png_colorp >( &_info._palette.front() )
                        , _info._num_palette
                        );
        }

        if( _info._valid_background )
        {
            png_set_bKGD( get_struct()
                        , get_info()
                        , const_cast< png_color_16p >( &_info._background )
                        );
        }

        if( _info._valid_histogram )
        {
            png_set_hIST( get_struct()
                        , get_info()
                        , const_cast< png_uint_16p >( &_info._histogram.front() )
                        );
        }

        if( _info._valid_offset )
        {
            png_set_oFFs( get_struct()
                        , get_info()
                        , _info._offset_x
                        , _info._offset_y
                        , _info._off_unit_type
                        );
        }

        if( _info._valid_pixel_calibration )
        {
            std::vector< const char* > params( _info._num_params );
            for( std::size_t i = 0; i < params.size(); ++i )
            {
                params[i] = _info._params[ i ].c_str();
            }

            png_set_pCAL( get_struct()
                        , get_info()
                        , const_cast< png_charp >( _info._purpose.c_str() )
                        , _info._X0
                        , _info._X1
                        , _info._cal_type
                        , _info._num_params
                        , const_cast< png_charp  >( _info._units.c_str() )
                        , const_cast< png_charpp >( &params.front()     )
                        );
        }

        if( _info._valid_resolution )
        {
            png_set_pHYs( get_struct()
                        , get_info()
                        , _info._res_x
                        , _info._res_y
                        , _info._phy_unit_type
                        );
        }

        if( _info._valid_significant_bits )
        {
            png_set_sBIT( get_struct()
                        , get_info()
                        , const_cast< png_color_8p >( &_info._sig_bits )
                        );
        }

#ifndef BOOST_GIL_IO_PNG_1_4_OR_LOWER

#ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
        if( _info._valid_scale_factors )
        {
            png_set_sCAL( get_struct()
                        , get_info()
                        , this->_info._scale_unit
                        , this->_info._scale_width
                        , this->_info._scale_height
                        );
        }
#else
#ifdef BOOST_GIL_IO_PNG_FIXED_POINT_SUPPORTED
        if( _info._valid_scale_factors )
        {
            png_set_sCAL_fixed( get_struct()
                              , get_info()
                              , this->_info._scale_unit
                              , this->_info._scale_width
                              , this->_info._scale_height
                              );
        }
#else
        if( _info._valid_scale_factors )
        {
            png_set_sCAL_s( get_struct()
                          , get_info()
                          , this->_info._scale_unit
                          , const_cast< png_charp >( this->_info._scale_width.c_str()  )
                          , const_cast< png_charp >( this->_info._scale_height.c_str() )
                          );
        }

#endif // BOOST_GIL_IO_PNG_FIXED_POINT_SUPPORTED
#endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
#endif // BOOST_GIL_IO_PNG_1_4_OR_LOWER

        if( _info._valid_text )
        {
            std::vector< png_text > texts( _info._num_text );
            for( std::size_t i = 0; i < texts.size(); ++i )
            {
                png_text pt;
                pt.compression = _info._text[i]._compression;
                pt.key         = const_cast< png_charp >( this->_info._text[i]._key.c_str()  );
                pt.text        = const_cast< png_charp >( this->_info._text[i]._text.c_str() );
                pt.text_length = _info._text[i]._text.length();

                texts[i] = pt;
            }

            png_set_text( get_struct()
                        , get_info()
                        , &texts.front()
                        , _info._num_text
                        );
        }

        if( _info._valid_modification_time )
        {
            png_set_tIME( get_struct()
                        , get_info()
                        , const_cast< png_timep >( &_info._mod_time )
                        );
        }

        if( _info._valid_transparency_factors )
        {
            int sample_max = ( 1u << _info._bit_depth );

            /* libpng doesn't reject a tRNS chunk with out-of-range samples */
            if( !(  (  _info._color_type == PNG_COLOR_TYPE_GRAY
                    && (int) _info._trans_values[0].gray > sample_max
                    )
                 || (  _info._color_type == PNG_COLOR_TYPE_RGB
                    &&(  (int) _info._trans_values[0].red   > sample_max
                      || (int) _info._trans_values[0].green > sample_max
                      || (int) _info._trans_values[0].blue  > sample_max
                      )
                    )
                 )
              )
            {
                //@todo Fix that once reading transparency values works
/*
                png_set_tRNS( get_struct()
                            , get_info()
                            , trans
                            , num_trans
                            , trans_values
                            );
*/
            }
        }

        // Compression Levels - valid values are [0,9]
        png_set_compression_level( get_struct()
                                 , _info._compression_level
                                 );

        png_set_compression_mem_level( get_struct()
                                     , _info._compression_mem_level
                                     );

        png_set_compression_strategy( get_struct()
                                    , _info._compression_strategy
                                    );

        png_set_compression_window_bits( get_struct()
                                       , _info._compression_window_bits
                                       );

        png_set_compression_method( get_struct()
                                  , _info._compression_method
                                  );

        png_set_compression_buffer_size( get_struct()
                                       , _info._compression_buffer_size
                                       );

#ifdef BOOST_GIL_IO_PNG_DITHERING_SUPPORTED
        // Dithering
        if( _info._set_dithering )
        {
            png_set_dither( get_struct()
                          , &_info._dithering_palette.front()
                          , _info._dithering_num_palette
                          , _info._dithering_maximum_colors
                          , &_info._dithering_histogram.front()
                          , _info._full_dither
                          );
        }
#endif // BOOST_GIL_IO_PNG_DITHERING_SUPPORTED

        // Filter
        if( _info._set_filter )
        {
            png_set_filter( get_struct()
                          , 0
                          , _info._filter
                          );
        }

        // Invert Mono
        if( _info._invert_mono )
        {
            png_set_invert_mono( get_struct() );
        }

        // True Bits
        if( _info._set_true_bits )
        {
            png_set_sBIT( get_struct()
                        , get_info()
                        , &_info._true_bits.front()
                        );
        }

        // sRGB Intent
        if( _info._set_srgb_intent )
        {
            png_set_sRGB( get_struct()
                        , get_info()
                        , _info._srgb_intent
                        );
        }

        // Strip Alpha
        if( _info._strip_alpha )
        {
            png_set_strip_alpha( get_struct() );
        }

        // Swap Alpha
        if( _info._swap_alpha )
        {
            png_set_swap_alpha( get_struct() );
        }


        png_write_info( get_struct()
                      , get_info()
                      );
    }
Esempio n. 4
0
static BOOL DLL_CALLCONV
Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
	png_structp png_ptr;
	png_infop info_ptr;
	png_colorp palette = NULL;
	png_uint_32 width, height;
	BOOL has_alpha_channel = FALSE;

	RGBQUAD *pal;					// pointer to dib palette
	int bit_depth, pixel_depth;		// pixel_depth = bit_depth * channels
	int palette_entries;
	int	interlace_type;

	fi_ioStructure fio;
    fio.s_handle = handle;
	fio.s_io = io;

	if ((dib) && (handle)) {
		try {
			// create the chunk manage structure

			png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, error_handler, warning_handler);

			if (!png_ptr)  {
				return FALSE;
			}

			// allocate/initialize the image information data.

			info_ptr = png_create_info_struct(png_ptr);

			if (!info_ptr)  {
				png_destroy_write_struct(&png_ptr,  (png_infopp)NULL);
				return FALSE;
			}

			// Set error handling.  REQUIRED if you aren't supplying your own
			// error handling functions in the png_create_write_struct() call.

			if (setjmp(png_jmpbuf(png_ptr)))  {
				// if we get here, we had a problem reading the file

				png_destroy_write_struct(&png_ptr, &info_ptr);

				return FALSE;
			}

			// init the IO
            
			png_set_write_fn(png_ptr, &fio, _WriteProc, _FlushProc);

			// set physical resolution

			png_uint_32 res_x = (png_uint_32)FreeImage_GetDotsPerMeterX(dib);
			png_uint_32 res_y = (png_uint_32)FreeImage_GetDotsPerMeterY(dib);

			if ((res_x > 0) && (res_y > 0))  {
				png_set_pHYs(png_ptr, info_ptr, res_x, res_y, PNG_RESOLUTION_METER);
			}
	
			// 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

			width = FreeImage_GetWidth(dib);
			height = FreeImage_GetHeight(dib);
			pixel_depth = FreeImage_GetBPP(dib);

			BOOL bInterlaced = FALSE;
			if( (flags & PNG_INTERLACED) == PNG_INTERLACED) {
				interlace_type = PNG_INTERLACE_ADAM7;
				bInterlaced = TRUE;
			} else {
				interlace_type = PNG_INTERLACE_NONE;
			}

			// set the ZLIB compression level or default to PNG default compression level (ZLIB level = 6)
			int zlib_level = flags & 0x0F;
			if((zlib_level >= 1) && (zlib_level <= 9)) {
				png_set_compression_level(png_ptr, zlib_level);
			} else if((flags & PNG_Z_NO_COMPRESSION) == PNG_Z_NO_COMPRESSION) {
				png_set_compression_level(png_ptr, Z_NO_COMPRESSION);
			}

			// filtered strategy works better for high color images
			if(pixel_depth >= 16){
				png_set_compression_strategy(png_ptr, Z_FILTERED);
				png_set_filter(png_ptr, 0, PNG_FILTER_NONE|PNG_FILTER_SUB|PNG_FILTER_PAETH);
			} else {
				png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY);
			}

			FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
			if(image_type == FIT_BITMAP) {
				// standard image type
				bit_depth = (pixel_depth > 8) ? 8 : pixel_depth;
			} else {
				// 16-bit greyscale or 16-bit RGB(A)
				bit_depth = 16;
			}

			switch (FreeImage_GetColorType(dib)) {
				case FIC_MINISWHITE:
					// Invert monochrome files to have 0 as black and 1 as white (no break here)
					png_set_invert_mono(png_ptr);

				case FIC_MINISBLACK:
					png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, 
						PNG_COLOR_TYPE_GRAY, interlace_type, 
						PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

					break;

				case FIC_PALETTE:
				{
					png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, 
						PNG_COLOR_TYPE_PALETTE, interlace_type, 
						PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

					// set the palette

					palette_entries = 1 << bit_depth;
					palette = (png_colorp)png_malloc(png_ptr, palette_entries * sizeof (png_color));
					pal = FreeImage_GetPalette(dib);

					for (int i = 0; i < palette_entries; i++) {
						palette[i].red   = pal[i].rgbRed;
						palette[i].green = pal[i].rgbGreen;
						palette[i].blue  = pal[i].rgbBlue;
					}
					
					png_set_PLTE(png_ptr, info_ptr, palette, palette_entries);

					// You must not free palette here, because png_set_PLTE only makes a link to
					// the palette that you malloced.  Wait until you are about to destroy
					// the png structure.

					break;
				}

				case FIC_RGBALPHA :
					has_alpha_channel = TRUE;

					png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, 
						PNG_COLOR_TYPE_RGBA, interlace_type, 
						PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
					// flip BGR pixels to RGB
					if(image_type == FIT_BITMAP) {
						png_set_bgr(png_ptr);
					}
#endif
					break;
	
				case FIC_RGB:
					png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, 
						PNG_COLOR_TYPE_RGB, interlace_type, 
						PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
					// flip BGR pixels to RGB
					if(image_type == FIT_BITMAP) {
						png_set_bgr(png_ptr);
					}
#endif
					break;
					
				case FIC_CMYK:
					break;
			}

			// write possible ICC profile

			FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(dib);
			if (iccProfile->size && iccProfile->data) {
				png_set_iCCP(png_ptr, info_ptr, "Embedded Profile", 0, (png_const_bytep)iccProfile->data, iccProfile->size);
			}

			// write metadata

			WriteMetadata(png_ptr, info_ptr, dib);

			// Optional gamma chunk is strongly suggested if you have any guess
			// as to the correct gamma of the image.
			// png_set_gAMA(png_ptr, info_ptr, gamma);

			// set the transparency table

			if (FreeImage_IsTransparent(dib) && (FreeImage_GetTransparencyCount(dib) > 0)) {
				png_set_tRNS(png_ptr, info_ptr, FreeImage_GetTransparencyTable(dib), FreeImage_GetTransparencyCount(dib), NULL);
			}

			// set the background color

			if(FreeImage_HasBackgroundColor(dib)) {
				png_color_16 image_background;
				RGBQUAD rgbBkColor;

				FreeImage_GetBackgroundColor(dib, &rgbBkColor);
				memset(&image_background, 0, sizeof(png_color_16));
				image_background.blue  = rgbBkColor.rgbBlue;
				image_background.green = rgbBkColor.rgbGreen;
				image_background.red   = rgbBkColor.rgbRed;
				image_background.index = rgbBkColor.rgbReserved;

				png_set_bKGD(png_ptr, info_ptr, &image_background);
			}
			
			// Write the file header information.

			png_write_info(png_ptr, info_ptr);

			// write out the image data

#ifndef FREEIMAGE_BIGENDIAN
			if (bit_depth == 16) {
				// turn on 16 bit byte swapping
				png_set_swap(png_ptr);
			}
#endif

			int number_passes = 1;
			if (bInterlaced) {
				number_passes = png_set_interlace_handling(png_ptr);
			}

			if ((pixel_depth == 32) && (!has_alpha_channel)) {
				BYTE *buffer = (BYTE *)malloc(width * 3);

				// transparent conversion to 24-bit
				// the number of passes is either 1 for non-interlaced images, or 7 for interlaced images
				for (int pass = 0; pass < number_passes; pass++) {
					for (png_uint_32 k = 0; k < height; k++) {
						FreeImage_ConvertLine32To24(buffer, FreeImage_GetScanLine(dib, height - k - 1), width);			
						png_write_row(png_ptr, buffer);
					}
				}
				free(buffer);
			} else {
				// the number of passes is either 1 for non-interlaced images, or 7 for interlaced images
				for (int pass = 0; pass < number_passes; pass++) {
					for (png_uint_32 k = 0; k < height; k++) {			
						png_write_row(png_ptr, FreeImage_GetScanLine(dib, height - k - 1));					
					}
				}
			}

			// It is REQUIRED to call this to finish writing the rest of the file
			// Bug with png_flush

			png_write_end(png_ptr, info_ptr);

			// clean up after the write, and free any memory allocated
			if (palette) {
				png_free(png_ptr, palette);
			}

			png_destroy_write_struct(&png_ptr, &info_ptr);

			return TRUE;
		} catch (const char *text) {
			FreeImage_OutputMessageProc(s_format_id, text);
		}
	}

	return FALSE;
}
Esempio n. 5
0
gint
gegl_buffer_export_png (GeglBuffer  *gegl_buffer,
                        const gchar *path,
                        gint         compression,
                        gint         bd,
                        gint         src_x,
                        gint         src_y,
                        gint         width,
                        gint         height)
{
    FILE          *fp;
    gint           i;
    png_struct    *png;
    png_info      *info;
    guchar        *pixels;
    png_color_16   white;
    int            png_color_type;
    gchar          format_string[16];
    const Babl    *format;
    gint           bit_depth = 8;

    if (!strcmp (path, "-"))
    {
        fp = stdout;
    }
    else
    {
        fp = fopen (path, "wb");
    }
    if (!fp)
    {
        return -1;
    }

    {
        const Babl *babl = gegl_buffer_get_format (gegl_buffer);

        if (bd == 16)
            bit_depth = 16;
        else
            bit_depth = 8;

        if (babl_format_has_alpha (babl))
            if (babl_format_get_n_components (babl) != 2)
            {
                png_color_type = PNG_COLOR_TYPE_RGB_ALPHA;
                strcpy (format_string, "R'G'B'A ");
            }
            else
            {
                png_color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
                strcpy (format_string, "Y'A ");
            }
        else if (babl_format_get_n_components (babl) != 1)
        {
            png_color_type = PNG_COLOR_TYPE_RGB;
            strcpy (format_string, "R'G'B' ");
        }
        else
        {
            png_color_type = PNG_COLOR_TYPE_GRAY;
            strcpy (format_string, "Y' ");
        }
    }

    if (bit_depth == 16)
        strcat (format_string, "u16");
    else
        strcat (format_string, "u8");

    png = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (png == NULL)
    {
        if (stdout != fp)
            fclose (fp);

        return -1;
    }

    info = png_create_info_struct (png);

    if (setjmp (png_jmpbuf (png)))
    {
        if (stdout != fp)
            fclose (fp);

        return -1;
    }

    png_set_compression_level (png, compression);
    png_init_io (png, fp);

    png_set_IHDR (png, info,
                  width, height, bit_depth, png_color_type,
                  PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_DEFAULT);

    if (png_color_type == PNG_COLOR_TYPE_RGB || png_color_type == PNG_COLOR_TYPE_RGB_ALPHA)
    {
        white.red = 0xff;
        white.blue = 0xff;
        white.green = 0xff;
    }
    else
        white.gray = 0xff;
    png_set_bKGD (png, info, &white);

    png_write_info (png, info);

#if BYTE_ORDER == LITTLE_ENDIAN
    if (bit_depth > 8)
        png_set_swap (png);
#endif

    format = babl_format (format_string);
    pixels = g_malloc0 (width * babl_format_get_bytes_per_pixel (format));

    for (i=0; i< height; i++)
    {
        GeglRectangle rect;

        rect.x = src_x;
        rect.y = src_y+i;
        rect.width = width;
        rect.height = 1;

        gegl_buffer_get (gegl_buffer, &rect, 1.0, babl_format (format_string), pixels, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);

        png_write_rows (png, &pixels, 1);
    }

    png_write_end (png, info);

    png_destroy_write_struct (&png, &info);
    g_free (pixels);

    if (stdout != fp)
        fclose (fp);

    return 0;
}
Esempio n. 6
0
/* returns 0 for success, 2 for libpng problem, 4 for out of memory, 11 for
 *  unexpected pnmtype; note that outfile might be stdout */
int writepng_init(mainprog_info *mainprog_ptr)
{
/*  This has been altered
    png_structp  png_ptr;*/       /* note:  temporary variables! */

    png_infop  info_ptr;
    int color_type, interlace_type;


    /* could also replace libpng warning-handler (final NULL), but no need: */
/*  This was altered
    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, mainprog_ptr,
      writepng_error_handler, NULL); */
    if (!png_ptr)
        return 4;   /* out of memory */

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        png_destroy_write_struct(&png_ptr, NULL);
        return 4;   /* out of memory */
    }

    /* setjmp() must be called in every function that calls a PNG-writing
     * libpng function, unless an alternate error handler was installed--
     * but compatible error handlers must either use longjmp() themselves
     * (as in this program) or exit immediately, so here we go: */

    if (setjmp(mainprog_ptr->jmpbuf)) {
        png_destroy_write_struct(&png_ptr, &info_ptr);
        return 2;
    }


    /* make sure outfile is (re)opened in BINARY mode */

/*  This was altered
    png_init_io(png_ptr, mainprog_ptr->outfile); */


    /* set the compression levels--in general, always want to leave filtering
     * turned on (except for palette images) and allow all of the filters,
     * which is the default; want 32K zlib window, unless entire image buffer
     * is 16K or smaller (unknown here)--also the default; usually want max
     * compression (NOT the default); and remaining compression flags should
     * be left alone */

    png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
/*
    >> this is default for no filtering; Z_FILTERED is default otherwise:
    png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY);
    >> these are all defaults:
    png_set_compression_mem_level(png_ptr, 8);
    png_set_compression_window_bits(png_ptr, 15);
    png_set_compression_method(png_ptr, 8);
 */


    /* set the image parameters appropriately */

    if (mainprog_ptr->pnmtype == 5)
        color_type = PNG_COLOR_TYPE_GRAY;
    else if (mainprog_ptr->pnmtype == 6)
        color_type = PNG_COLOR_TYPE_RGB;
    else if (mainprog_ptr->pnmtype == 8)
        color_type = PNG_COLOR_TYPE_RGB_ALPHA;
    else {
        png_destroy_write_struct(&png_ptr, &info_ptr);
        return 11;
    }

    interlace_type = mainprog_ptr->interlaced? PNG_INTERLACE_ADAM7 :
                                               PNG_INTERLACE_NONE;

    png_set_IHDR(png_ptr, info_ptr, mainprog_ptr->width, mainprog_ptr->height,
      mainprog_ptr->sample_depth, color_type, interlace_type,
      PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

    if (mainprog_ptr->gamma > 0.0)
        png_set_gAMA(png_ptr, info_ptr, mainprog_ptr->gamma);

    if (mainprog_ptr->have_bg) {   /* we know it's RGBA, not gray+alpha */
        png_color_16  background;

        background.red = mainprog_ptr->bg_red;
        background.green = mainprog_ptr->bg_green;
        background.blue = mainprog_ptr->bg_blue;
        png_set_bKGD(png_ptr, info_ptr, &background);
    }

    if (mainprog_ptr->have_time) {
        png_time  modtime;

        png_convert_from_time_t(&modtime, mainprog_ptr->modtime);
        png_set_tIME(png_ptr, info_ptr, &modtime);
    }

    if (mainprog_ptr->have_text) {
        png_text  text[6];
        int  num_text = 0;

        if (mainprog_ptr->have_text & TEXT_TITLE) {
            text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
            text[num_text].key = "Title";
            text[num_text].text = mainprog_ptr->title;
            ++num_text;
        }
        if (mainprog_ptr->have_text & TEXT_AUTHOR) {
            text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
            text[num_text].key = "Author";
            text[num_text].text = mainprog_ptr->author;
            ++num_text;
        }
        if (mainprog_ptr->have_text & TEXT_DESC) {
            text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
            text[num_text].key = "Description";
            text[num_text].text = mainprog_ptr->desc;
            ++num_text;
        }
        if (mainprog_ptr->have_text & TEXT_COPY) {
            text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
            text[num_text].key = "Copyright";
            text[num_text].text = mainprog_ptr->copyright;
            ++num_text;
        }
        if (mainprog_ptr->have_text & TEXT_EMAIL) {
            text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
            text[num_text].key = "E-mail";
            text[num_text].text = mainprog_ptr->email;
            ++num_text;
        }
        if (mainprog_ptr->have_text & TEXT_URL) {
            text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
            text[num_text].key = "URL";
            text[num_text].text = mainprog_ptr->url;
            ++num_text;
        }
        png_set_text(png_ptr, info_ptr, text, num_text);
    }


    /* write all chunks up to (but not including) first IDAT */

    png_write_info(png_ptr, info_ptr);


    /* if we wanted to write any more text info *after* the image data, we
     * would set up text struct(s) here and call png_set_text() again, with
     * just the new data; png_set_tIME() could also go here, but it would
     * have no effect since we already called it above (only one tIME chunk
     * allowed) */


    /* set up the transformations:  for now, just pack low-bit-depth pixels
     * into bytes (one, two or four pixels per byte) */

    png_set_packing(png_ptr);
/*  png_set_shift(png_ptr, &sig_bit);  to scale low-bit-depth values */


    /* make sure we save our pointers for use in writepng_encode_image() */

    mainprog_ptr->png_ptr = png_ptr;
    mainprog_ptr->info_ptr = info_ptr;


    /* OK, that's all we need to do for now; return happy */
    return 0;
}
Esempio n. 7
0
int main(int argc, char *argv[]) {
	setlocale(LC_ALL, "");
	setvbuf(stdout, (char*)NULL, _IONBF, 0);

	if(argc != 4) {
		fprintf(stderr, MSG[I_HELP1], argv[0]);
		fputs(MSG[I_HELP2], stderr);
		return EXIT_FAILURE;
	}

	char *inname  = argv[1],
		 *outname = argv[2],
		 *valarg   = argv[3];

	/* Quelldatei oeffnen und auf PNG-Signatur ueberpruefen **********************/

	puts(MSG[I_OPEN]);

	FILE *f;

	f = fopen(inname, "rb");
	if (f == NULL) {
		fputs(inname, stderr);
		fputs(MSG[E_OPEN], stderr);
		fputc('\n', stderr);
		return EXIT_FAILURE;
	}

	unsigned char sig[SIG_BYTES];
	fread(sig, 1, SIG_BYTES, f);
	if (png_sig_cmp(sig, 0, SIG_BYTES)) {
		fputs(inname, stderr);
		fputs(MSG[E_CORRUPTED], stderr);
		fputc('\n', stderr);
		fclose(f);
		return EXIT_FAILURE;
	}

	/* PNG-Lesevorgang initialisieren *****************************************/

	png_struct *png_ptr;
	png_info *info_ptr, *end_info;

	png_ptr = png_create_read_struct(
		PNG_LIBPNG_VER_STRING,
		(png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL
	);
	if (png_ptr == NULL) {
		fputs(MSG[E_GENERIC], stderr);
		fputc('\n', stderr);
		fclose(f);
		return EXIT_FAILURE;
	}
	
	info_ptr = png_create_info_struct(png_ptr);
	end_info = png_create_info_struct(png_ptr);

	try_png_read(
		(info_ptr == NULL) || (end_info == NULL),
		&png_ptr, &info_ptr, &end_info, f, (char*)NULL
	);

	try_png_read(
		setjmp(png_jmpbuf(png_ptr)),
		&png_ptr, &info_ptr, &end_info, f, MSG[E_READ]
	);

   	png_init_io(png_ptr, f);
	png_set_sig_bytes(png_ptr, SIG_BYTES);

	/* Bildinfo lesen: Bilddimensionen und ggf. Farbpalette.
	 * Palette ggf. konvertieren. *********************************************/

	long int width, height, pwidth, pheight;
//	png_uint_32 width, height, pwidth, pheight;
	comp_t *image, **row, *rwp;

	png_read_info(png_ptr, info_ptr);

	width = info_ptr->width;
	height = info_ptr->height;
	
	const long int original_width = info_ptr->width;

	const int bit_depth = info_ptr->bit_depth,
			 color_type = info_ptr->color_type;
	const bool image_is_pal = (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE);
	const bool image_is_gray = (
		(color_type == PNG_COLOR_TYPE_GRAY) ||
		(color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
	);
	const bool alpha = (
		(color_type == PNG_COLOR_TYPE_GRAY_ALPHA) ||
		(color_type == PNG_COLOR_TYPE_RGB_ALPHA)
	);

	int num_palette = 0;
	png_color *png_pal_got = NULL;

	if (image_is_pal)

		try_png_read(
			!png_get_PLTE(png_ptr, info_ptr, &png_pal_got, &num_palette),
			&png_ptr, &info_ptr, &end_info, f, MSG[E_READPAL]
		);

	png_color   png_pal[num_palette];	
	comp_t     comp_pal[num_palette];	

	if (image_is_pal)
		for (int i = 0; i < num_palette; i++) {
			png_pal[i] = png_pal_got[i];
			comp_t c;
			c = png_pal[i].red;
			c <<= CHAR_BIT;
			c |= png_pal[i].green;
			c <<= CHAR_BIT;
			c |= png_pal[i].blue;
			comp_pal[i] = c;
		}

	png_color_16 *img_bkgd;
	png_color_16 background;
	if (png_get_bKGD(png_ptr, info_ptr, &img_bkgd))
		background = *img_bkgd;

	/* Parameter fuer Groessenaenderung auswerten:
	 * diff: (Seitenlaenge nachher) - (Seitenlaenge vorher),
	 * vert: true <=> Aenderung der Bildhoehe (sonst -breite). ******************/

	long int diff;
	bool vert;

	bool aspp = false,
		 asp2 = false,
		 enlg = false,
		 sign = true;
	
	switch (tolower(*valarg++)) {
		case 'h': vert = false; break;
		case 'v': vert = true;  break;
		case '%': aspp = true;  break;
		case '@': asp2 = true;  break;
		default :
			try_png_read(true, &png_ptr, &info_ptr, &end_info, f, MSG[E_DIM]);
	}

	switch (*valarg) {
		case '+': enlg = true;  break;
		case '-': enlg = false; break;
		default:  sign = false; break;
	}

	diff = atol(valarg);
	bool valargok = !!diff;

	if (aspp || asp2) {
		try_png_read(!sign, &png_ptr, &info_ptr, &end_info, f, MSG[E_SIGN]);

		const float fheight = (float)height,
					fwidth  = (float)width,
					casp =  fheight / fwidth;
		float nasp;
		if (asp2) {
			const char *aspsw = strtok(valarg, ":"),
					   *aspsh = strtok((char*)NULL, ":");
			valargok = ((aspsw != NULL) && (aspsh != NULL));
			const float aspw = valargok? atol(aspsw): 0,
						asph = valargok? atol(aspsh): 0;
						nasp = valargok? fabs(asph / aspw): 0;
		} else
			nasp = ((float)labs(diff) / 100.0f);

		vert = ((nasp < casp) ^ enlg);
		
		diff = valargok? labs(vert?
			(height - (fwidth  * nasp)):
			(width  - (fheight / nasp))
		): 0;
		if (!enlg)
			diff = -diff;
	}

	if (!diff) {
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		fclose(f);
		if (valargok) {
			puts(MSG[I_NOTHINGTODO]);

//			const char copycmd[] = "copy /b /y";
			const char copycmd[] = "cp";

			char copycmdln[
				strlen(copycmd) + strlen(argv[1]) + strlen(argv[2]) + 7
			];
			sprintf(
				copycmdln, "%s \"%s\" \"%s\"",
				copycmd, argv[1], argv[2]
			);
			return system(copycmdln);
		}
		try_png_read(!valargok, &png_ptr, &info_ptr, &end_info, f, MSG[E_PAR]);
	}

	if (!(aspp || asp2 || sign))
		diff -= vert? height: width;
	
		try_png_read(
			labs(diff) > (vert? height: width),
			&png_ptr, &info_ptr, &end_info, f, MSG[E_SIZE]
		);

	/* Bild- sowie Zeilenzeigerspeicher anfordern und Zeiger setzen. **********/

	image = malloc(width * height * sizeof(comp_t));
	try_png_read(image == NULL, &png_ptr, &info_ptr, &end_info, f, (char*)NULL);
	
	row = malloc(height * sizeof(comp_t*));
	try_png_read(row == NULL, &png_ptr, &info_ptr, &end_info, f, (char*)NULL);
	
	rwp = image;
	for (int i = 0; i < height; i++) {
		row[i] = rwp;
		rwp += width;
	}
	
	/* Bild laden.
	 * Falls Alphakanal vorhanden, Alpha invertieren: hoher Wert => hohe Deckung.
	 * Falls Nicht-Palettenbild ohne Alphakanal (24 bpp) oder Graubild
	 * (8 oder 16 bpp), mit "png_set_filler" die Bilddaten auf 32 bzw. 16 bpp
	 * ausweiten. 32 Bit ist die *  comp_t-Breite. ****************************/

	puts(MSG[I_LOAD]);

	if (alpha)
		png_set_invert_alpha(png_ptr);
	else if (!image_is_pal)
		png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);

	png_read_image(png_ptr, (void*)row);

	/* Falls 8 oder 16 bpp, Bilddaten auf "Pixel = comp_t-Element" ausweiten. */

//	trw: Temporaere Zeile.
	void *trw = malloc(image_is_gray? (width * 2): width);

	try_png_read(trw == NULL, &png_ptr, &info_ptr, &end_info, f, (char*)NULL);

//	Zunaechst Bildzeile nach Temporaerzeile kopieren, dann Elemente einzeln zurueck.
	if (image_is_pal) {
		for (int i = 0; i < height; i++) {
			uint8_t *trwp = trw;
			rwp = row[i];
			memcpy(trw, row[i], width * sizeof *trwp);
			for (int j = 0; j < width; j++)
				*rwp++ = *trwp++;
		}
	}

	if (image_is_gray) {
		for (int i = 0; i < height; i++) {
			uint16_t *trwp = trw;
			rwp = row[i];
			memcpy(trw, row[i], width * sizeof *trwp);
			for (int j = 0; j < width; j++)
				*rwp++ = *trwp++;
		}
	}

	/* Lesevorgang beenden und Quelldatei schliessen. ************************/
	
	png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
	fclose(f);

	printf(
		"%s: %d*%d > %d*%d: %s %+d\n",
		MSG[I_MEASURES],
		width, height,
		vert? width: width + diff,
		vert? height + diff: height,
		vert? MSG[I_VERT]: MSG[I_HORI], diff
	);

	/* Hier kommt Fugenschnitzer zum Einsatz.
	 * diff: (Seitenlaenge nachher) - (Seitenlaenge vorher),
	 * vert: true <=> Aenderung der Bildhoehe (sonst -breite). ****************/

	sc_init();
	sc_load(image, &width, &height, 0);

	const int prep = sc_prepare(
		vert, diff,									// Bild ggf. erweitern
		false,		
		alpha? MARK_ALPHA: MARK_KEEP,				// Ggf. Alpha-Markierung
		(mark_t*)NULL,								// keine Markierung sonst
		&width, &height, &pwidth, &pheight
	);
	
	if (prep < 0) {
		fputs(MSG[E_GENERIC], stderr);
		fputc('\n', stderr);
		free(image);
		free(row);
		return EXIT_FAILURE;
	}
	
	if (prep & 2)
		puts(MSG[E_ALPHA]);

//	Bildspeicher erweitern, falls das Bild vergroessert wurde:

	if (prep & 1) {
		image = realloc(image, (size_t)width * (size_t)height * sizeof(comp_t));
		if (image == NULL) {
			fputs(MSG[E_GENERIC], stderr);
			fputc('\n', stderr);
			return EXIT_FAILURE;		
		}
		
		if (vert) {
			row = realloc(row, (size_t)height * sizeof(comp_t*));
			if (row == NULL) {
				fputs(MSG[E_GENERIC], stderr);
				fputc('\n', stderr);
				free(image);
				return EXIT_FAILURE;		
			}
		}		
	}

	pthread_t seam_th;
	pthread_create(&seam_th, NULL, seam_progress, (void*)(&diff));
	
//	sc_seam(diff);
	seam_paral(diff);
	
	pthread_join(seam_th, NULL);

	putchar('\n');
	printf(MSG[I_RESIZING]);
	
//	sc_carve(diff, &width, &height, &pwidth, &pheight);

	carve_paral(diff, &width, &height, &pwidth, &pheight);
	sc_fix(
		false,									// Nicht wiederherstellen
		&width, &height, &pwidth, &pheight
	);

	sc_eject(image);

	sc_close();

	/* Das war's mit Fugenschnitzer. -- Zeilenzeiger neu setzen. **************/

	rwp = image;
	for (int i = 0; i < height; i++) {
		row[i] = rwp;
		rwp += width;
	}

    /* Zieldatei oeffnen und Schreibvorgang initialisieren. ********************/

	putchar('\n');
	printf(MSG[I_SAVE]);

	f = fopen(outname, "wb");
	if (f == NULL) {
		fputs(outname, stderr);
		fputs(MSG[E_SAVE], stderr);
		fputc('\n', stderr);
		return EXIT_FAILURE;
	}

	png_ptr = png_create_write_struct(
		PNG_LIBPNG_VER_STRING,
		(png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL
	);
	if (png_ptr == NULL) {
		fputs(MSG[E_GENERIC], stderr);
		fputc('\n', stderr);
		fclose(f);
		return EXIT_FAILURE;
	}
	
	info_ptr = png_create_info_struct(png_ptr);
	try_png_write(info_ptr == NULL, &png_ptr, &info_ptr, f, (char*)NULL);

	try_png_write(
		setjmp(png_jmpbuf(png_ptr)),
		&png_ptr, &info_ptr, f, MSG[E_WRITE]
	);

   	png_init_io(png_ptr, f);

	/* Bildparameter setzen. **************************************************/

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

	if (image_is_pal)
		png_set_PLTE(png_ptr, info_ptr, png_pal, num_palette);

	if (alpha)
		png_set_bKGD(png_ptr, info_ptr, &background);

	png_write_info(png_ptr, info_ptr);

	/* Falls 8 oder 16 bpp, Bilddaten wieder zusammenschieben. ****************/

	trw = realloc(trw, image_is_gray? (width * 2): width);
	try_png_write(trw == NULL, &png_ptr, &info_ptr, f, (char*)NULL);

	if (image_is_pal) {
		for (int i = 0; i < height; i++) {
			uint8_t *trwp = trw;
			rwp = row[i];
			for (int j = 0; j < width; j++)
				*trwp++ = *rwp++;
			memcpy(row[i], trw, width * sizeof *trwp);
		}
	}

	if (image_is_gray) {
		for (int i = 0; i < height; i++) {
			uint16_t *trwp = trw;
			rwp = row[i];
			for (int j = 0; j < width; j++)
				*trwp++ = *rwp++;
			memcpy(row[i], trw, width * sizeof *trwp);
		}
	}

	/* Bild speichern. Wieder Alpha invertieren (hoher Wert => hohe Transparenz)
	*  sowie mit "png_set_filler" 32/16 bpp => 24/8 bpp setzen. ***************/

	if (alpha)
		png_set_invert_alpha(png_ptr);
	else
		png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);

	png_write_image(png_ptr, (void*)row);
	png_write_end(png_ptr, (png_info*)NULL);

	puts(MSG[I_FINISHED]);

	/* Schreibvorgang beenden, Datei schliessen, Speicher freigeben, fertig. ***/

	png_destroy_write_struct(&png_ptr, &info_ptr);
	fclose(f);

	free(trw);
	free(image);
	free(row);
	
	puts(MSG[I_COMPLETED]);
	
	return EXIT_SUCCESS;
}
Esempio n. 8
0
AFRAMES OneFrameReader(png_structp png_ptr_read, png_infop info_ptr_read,
                 png_structp png_ptr_write, png_infop info_ptr_write,
                 png_uint_32 width, png_uint_32 height)
{
    /* IHDR */
    /* struct data need from background */
    AFRAMES pframe;
    png_uint_32 garbage;
    int bit_depth;
    int colour_type;
    int interlace_method;
    int compression_method;
    int filter_method;
    
    /* PLTE */
    png_colorp palette = NULL;
    int palette_size = 0;
    
    /* gAMA */
    double gamma;
    
    /* tRNS */
    png_bytep trans;
    int num_trans;
    png_color_16p trans_values;
    
    /* bKGD */
    png_color_16p background;
    
    png_get_IHDR(png_ptr_read, info_ptr_read, &garbage, &garbage,
                 &bit_depth, &colour_type, &interlace_method,
                 &compression_method, &filter_method);
    png_set_IHDR(png_ptr_write, info_ptr_write, width, height,
                 bit_depth, colour_type, interlace_method,
                 compression_method, filter_method);
                 
                 
    
    
    int r = 0, g = 0, b = 0;
    int bpp = bit_depth;
    
    switch (colour_type) {
                case PNG_COLOR_TYPE_GRAY      :           break;
                case PNG_COLOR_TYPE_RGB       : bpp *= 3; break;
                case PNG_COLOR_TYPE_PALETTE   :           break;
                case PNG_COLOR_TYPE_GRAY_ALPHA: bpp *= 2; break;
                case PNG_COLOR_TYPE_RGB_ALPHA : bpp *= 4; break;
                default: 
                return pframe;
    }
    
    pframe.colortype = colour_type;
    pframe.bytedep = bpp;
    pframe.pngBG = trans_values;
    
    /////////qDebug() << "### color type  " << colour_type << bpp << num_trans;
    
                 
    
    if(png_get_valid(png_ptr_read, info_ptr_read, PNG_INFO_PLTE))
    {
        /////////qDebug() << "### PNG_INFO_PLTE";
        
        png_get_PLTE(png_ptr_read, info_ptr_read, &palette, &palette_size);
        png_set_PLTE(png_ptr_write, info_ptr_write, palette, palette_size);
    }
    
    if(png_get_valid(png_ptr_read, info_ptr_read, PNG_INFO_gAMA))
    {
        /////////qDebug() << "### PNG_INFO_gAMA";
        
        png_get_gAMA(png_ptr_read, info_ptr_read, &gamma);
        png_set_gAMA(png_ptr_write, info_ptr_write, gamma);
    }
    
    if(png_get_valid(png_ptr_read, info_ptr_read, PNG_INFO_tRNS))
    {
        //////////qDebug() << "### PNG_INFO_tRNS";
        
        png_get_tRNS(png_ptr_read, info_ptr_read, &trans, &num_trans, &trans_values);
        png_set_tRNS(png_ptr_write, info_ptr_write, trans, num_trans, trans_values);
    }
    
    if(png_get_valid(png_ptr_read, info_ptr_read, PNG_INFO_bKGD))
    {
        ////////qDebug() << "### PNG_INFO_bKGD";
        
        png_get_bKGD(png_ptr_read, info_ptr_read, &background);
        png_set_bKGD(png_ptr_write, info_ptr_write, background);
        png_color_16p bkgd = background;
        pframe.pngBG = background;
        
        int r = 0, g = 0, b = 0;
        
                if(colour_type == PNG_COLOR_TYPE_RGB || colour_type == PNG_COLOR_TYPE_RGB_ALPHA) {
                r = bkgd->red;
                g = bkgd->green;
                b = bkgd->blue;
                }
                if(colour_type == PNG_COLOR_TYPE_GRAY || colour_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
                r = g = b = bkgd->gray;
                }
                if(colour_type == PNG_COLOR_TYPE_PALETTE) {
                r = palette[bkgd->index].red;
                g = palette[bkgd->index].green;
                b = palette[bkgd->index].blue;
                }
                    // scale down to 8 bit color since QColor doesn't support 16 bit colors
                if(bit_depth > 8) {
                r >>= 8;
                g >>= 8;
                b >>= 8;
                }
                
                ////////qDebug() << "### color  " << r << g << b;
                
                pframe.bg = QColor(r,g,b);
                pframe.foundcolor = true; 
        
    } else {
static Bool
writePng (unsigned char *buffer,
	  png_rw_ptr	writeFunc,
	  void		*closure,
	  int		width,
	  int		height,
	  int		stride)
{
    png_struct	 *png;
    png_info	 *info;
    png_byte	 **rows;
    png_color_16 white;
    int		 i;

    rows = malloc (height * sizeof (png_byte *));
    if (!rows)
	return FALSE;

    for (i = 0; i < height; i++)
	rows[height - i - 1] = buffer + i * stride;

    png = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png)
    {
	free (rows);

	return FALSE;
    }

    info = png_create_info_struct (png);
    if (!info)
    {
	png_destroy_read_struct (&png, NULL, NULL);
	free (rows);

	return FALSE;
    }

    if (setjmp (png_jmpbuf (png)))
    {
	png_destroy_read_struct (&png, NULL, NULL);
	free (rows);

	return FALSE;
    }

    png_set_write_fn (png, closure, writeFunc, NULL);

    png_set_IHDR (png, info,
		  width, height, 8,
		  PNG_COLOR_TYPE_RGB_ALPHA,
		  PNG_INTERLACE_NONE,
		  PNG_COMPRESSION_TYPE_DEFAULT,
		  PNG_FILTER_TYPE_DEFAULT);

    white.red   = 0xff;
    white.blue  = 0xff;
    white.green = 0xff;

    png_set_bKGD (png, info, &white);

    png_write_info (png, info);
    png_write_image (png, rows);
    png_write_end (png, info);

    png_destroy_write_struct (&png, &info);
    free (rows);

    return TRUE;
}
Esempio n. 10
0
int main( int argc, char *argv[] ) {
	int f, rowbytes;
	char buf[256];
	static FILE *fpout;  /* "static" prevents setjmp corruption */
	png_structp write_ptr;
	png_infop write_info_ptr, end_info_ptr;
	png_bytep row_buf, here;
	png_uint_32 y;
	png_textp text_ptr, new_text_ptr;
	int num_text;

	int interlace_type, compression_type, filter_type, bit_depth, color_type;
	int it, ct, ft, bd, clrt;
	png_uint_32 width, height, w, h;

	int duration;

	if( argc < 4 ) {
		printf( "makeanim v0.2\nusage: makeanim <duration in milliseconds> <input files ...> <output file>\n" );
		printf( "example: makeanim 1500 a00.png a01.png a02.png a03.png a04.png a.anim\n" );
		return 1;
		}

	duration = atoi( argv[1] );
	if( duration < 1 ) {
		printf( "duration is incorrect\n" );
		return 1;
		}

	numfiles = argc - 3;
	input = (struct inputstruct *)malloc( sizeof( struct inputstruct ) * numfiles );
	if( !input ) return 1;

	for( f = 0; f < numfiles; f++ ) {
		input[f].name = argv[f + 2];
		printf( "opening file %d, \"%s\"\n", f, input[f].name );

		/* open the file handle */
		input[f].file = fopen( input[f].name, "rb" );
		if( input[f].file == NULL ) {
			printf( "fopen() failed\n" );
			return 1;
			}

		/* check if it's PNG */
		if( fread( buf, 1, 8, input[f].file ) != 8 ) {
			printf( "fread() failed for file \"%s\"\n", input[f].name );
			return 1;
			}
		if( png_sig_cmp( buf, (png_size_t)0, 8 ) ) {
			printf( "not a PNG file\n" );
			return 1;
			}
		fseek( input[f].file, 0, SEEK_SET );

		/* allocate read structure */
		input[f].read_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL );
		if( input[f].read_ptr == NULL ) {
			printf( "png_create_read_struct() failed\n" );
			return 1;
			}
		
		/* allocate read info structure */
		input[f].read_info_ptr = png_create_info_struct( input[f].read_ptr );
		if( input[f].read_info_ptr == NULL ) {
			printf( "png_create_info_struct() failed\n" );
			return 1;
			}


		/* set error handler code */
		if( setjmp( input[f].read_ptr->jmpbuf ) ) {
			printf( "libpng read error\n" );
			return 1;
			}

		/* initialize stream */
		png_init_io( input[f].read_ptr, input[f].file );
		png_set_read_status_fn( input[f].read_ptr, NULL );

		/* read png info struct */
		png_read_info( input[f].read_ptr, input[f].read_info_ptr );

		/* get the info */
		if( !png_get_IHDR( input[f].read_ptr, input[f].read_info_ptr, &w, &h, &bd, &clrt, &it, &ct, &ft ) ) {
			printf( "png_get_IHDR() failed\n" );
			return 1;
			}

		/* save the info of the first frame */
		if( f == 0 ) {
			width = w;
			height = h;
			bit_depth = bd;
			color_type = clrt;
			interlace_type = it;
			compression_type = ct;
			filter_type = ft;
			}
		/* compare all other frames to first frame */
		else if( (w != width) ||
				(h != height) ||
				(bd != bit_depth) ||
				(clrt != color_type) ||
				(it != interlace_type) ||
				(ct != compression_type) ||
				(ft != filter_type) ) {
			if( w != width ) printf( "width is different\n" );
			if( h != height ) printf( "height  is different\n" );
			if( bd != bit_depth ) printf( "bit depth is different\n" );
			if( clrt != color_type ) printf( "color type is different\n" );
			if( it != interlace_type ) printf( "interlace type is different\n" );
			if( ct != compression_type ) printf( "compression type is different\n" );
			if( ft != filter_type ) printf( "filter type is different\n" );
			return 1;
			}
		}
	
	row_buf = (png_bytep)NULL;
	
	/* open output file */
	printf( "opening file \"%s\"\n", argv[numfiles + 2] );
	fpout = fopen( argv[numfiles + 2], "wb" );
	if( fpout == NULL ) {
		printf( "fopen() failed\n" );
		return 1;
		}

	/* allocate write structure */
	write_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL );

	/* allocate info structures */
	write_info_ptr = png_create_info_struct( write_ptr );
	end_info_ptr = png_create_info_struct( write_ptr );

	/* error handling */
	if( setjmp( write_ptr->jmpbuf ) ) {
		printf( "libpng write error\n" );
		return 1;
		}

	/* initialize output stream */
	png_init_io( write_ptr, fpout );
	png_set_write_status_fn( write_ptr, NULL );

	/* set info */
	png_set_IHDR( write_ptr, write_info_ptr, width * numfiles, height, bit_depth, color_type, PNG_INTERLACE_NONE, compression_type, filter_type);

	/* image characteristics */
	{
		png_color_16p background;
		double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
		double gamma;
		int intent;
		png_uint_16p hist;
		png_uint_32 offset_x, offset_y;
		int unit_type;
		png_charp purpose, units;
		png_charpp params;
		png_int_32 X0, X1;
		int type, nparams;
		png_uint_32 res_x, res_y;
		png_colorp palette;
		int num_palette;
		png_color_8p sig_bit;
		png_bytep trans;
		int num_trans;
		png_color_16p trans_values;

		/* background color */
		if( png_get_bKGD( input[0].read_ptr, input[0].read_info_ptr, &background ) ) {
			png_set_bKGD( write_ptr, write_info_ptr, background );
			}

		if( png_get_cHRM( input[0].read_ptr, input[0].read_info_ptr, &white_x, &white_y, &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y ) ) {
			png_set_cHRM( write_ptr, write_info_ptr, white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y );
			}

		/* gamma */
		if( png_get_gAMA( input[0].read_ptr, input[0].read_info_ptr, &gamma ) ) {
			png_set_gAMA( write_ptr, write_info_ptr, gamma );
			}

		/* rendering intent */
		if( png_get_sRGB( input[0].read_ptr, input[0].read_info_ptr, &intent ) ) {
			png_set_sRGB( write_ptr, write_info_ptr, intent );
			}

		/* Histogram */
		if( png_get_hIST( input[0].read_ptr, input[0].read_info_ptr, &hist ) ) {
			png_set_hIST( write_ptr, write_info_ptr, hist );
			}

		/* offsets */
		if( png_get_oFFs( input[0].read_ptr, input[0].read_info_ptr, &offset_x, &offset_y, &unit_type ) ) {
			png_set_oFFs( write_ptr, write_info_ptr, offset_x, offset_y, unit_type );
			}

		if( png_get_pCAL( input[0].read_ptr, input[0].read_info_ptr, &purpose, &X0, &X1, &type, &nparams, &units, &params ) ) {
			png_set_pCAL( write_ptr, write_info_ptr, purpose, X0, X1, type, nparams, units, params );
			}

		/* pixel density */
		if( png_get_pHYs( input[0].read_ptr, input[0].read_info_ptr, &res_x, &res_y, &unit_type ) ) {
			png_set_pHYs( write_ptr, write_info_ptr, res_x, res_y, unit_type );
			}

		/* text chunks */
/*		if( png_get_text( input[0].read_ptr, input[0].read_info_ptr, &text_ptr, &num_text ) > 0 ) {
			printf( "Handling %d tEXt/zTXt chunks\n", num_text );
			png_set_text( write_ptr, write_info_ptr, text_ptr, num_text );
			}
*/
		/* palette */
		if( png_get_PLTE( input[0].read_ptr, input[0].read_info_ptr, &palette, &num_palette ) ) {
			png_set_PLTE( write_ptr, write_info_ptr, palette, num_palette );
			}

		/* significant bits */
		if( png_get_sBIT( input[0].read_ptr, input[0].read_info_ptr, &sig_bit ) ) {
			png_set_sBIT( write_ptr, write_info_ptr, sig_bit );
			}

		/* transparency */
		if( png_get_tRNS( input[0].read_ptr, input[0].read_info_ptr, &trans, &num_trans, &trans_values ) ) {
			png_set_tRNS( write_ptr, write_info_ptr, trans, num_trans, trans_values );
			}
		}

	/* text chunks */
	num_text = 0;
	if( !png_get_text( input[0].read_ptr, input[0].read_info_ptr, &text_ptr, &num_text ) ) num_text = 0;
	new_text_ptr = (struct png_text_struct *)malloc( sizeof( struct png_text_struct ) * num_text + 1 );
	if( !new_text_ptr ) {
		printf( "malloc() failed\n" );
		return 1;
		}
	
	memcpy( new_text_ptr, text_ptr, sizeof( struct png_text_struct ) * num_text );

	snprintf( buf, 255, "SDL_anim %d %d %d", duration, width, numfiles );
	buf[255] = 0;
	new_text_ptr[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
	new_text_ptr[num_text].key = "format";
	new_text_ptr[num_text].text = buf;
	new_text_ptr[num_text].text_length = strlen( buf );
	num_text++;
	png_set_text( write_ptr, write_info_ptr, new_text_ptr, num_text );

	/* write info */
	png_write_info( write_ptr, write_info_ptr );

	/* allocate buffer */
	rowbytes = png_get_rowbytes( input[0].read_ptr, input[0].read_info_ptr );
	row_buf = (png_bytep)png_malloc( write_ptr, rowbytes * numfiles );
	if( row_buf == NULL ) {
		printf( "png_malloc() failed\n" );
		return 1;
		}

	/* copy raw data */
	for( y = 0; y < height; y++ ) {
		/* grab a scanline from each file */
		here = row_buf;
		for( f = 0; f < numfiles; f++ ) {
			png_read_rows( input[f].read_ptr, (png_bytepp)&here, (png_bytepp)NULL, 1 );
			here += rowbytes;
			}
		/* write the long scanline */
		png_write_rows( write_ptr, (png_bytepp)&row_buf, 1 );
		}

	/* end io */
	for( f = 0; f < numfiles; f++ ) png_read_end( input[f].read_ptr, end_info_ptr );
	png_write_end( write_ptr, end_info_ptr );

	/* cleanup */
	png_free( write_ptr, row_buf );
	for( f = 0; f < numfiles; f++ ) {
		png_destroy_read_struct( &input[f].read_ptr, &input[f].read_info_ptr, &end_info_ptr);
		fclose( input[f].file );
		}
	png_destroy_write_struct( &write_ptr, &write_info_ptr );
	fclose( fpout );

	return 0;
	}
Esempio n. 11
0
/* This routine is used for all formats. */
static int
png_print_page(gx_device_printer * pdev, FILE * file)
{
    gs_memory_t *mem = pdev->memory;
    int raster = gdev_prn_raster(pdev);

    /* PNG structures */
    byte *row = gs_alloc_bytes(mem, raster, "png raster buffer");
    png_struct *png_ptr =
    png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    png_info *info_ptr =
    png_create_info_struct(png_ptr);
    int height = pdev->height;
    int depth = pdev->color_info.depth;
    int y;
    int code;			/* return code */
    char software_key[80];
    char software_text[256];
    png_text text_png;

    if (row == 0 || png_ptr == 0 || info_ptr == 0) {
	code = gs_note_error(gs_error_VMerror);
	goto done;
    }
    /* set error handling */
    if (setjmp(png_ptr->jmpbuf)) {
	/* If we get here, we had a problem reading the file */
	code = gs_note_error(gs_error_VMerror);
	goto done;
    }
    code = 0;			/* for normal path */
    /* set up the output control */
    png_init_io(png_ptr, file);

    /* set the file information here */
    info_ptr->width = pdev->width;
    info_ptr->height = pdev->height;
    /* resolution is in pixels per meter vs. dpi */
    info_ptr->x_pixels_per_unit =
	(png_uint_32) (pdev->HWResolution[0] * (100.0 / 2.54));
    info_ptr->y_pixels_per_unit =
	(png_uint_32) (pdev->HWResolution[1] * (100.0 / 2.54));
    info_ptr->phys_unit_type = PNG_RESOLUTION_METER;
    info_ptr->valid |= PNG_INFO_pHYs;
    switch (depth) {
	case 32:
	    info_ptr->bit_depth = 8;
	    info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
	    png_set_invert_alpha(png_ptr);
	    {   gx_device_pngalpha *ppdev = (gx_device_pngalpha *)pdev;
		png_color_16 background;
		background.index = 0;
		background.red =   (ppdev->background >> 16) & 0xff;
		background.green = (ppdev->background >> 8)  & 0xff;
		background.blue =  (ppdev->background)       & 0xff;
		background.gray = 0;
		png_set_bKGD(png_ptr, info_ptr, &background);
	    }
	    break;
	case 48:
	    info_ptr->bit_depth = 16;
	    info_ptr->color_type = PNG_COLOR_TYPE_RGB;
#if defined(ARCH_IS_BIG_ENDIAN) && (!ARCH_IS_BIG_ENDIAN) 
	    png_set_swap(png_ptr);
#endif
	    break;
	case 24:
	    info_ptr->bit_depth = 8;
	    info_ptr->color_type = PNG_COLOR_TYPE_RGB;
	    break;
	case 8:
	    info_ptr->bit_depth = 8;
	    if (gx_device_has_color(pdev))
		info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
	    else
		info_ptr->color_type = PNG_COLOR_TYPE_GRAY;
	    break;
	case 4:
	    info_ptr->bit_depth = 4;
	    info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
	    break;
	case 1:
	    info_ptr->bit_depth = 1;
	    info_ptr->color_type = PNG_COLOR_TYPE_GRAY;
	    /* invert monocrome pixels */
	    png_set_invert_mono(png_ptr);
	    break;
    }

    /* set the palette if there is one */
    if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) {
	int i;
	int num_colors = 1 << depth;
	gx_color_value rgb[3];

	info_ptr->palette =
	    (void *)gs_alloc_bytes(mem, 256 * sizeof(png_color),
				   "png palette");
	if (info_ptr->palette == 0) {
	    code = gs_note_error(gs_error_VMerror);
	    goto done;
	}
	info_ptr->num_palette = num_colors;
	info_ptr->valid |= PNG_INFO_PLTE;
	for (i = 0; i < num_colors; i++) {
	    (*dev_proc(pdev, map_color_rgb)) ((gx_device *) pdev,
					      (gx_color_index) i, rgb);
	    info_ptr->palette[i].red = gx_color_value_to_byte(rgb[0]);
	    info_ptr->palette[i].green = gx_color_value_to_byte(rgb[1]);
	    info_ptr->palette[i].blue = gx_color_value_to_byte(rgb[2]);
	}
    }
    /* add comment */
    strncpy(software_key, "Software", sizeof(software_key));
    sprintf(software_text, "%s %d.%02d", gs_product,
	    (int)(gs_revision / 100), (int)(gs_revision % 100));
    text_png.compression = -1;	/* uncompressed */
    text_png.key = software_key;
    text_png.text = software_text;
    text_png.text_length = strlen(software_text);
    info_ptr->text = &text_png;
    info_ptr->num_text = 1;

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

    /* don't write the comments twice */
    info_ptr->num_text = 0;
    info_ptr->text = NULL;

    /* Write the contents of the image. */
    for (y = 0; y < height; y++) {
	gdev_prn_copy_scan_lines(pdev, y, row, raster);
	png_write_rows(png_ptr, &row, 1);
    }

    /* write the rest of the file */
    png_write_end(png_ptr, info_ptr);

    /* if you alloced the palette, free it here */
    gs_free_object(mem, info_ptr->palette, "png palette");

  done:
    /* free the structures */
    png_destroy_write_struct(&png_ptr, &info_ptr);
    gs_free_object(mem, row, "png raster buffer");

    return code;
}
Esempio n. 12
0
static gint
export_png (GeglOperation       *operation,
            GeglBuffer          *input,
            const GeglRectangle *result,
            png_structp          png,
            png_infop            info,
            gint                 compression,
            gint                 bit_depth)
{
  gint           i, src_x, src_y;
  png_uint_32    width, height;
  guchar        *pixels;
  png_color_16   white;
  int            png_color_type;
  gchar          format_string[16];
  const Babl    *format;

  src_x = result->x;
  src_y = result->y;
  width = result->width;
  height = result->height;

  {
    const Babl *babl = gegl_buffer_get_format (input);

    if (bit_depth != 16)
      bit_depth = 8;

    if (babl_format_has_alpha (babl))
      if (babl_format_get_n_components (babl) != 2)
        {
          png_color_type = PNG_COLOR_TYPE_RGB_ALPHA;
          strcpy (format_string, "R'G'B'A ");
        }
      else
        {
          png_color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
          strcpy (format_string, "Y'A ");
        }
    else
      if (babl_format_get_n_components (babl) != 1)
        {
          png_color_type = PNG_COLOR_TYPE_RGB;
          strcpy (format_string, "R'G'B' ");
        }
      else
        {
          png_color_type = PNG_COLOR_TYPE_GRAY;
          strcpy (format_string, "Y' ");
        }
  }

  if (bit_depth == 16)
    strcat (format_string, "u16");
  else
    strcat (format_string, "u8");

  if (setjmp (png_jmpbuf (png)))
    return -1;

  png_set_compression_level (png, compression);

  png_set_IHDR (png, info,
     width, height, bit_depth, png_color_type,
     PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_DEFAULT);

  if (png_color_type == PNG_COLOR_TYPE_RGB || png_color_type == PNG_COLOR_TYPE_RGB_ALPHA)
    {
      white.red = 0xff;
      white.blue = 0xff;
      white.green = 0xff;
      png_set_sRGB_gAMA_and_cHRM (png, info, PNG_sRGB_INTENT_RELATIVE);
    }
  else
    white.gray = 0xff;
  png_set_bKGD (png, info, &white);

  png_write_info (png, info);

#if BYTE_ORDER == LITTLE_ENDIAN
  if (bit_depth > 8)
    png_set_swap (png);
#endif

  format = babl_format (format_string);
  pixels = g_malloc0 (width * babl_format_get_bytes_per_pixel (format));

  for (i=0; i< height; i++)
    {
      GeglRectangle rect;

      rect.x = src_x;
      rect.y = src_y+i;
      rect.width = width;
      rect.height = 1;

      gegl_buffer_get (input, &rect, 1.0, babl_format (format_string), pixels, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);

      png_write_rows (png, &pixels, 1);
    }

  png_write_end (png, info);

  g_free (pixels);

  return 0;
}
Esempio n. 13
0
/**
 * Write PNG image data
 * @param buffer Image data
 * @param filename A filename of the PNG image to save
 * @param width Image width in pixels
 * @param height Image height in pixels
 * @param depth The bit depth of the image.
 *              Valid values shall include 1, 2, 4, 8, 16. 
 * @return TRUE if it completed successfully or FALSE otherwise
 */
static bool
png_create (char *buffer, const char *filename, Uint32 width, Uint32 height,
            Sint32 depth)
{
  Uint32 i;
  FILE *out;
  LOG_DBG ("Write %s", filename);
  if (buffer == NULL)
    {
      LOG_ERR ("image_to_buffer() failed! (filename = %s)", filename);
      return FALSE;
    }
  out = fopen_data (filename, "w");
  if (out == NULL)
    {
      LOG_ERR ("can't open \"%s\"", filename);
      return FALSE;
    }

  /* allocate and initialize png_ptr struct for writing */
  png_structp png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING,
                                                 /* error_ptr */
                                                 (png_voidp) NULL,
                                                 /* error_fn */
                                                 NULL,
                                                 /* warn_fn */
                                                 NULL);
  if (png_ptr == NULL)
    {
      LOG_ERR ("png_create_write_struct() failed");
      return FALSE;
    }

  /* allocate and initialize the info structure */
  png_infop info_ptr = png_create_info_struct (png_ptr);
  if (png_ptr == NULL)
    {
      LOG_ERR ("png_create_info_struct() failed");
      return FALSE;
    }

  /* initialize input/output for PNG file to the default functions */
  png_init_io (png_ptr, out);

  /* set library compression level */
  png_set_IHDR (png_ptr, info_ptr,
                /* width */
                width,
                /* height */
                height,
                /* bit depth */
                depth,
                PNG_COLOR_TYPE_RGB_ALPHA,
                PNG_INTERLACE_NONE,
                PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
  png_set_compression_level (png_ptr, Z_BEST_COMPRESSION);

  png_set_text (png_ptr, info_ptr, text, sizeof text / sizeof text[0]);
  png_color_16 background;
  background.red = 0;
  background.green = 0;
  background.blue = 0;
  png_set_bKGD (png_ptr, info_ptr, &background);
  png_write_info (png_ptr, info_ptr);
  for (i = 0; i < height; i++)
    {
      {
        png_write_row (png_ptr, (png_byte *) & buffer[i * width * 4]);
      }
    }
  png_write_end (png_ptr, info_ptr);
  png_destroy_write_struct (&png_ptr, &info_ptr);
  fclose (out);
  return TRUE;
}
static gsize
photos_operation_png_guess_sizes_count (GeglBuffer *buffer,
                                        gint compression,
                                        gint bitdepth,
                                        gboolean background,
                                        gdouble zoom,
                                        gint src_x,
                                        gint src_y,
                                        gint width,
                                        gint height)
{
  gint bpp;
  gint i;
  gint png_color_type;
  gchar format_string[16];
  const Babl *format;
  const Babl *format_buffer;
  gsize ret_val = 0;
  gsize size;
  guchar *pixels = NULL;
  png_infop info_ptr = NULL;
  png_structp png_ptr = NULL;

  format_buffer = gegl_buffer_get_format (buffer);
  if (babl_format_has_alpha (format_buffer))
    {
      if (babl_format_get_n_components (format_buffer) != 2)
        {
          png_color_type = PNG_COLOR_TYPE_RGB_ALPHA;
          strcpy (format_string, "R'G'B'A ");
        }
      else
        {
          png_color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
          strcpy (format_string, "Y'A ");
        }
    }
  else
    {
      if (babl_format_get_n_components (format_buffer) != 1)
        {
          png_color_type = PNG_COLOR_TYPE_RGB;
          strcpy (format_string, "R'G'B' ");
        }
      else
        {
          png_color_type = PNG_COLOR_TYPE_GRAY;
          strcpy (format_string, "Y' ");
        }
    }

  if (bitdepth == 16)
    strcat (format_string, "u16");
  else
    strcat (format_string, "u8");

  png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (png_ptr == NULL)
    goto out;

  info_ptr = png_create_info_struct (png_ptr);
  if (info_ptr == NULL)
    goto out;

  if (setjmp (png_jmpbuf (png_ptr)))
    {
      ret_val = 0;
      goto out;
    }

  if (compression >= 0)
    png_set_compression_level (png_ptr, compression);

  photos_png_init_count (png_ptr, &size);

  png_set_IHDR (png_ptr,
                info_ptr,
                width,
                height,
                bitdepth,
                png_color_type,
                PNG_INTERLACE_NONE,
                PNG_COMPRESSION_TYPE_BASE,
                PNG_FILTER_TYPE_DEFAULT);

  if (background)
    {
      png_color_16 white;

      if (png_color_type == PNG_COLOR_TYPE_RGB || png_color_type == PNG_COLOR_TYPE_RGB_ALPHA)
        {
          white.red = 0xff;
          white.blue = 0xff;
          white.green = 0xff;
        }
      else
        {
          white.gray = 0xff;
        }

      png_set_bKGD (png_ptr, info_ptr, &white);
    }

  png_write_info (png_ptr, info_ptr);

#if BYTE_ORDER == LITTLE_ENDIAN
  if (bitdepth > 8)
    png_set_swap (png_ptr);
#endif

  format = babl_format (format_string);
  bpp = babl_format_get_bytes_per_pixel (format);
  pixels = g_malloc0 (width * bpp);

  for (i = 0; i < height; i++)
    {
      GeglRectangle rect;

      rect.x = src_x;
      rect.y = src_y + i;
      rect.width = width;
      rect.height = 1;
      gegl_buffer_get (buffer, &rect, zoom, format, pixels, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
      png_write_rows (png_ptr, &pixels, 1);
    }

  png_write_end (png_ptr, info_ptr);
  ret_val = size;

 out:
  g_free (pixels);
  png_destroy_write_struct (&png_ptr, &info_ptr);
  return ret_val;
}
Esempio n. 15
0
bool
PngScreen::writePng (unsigned char *buffer,
		     std::ostream  &file,
		     CompSize      &size,
		     int           stride)
{
    png_struct	 *png;
    png_info	 *info;
    png_byte	 **rows;
    png_color_16 white;
    int		 i, height = size.height ();

    rows = new png_byte *[height];
    if (!rows)
	return false;

    for (i = 0; i < height; i++)
	rows[height - i - 1] = buffer + i * stride;

    png = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png)
    {
	delete [] rows;
	return false;
    }

    info = png_create_info_struct (png);
    if (!info)
    {
	png_destroy_write_struct (&png, NULL);
	delete [] rows;
	return false;
    }

    if (setjmp (png_jmpbuf (png)))
    {
	png_destroy_write_struct (&png, NULL);
	delete [] rows;
	return false;
    }

    png_set_write_fn (png, &file, stdioWriteFunc, NULL);

    png_set_IHDR (png, info,
		  size.width (), size.height (), 8,
		  PNG_COLOR_TYPE_RGB_ALPHA,
		  PNG_INTERLACE_NONE,
		  PNG_COMPRESSION_TYPE_DEFAULT,
		  PNG_FILTER_TYPE_DEFAULT);

    white.red   = 0xff;
    white.blue  = 0xff;
    white.green = 0xff;

    png_set_bKGD (png, info, &white);

    png_write_info (png, info);
    png_write_image (png, rows);
    png_write_end (png, info);

    png_destroy_write_struct (&png, &info);
    delete [] rows;

    return true;
}
Esempio n. 16
0
/*---------------------------------------------------------------------------
   Saves a PNG file.

   Image    : Image to save.
   Path     : Path to image file, relative to the current working directory.
   Compress : Specifies the compression level to use for encoding.
  ---------------------------------------------------------------------------*/
void PNG::Save(const Texture &Image, const std::string &Path, CompLevel Compress)
   {
   Destroy();

   //Important - set class to writing mode
   Mode = PNG::ModeWrite;

   vector2u Res = Image.Resolution();
   if (Res.U < 1 || Res.V < 1) {return;}

   #if defined (WINDOWS)
      if (fopen_s(&File, Path.c_str(), "wb") != 0)
         {throw dexception("Failed to open file: %s.", Path.c_str());}
   #else
      File = fopen(Path.c_str(), "wb");
      if (File == nullptr) {throw dexception("Failed to open file: %s.", Path.c_str());}
   #endif

   PngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
   if (PngPtr == nullptr) {throw dexception("png_create_write_struct( ) failed.");}

   InfoPtr = png_create_info_struct(PngPtr);
   if (InfoPtr == nullptr) {throw dexception("png_create_info_struct( ) failed.");}

   if (setjmp(png_jmpbuf(PngPtr)))
      {throw dexception("setjmp( ) failed.");}

   png_init_io(PngPtr, File);

   png_set_compression_level(PngPtr, (int)Compress);

   int BitDepth, ColourType;
   switch (Image.DataType())
      {
      case Texture::TypeAlpha : BitDepth = 8;  ColourType = PNG_COLOR_TYPE_GRAY; break;
      case Texture::TypeLum   : BitDepth = 8;  ColourType = PNG_COLOR_TYPE_GRAY; break;
      case Texture::TypeDepth : BitDepth = 16; ColourType = PNG_COLOR_TYPE_GRAY; break;
      case Texture::TypeRGB   : BitDepth = 8;  ColourType = PNG_COLOR_TYPE_RGB; break;
      case Texture::TypeRGBA  : BitDepth = 8;  ColourType = PNG_COLOR_TYPE_RGB_ALPHA; break;
      default : throw dexception("Unsupported image type."); break;
      }

   png_set_IHDR(PngPtr, InfoPtr, (png_uint_32)Res.U, (png_uint_32)Res.V, BitDepth, ColourType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

   png_set_sRGB(PngPtr, InfoPtr, PNG_sRGB_INTENT_ABSOLUTE);
   png_set_sRGB_gAMA_and_cHRM(PngPtr, InfoPtr, PNG_sRGB_INTENT_ABSOLUTE);

   png_color_16 BackGnd;
   BackGnd.red   = 0;
   BackGnd.green = 0;
   BackGnd.blue  = 0;
   png_set_bKGD(PngPtr, InfoPtr, &BackGnd);

   png_text PngText[2];
   memset(PngText, 0, sizeof(PngText));

   PngText[0].compression = PNG_TEXT_COMPRESSION_NONE;
   PngText[0].key = const_cast<png_charp>("Software");
   PngText[0].text = const_cast<png_charp>(AppName);
   PngText[0].text_length = strlen(PngText[0].text);

   PngText[1].compression = PNG_TEXT_COMPRESSION_NONE;
   PngText[1].key = const_cast<png_charp>("Author");
   PngText[1].text = const_cast<png_charp>(AppAuthor);
   PngText[1].text_length = strlen(PngText[1].text);

   png_set_text(PngPtr, InfoPtr, PngText, 2);

   png_write_info(PngPtr, InfoPtr);

   //Populate row pointer array
   Rows.Create((usize)Res.V);
   for (uiter I = 0; I < (usize)Res.V; I++)
      {
      Rows[I] = Image.Address(0, I);
      }

   //Encode
   png_write_image(PngPtr, Rows.Pointer());
   png_write_end(PngPtr, nullptr);

   //Clean up
   Destroy();
   }