Beispiel #1
0
static gboolean
ico_write_png (FILE   *fp,
               gint32  layer,
               gint32  depth)
{
  png_structp png_ptr;
  png_infop   info_ptr;
  png_byte  **row_pointers;
  gint        i, rowstride;
  gint        width, height;
  gint        num_colors_used;
  guchar     *palette;
  guchar     *buf;

  row_pointers = NULL;
  palette = NULL;
  buf = NULL;

  width = gimp_drawable_width (layer);
  height = gimp_drawable_height (layer);

  png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if ( !png_ptr )
    return FALSE;

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

  if (setjmp (png_jmpbuf (png_ptr)))
    {
      png_destroy_write_struct (&png_ptr, &info_ptr);
      if ( row_pointers )
        g_free (row_pointers);
      if (palette)
        g_free (palette);
      if (buf)
        g_free (buf);
      return FALSE;
    }

  ico_image_get_reduced_buf (layer, depth, &num_colors_used,
                             &palette, &buf);

  png_init_io (png_ptr, fp);
  png_set_IHDR (png_ptr, info_ptr, width, height,
                8,
                PNG_COLOR_TYPE_RGBA,
                PNG_INTERLACE_NONE,
                PNG_COMPRESSION_TYPE_DEFAULT,
                PNG_FILTER_TYPE_DEFAULT);
  png_write_info (png_ptr, info_ptr);

  rowstride = ico_rowstride (width, 32);
  row_pointers = g_new (png_byte*, height);
  for (i = 0; i < height; i++)
    {
      row_pointers[i] = buf + rowstride * i;
    }
  png_write_image (png_ptr, row_pointers);

  row_pointers = NULL;

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

  g_free (row_pointers);
  g_free (palette);
  g_free (buf);
  return TRUE;
}
Beispiel #2
0
PyObject *
save_png_fast_progressive (char *filename,
                           int w, int h,
                           bool has_alpha,
                           PyObject *data_generator,
                           bool write_legacy_png)
{
  png_structp png_ptr = NULL;
  png_infop info_ptr = NULL;
  PyObject * result = NULL;
  int bpc;
  FILE * fp = NULL;
  PyObject *iterator = NULL;

  /* TODO: try if this silliness helps
#if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200)
  png_uint_32 mask, flags;
  
  flags = png_get_asm_flags(png_ptr);
  mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE);
  png_set_asm_flags(png_ptr, flags | mask);
#endif
  */

  bpc = 8;
  
  fp = fopen(filename, "wb");
  if (!fp) {
    PyErr_SetFromErrno(PyExc_IOError);
    //PyErr_Format(PyExc_IOError, "Could not open PNG file for writing: %s", filename);
    goto cleanup;
  }

  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, png_write_error_callback, NULL);
  if (!png_ptr) {
    PyErr_SetString(PyExc_MemoryError, "png_create_write_struct() failed");
    goto cleanup;
  }

  info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr) {
    PyErr_SetString(PyExc_MemoryError, "png_create_info_struct() failed");
    goto cleanup;
  }

  if (setjmp(png_jmpbuf(png_ptr))) {
    goto cleanup;
  }

  png_init_io(png_ptr, fp);

  png_set_IHDR (png_ptr, info_ptr,
                w, h, bpc,
                has_alpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB,
                PNG_INTERLACE_NONE,
                PNG_COMPRESSION_TYPE_BASE,
                PNG_FILTER_TYPE_BASE);

  if (! write_legacy_png) {
    // Internal data is sRGB by the time it gets here.
    // Explicitly save with the recommended chunks to advertise that fact.
    png_set_sRGB_gAMA_and_cHRM (png_ptr, info_ptr, PNG_sRGB_INTENT_PERCEPTUAL);
  }

  // default (all filters enabled):                 1350ms, 3.4MB
  //png_set_filter(png_ptr, 0, PNG_FILTER_NONE);  // 790ms, 3.8MB
  //png_set_filter(png_ptr, 0, PNG_FILTER_PAETH); // 980ms, 3.5MB
  png_set_filter(png_ptr, 0, PNG_FILTER_SUB);     // 760ms, 3.4MB

  //png_set_compression_level(png_ptr, 0); // 0.49s, 32MB
  //png_set_compression_level(png_ptr, 1); // 0.98s, 9.6MB
  png_set_compression_level(png_ptr, 2);   // 1.08s, 9.4MB
  //png_set_compression_level(png_ptr, 9); // 18.6s, 9.3MB

  png_write_info(png_ptr, info_ptr);

  if (!has_alpha) {
    // input array format format is rgbu
    png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
  }

  {
    iterator = PyObject_GetIter(data_generator);
    if (!iterator) goto cleanup;

    int y = 0;
    while (y < h) {
      int rows;
      PyObject * arr = PyIter_Next(iterator);
      if (PyErr_Occurred()) goto cleanup;
      assert(arr); // iterator should have data
      assert(PyArray_ISALIGNED(arr));
      assert(PyArray_NDIM(arr) == 3);
      assert(PyArray_DIM(arr, 1) == w);
      assert(PyArray_DIM(arr, 2) == 4); // rgbu
      assert(PyArray_TYPE(arr) == NPY_UINT8);
      assert(PyArray_STRIDE(arr, 1) == 4);
      assert(PyArray_STRIDE(arr, 2) == 1);

      rows = PyArray_DIM(arr, 0);
      assert(rows > 0);
      y += rows;
      png_bytep p = (png_bytep)PyArray_DATA(arr);
      for (int row=0; row<rows; row++) {
        png_write_row (png_ptr, p);
        p += PyArray_STRIDE(arr, 0);
      }
      Py_DECREF(arr);
    }
    assert(y == h);
    PyObject * obj = PyIter_Next(iterator);
    assert(!obj); // iterator should be finished
    if (PyErr_Occurred()) goto cleanup;
  }

  png_write_end (png_ptr, NULL);

  result = Py_BuildValue("{}");

 cleanup:
  if (iterator) Py_DECREF(iterator);
  if (info_ptr) png_destroy_write_struct(&png_ptr, &info_ptr);
  if (fp) fclose(fp);
  return result;
}
bool PNGImageFileType::write(const Image        *OSG_PNG_ARG(pImage  ), 
                                   std::ostream &OSG_PNG_ARG(os      ),
                             const std::string  &OSG_PNG_ARG(mimetype))
{
#ifdef OSG_WITH_PNG

    png_structp png_ptr;
    png_infop info_ptr;

    if(pImage->getDimension() < 1 || pImage->getDimension() > 2)
    {
        FWARNING(("PNGImageFileType::write: invalid dimension %d!\n",
                  pImage->getDimension()));

        return false;
    }
    
    /* Create and initialize the png_struct with the desired error handler
    * functions.  If you want to use the default stderr and longjump method,
    * you can supply NULL for the last three parameters.  We also check that
    * the library version is compatible with the one used at compile time,
    * in case we are using dynamically linked libraries.  REQUIRED.
     */
    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
                                      0, &errorOutput, &warningOutput);

    if(png_ptr == NULL)
        return false;

    /* Allocate/initialize the image information data.  REQUIRED */
    info_ptr = png_create_info_struct(png_ptr);

    if(info_ptr == NULL)
    {
        png_destroy_write_struct(&png_ptr,  NULL);
        return false;
    }
    
    /* set up the output handlers */
    png_set_write_fn(png_ptr, &os, &osWriteFunc, &osFlushFunc);

    /* This is the hard way */

    /* 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
    */

    Int32 ctype;
    switch(pImage->getPixelFormat())
    {
        case Image::OSG_L_PF:       
            ctype = PNG_COLOR_TYPE_GRAY;        
            break;
            
        case Image::OSG_LA_PF:      
            ctype = PNG_COLOR_TYPE_GRAY_ALPHA;          
            break;
            
#if defined(GL_BGR) || defined(GL_BGR_EXT)
        case Image::OSG_BGR_PF:
#endif
        case Image::OSG_RGB_PF:     
            ctype = PNG_COLOR_TYPE_RGB;                 
            break;
            
#if defined(GL_BGRA) || defined(GL_BGRA_EXT)
        case Image::OSG_BGRA_PF:
#endif
        case Image::OSG_RGBA_PF:    
            ctype = PNG_COLOR_TYPE_RGB_ALPHA;           
            break;
            
        default:
            FWARNING(("PNGImageFileType::write: unknown pixel format %d!\n",
                      pImage->getPixelFormat()));
            png_destroy_write_struct(&png_ptr,  NULL);
            return false;
            
    }
    
    Int32 bit_depth;
    switch(pImage->getDataType()) 
    {
        case Image::OSG_UINT8_IMAGEDATA:
            bit_depth = 8;
            break;
        case Image::OSG_UINT16_IMAGEDATA:
            bit_depth = 16;
            break;
        default:
            FWARNING (("Invalid pixeldepth, cannot store data\n"));
            return false;
    };

    png_set_IHDR(png_ptr, info_ptr, pImage->getWidth(), pImage->getHeight(),
                 bit_depth,ctype,      
                 PNG_INTERLACE_NONE, 
                 PNG_COMPRESSION_TYPE_BASE, 
                 PNG_FILTER_TYPE_BASE);

    // set resolution png supports only meter per pixel,
    // so we do a conversion from dpi with some rounding.
    png_uint_32 res_x = png_uint_32(pImage->getResX());
    png_uint_32 res_y = png_uint_32(pImage->getResY());
    if(pImage->getResUnit() == Image::OSG_RESUNIT_INCH)
    {
        res_x = png_uint_32((pImage->getResX() * 39.37007874f) < 0.0f ?
                            (pImage->getResX() * 39.37007874f) - 0.5f :
                            (pImage->getResX() * 39.37007874f) + 0.5f);
        res_y = png_uint_32((pImage->getResY() * 39.37007874f) < 0.0f ?
                            (pImage->getResY() * 39.37007874f) - 0.5f :
                            (pImage->getResY() * 39.37007874f) + 0.5f);
    }

    png_set_pHYs(png_ptr, info_ptr, res_x, res_y,
                 PNG_RESOLUTION_METER);

#if 0
    /* optional significant bit chunk */
    /* if we are dealing with a grayscale image then */
    sig_bit.gray = true_bit_depth;
    /* otherwise, if we are dealing with a color image then */
    sig_bit.red = true_red_bit_depth;
    sig_bit.green = true_green_bit_depth;
    sig_bit.blue = true_blue_bit_depth;
    /* if the image has an alpha channel then */
    sig_bit.alpha = true_alpha_bit_depth;
    png_set_sBIT(png_ptr, info_ptr, sig_bit);


    /* 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);

    /* Optionally write comments into the image */
    text_ptr[0].key = "Title";
    text_ptr[0].text = "Mona Lisa";
    text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
    text_ptr[1].key = "Author";
    text_ptr[1].text = "Leonardo DaVinci";
    text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
    text_ptr[2].key = "Description";
    text_ptr[2].text = "<long text>";
    text_ptr[2].compression = PNG_TEXT_COMPRESSION_zTXt;
#ifdef PNG_iTXt_SUPPORTED
    text_ptr[0].lang = NULL;
    text_ptr[1].lang = NULL;
    text_ptr[2].lang = NULL;
#endif
    png_set_text(png_ptr, info_ptr, text_ptr, 3);
#endif
    /* other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs, */
    /* note that if sRGB is present the gAMA and cHRM chunks must be ignored
    * on read and must be written in accordance with the sRGB profile */

    /* Write the file header information.  REQUIRED */
    png_write_info(png_ptr, info_ptr);

#if BYTE_ORDER == LITTLE_ENDIAN
    if (bit_depth == 16) 
      png_set_swap(png_ptr);
#endif

#if 0
    /* invert monochrome pixels */
    png_set_invert_mono(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, &sig_bit);

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

    /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into
    * RGB (4 channels -> 3 channels). The second parameter is not used.
    */
    png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);

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

    /* swap bits of 1, 2, 4 bit packed pixel formats */
    png_set_packswap(png_ptr);
#endif

    if(pImage->getPixelFormat() == Image::OSG_BGR_PF ||
       pImage->getPixelFormat() == Image::OSG_BGRA_PF )
    {
        /* flip BGR pixels to RGB */
        png_set_bgr(png_ptr);
        
        /* swap location of alpha bytes from ARGB to RGBA */
        png_set_swap_alpha(png_ptr);
    }
    
    /* The easiest way to write the image (you may have a different memory
     * layout, however, so choose what fits your needs best).  You need to
     * use the first method if you aren't handling interlacing yourself.
     */
    png_bytep *row_pointers = new png_bytep [pImage->getHeight()];
    
    for(Int32 k = 0; k < pImage->getHeight(); k++)
    {
        row_pointers[k] = 
            (const_cast<UInt8 *>(pImage->getData())) + 
            (pImage->getHeight() - 1 - k) * 
            pImage->getWidth() * pImage->getBpp();
    }
    
    /* write out the entire image data in one call */
    png_write_image(png_ptr, row_pointers);

    /* It is REQUIRED to call this to finish writing the rest of the file */
    png_write_end(png_ptr, info_ptr);
    
    /* clean up after the write, and free any memory allocated */
    png_destroy_write_struct(&png_ptr, &info_ptr);

    delete [] row_pointers;

    /* that's it */
    return true;

#else
    SWARNING << getMimeType() 
             << " write is not compiled into the current binary " 
             << endLog;

    return false;
#endif
}
Beispiel #4
0
    template<typename T> void
    encodeImageToPNG (typename std::vector<T>& image_arg,
                      size_t width_arg,
                      size_t height_arg,
                      int image_format_arg,
                      typename std::vector<uint8_t>& pngData_arg,
                      int png_level_arg)
    {
      png_structp png_ptr;
      png_infop info_ptr;
      volatile int channels;

      if (image_arg.size () ==0)
        return;

      // Get amount of channels
      switch (image_format_arg)
       {
         case PNG_COLOR_TYPE_GRAY:
           channels = 1;
           break;
         case PNG_COLOR_TYPE_GRAY_ALPHA:
           channels = 2;
           break;
         case PNG_COLOR_TYPE_RGB:
           channels = 3;
           break;
         case PNG_COLOR_TYPE_RGB_ALPHA:
           channels = 4;
           break;
         default:
           channels = 0;
           break;
       }

      // Ensure valid input array
      assert (image_arg.size () == width_arg*height_arg*channels);

      // Initialize write structure
      png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, 0, 0, 0);
      assert (png_ptr && "creating png_create_write_structpng_create_write_struct failed");

      // Initialize info structure
      info_ptr = png_create_info_struct (png_ptr);
      assert (info_ptr && "Could not allocate info struct");

      // Setup Exception handling
      setjmp(png_jmpbuf(png_ptr));

      // reserve memory for output data (300kB)
      pngData_arg.clear ();
      pngData_arg.reserve (300 * 1024);

      // Define I/O methods
      png_set_write_fn (png_ptr, reinterpret_cast<void*> (&pngData_arg), 
                        user_write_data, user_flush_data);

      // Define zlib compression level
      if (png_level_arg >= 0)
      {
        png_set_compression_level (png_ptr, png_level_arg);
      }
      else
      {
        png_set_compression_level (png_ptr, Z_DEFAULT_COMPRESSION);
      }

      // Write header
      png_set_IHDR (png_ptr, info_ptr, width_arg, height_arg, sizeof(T) * 8,
          image_format_arg, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
          PNG_FILTER_TYPE_DEFAULT);

      png_write_info (png_ptr, info_ptr);

      // Write image data
      size_t y;
      for (y = 0; y < height_arg; y++)
      {
        png_write_row (png_ptr, reinterpret_cast<png_bytep> (&image_arg[y * width_arg * channels]));
      }

      // End write
      png_write_end (png_ptr, 0);

      if (info_ptr)
        png_free_data (png_ptr, info_ptr, PNG_FREE_ALL, -1);
      if (png_ptr)
        png_destroy_write_struct (&png_ptr, 0);
    }
Beispiel #5
0
void CAPTURE_AddImage(Bitu width, Bitu height, Bitu bpp, Bitu pitch, Bitu flags, float fps, Bit8u * data, Bit8u * pal) {
#if (C_SSHOT)
	Bitu i;
	Bit8u doubleRow[SCALER_MAXWIDTH*4];
	Bitu countWidth = width;

	if (flags & CAPTURE_FLAG_DBLH)
		height *= 2;
	if (flags & CAPTURE_FLAG_DBLW)
		width *= 2;

	if (height > SCALER_MAXHEIGHT)
		return;
	if (width > SCALER_MAXWIDTH)
		return;
	
	if (CaptureState & CAPTURE_IMAGE) {
		png_structp png_ptr;
		png_infop info_ptr;
		png_color palette[256];

		CaptureState &= ~CAPTURE_IMAGE;
		/* Open the actual file */
		FILE * fp=OpenCaptureFile("Screenshot",".png");
		if (!fp) goto skip_shot;
		/* First try to allocate the png structures */
		png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,NULL, NULL);
		if (!png_ptr) goto skip_shot;
		info_ptr = png_create_info_struct(png_ptr);
		if (!info_ptr) {
			png_destroy_write_struct(&png_ptr,(png_infopp)NULL);
			goto skip_shot;
		}
	
		/* Finalize the initing of png library */
		png_init_io(png_ptr, fp);
		png_set_compression_level(png_ptr,Z_BEST_COMPRESSION);
		
		/* set other zlib parameters */
		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);
		png_set_compression_buffer_size(png_ptr, 8192);
	
		if (bpp==8) {
			png_set_IHDR(png_ptr, info_ptr, width, height,
				8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
				PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
			for (i=0;i<256;i++) {
				palette[i].red=pal[i*4+0];
				palette[i].green=pal[i*4+1];
				palette[i].blue=pal[i*4+2];
			}
			png_set_PLTE(png_ptr, info_ptr, palette,256);
		} else {
			png_set_bgr( png_ptr );
			png_set_IHDR(png_ptr, info_ptr, width, height,
				8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
				PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
		}
#ifdef PNG_TEXT_SUPPORTED
		int fields = 1;
		png_text text[1];
		const char* text_s = "DOSBox " VERSION;
		size_t strl = strlen(text_s);
		char* ptext_s = new char[strl + 1];
		strcpy(ptext_s, text_s);
		char software[9] = { 'S','o','f','t','w','a','r','e',0};
		text[0].compression = PNG_TEXT_COMPRESSION_NONE;
		text[0].key  = software;
		text[0].text = ptext_s;
		png_set_text(png_ptr, info_ptr, text, fields);
#endif
		png_write_info(png_ptr, info_ptr);
#ifdef PNG_TEXT_SUPPORTED
		delete [] ptext_s;
#endif
		for (i=0;i<height;i++) {
			void *rowPointer;
			void *srcLine;
			if (flags & CAPTURE_FLAG_DBLH)
				srcLine=(data+(i >> 1)*pitch);
			else
				srcLine=(data+(i >> 0)*pitch);
			rowPointer=srcLine;
			switch (bpp) {
			case 8:
				if (flags & CAPTURE_FLAG_DBLW) {
   					for (Bitu x=0;x<countWidth;x++)
						doubleRow[x*2+0] =
						doubleRow[x*2+1] = ((Bit8u *)srcLine)[x];
					rowPointer = doubleRow;
				}
				break;
			case 15:
				if (flags & CAPTURE_FLAG_DBLW) {
					for (Bitu x=0;x<countWidth;x++) {
						Bitu pixel = ((Bit16u *)srcLine)[x];
						doubleRow[x*6+0] = doubleRow[x*6+3] = ((pixel& 0x001f) * 0x21) >>  2;
						doubleRow[x*6+1] = doubleRow[x*6+4] = ((pixel& 0x03e0) * 0x21) >>  7;
						doubleRow[x*6+2] = doubleRow[x*6+5] = ((pixel& 0x7c00) * 0x21) >>  12;
					}
				} else {
					for (Bitu x=0;x<countWidth;x++) {
						Bitu pixel = ((Bit16u *)srcLine)[x];
						doubleRow[x*3+0] = ((pixel& 0x001f) * 0x21) >>  2;
						doubleRow[x*3+1] = ((pixel& 0x03e0) * 0x21) >>  7;
						doubleRow[x*3+2] = ((pixel& 0x7c00) * 0x21) >>  12;
					}
				}
				rowPointer = doubleRow;
				break;
			case 16:
				if (flags & CAPTURE_FLAG_DBLW) {
					for (Bitu x=0;x<countWidth;x++) {
						Bitu pixel = ((Bit16u *)srcLine)[x];
						doubleRow[x*6+0] = doubleRow[x*6+3] = ((pixel& 0x001f) * 0x21) >> 2;
						doubleRow[x*6+1] = doubleRow[x*6+4] = ((pixel& 0x07e0) * 0x41) >> 9;
						doubleRow[x*6+2] = doubleRow[x*6+5] = ((pixel& 0xf800) * 0x21) >> 13;
					}
				} else {
					for (Bitu x=0;x<countWidth;x++) {
Beispiel #6
0
static DVector<uint8_t> _lossless_pack_png(const Image& p_image) {


	Image img = p_image;
	if (img.get_format() > Image::FORMAT_INDEXED_ALPHA)
		img.decompress();


	ERR_FAIL_COND_V(img.get_format() > Image::FORMAT_INDEXED_ALPHA, DVector<uint8_t>());

	png_structp png_ptr;
	png_infop info_ptr;
	png_bytep * row_pointers;


	/* initialize stuff */
	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

	ERR_FAIL_COND_V(!png_ptr,DVector<uint8_t>());

	info_ptr = png_create_info_struct(png_ptr);

	ERR_FAIL_COND_V(!info_ptr,DVector<uint8_t>());

	if (setjmp(png_jmpbuf(png_ptr))) {
		ERR_FAIL_V(DVector<uint8_t>());
	}
	DVector<uint8_t> ret;
	ret.push_back('P');
	ret.push_back('N');
	ret.push_back('G');
	ret.push_back(' ');

	png_set_write_fn(png_ptr,&ret,_write_png_data,NULL);

	/* write header */
	if (setjmp(png_jmpbuf(png_ptr))) {
		ERR_FAIL_V(DVector<uint8_t>());
	}

	int pngf=0;
	int pngb=8;
	int cs=0;

	switch(img.get_format()) {

		case Image::FORMAT_GRAYSCALE: {

			pngf=PNG_COLOR_TYPE_GRAY;
			cs=1;
		} break;
		case Image::FORMAT_GRAYSCALE_ALPHA: {

			pngf=PNG_COLOR_TYPE_GRAY_ALPHA;
			cs=2;
		} break;
		case Image::FORMAT_RGB: {

			pngf=PNG_COLOR_TYPE_RGB;
			cs=3;
		} break;
		case Image::FORMAT_RGBA: {

			pngf=PNG_COLOR_TYPE_RGB_ALPHA;
			cs=4;
		} break;
		default: {

			if (img.detect_alpha()) {

				img.convert(Image::FORMAT_RGBA);
				pngf=PNG_COLOR_TYPE_RGB_ALPHA;
				cs=4;
			} else {

				img.convert(Image::FORMAT_RGB);
				pngf=PNG_COLOR_TYPE_RGB;
				cs=3;
			}

		}
	}

	int w = img.get_width();
	int h = img.get_height();
	png_set_IHDR(png_ptr, info_ptr, w,h,
		     8, pngf, PNG_INTERLACE_NONE,
		     PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

	png_write_info(png_ptr, info_ptr);


	/* write bytes */
	if (setjmp(png_jmpbuf(png_ptr))) {
		ERR_FAIL_V(DVector<uint8_t>());
	}


	DVector<uint8_t>::Read r = img.get_data().read();

	row_pointers = (png_bytep*)memalloc(sizeof(png_bytep)*h);
	for(int i=0;i<h;i++) {

		row_pointers[i]=(png_bytep)&r[i*w*cs];
	}
	png_write_image(png_ptr, row_pointers);

	memfree(row_pointers);

	/* end write */
	if (setjmp(png_jmpbuf(png_ptr))) {

		ERR_FAIL_V(DVector<uint8_t>());
	}

	png_write_end(png_ptr, NULL);


	return ret;
}
Beispiel #7
0
static int save_png(SDL_Surface* surface, char *path)
{
  int w = surface->w;
  int h = surface->h;
  unsigned char * pix = (unsigned char *)surface->pixels;
  unsigned char writeBuffer[1024 * 3];
  FILE *f  = fopen(path,"wb");
  if(!f) return 0;
  png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
                                                NULL,
                                                NULL,
                                                NULL);
  if(!png_ptr) {
    fclose(f);
    return 0;
  }

  png_infop info_ptr = png_create_info_struct(png_ptr);

  if(!info_ptr) {
    png_destroy_write_struct(&png_ptr,NULL);
    fclose(f);
    return 0;
  }

  png_init_io(png_ptr,f);

  png_set_IHDR(png_ptr,
               info_ptr,
               w,
               h,
               8,
               PNG_COLOR_TYPE_RGB,
               PNG_INTERLACE_NONE,
               PNG_COMPRESSION_TYPE_DEFAULT,
               PNG_FILTER_TYPE_DEFAULT);

  png_write_info(png_ptr,info_ptr);

  unsigned char *b = writeBuffer;

  int sizeX = w;
  int sizeY = h;
  int y;
  int x;

  unsigned short *p = (unsigned short *)pix;
  for(y = 0; y < sizeY; y++) 
  {
     for(x = 0; x < sizeX; x++) 
     {
       unsigned short v = p[x];
  
       *b++ = ((v & systemRedMask  ) >> systemRedShift  ) << 3; // R
       *b++ = ((v & systemGreenMask) >> systemGreenShift) << 2; // G 
       *b++ = ((v & systemBlueMask ) >> systemBlueShift ) << 3; // B
     }
     p += surface->pitch / 2;
     png_write_row(png_ptr,writeBuffer);
     b = writeBuffer;
  }

  png_write_end(png_ptr, info_ptr);

  png_destroy_write_struct(&png_ptr, &info_ptr);

  fclose(f);
  return 1;
}
Beispiel #8
0
int convertToPNG(AbstractFile* imageWrapper, const unsigned int* key, const unsigned int* iv, const char* png) {
	AbstractFile* imageFile;

	FILE *fp = fopen(png, "wb");
	if(!fp)
		return -1;

	if(key != NULL) {
		imageFile = openAbstractFile2(imageWrapper, key, iv);
	} else {	
		imageFile = openAbstractFile(imageWrapper);
	}
	InfoIBootIM* info = (InfoIBootIM*) (imageFile->data);

	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, pngError, pngWarn);
	if (!png_ptr) {
		return -1;
	}

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

	png_init_io(png_ptr, fp);

	int color_type;
	int bytes_per_pixel;

	if(info->header.format == IBOOTIM_ARGB) {
		XLOG(3, "ARGB");
		color_type = PNG_COLOR_TYPE_RGB_ALPHA;
		bytes_per_pixel = 4;
	} else if(info->header.format == IBOOTIM_GREY) {
		XLOG(3, "Grayscale");
		color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
		bytes_per_pixel = 2;
	} else {
		XLOG(3, "Unknown color type!");
	}

	png_set_IHDR(png_ptr, info_ptr, info->header.width, info->header.height,
		     8, color_type, PNG_INTERLACE_NONE,
		     PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

	png_set_bgr(png_ptr);
	png_set_invert_alpha(png_ptr);

	png_write_info(png_ptr, info_ptr);


	void* imageBuffer = malloc(imageFile->getLength(imageFile));
	imageFile->read(imageFile, imageBuffer, imageFile->getLength(imageFile));

	png_bytepp row_pointers = (png_bytepp) malloc(sizeof(png_bytep) * info->header.height);
	int i;
	for(i = 0; i < png_get_image_height(png_ptr, info_ptr); i++) {
		row_pointers[i] = imageBuffer + (info->header.width * bytes_per_pixel * i);
	}

	png_write_image(png_ptr, row_pointers);

	png_write_end(png_ptr, NULL);

	free(imageBuffer);

	return 0;
}
Beispiel #9
0
void SavePNG(const char *name, const byte * pic, int width, int height, int numBytes, qboolean flip)
{
	png_structp     png;
	png_infop       info;
	int             i;
	int             row_stride;
	byte           *buffer;
	byte           *row;
	png_bytep      *row_pointers;

	png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

	if(!png)
		return;

	// Allocate/initialize the image information data
	info = png_create_info_struct(png);
	if(!info)
	{
		png_destroy_write_struct(&png, (png_infopp) NULL);
		return;
	}

	png_compressed_size = 0;
	buffer = ri.Hunk_AllocateTempMemory(width * height * numBytes);

	// set error handling
	if(setjmp(png_jmpbuf(png)))
	{
		ri.Hunk_FreeTempMemory(buffer);
		png_destroy_write_struct(&png, &info);
		return;
	}

	png_set_write_fn(png, buffer, png_write_data, png_flush_data);

	switch ( numBytes )
	{
	default:
		png_set_IHDR(png, info, width, height, 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
				 PNG_FILTER_TYPE_DEFAULT);
		break;
	case 3:
		png_set_IHDR(png, info, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
				PNG_FILTER_TYPE_DEFAULT);
		break;
	case 2:
		png_set_IHDR( png, info, width, height, 8, PNG_COLOR_TYPE_GA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
		              PNG_FILTER_TYPE_DEFAULT );
		break;
	case 1:
		png_set_IHDR( png, info, width, height, 8, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
		              PNG_FILTER_TYPE_DEFAULT );
		break;
	}

	// write the file header information
	png_write_info(png, info);

	row_pointers = ri.Hunk_AllocateTempMemory(height * sizeof(png_bytep));

	if(setjmp(png_jmpbuf(png)))
	{
		ri.Hunk_FreeTempMemory(row_pointers);
		ri.Hunk_FreeTempMemory(buffer);
		png_destroy_write_struct(&png, &info);
		return;
	}

	row_stride = width * numBytes;
	row = (byte *)pic + (height - 1) * row_stride;

	if(flip)
	{
		for(i = height - 1; i >= 0; i--)
		{
			row_pointers[i] = row;
			row -= row_stride;
		}
	}
	else
	{
		for(i = 0; i < height; i++)
		{
			row_pointers[i] = row;
			row -= row_stride;
		}
	}

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

	// clean up after the write, and free any memory allocated
	png_destroy_write_struct(&png, &info);

	ri.Hunk_FreeTempMemory(row_pointers);

	ri.FS_WriteFile(name, buffer, png_compressed_size);

	ri.Hunk_FreeTempMemory(buffer);
}
Beispiel #10
0
/**************************************************************************
  Save given buffer type to file.
**************************************************************************/
bool savePngInternal(const char *filename, unsigned char *pixels, int w, int h, int bitdepth, int color_type)
{
	png_structp pngp;
	png_infop infop;
	int y;
	FILE *fp;
	png_bytep *row_pointers;
	int const bytes = bitdepth / 8;

	if (filename == NULL || *filename == '\0' || pixels == NULL)
	{
		return false;
	}
	if (!(fp = fopen(filename, "wb")))
	{
		debug(LOG_ERROR, "%s won't open for writing!", filename);
		return false;
	}
	pngp = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (!pngp)
	{
		debug(LOG_ERROR, "fgl_save_pixmap: Failed to create PNG write struct");
		fclose(fp);
		return false;
	}

	infop = png_create_info_struct(pngp);
	if (!infop)
	{
		debug(LOG_ERROR, "fgl_save_pixmap: Failed to create PNG info struct");
		fclose(fp);
		png_destroy_write_struct(&pngp, NULL);
		return false;
	}

	if (setjmp(png_jmpbuf(pngp)))
	{
		debug(LOG_ERROR, "fgl_save_pixmap: Failed to initialize IO during PNG save");
		fclose(fp);
		png_destroy_write_struct(&pngp, NULL);
		return false;
	}
	png_init_io(pngp, fp);

	/* write header */
	if (setjmp(png_jmpbuf(pngp)))
	{
		debug(LOG_ERROR, "fgl_save_pixmap: Failed to write PNG header");
		fclose(fp);
		png_destroy_write_struct(&pngp, NULL);
		return false;
	}
	png_set_IHDR(pngp, infop, w, h, bitdepth, color_type,
	             PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
	             PNG_FILTER_TYPE_BASE);
	png_write_info(pngp, infop);

	/* Create pointers to each row of the data, as libpng wants it */
	row_pointers = malloc(sizeof(png_bytep) * h);
	for (y = 0; y < h; y++)
	{
		row_pointers[y] = pixels + (y * w * bytes);
	}

	if (setjmp(png_jmpbuf(pngp)))
	{
		debug(LOG_ERROR, "fgl_save_pixmap: Failed to write PNG body");
		fclose(fp);
		png_destroy_write_struct(&pngp, NULL);
		return false;
	}
	png_write_image(pngp, row_pointers);

	if (setjmp(png_jmpbuf(pngp)))
	{
		debug(LOG_ERROR, "fgl_save_pixmap: Failed to finalize PNG");
		fclose(fp);
		png_destroy_write_struct(&pngp, NULL);
		return false;
	}
	png_write_end(pngp, NULL);

	free(row_pointers);
	fclose(fp);
	png_destroy_write_struct(&pngp, NULL);

	return true;
}
Beispiel #11
0
int write_PNG(char *filename, int interlace, char borfb)
{
    //hardcore theft from fbgrab.c
	/*
	 * fbgrab - takes screenshots using the framebuffer.
	 *
	 * (C) Gunnar Monell <gmo@linux.nu> 2002
	 *
	 * This program is free Software, see the COPYING file
	 * and is based on Stephan Beyer's <fbshot@s-beyer.de> FBShot
	 * (C) 2000.
	 *
	 * For features and differences, read the manual page. 
	 *
	 * This program has been checked with "splint +posixlib" without
	 * warnings. Splint is available from http://www.splint.org/ .
	 * Patches and enhancements of fbgrab have to fulfill this too.
	 */

    png_uint_32 i;
    int bit_depth=0, color_type;
    png_uint_32 uheight, uwidth;

    uheight = (png_uint_32)height;
    uwidth = (png_uint_32)width;

    png_bytep row_pointers[uheight];
    png_structp png_ptr;
    png_infop info_ptr;
    FILE *outfile = fopen(filename, "wb");

    interlace = PNG_INTERLACE_NONE;    

    //printf ("%d, %d\n", uheight, uwidth);

    //well, either from the buffer or the framebuffer...
    //yih, gotta clean this one up, reallyyyyy
    //
    if (borfb == 0)
        for (i=0; i<uheight; i++)
	        row_pointers[i] = (unsigned char *)(fbp + (BPP*Ox) + (Oy + i) * 1 * (finfo.line_length/*uwidth+10*/));
    if (borfb == 1)
        for (i=0; i<uheight; i++)
	        row_pointers[i] = (unsigned char *)(tmp_buf + (BPP*Ox) + (Oy + i) * 1 * (finfo.line_length/*uwidth+10*/));
 
    if (!outfile){ 
	    fprintf (stderr, "Error: Couldn't fopen %s.\n", filename);
	    return -1;
    }
    
    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
        (png_voidp) NULL, (png_error_ptr) NULL, (png_error_ptr) NULL);
    
    if (!png_ptr){
	    fprintf(stderr,"Error: Couldn't create PNG write struct.");
        return -1;
    }

    info_ptr = png_create_info_struct(png_ptr);

    if (!info_ptr){
	    png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
	    fprintf(stderr, "Error: Couldn't create PNG info struct.");
        return -1;
    }
    if (setjmp(png_jmpbuf(png_ptr))){
        fclose(outfile);
        png_destroy_write_struct(&png_ptr, &info_ptr);
        return -2;
    }
 
    png_init_io(png_ptr, outfile);
    
    //png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
    
    bit_depth = 8;
    color_type = PNG_COLOR_TYPE_RGB_ALPHA;
    
    png_set_IHDR(png_ptr, info_ptr, uwidth, uheight, 
		 bit_depth, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, 
		 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

    //png_set_packing(png_ptr);
    png_set_invert_alpha(png_ptr);
    //
    //png_set function must be after set_IHDR
    //according to libpng-manual
    png_set_filter(png_ptr, 0, PNG_FILTER_NONE);
    png_set_filler(png_ptr, 0 , PNG_FILLER_BEFORE);
    png_set_bgr(png_ptr);
    
    png_write_info(png_ptr, info_ptr);
    
    //printf ("Now writing PNG file\n");
    png_write_image(png_ptr, row_pointers);
    //png_write_rows(png_ptr, row_pointers, uheight);
    png_write_end(png_ptr, info_ptr);
    //puh, done, now freeing memory... 
    png_destroy_write_struct(&png_ptr, &info_ptr);
    
    if (outfile != NULL)
	    (void) fclose(outfile);
    //printf("Done writing...\n");
    return 0;
}
Beispiel #12
0
bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image, volatile int quality_in, const QString &description,
                                 int off_x_in, int off_y_in)
{
    QPoint offset = image.offset();
    int off_x = off_x_in + offset.x();
    int off_y = off_y_in + offset.y();

    png_structp png_ptr;
    png_infop info_ptr;

    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,0,0,0);
    if (!png_ptr) {
        return false;
    }

    png_set_error_fn(png_ptr, 0, 0, qt_png_warning);

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

    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_write_struct(&png_ptr, &info_ptr);
        return false;
    }

    int quality = quality_in;
    if (quality >= 0) {
        if (quality > 9) {
            qWarning("PNG: Quality %d out of range", quality);
            quality = 9;
        }
        png_set_compression_level(png_ptr, quality);
    }

    png_set_write_fn(png_ptr, (void*)this, qpiw_write_fn, qpiw_flush_fn);


    int color_type = 0;
    if (image.colorCount()) {
        if (image.isGrayscale())
            color_type = PNG_COLOR_TYPE_GRAY;
        else
            color_type = PNG_COLOR_TYPE_PALETTE;
    }
    else if (image.format() == QImage::Format_Grayscale8)
        color_type = PNG_COLOR_TYPE_GRAY;
    else if (image.hasAlphaChannel())
        color_type = PNG_COLOR_TYPE_RGB_ALPHA;
    else
        color_type = PNG_COLOR_TYPE_RGB;

    png_set_IHDR(png_ptr, info_ptr, image.width(), image.height(),
                 image.depth() == 1 ? 1 : 8, // per channel
                 color_type, 0, 0, 0);       // sets #channels

    if (gamma != 0.0) {
        png_set_gAMA(png_ptr, info_ptr, 1.0/gamma);
    }

    if (image.format() == QImage::Format_MonoLSB)
       png_set_packswap(png_ptr);

    if (color_type == PNG_COLOR_TYPE_PALETTE) {
        // Paletted
        int num_palette = qMin(256, image.colorCount());
        png_color palette[256];
        png_byte trans[256];
        int num_trans = 0;
        for (int i=0; i<num_palette; i++) {
            QRgb rgba=image.color(i);
            palette[i].red = qRed(rgba);
            palette[i].green = qGreen(rgba);
            palette[i].blue = qBlue(rgba);
            trans[i] = qAlpha(rgba);
            if (trans[i] < 255) {
                num_trans = i+1;
            }
        }
        png_set_PLTE(png_ptr, info_ptr, palette, num_palette);

        if (num_trans) {
            png_set_tRNS(png_ptr, info_ptr, trans, num_trans, 0);
        }
    }

    // Swap ARGB to RGBA (normal PNG format) before saving on
    // BigEndian machines
    if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
        png_set_swap_alpha(png_ptr);
    }

    // Qt==ARGB==Big(ARGB)==Little(BGRA). But RGB888 is RGB regardless
    if (QSysInfo::ByteOrder == QSysInfo::LittleEndian
        && image.format() != QImage::Format_RGB888) {
        png_set_bgr(png_ptr);
    }

    if (off_x || off_y) {
        png_set_oFFs(png_ptr, info_ptr, off_x, off_y, PNG_OFFSET_PIXEL);
    }

    if (frames_written > 0)
        png_set_sig_bytes(png_ptr, 8);

    if (image.dotsPerMeterX() > 0 || image.dotsPerMeterY() > 0) {
        png_set_pHYs(png_ptr, info_ptr,
                image.dotsPerMeterX(), image.dotsPerMeterY(),
                PNG_RESOLUTION_METER);
    }

    set_text(image, png_ptr, info_ptr, description);

    png_write_info(png_ptr, info_ptr);

    if (image.depth() != 1)
        png_set_packing(png_ptr);

    if (color_type == PNG_COLOR_TYPE_RGB && image.format() != QImage::Format_RGB888)
        png_set_filler(png_ptr, 0,
            QSysInfo::ByteOrder == QSysInfo::BigEndian ?
                PNG_FILLER_BEFORE : PNG_FILLER_AFTER);

    if (looping >= 0 && frames_written == 0) {
        uchar data[13] = "NETSCAPE2.0";
        //                0123456789aBC
        data[0xB] = looping%0x100;
        data[0xC] = looping/0x100;
        png_write_chunk(png_ptr, const_cast<png_bytep>((const png_byte *)"gIFx"), data, 13);
    }
    if (ms_delay >= 0 || disposal!=Unspecified) {
        uchar data[4];
        data[0] = disposal;
        data[1] = 0;
        data[2] = (ms_delay/10)/0x100; // hundredths
        data[3] = (ms_delay/10)%0x100;
        png_write_chunk(png_ptr, const_cast<png_bytep>((const png_byte *)"gIFg"), data, 4);
    }

    int height = image.height();
    int width = image.width();
    switch (image.format()) {
    case QImage::Format_Mono:
    case QImage::Format_MonoLSB:
    case QImage::Format_Indexed8:
    case QImage::Format_Grayscale8:
    case QImage::Format_RGB32:
    case QImage::Format_ARGB32:
    case QImage::Format_RGB888:
        {
            png_bytep* row_pointers = new png_bytep[height];
            for (int y=0; y<height; y++)
                row_pointers[y] = const_cast<png_bytep>(image.constScanLine(y));
            png_write_image(png_ptr, row_pointers);
            delete [] row_pointers;
        }
        break;
    default:
        {
            QImage::Format fmt = image.hasAlphaChannel() ? QImage::Format_ARGB32 : QImage::Format_RGB32;
            QImage row;
            png_bytep row_pointers[1];
            for (int y=0; y<height; y++) {
                row = image.copy(0, y, width, 1).convertToFormat(fmt);
                row_pointers[0] = const_cast<png_bytep>(row.constScanLine(0));
                png_write_rows(png_ptr, row_pointers, 1);
            }
        }
        break;
    }

    png_write_end(png_ptr, info_ptr);
    frames_written++;

    png_destroy_write_struct(&png_ptr, &info_ptr);

    return true;
}
Beispiel #13
0
/* Write "bitmap" to a PNG file specified by "path"; returns 0 on
   success, non-zero on error. */
int save_png_to_file(const char *path) {
    FILE *fp;
    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL;
    size_t x, y;


    /* "status" contains the return value of this function. At first
       it is set to a value which means 'failure'. When the routine
       has finished its work, it is set to a value which means
       'success'. */
    int status = -1;

    /* The following number is set by trial and error only. I cannot
       see where it it is documented in the libpng manual.
     */
    int pixel_size = 3;
    int depth = 8;


    /****************************************************************************/
    /****************************************************************************/
    /****************************************************************************/
    /*                para el manejo de errores                                 */
    fp = fopen(path, "wb");
    if (!fp) {
        return status;
    }

    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (png_ptr == NULL) {

        fclose(fp);
        return status;
    }

    info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL) {

        png_destroy_write_struct(&png_ptr, &info_ptr);
        fclose(fp);
        return status;
    }

    /* Set up error handling. */
    if (setjmp(png_jmpbuf(png_ptr))) {

        png_destroy_write_struct(&png_ptr, &info_ptr);
        fclose(fp);
        return status;
    }
    /****************************************************************************/
    /****************************************************************************/
    /****************************************************************************/


    /* Set image attributes. */
    png_set_IHDR(png_ptr,
            info_ptr,

            H_RES, //bitmap->width,
            V_RES, // bitmap->height,
            depth,
            PNG_COLOR_TYPE_RGB,
            PNG_INTERLACE_NONE,
            PNG_COMPRESSION_TYPE_DEFAULT,
            PNG_FILTER_TYPE_DEFAULT);

    /* Initialize rows of PNG. */
    png_byte **row_pointers = NULL;
    row_pointers = png_malloc(png_ptr, V_RES * sizeof (png_byte *));

    //recorro todo el eje vertical(y) para ir obteniendo las filas
    for (y = 0; y < V_RES; y++) {

        //obtener el inverso de la fila
        int y_temp = (V_RES - y) - 1;

        png_byte *row = png_malloc(png_ptr, sizeof (uint8_t) * H_RES * pixel_size);
        row_pointers[y_temp] = row;

        //recorro todos los puntos
        for (x = 0; x < H_RES; x++) {
            //pixel_t * pixel = pixel_at(bitmap, x, y);
            *row++ = (int) (frameBuffer[x][y].r * 255);
            *row++ = (int) (frameBuffer[x][y].g * 255);
            *row++ = (int) (frameBuffer[x][y].b * 255);

        }
    }

    /* Write the image data to "fp". */
    png_init_io(png_ptr, fp);
    png_set_rows(png_ptr, info_ptr, row_pointers);
    png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

    /* The routine has successfully written the file, so we set
       "status" to a value which indicates success. */
    status = 0;
    for (y = 0; y < V_RES; y++) {
        png_free(png_ptr, row_pointers[y]);
    }
    png_free(png_ptr, row_pointers);
}
Beispiel #14
0
int writepng_init(mainprog_info *mainprog_ptr)
{   
  AMJU_CALL_STACK;

    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: */

    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 */

    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 = (char*)"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 = (char*)"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 = (char*)"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 = (char*)"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 = (char*)"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 = (char*)"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;
}
Beispiel #15
0
void Mesh::generateHeightmap(const char* filename)
{
    // Shoot rays down from a point just above the max Y position of the mesh.
    // Compute ray-triangle intersection tests against the ray and this mesh to 
    // generate heightmap data.
    Vector3 rayOrigin(0, bounds.max.y + 10, 0);
    Vector3 rayDirection(0, -1, 0);
    Vector3 intersectionPoint;
    int minX = (int)ceil(bounds.min.x);
    int maxX = (int)floor(bounds.max.x);
    int minZ = (int)ceil(bounds.min.z);
    int maxZ = (int)floor(bounds.max.z);
    int width = maxX - minX + 1;
    int height = maxZ - minZ + 1;
    float* heights = new float[width * height];
    int index = 0;
    float minHeight = FLT_MAX;
    float maxHeight = FLT_MIN;
    for (int z = minZ; z <= maxZ; z++)
    {
        rayOrigin.z = (float)z;
        for (int x = minX; x <= maxX; x++)
        {
            float h;
            rayOrigin.x = (float)x;
            if (intersect(rayOrigin, rayDirection, vertices, parts, &intersectionPoint))
            {
                h = intersectionPoint.y;
            }
            else
            {
                h = 0;
                fprintf(stderr, "Warning: Heightmap triangle intersection failed for (%d, %d).\n", x, z);
            }
            if (h < minHeight)
                minHeight = h;
            if (h > maxHeight)
                maxHeight = h;
            heights[index++] = h;
        }
    }
    
    // Normalize the max height value
    maxHeight = maxHeight - minHeight;

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

    FILE* fp = fopen(filename, "wb");
    if (fp == NULL)
    {
        fprintf(stderr, "Error: Failed to open file for writing: %s\n", filename);
        goto error;
    }

    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (png_ptr == NULL)
    {
        fprintf(stderr, "Error: Write struct creation failed: %s\n", filename);
        goto error;
    }

    info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL)
    {
        fprintf(stderr, "Error: Info struct creation failed: %s\n", filename);
        goto error;
    }

    png_init_io(png_ptr, fp);

    png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

    png_write_info(png_ptr, info_ptr);

    // Allocate memory for a single row of image data
    row = (png_bytep)malloc(3 * width * sizeof(png_byte));

    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
        {
            // Write height value normalized between 0-255 (between min and max height)
            float h = heights[y*width + x];
            float nh = (h - minHeight) / maxHeight;
            png_byte b = (png_byte)(nh * 255.0f);
            
            int pos = x*3;
            row[pos] = row[pos+1] = row[pos+2] = b;
        }
        png_write_row(png_ptr, row);
    }

    png_write_end(png_ptr, NULL);
    DEBUGPRINT_VARG("> Saved heightmap: %s\n", filename);

error:
    if (heights)
        delete[] heights;
    if (fp)
        fclose(fp);
    if (row)
        free(row);
    if (info_ptr)
        png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
    if (png_ptr)
        png_destroy_write_struct(&png_ptr, (png_infopp)NULL);

}
Beispiel #16
0
int enc_png(char *data,g2int width,g2int height,g2int nbits,char *pngbuf)
{
 
    int color_type;
    g2int j,bytes,pnglen,bit_depth;
    png_structp png_ptr;
    png_infop info_ptr;
//    png_bytep *row_pointers[height];
    png_bytep **row_pointers;
    png_stream write_io_ptr;

/* create and initialize png_structs  */

    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, 
                                      NULL, NULL);
    if (!png_ptr)
       return (-1);

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
    {
       png_destroy_write_struct(&png_ptr,(png_infopp)NULL);
       return (-2);
    }

/*     Set Error callback   */

    if (setjmp(png_jmpbuf(png_ptr)))
    {
       png_destroy_write_struct(&png_ptr, &info_ptr);
       return (-3);
    }

/*    Initialize info for writing PNG stream to memory   */

    write_io_ptr.stream_ptr=(png_voidp)pngbuf;
    write_io_ptr.stream_len=0;

/*    Set new custom write functions    */

    png_set_write_fn(png_ptr,(png_voidp)&write_io_ptr,(png_rw_ptr)user_write_data,
                    (png_flush_ptr)user_flush_data);
/*    png_init_io(png_ptr, fptr);   */
/*    png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);  */

/*     Set the image size, colortype, filter type, etc...      */

/*    printf("SAGTsettingIHDR %d %d %d\n",width,height,bit_depth); */
    bit_depth=nbits;
    color_type=PNG_COLOR_TYPE_GRAY;
    if (nbits == 24 ) {
        bit_depth=8;
        color_type=PNG_COLOR_TYPE_RGB;
    }
    else if (nbits == 32 ) {
        bit_depth=8;
        color_type=PNG_COLOR_TYPE_RGB_ALPHA;
    }
    png_set_IHDR(png_ptr, info_ptr, width, height,
       bit_depth, color_type, PNG_INTERLACE_NONE,
       PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

/*     Put image data into the PNG info structure    */

    /*bytes=bit_depth/8;*/
    bytes=nbits/8;
    row_pointers=malloc(height*sizeof(png_bytep));
    for (j=0;j<height;j++) row_pointers[j]=(png_bytep *)(data+(j*width*bytes));
    png_set_rows(png_ptr, info_ptr, (png_bytepp)row_pointers);

/*     Do the PNG encoding, and write out PNG stream  */

    png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

/*     Clean up   */

    png_destroy_write_struct(&png_ptr, &info_ptr);
    free(row_pointers);
    pnglen=write_io_ptr.stream_len;
    return pnglen;

}
Beispiel #17
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
      }
   }
Beispiel #18
0
int icns_image_to_png(icns_image_t *image, icns_size_t *dataSizeOut, icns_byte_t **dataPtrOut)
{
	int 			width = 0;
	int 			height = 0;
	int 			image_channels = 0;
	int			  image_pixel_depth = 0;
	int 			mask_channels = 0;
	png_structp 		png_ptr;
	png_infop 		info_ptr;
	png_bytep 		*row_pointers;
	int			i, j;
	
	if(image == NULL)
	{
		icns_print_err("icns_image_to_png: Image is NULL!\n");
		return ICNS_STATUS_NULL_PARAM;
	}
	
	if(dataSizeOut == NULL)
	{
		icns_print_err("icns_image_to_png: Data size NULL!\n");
		return ICNS_STATUS_NULL_PARAM;
	}
	
	if(dataPtrOut == NULL)
	{
		icns_print_err("icns_image_to_png: Data ref is NULL!\n");
		return ICNS_STATUS_NULL_PARAM;
	}

	if (image->pngFilename) {
		FILE *fp = fopen(image->pngFilename, "rb");
		if (fp) {
			fseek(fp, 0, SEEK_END);
			*dataSizeOut = ftell(fp);
			fseek(fp, 0, SEEK_SET);
			*dataPtrOut = malloc(*dataSizeOut);
			if (fread(*dataPtrOut, 1, *dataSizeOut, fp)) {
				return ICNS_STATUS_OK;
			}
		}
	}

	#ifdef ICNS_DEBUG
	printf("Encoding PNG image...\n");
	#endif
	
	width = image->imageWidth;
	height = image->imageHeight;
	image_channels = image->imageChannels;
	image_pixel_depth = image->imagePixelDepth;
	
	png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	
	if (png_ptr == NULL)
	{
		fprintf (stderr, "PNG error: cannot allocate libpng main struct\n");
		return ICNS_STATUS_NO_MEMORY;
	}

	info_ptr = png_create_info_struct (png_ptr);

	if (info_ptr == NULL)
	{
		fprintf (stderr, "PNG error: cannot allocate libpng info struct\n");
		png_destroy_write_struct (&png_ptr, (png_infopp) NULL);
		return ICNS_STATUS_NO_MEMORY;
	}

  icns_png_io_ref io_data = { NULL, 0, 0 };
	png_set_write_fn(png_ptr, (void *)&io_data, &icns_png_write_memory, NULL);
	
	png_set_filter(png_ptr, 0, PNG_FILTER_NONE);
	
	png_set_IHDR (png_ptr, info_ptr, width, height, image_pixel_depth, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
	
	png_write_info (png_ptr, info_ptr);
	
	if(image_pixel_depth < 8)
		png_set_packing (png_ptr);
	
	row_pointers = (png_bytep*)malloc(sizeof(png_bytep)*height);
	
	if (row_pointers == NULL)
	{
		fprintf (stderr, "PNG error: unable to allocate row_pointers\n");
	}
	else
	{
		for (i = 0; i < height; i++)
		{
			if ((row_pointers[i] = (png_bytep)malloc(width*image_channels)) == NULL)
			{
				fprintf (stderr, "PNG error: unable to allocate rows\n");
				for (j = 0; j < i; j++)
					free(row_pointers[j]);
				free(row_pointers);
				return ICNS_STATUS_NO_MEMORY;
			}
			
			for(j = 0; j < width; j++)
			{
				icns_uint32_t *src_pixel = (icns_uint32_t*)&(image->imageData[i*width*image_channels+j*image_channels]);
				icns_uint32_t *dst_pixel = (icns_uint32_t*)&(row_pointers[i][j*image_channels]);
				*dst_pixel = *src_pixel;
			}
		}
	}
	
	png_write_image (png_ptr,row_pointers);
	
	png_write_end (png_ptr, info_ptr);
	
	*dataSizeOut = io_data.offset;
	*dataPtrOut = io_data.data;
	
	png_destroy_write_struct (&png_ptr, &info_ptr);
	
	for (j = 0; j < height; j++)
		free(row_pointers[j]);
	free(row_pointers);

	return ICNS_STATUS_OK;
}
Beispiel #19
0
int GImageWrite_Png(GImage *gi, FILE *fp, int progressive) {
    struct _GImage *base = gi->list_len==0?gi->u.image:gi->u.images[0];
    png_structp png_ptr;
    png_infop info_ptr;
    png_byte **rows;
    int i;
    int bit_depth;
    int color_type;
    int num_palette;
    png_bytep trans_alpha = NULL;
    png_color_16p trans_color = NULL;
    png_colorp palette = NULL;

   png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
      (void *)NULL, user_error_fn, user_warning_fn);

   if (!png_ptr) {
return(false);
   }

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

#if (PNG_LIBPNG_VER < 10500)
    if (setjmp(png_ptr->jmpbuf))
#else
   if (setjmp(*png_set_longjmp_fn(png_ptr, longjmp, sizeof (jmp_buf))))
#endif
   {
      png_destroy_write_struct(&png_ptr,  (png_infopp)NULL);
return(false);
   }

   png_init_io(png_ptr, fp);

   bit_depth = 8;
   num_palette = base->clut==NULL?2:base->clut->clut_len;
   if ( base->image_type==it_index || base->image_type==it_bitmap ) {
       color_type = PNG_COLOR_TYPE_PALETTE;
       if ( num_palette<=2 )
	   bit_depth=1;
       else if ( num_palette<=4 )
	   bit_depth=2;
       else if ( num_palette<=16 )
	   bit_depth=4;
   } else {
       color_type = PNG_COLOR_TYPE_RGB;
       if ( base->image_type == it_rgba )
	   color_type = PNG_COLOR_TYPE_RGB_ALPHA;
   }

   png_set_IHDR(png_ptr, info_ptr, base->width, base->height,
		bit_depth, color_type, progressive,
		PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
   if ( base->image_type==it_index || base->image_type==it_bitmap ) {
       palette = (png_color *) galloc(num_palette*sizeof(png_color));
       if ( base->clut==NULL ) {
	    palette[0].red = palette[0].green = palette[0].blue = 0;
	    palette[1].red = palette[1].green = palette[1].blue = 0xff;
       } else {
	   for ( i=0; i<num_palette; ++i ) {
		long col = base->clut->clut[i];
		palette[i].red = COLOR_RED(col);
		palette[i].green = COLOR_GREEN(col);
		palette[i].blue = COLOR_BLUE(col);
	   }
       }
       png_set_PLTE(png_ptr, info_ptr, palette, num_palette);
       if ( num_palette<=16 )
	   png_set_packing(png_ptr);

       if ( base->trans!=-1 ) {
	   trans_alpha = (png_bytep) galloc(1);
	   trans_alpha[0] = base->trans;
       }
   } else {
       if ( base->trans!=-1 ) {
	   trans_color = (png_color_16p) galloc(sizeof(png_color_16));
	   trans_color->red = COLOR_RED(base->trans);
	   trans_color->green = COLOR_GREEN(base->trans);
	   trans_color->blue = COLOR_BLUE(base->trans);
       }
   }
   if ( base->trans!=-1 ) {
       png_set_tRNS(png_ptr, info_ptr, trans_alpha, 1, trans_color);
   }
   png_write_info(png_ptr, info_ptr);

    if (color_type == PNG_COLOR_TYPE_RGB)
	png_set_filler(png_ptr, '\0', PNG_FILLER_BEFORE);

    rows = (png_byte **) galloc(base->height*sizeof(png_byte *));
    for ( i=0; i<base->height; ++i )
	rows[i] = (png_byte *) (base->data + i*base->bytes_per_line);

    png_write_image(png_ptr,rows);

    png_write_end(png_ptr, info_ptr);

    if ( trans_alpha!=NULL ) gfree(trans_alpha);
    if ( trans_color!=NULL ) gfree(trans_color);
    if ( palette!=NULL ) gfree(palette);
    png_destroy_write_struct(&png_ptr, &info_ptr);
    gfree(rows);
return( 1 );
}
void take_screenshot(FILE *fb_in, FILE *fb_out) {
    int fb;
    char imgbuf[0x10000];
    struct fb_var_screeninfo vinfo;
    png_structp png;
    png_infop info;
    unsigned int r,c,rowlen;
    unsigned int bytespp,offset;

    fb = fileno(fb_in);
    if(fb < 0) {
        ALOGE("failed to open framebuffer\n");
        return;
    }
    fb_in = fdopen(fb, "r");

    if(ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) < 0) {
        ALOGE("failed to get framebuffer info\n");
        return;
    }
    fcntl(fb, F_SETFD, FD_CLOEXEC);

    png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (png == NULL) {
        ALOGE("failed png_create_write_struct\n");
        fclose(fb_in);
        return;
    }

    png_init_io(png, fb_out);
    info = png_create_info_struct(png);
    if (info == NULL) {
        ALOGE("failed png_create_info_struct\n");
        png_destroy_write_struct(&png, NULL);
        fclose(fb_in);
        return;
    }
    if (setjmp(png_jmpbuf(png))) {
        ALOGE("failed png setjmp\n");
        png_destroy_write_struct(&png, NULL);
        fclose(fb_in);
        return;
    }

    bytespp = vinfo.bits_per_pixel / 8;
    png_set_IHDR(png, info,
        vinfo.xres, vinfo.yres, vinfo.bits_per_pixel / 4, 
        PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
        PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
    png_write_info(png, info);

    rowlen=vinfo.xres * bytespp;
    if (rowlen > sizeof(imgbuf)) {
        ALOGE("crazy rowlen: %d\n", rowlen);
        png_destroy_write_struct(&png, NULL);
        fclose(fb_in);
        return;
    }

    offset = vinfo.xoffset * bytespp + vinfo.xres * vinfo.yoffset * bytespp;
    fseek(fb_in, offset, SEEK_SET);

    for(r=0; r<vinfo.yres; r++) {
        int len = fread(imgbuf, 1, rowlen, fb_in);
        if (len <= 0) break;
        png_write_row(png, (png_bytep)imgbuf);
    }

    png_write_end(png, info);
    fclose(fb_in);
    png_destroy_write_struct(&png, NULL);
}
Beispiel #21
0
int write_png(image_t* img, const char* file_name) {
  size_t x, y;
  png_structp png_ptr;
  png_infop info_ptr;
  png_byte** row_pointers;

  int depth = 8;
  int pixel_size = 3;

  /* init the file and structs */

  FILE* fp = fopen(file_name, "wb");
  if (!fp) {
    return fail(fp, "Failed to open file for writing");
  }

  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (!png_ptr) {
    png_destroy_write_struct(&png_ptr, &info_ptr);
    return fail(fp, "png_create_write_struct failed");
  }

  info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr) {
    png_destroy_write_struct(&png_ptr, &info_ptr);
    return fail(fp, "png_create_info_struct failed");
  }

  /* setup error handling */

  if (setjmp(png_jmpbuf(png_ptr))) {
    png_destroy_write_struct(&png_ptr, &info_ptr);
    return fail(fp, "error");
  }

  /* set image attributes */

  png_set_IHDR(png_ptr,
               info_ptr,
               img->width,
               img->height,
               depth,
               PNG_COLOR_TYPE_RGB,
               PNG_INTERLACE_NONE,
               PNG_COMPRESSION_TYPE_DEFAULT,
               PNG_FILTER_TYPE_DEFAULT);

  /* init rows */

  row_pointers = png_malloc(png_ptr, sizeof(png_byte*) * img->height);
  for (y = 0; y < img->height; ++y) {
    png_byte* row = png_malloc(png_ptr, sizeof(uint8_t) * img->width * pixel_size);
    row_pointers[y] = row;
    for (x = 0; x < img->width; ++x) {
      pixel_t* pixel = pixel_at(img, x, y);
      *row++ = pixel->red;
      *row++ = pixel->green;
      *row++ = pixel->blue;
    }
  }

  /* write data to file */

  png_init_io(png_ptr, fp);
  png_set_rows(png_ptr, info_ptr, row_pointers);
  png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

  /* cleanup */

  for (y = 0; y < img->height; y++) {
    png_free(png_ptr, row_pointers[y]);
  }
  png_free(png_ptr, row_pointers);

  png_destroy_write_struct(&png_ptr, &info_ptr);

  fclose(fp);
  return 0;
}
Beispiel #22
0
int img_save_png( t_image *image)
{
	FILE *fp = fopen( image->id.name, "wb");
	png_structp png_ptr = NULL;
	png_infop info_ptr = NULL;
	png_uint_32 bytes_per_row;
	png_byte **row_pointers = NULL;
	int x, y;

	int bytes_per_pixel;
	int COLOR_TYPE;

	unsigned char *bitmap = image->vlst->data;

	switch( image->color_type)
	{
		case( IMG_RGB):
			if( image->alpha)
			{
				COLOR_TYPE = PNG_COLOR_TYPE_RGBA;
				bytes_per_pixel=4;
			}
			else
			{
				COLOR_TYPE = PNG_COLOR_TYPE_RGB;
				bytes_per_pixel=3;
			}
			break;
		case( IMG_GRAYSCALE):
			if( image->alpha)
			{
				COLOR_TYPE = PNG_COLOR_TYPE_GRAY_ALPHA;
				bytes_per_pixel=2;
			}
			else
			{
				COLOR_TYPE = PNG_COLOR_TYPE_GRAY;
				bytes_per_pixel=1;
			}
			break;
		case( IMG_BITMAP):
			printf("[PNG] Color_type not implemented\n");
			return 0;
			break;
		case IMG_COLOR:
			printf("[PNG] Color_type not set\n");
			return 0;
			break;
			
	}
			
	if (fp == NULL) return -1;

	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

	if (png_ptr == NULL)
	{
		fclose(fp);
		return -1;
	}

	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL)
	{
		png_destroy_write_struct(&png_ptr, NULL);
		fclose(fp);
		return -1;
	}

	if (setjmp(png_jmpbuf(png_ptr)))
	{
		png_destroy_write_struct(&png_ptr, &info_ptr);
		fclose(fp);
		return -1;
	}

	png_set_IHDR(
		png_ptr,			// struct ptr
		info_ptr,			// info ptr
		image->width,				// in px
		image->height,				// in px
		8,				// bit depth aka color depth, bits per color [ 1 | 2 | 4 | 8 | 16 ]
		COLOR_TYPE,			// PNG_COLOR_TYPE_[ GRAY | GRAY_ALPHA | PALETTE | RGB | RGB_ALPHA ] or PNG_COLOR_MASK_[ PALETTE | COLOR | ALPHA ]
		PNG_INTERLACE_NONE,		// or PNG_INTERLACE_ADAM7
		PNG_COMPRESSION_TYPE_DEFAULT,
		PNG_FILTER_TYPE_DEFAULT);

	bytes_per_row = image->width * bytes_per_pixel;
	row_pointers = png_malloc(png_ptr, image->height * sizeof(png_byte *));

	for (y = image->height-1 ; y >= 0 ; --y)
	{
		unsigned char *row = png_malloc(png_ptr, sizeof(unsigned char) * bytes_per_row);
		row_pointers[y] = (png_byte *)row;
		for (x = 0; x < image->width; ++x)
		{
			if( image->alpha)
			{
				*row++=*bitmap++;
				*row++=*bitmap++;
				*row++=*bitmap++;
				*row++=*bitmap++;
			}
			else
			{
				*row++=*bitmap++;
				*row++=*bitmap++;
				*row++=*bitmap++;
			}
		}
	}

	png_init_io(png_ptr, fp);
	png_set_rows(png_ptr, info_ptr, row_pointers);
	png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

	for (y = 0; y < image->height; y++)
	{
		png_free(png_ptr, row_pointers[y]);
	}

	png_free(png_ptr, row_pointers);
	png_destroy_write_struct(&png_ptr, &info_ptr);

	fclose(fp);
	return 0;
}
Beispiel #23
0
void WritePng(char *path, struct Image *image)
{
	FILE *fp = fopen(path, "wb");

	if (fp == NULL)
		FATAL_ERROR("Failed to open \"%s\" for writing.\n", path);

	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

	if (!png_ptr)
		FATAL_ERROR("Failed to create PNG write struct.\n");

	png_infop info_ptr = png_create_info_struct(png_ptr);

	if (!info_ptr)
		FATAL_ERROR("Failed to create PNG info struct.\n");

	if (setjmp(png_jmpbuf(png_ptr)))
		FATAL_ERROR("Failed to init I/O for writing \"%s\".\n", path);

	png_init_io(png_ptr, fp);

	if (setjmp(png_jmpbuf(png_ptr)))
		FATAL_ERROR("Error writing header for \"%s\".\n", path);

	int color_type = image->hasPalette ? PNG_COLOR_TYPE_PALETTE : PNG_COLOR_TYPE_GRAY;

	png_set_IHDR(png_ptr, info_ptr, image->width, image->height,
		image->bitDepth, color_type, PNG_INTERLACE_NONE,
		PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

	if (image->hasPalette) {
		SetPngPalette(png_ptr, info_ptr, &image->palette);

		if (image->hasTransparency) {
			png_byte trans = 0;
			png_set_tRNS(png_ptr, info_ptr, &trans, 1, 0);
		}
	}

	png_write_info(png_ptr, info_ptr);

	png_bytepp row_pointers = malloc(image->height * sizeof(png_bytep));

	if (row_pointers == NULL)
		FATAL_ERROR("Failed to allocate row pointers.\n");

	int rowbytes = png_get_rowbytes(png_ptr, info_ptr);

	for (int i = 0; i < image->height; i++)
		row_pointers[i] = (png_bytep)(image->pixels + (i * rowbytes));

	if (setjmp(png_jmpbuf(png_ptr)))
		FATAL_ERROR("Error writing \"%s\".\n", path);

	png_write_image(png_ptr, row_pointers);

	if (setjmp(png_jmpbuf(png_ptr)))
		FATAL_ERROR("Error ending write of \"%s\".\n", path);

	png_write_end(png_ptr, NULL);

	fclose(fp);

	png_destroy_write_struct(&png_ptr, &info_ptr);
	free(row_pointers);
}
Beispiel #24
0
static inline bool caerFrameEventPNGCompress(uint8_t **outBuffer, size_t *outSize, uint16_t *inBuffer, int32_t xSize,
	int32_t ySize, enum caer_frame_event_color_channels channels) {
	png_structp png_ptr = NULL;
	png_infop info_ptr = NULL;
	png_byte **row_pointers = NULL;

	// Initialize the write struct.
	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (png_ptr == NULL) {
		return (false);
	}

	// Initialize the info struct.
	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL) {
		png_destroy_write_struct(&png_ptr, NULL);
		return (false);
	}

	// Set up error handling.
	if (setjmp(png_jmpbuf(png_ptr))) {
		if (row_pointers != NULL) {
			png_free(png_ptr, row_pointers);
		}
		png_destroy_write_struct(&png_ptr, &info_ptr);
		return (false);
	}

	// Set image attributes.
	png_set_IHDR(png_ptr, info_ptr, (png_uint_32) xSize, (png_uint_32) ySize, 16, caerFrameEventColorToLibPNG(channels),
	PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

	// Handle endianness of 16-bit depth pixels correctly.
	// PNG assumes big-endian, our Frame Event is always little-endian.
	png_set_swap(png_ptr);

	// Initialize rows of PNG.
	row_pointers = png_malloc(png_ptr, (size_t) ySize * sizeof(png_byte *));
	if (row_pointers == NULL) {
		png_destroy_write_struct(&png_ptr, &info_ptr);
		return (false);
	}

	for (size_t y = 0; y < (size_t) ySize; y++) {
		row_pointers[y] = (png_byte *) &inBuffer[y * (size_t) xSize * channels];
	}

	// Set write function to buffer one.
	struct mem_encode state = { .buffer = NULL, .size = 0 };
	png_set_write_fn(png_ptr, &state, &caerLibPNGWriteBuffer, NULL);

	// Actually write the image data.
	png_set_rows(png_ptr, info_ptr, row_pointers);
	png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

	// Free allocated memory for rows.
	png_free(png_ptr, row_pointers);

	// Destroy main structs.
	png_destroy_write_struct(&png_ptr, &info_ptr);

	// Pass out buffer with resulting PNG image.
	*outBuffer = state.buffer;
	*outSize = state.size;

	return (true);
}
#endif

static size_t compressEventPacket(outputCommonState state, caerEventPacketHeader packet, size_t packetSize) {
	// Data compression technique 1: serialize timestamps for event types that tend to repeat them a lot.
	// Currently, this means polarity events.
	if ((state->format & 0x01) && caerEventPacketHeaderGetEventType(packet) == POLARITY_EVENT) {
		// Search for runs of at least 3 events with the same timestamp, and convert them to a special
		// sequence: leave first event unchanged, but mark its timestamp as special by setting the
		// highest bit (bit 31) to one (it is forbidden for timestamps in memory to have that bit set for
		// signed-integer-only language compatibility). Then, for the second event, change its timestamp
		// to a 4-byte integer saying how many more events will follow afterwards with this same timestamp
		// (this is used for decoding), so only their data portion will be given. Then follow with those
		// event's data, back to back, with their timestamps removed.
		// So let's assume there are 6 events with TS=1234. In memory this looks like this:
		// E1(data,ts), E2(data,ts), E3(data,ts), E4(data,ts), E5(data,ts), E6(data,ts)
		// After timestamp serialization compression step:
		// E1(data,ts|0x80000000), E2(data,4), E3(data), E4(data), E5(data), E5(data)
		// This change is only in the data itself, not in the packet headers, so that we can still use the
		// eventCapacity and eventSize fields to calculate memory allocation when doing decompression.
		// As such, to correctly interpret this data, the Format flags must be correctly set. All current
		// file or network formats do specify those as mandatory in their headers, so we can rely on that.
		// Also all event types where this kind of thing makes any sense do have the timestamp as their last
		// data member in their struct, so we can use that information, stored in tsOffset header field,
		// together with eventSize, to come up with a generic implementation applicable to all other event
		// types that satisfy this condition of TS-as-last-member (so we can use that offset as event size).
		// When this is enabled, it requires full iteration thorough the whole event packet, both at
		// compression and at decompression time.
		size_t currPacketOffset = CAER_EVENT_PACKET_HEADER_SIZE; // Start here, no change to header.
		int32_t eventSize = caerEventPacketHeaderGetEventSize(packet);
		int32_t eventTSOffset = caerEventPacketHeaderGetEventTSOffset(packet);

		int32_t lastTS = -1;
		int32_t currTS = -1;
		size_t tsRun = 0;
		bool doMemMove = false; // Initially don't move memory, until we actually shrink the size.

		for (int32_t caerIteratorCounter = 0; caerIteratorCounter <= caerEventPacketHeaderGetEventNumber(packet);
			caerIteratorCounter++) {
			// Iterate until one element past the end, to flush the last run. In that particular case,
			// we don't get a new element or TS, as we'd be past the end of the array.
			if (caerIteratorCounter < caerEventPacketHeaderGetEventNumber(packet)) {
				void *caerIteratorElement = caerGenericEventGetEvent(packet, caerIteratorCounter);

				currTS = caerGenericEventGetTimestamp(caerIteratorElement, packet);
				if (currTS == lastTS) {
					// Increase size of run of same TS events currently being seen.
					tsRun++;
					continue;
				}
			}

			// TS are different, at this point look if the last run was long enough
			// and if it makes sense to compress. It does starting with 3 events.
			if (tsRun >= 3) {
				// First event to remains there, we set its TS highest bit.
				uint8_t *firstEvent = caerGenericEventGetEvent(packet, caerIteratorCounter - (int32_t) tsRun--);
				caerGenericEventSetTimestamp(firstEvent, packet,
					caerGenericEventGetTimestamp(firstEvent, packet) | I32T(0x80000000));

				// Now use second event's timestamp for storing how many further events.
				uint8_t *secondEvent = caerGenericEventGetEvent(packet, caerIteratorCounter - (int32_t) tsRun--);
				caerGenericEventSetTimestamp(secondEvent, packet, I32T(tsRun)); // Is at least 1.

				// Finally move modified memory where it needs to go.
				if (doMemMove) {
					memmove(((uint8_t *) packet) + currPacketOffset, firstEvent, (size_t) eventSize * 2);
				}
				else {
					doMemMove = true; // After first shrink always move memory.
				}
				currPacketOffset += (size_t) eventSize * 2;

				// Now go through remaining events and move their data close together.
				while (tsRun > 0) {
					uint8_t *thirdEvent = caerGenericEventGetEvent(packet, caerIteratorCounter - (int32_t) tsRun--);
					memmove(((uint8_t *) packet) + currPacketOffset, thirdEvent, (size_t) eventTSOffset);
					currPacketOffset += (size_t) eventTSOffset;
				}
			}
			else {
				// Just copy data unchanged if no compression is possible.
				if (doMemMove) {
					uint8_t *startEvent = caerGenericEventGetEvent(packet, caerIteratorCounter - (int32_t) tsRun);
					memmove(((uint8_t *) packet) + currPacketOffset, startEvent, (size_t) eventSize * tsRun);
				}
				currPacketOffset += (size_t) eventSize * tsRun;
			}

			// Reset values for next iteration.
			lastTS = currTS;
			tsRun = 1;
		}

		return (currPacketOffset);
	}

#ifdef ENABLE_INOUT_PNG_COMPRESSION
	// Data compression technique 2: do PNG compression on frames, Grayscale and RGB(A).
	if ((state->format & 0x02) && caerEventPacketHeaderGetEventType(packet) == FRAME_EVENT) {
		size_t currPacketOffset = CAER_EVENT_PACKET_HEADER_SIZE; // Start here, no change to header.
		size_t frameHeaderSize = sizeof(struct caer_frame_event);

		CAER_FRAME_ITERATOR_ALL_START((caerFrameEventPacket) packet)
			size_t pixelSize = caerFrameEventGetPixelsSize(caerFrameIteratorElement);

			// Keep frame event header intact, compress image data, move memory close together.
			memmove(((uint8_t *) packet) + currPacketOffset, caerFrameIteratorElement, frameHeaderSize);
			currPacketOffset += frameHeaderSize;

			uint8_t *outBuffer;
			size_t outSize;
			if (!caerFrameEventPNGCompress(&outBuffer, &outSize,
				caerFrameEventGetPixelArrayUnsafe(caerFrameIteratorElement),
				caerFrameEventGetLengthX(caerFrameIteratorElement), caerFrameEventGetLengthY(caerFrameIteratorElement),
				caerFrameEventGetChannelNumber(caerFrameIteratorElement))) {
				// Failed to generate PNG.
				// Discard this frame event.
				currPacketOffset -= frameHeaderSize;
				continue;
			}

			// Check that the image didn't actually grow.
			// Add integer needed for storing PNG block length.
			if ((outSize + sizeof(int32_t)) > pixelSize) {
				caerLog(CAER_LOG_ERROR, state->parentModule->moduleSubSystemString, "Failed to compress frame event. "
					"Image actually grew by %zu bytes to a total of %zu bytes.", (outSize - pixelSize), outSize);

				free(outBuffer);
				currPacketOffset -= frameHeaderSize;
				continue;
			}

			// Store size of PNG image block as 4 byte integer.
			int32_t outSizeInt = I32T(outSize);
			memcpy(((uint8_t *) packet) + currPacketOffset, &outSizeInt, sizeof(int32_t));
			currPacketOffset += sizeof(int32_t);

			memcpy(((uint8_t *) packet) + currPacketOffset, outBuffer, outSize);
			currPacketOffset += outSize;

			// Free allocated PNG block memory.
			free(outBuffer);
		}

		return (currPacketOffset);
	}
#endif

	return (packetSize);
}
Beispiel #25
0
/*
TextureToPng

Inputs:
data      : This is an array of RGBA with 8 bits per channel. 4 bytes for each pixel.
row_stride: Determines the amount of bytes per row of pixels.
*/
bool TextureToPng(u8* data, int row_stride, const std::string filename, int width, int height, bool saveAlpha)
{
	bool success = false;

	if (!data)
		return false;

	char title[] = "Dolphin Screenshot";
	char title_key[] = "Title";
	png_structp png_ptr = NULL;
	png_infop info_ptr = NULL;

	// Open file for writing (binary mode)
	File::IOFile fp(filename, "wb");
	if (!fp.IsOpen()) {
		PanicAlert("Screenshot failed: Could not open file %s %d\n", filename.c_str(), errno);
		goto finalise;
	}

	// Initialize write structure
	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (png_ptr == NULL) {
		PanicAlert("Screenshot failed: Could not allocate write struct\n");
		goto finalise;

	}

	// Initialize info structure
	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL) {
		PanicAlert("Screenshot failed: Could not allocate info struct\n");
		goto finalise;
	}

	// Setup Exception handling
	if (setjmp(png_jmpbuf(png_ptr))) {
		PanicAlert("Screenshot failed: Error during png creation\n");
		goto finalise;
	}

	png_init_io(png_ptr, fp.GetHandle());

	// Write header (8 bit colour depth)
	png_set_IHDR(png_ptr, info_ptr, width, height,
		8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
		PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

	png_text title_text;
	title_text.compression = PNG_TEXT_COMPRESSION_NONE;
	title_text.key = title_key;
	title_text.text = title;
	png_set_text(png_ptr, info_ptr, &title_text, 1);

	png_write_info(png_ptr, info_ptr);

	// Write image data
	for (auto y = 0; y < height; ++y)
	{
		u8* row_ptr = (u8*)data + y * row_stride;
		u8* ptr = row_ptr;
		for (auto x = 0; x < row_stride / 4; ++x)
		{
			if (!saveAlpha)
				ptr[3] = 0xff;
			ptr += 4;
		}
		png_write_row(png_ptr, row_ptr);
	}

	// End write
	png_write_end(png_ptr, NULL);

	success = true;

finalise:
	if (info_ptr != NULL) png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
	if (png_ptr != NULL) png_destroy_write_struct(&png_ptr, (png_infopp)NULL);

	return success;
}
Beispiel #26
0
/*!
 *  pixWriteStreamPng()
 *
 *      Input:  stream
 *              pix
 *              gamma (use 0.0 if gamma is not defined)
 *      Return: 0 if OK; 1 on error
 *
 *  Notes:
 *      (1) If called from pixWriteStream(), the stream is positioned
 *          at the beginning of the file.
 *      (2) To do sequential writes of png format images to a stream,
 *          use pixWriteStreamPng() directly.
 *      (3) gamma is an optional png chunk.  If no gamma value is to be
 *          placed into the file, use gamma = 0.0.  Otherwise, if
 *          gamma > 0.0, its value is written into the header.
 *      (4) The use of gamma in png is highly problematic.  For an illuminating
 *          discussion, see:  http://hsivonen.iki.fi/png-gamma/
 *      (5) What is the effect/meaning of gamma in the png file?  This
 *          gamma, which we can call the 'source' gamma, is the
 *          inverse of the gamma that was used in enhance.c to brighten
 *          or darken images.  The 'source' gamma is supposed to indicate
 *          the intensity mapping that was done at the time the
 *          image was captured.  Display programs typically apply a
 *          'display' gamma of 2.2 to the output, which is intended
 *          to linearize the intensity based on the response of
 *          thermionic tubes (CRTs).  Flat panel LCDs have typically
 *          been designed to give a similar response as CRTs (call it
 *          "backward compatibility").  The 'display' gamma is
 *          in some sense the inverse of the 'source' gamma.
 *          jpeg encoders attached to scanners and cameras will lighten
 *          the pixels, applying a gamma corresponding to approximately
 *          a square-root relation of output vs input:
 *                output = input^(gamma)
 *          where gamma is often set near 0.4545  (1/gamma is 2.2).
 *          This is stored in the image file.  Then if the display
 *          program reads the gamma, it will apply a display gamma,
 *          typically about 2.2; the product is 1.0, and the
 *          display program produces a linear output.  This works because
 *          the dark colors were appropriately boosted by the scanner,
 *          as described by the 'source' gamma, so they should not
 *          be further boosted by the display program.
 *      (6) As an example, with xv and display, if no gamma is stored,
 *          the program acts as if gamma were 0.4545, multiplies this by 2.2,
 *          and does a linear rendering.  Taking this as a baseline
 *          brightness, if the stored gamma is:
 *              > 0.4545, the image is rendered lighter than baseline
 *              < 0.4545, the image is rendered darker than baseline
 *          In contrast, gqview seems to ignore the gamma chunk in png.
 *      (7) The only valid pixel depths in leptonica are 1, 2, 4, 8, 16
 *          and 32.  However, it is possible, and in some cases desirable,
 *          to write out a png file using an rgb pix that has 24 bpp.
 *          For example, the open source xpdf SplashBitmap class generates
 *          24 bpp rgb images.  Consequently, we anble writing 24 bpp pix.
 *          To generate such a pix, you can make a 24 bpp pix without data
 *          and assign the data array to the pix; e.g.,
 *              pix = pixCreateHeader(w, h, 24);
 *              pixSetData(pix, rgbdata);
 *          See pixConvert32To24() for an example, where we get rgbdata
 *          from the 32 bpp pix.  Caution: do not call pixSetPadBits(),
 *          because the alignment is wrong and you may erase part of the
 *          last pixel on each line.
 */
l_int32
pixWriteStreamPng(FILE      *fp,
                  PIX       *pix,
                  l_float32  gamma)
{
char         commentstring[] = "Comment";
l_int32      i, j, k;
l_int32      wpl, d, cmflag;
l_int32      ncolors;
l_int32     *rmap, *gmap, *bmap;
l_uint32    *data, *ppixel;
png_byte     bit_depth, color_type;
png_uint_32  w, h;
png_uint_32  xres, yres;
png_bytep   *row_pointers;
png_bytep    rowbuffer;
png_structp  png_ptr;
png_infop    info_ptr;
png_colorp   palette;
PIX         *pixt;
PIXCMAP     *cmap;
char        *text;

    PROCNAME("pixWriteStreamPng");

    if (!fp)
        return ERROR_INT("stream not open", procName, 1);
    if (!pix)
        return ERROR_INT("pix not defined", procName, 1);

        /* Allocate the 2 data structures */
    if ((png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
                   (png_voidp)NULL, NULL, NULL)) == NULL)
        return ERROR_INT("png_ptr not made", procName, 1);

    if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) {
        png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
        return ERROR_INT("info_ptr not made", procName, 1);
    }

        /* Set up png setjmp error handling */
    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_write_struct(&png_ptr, &info_ptr);
        return ERROR_INT("internal png error", procName, 1);
    }

    png_init_io(png_ptr, fp);

        /* With best zlib compression (9), get between 1 and 10% improvement
         * over default (5), but the compression is 3 to 10 times slower.
         * Our default compression is the zlib default (5). */
    png_set_compression_level(png_ptr, var_ZLIB_COMPRESSION);

    w = pixGetWidth(pix);
    h = pixGetHeight(pix);
    d = pixGetDepth(pix);
    if ((cmap = pixGetColormap(pix)))
        cmflag = 1;
    else
        cmflag = 0;

        /* Set the color type and bit depth. */
    if (d == 32 && var_PNG_WRITE_ALPHA == 1) {
        bit_depth = 8;
        color_type = PNG_COLOR_TYPE_RGBA;   /* 6 */
        cmflag = 0;  /* ignore if it exists */
    }
    else if (d == 24 || d == 32) {
        bit_depth = 8;
        color_type = PNG_COLOR_TYPE_RGB;   /* 2 */
        cmflag = 0;  /* ignore if it exists */
    }
    else {
        bit_depth = d;
        color_type = PNG_COLOR_TYPE_GRAY;  /* 0 */
    }
    if (cmflag)
        color_type = PNG_COLOR_TYPE_PALETTE;  /* 3 */

#if  DEBUG
    fprintf(stderr, "cmflag = %d, bit_depth = %d, color_type = %d\n",
            cmflag, bit_depth, color_type);
#endif  /* DEBUG */

    png_set_IHDR(png_ptr, info_ptr, w, h, bit_depth, color_type,
                 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
                 PNG_FILTER_TYPE_BASE);

        /* Store resolution in ppm, if known */
    xres = (png_uint_32)(39.37 * (l_float32)pixGetXRes(pix) + 0.5);
    yres = (png_uint_32)(39.37 * (l_float32)pixGetYRes(pix) + 0.5);
    if ((xres == 0) || (yres == 0))
        png_set_pHYs(png_ptr, info_ptr, 0, 0, PNG_RESOLUTION_UNKNOWN);
    else
        png_set_pHYs(png_ptr, info_ptr, xres, yres, PNG_RESOLUTION_METER);

    if (cmflag) {
        pixcmapToArrays(cmap, &rmap, &gmap, &bmap);
        ncolors = pixcmapGetCount(cmap);

            /* Make and save the palette */
        if ((palette = (png_colorp)(CALLOC(ncolors, sizeof(png_color))))
                == NULL)
            return ERROR_INT("palette not made", procName, 1);

        for (i = 0; i < ncolors; i++) {
            palette[i].red = (png_byte)rmap[i];
            palette[i].green = (png_byte)gmap[i];
            palette[i].blue = (png_byte)bmap[i];
        }

        png_set_PLTE(png_ptr, info_ptr, palette, (int)ncolors);
        FREE(rmap);
        FREE(gmap);
        FREE(bmap);
    }

        /* 0.4545 is treated as the default by some image
         * display programs (not gqview).  A value > 0.4545 will
         * lighten an image as displayed by xv, display, etc. */
    if (gamma > 0.0)
        png_set_gAMA(png_ptr, info_ptr, (l_float64)gamma);

    if ((text = pixGetText(pix))) {
        png_text text_chunk;
        text_chunk.compression = PNG_TEXT_COMPRESSION_NONE;
        text_chunk.key = commentstring;
        text_chunk.text = text;
        text_chunk.text_length = strlen(text);
#ifdef PNG_ITXT_SUPPORTED
        text_chunk.itxt_length = 0;
        text_chunk.lang = NULL;
        text_chunk.lang_key = NULL;
#endif
        png_set_text(png_ptr, info_ptr, &text_chunk, 1);
    }

        /* Write header and palette info */
    png_write_info(png_ptr, info_ptr);

    if ((d != 32) && (d != 24)) {  /* not rgb color */
            /* Generate a temporary pix with bytes swapped.
             * For a binary image, there are two conditions in
             * which you must first invert the data for writing png:
             *    (a) no colormap
             *    (b) colormap with BLACK set to 0
             * png writes binary with BLACK = 0, unless contradicted
             * by a colormap.  If the colormap has BLACK = "1"
             * (typ. about 255), do not invert the data.  If there
             * is no colormap, you must invert the data to store
             * in default BLACK = 0 state.  */
        if (d == 1 &&
            (!cmap || (cmap && ((l_uint8 *)(cmap->array))[0] == 0x0))) {
            pixt = pixInvert(NULL, pix);
            pixEndianByteSwap(pixt);
        }
        else
            pixt = pixEndianByteSwapNew(pix);
        if (!pixt) {
            png_destroy_write_struct(&png_ptr, &info_ptr);
            return ERROR_INT("pixt not made", procName, 1);
        }

            /* Make and assign array of image row pointers */
        if ((row_pointers = (png_bytep *)CALLOC(h, sizeof(png_bytep))) == NULL)
            return ERROR_INT("row-pointers not made", procName, 1);
        wpl = pixGetWpl(pixt);
        data = pixGetData(pixt);
        for (i = 0; i < h; i++)
            row_pointers[i] = (png_bytep)(data + i * wpl);
        png_set_rows(png_ptr, info_ptr, row_pointers);

            /* Transfer the data */
        png_write_image(png_ptr, row_pointers);
        png_write_end(png_ptr, info_ptr);

        if (cmflag)
            FREE(palette);
        FREE(row_pointers);
        pixDestroy(&pixt);
        png_destroy_write_struct(&png_ptr, &info_ptr);
        return 0;
    }

        /* For rgb, compose and write a row at a time */
    data = pixGetData(pix);
    wpl = pixGetWpl(pix);
    if (d == 24) {  /* See note 7 above: special case of 24 bpp rgb */
        for (i = 0; i < h; i++) {
            ppixel = data + i * wpl;
            png_write_rows(png_ptr, (png_bytepp)&ppixel, 1);
        }
    }
    else {  /* 32 bpp rgb and rgba */
        if ((rowbuffer = (png_bytep)CALLOC(w, 4)) == NULL)
            return ERROR_INT("rowbuffer not made", procName, 1);
        for (i = 0; i < h; i++) {
            ppixel = data + i * wpl;
            for (j = k = 0; j < w; j++) {
                rowbuffer[k++] = GET_DATA_BYTE(ppixel, COLOR_RED);
                rowbuffer[k++] = GET_DATA_BYTE(ppixel, COLOR_GREEN);
                rowbuffer[k++] = GET_DATA_BYTE(ppixel, COLOR_BLUE);
                if (var_PNG_WRITE_ALPHA == 1)
                    rowbuffer[k++] = GET_DATA_BYTE(ppixel, L_ALPHA_CHANNEL);
                ppixel++;
            }

            png_write_rows(png_ptr, &rowbuffer, 1);
        }
        FREE(rowbuffer);
    }

    png_write_end(png_ptr, info_ptr);

    if (cmflag)
        FREE(palette);
    png_destroy_write_struct(&png_ptr, &info_ptr);
    return 0;

}
Beispiel #27
0
void
write_png( ImgGray *img, const char *filename )
{
    int width = img->Width();
    int height = img->Height();
    int bit_depth = 8;
    int color_type = PNG_COLOR_TYPE_GRAY; // to be changed to the correct value!

    /* create file */
    FILE *fp = fopen(filename, "wb");
    if (!fp) {
        dbg(DBG_ERROR,"[write_png_file] File %s could not be opened for writing", filename);
        return;
    }
    
    /* initialize stuff */
    png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    
    if (!png_ptr) {
        dbg(DBG_ERROR,"[write_png_file] png_create_write_struct failed");
        return;
    }

    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        dbg(DBG_ERROR,"[write_png_file] png_create_info_struct failed");
        return;
    }

    if (setjmp(png_jmpbuf(png_ptr)))
        dbg(DBG_ERROR,"[write_png_file] Error during init_io");
    
    png_init_io(png_ptr, fp);
    
    /* write header */
    
    if (setjmp(png_jmpbuf(png_ptr)))
        dbg(DBG_ERROR,"[write_png_file] Error during writing header");
    
    png_set_IHDR(png_ptr, info_ptr, width, height,
                 bit_depth, color_type, PNG_INTERLACE_NONE,
                 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
    
    png_write_info(png_ptr, info_ptr);
        
    int x,y;
    png_bytep *row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
    for (y=0; y<height; y++) {
        row_pointers[y] = (png_byte*) malloc(width*sizeof(png_byte));
        for (x=0;x<width;x++) {
            
            row_pointers[y][x] = (png_byte)(img->GetPixel(x,y));
        }
    }

    /* write bytes */
    if (setjmp(png_jmpbuf(png_ptr)))
        dbg(DBG_ERROR,"[write_png_file] Error during writing bytes");
    
    png_write_image(png_ptr, row_pointers);
        
    /* end write */
    if (setjmp(png_jmpbuf(png_ptr)))
        dbg(DBG_ERROR,"[write_png_file] Error during end of write");
    
    png_write_end(png_ptr, NULL);
    
    /* cleanup heap allocation */
    for (y=0; y<height; y++) {
        free( row_pointers[y]);
    }
    free( row_pointers );

    fclose(fp);
}
Beispiel #28
0
bool ImageMemory::_SavePngImage(const std::string &filename) const
{
    // open up the file for writing
    FILE *fp = fopen(filename.c_str(), "wb");

    if(fp == NULL) {
        IF_PRINT_WARNING(VIDEO_DEBUG) << "could not open file: " << filename << std::endl;
        return false;
    }

    // aah, RGB data! We can only handle RGBA at the moment
    if(rgb_format == true) {
        IF_PRINT_WARNING(VIDEO_DEBUG) << "attempting to save RGB format image data as a RGBA format PNG image" << std::endl;
    }

    // grab a write structure
    png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL);

    if(!png_ptr) {
        IF_PRINT_WARNING(VIDEO_DEBUG) << "png_create_write_struct() failed for file: " << filename << std::endl;
        fclose(fp);
        return false;
    }

    // and a place to store the metadata
    png_infop info_ptr = png_create_info_struct(png_ptr);

    if(!info_ptr) {
        IF_PRINT_WARNING(VIDEO_DEBUG) << "png_create_info_struct() failed for file: " << filename << std::endl;
        png_destroy_write_struct(&png_ptr, NULL);
        fclose(fp);
        return false;
    }

    // prepare for error handling!
    if(setjmp(png_jmpbuf(png_ptr))) {
        IF_PRINT_WARNING(VIDEO_DEBUG) << "setjmp returned non-zero for file: " << filename << std::endl;
        png_destroy_write_struct(&png_ptr, &info_ptr);
        fclose(fp);
        return false;
    }

    // tell it where to look
    png_init_io(png_ptr, fp);

    // write the header
    png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA,
                 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

    // get the row array from our data
    png_byte **row_pointers = new png_byte*[height];
    int32 bytes_per_row = width * 4;
    for(uint32 i = 0; i < height; ++i) {
        row_pointers[i] = (png_byte *)pixels + bytes_per_row * i;
    }

    // tell it what the rows are
    png_set_rows(png_ptr, info_ptr, row_pointers);
    // and write the PNG
    png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
    png_write_image(png_ptr, row_pointers);
    // clean up
    png_write_end(png_ptr, info_ptr);
    png_destroy_write_struct(&png_ptr, &info_ptr);

    // free the memory we ate
    delete[] row_pointers;

    // peace and love for all
    return true;
} // bool ImageMemory::_SavePngImage(const std::string& filename) const
UInt64 PNGImageFileType::storeData(const Image  *OSG_PNG_ARG  (pImage  ), 
                                         UChar8 *OSG_PNG_ARG  (buffer ),
                                         Int32   OSG_CHECK_ARG(memSize))
{
#ifdef OSG_WITH_PNG

    png_structp png_ptr;
    png_infop info_ptr;

    if(pImage->getDimension() < 1 || pImage->getDimension() > 2)
    {
        FWARNING(("PNGImageFileType::write: invalid dimension %d!\n",
                  pImage->getDimension()));
        return 0;
    }

    /* Create and initialize the png_struct with the desired error handler
    * functions.  If you want to use the default stderr and longjump method,
    * you can supply NULL for the last three parameters.  We also check that
    * the library version is compatible with the one used at compile time,
    * in case we are using dynamically linked libraries.  REQUIRED.
    */

    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
                                      0, &errorOutput, &warningOutput);
    
    if (png_ptr == NULL)
    {
        return 0;
    }

    /* Allocate/initialize the image information data.  REQUIRED */
    info_ptr = png_create_info_struct(png_ptr);

    if(info_ptr == NULL)
    {
        png_destroy_write_struct(&png_ptr,  NULL);
        return 0;
    }
    
    BufferInfo bufferInfo;
    bufferInfo.buffer = buffer;
    bufferInfo.length = 0;

    png_set_write_fn(png_ptr, 
                     static_cast<void *>(&bufferInfo), 
                     user_write_data, 
                     user_flush_data);

    /* This is the hard way */

    /* 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
    */

    Int32 ctype;
    switch(pImage->getPixelFormat())
    {
        case Image::OSG_L_PF:
            ctype = PNG_COLOR_TYPE_GRAY;        
            break;
            
        case Image::OSG_LA_PF:
            ctype = PNG_COLOR_TYPE_GRAY_ALPHA;          
            break;
            
#if defined(GL_BGR) || defined(GL_BGR_EXT)
        case Image::OSG_BGR_PF:
#endif
        case Image::OSG_RGB_PF: 
            ctype = PNG_COLOR_TYPE_RGB;                 
            break;
            
#if defined(GL_BGRA) || defined(GL_BGRA_EXT)
        case Image::OSG_BGRA_PF:
#endif
        case Image::OSG_RGBA_PF:
            ctype = PNG_COLOR_TYPE_RGB_ALPHA;           
            break;
            
        default:
            FWARNING(("PNGImageFileType::write: unknown pixel format %d!\n",
                      pImage->getPixelFormat()));
            png_destroy_write_struct(&png_ptr,  NULL);

            return 0;
    }
    
    Int32 bit_depth;

    switch (pImage->getDataType()) 
    {
        case Image::OSG_UINT8_IMAGEDATA:
            bit_depth = 8;
            break;
        case Image::OSG_UINT16_IMAGEDATA:
            bit_depth = 16;
            break;
        default:
            FWARNING (("Invalid pixeldepth, cannot store data\n"));
            return 0;
    };

    png_set_IHDR(png_ptr, 
                 info_ptr, 
                 pImage->getWidth(), 
                 pImage->getHeight(),
                 bit_depth,
                 ctype,      
                 PNG_INTERLACE_NONE, 
                 PNG_COMPRESSION_TYPE_BASE, 
                 PNG_FILTER_TYPE_BASE);
    
    /* other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs, */
    /* note that if sRGB is present the gAMA and cHRM chunks must be ignored
    * on read and must be written in accordance with the sRGB profile */

    /* Write the file header information.  REQUIRED */

    png_write_info(png_ptr, info_ptr);

#if BYTE_ORDER == LITTLE_ENDIAN
    if (bit_depth == 16)
        png_set_swap(png_ptr);
#endif
    
    if(pImage->getPixelFormat() == Image::OSG_BGR_PF ||
       pImage->getPixelFormat() == Image::OSG_BGRA_PF)
    {
        /* flip BGR pixels to RGB */
        png_set_bgr(png_ptr);
        
        /* swap location of alpha bytes from ARGB to RGBA */
        png_set_swap_alpha(png_ptr);
    }
    
    /* The easiest way to write the image (you may have a different memory
     * layout, however, so choose what fits your needs best).  You need to
     * use the first method if you aren't handling interlacing yourself.
     */

    png_bytep *row_pointers = new png_bytep [pImage->getHeight()];
    
    for(Int32 k = 0; k < pImage->getHeight(); k++)
    {
        row_pointers[k] = 
            (const_cast<UInt8 *>(pImage->getData())) + 
            (pImage->getHeight() - 1 - k) * 
            pImage->getWidth() * pImage->getBpp();
    }
    
    /* write out the entire image data in one call */
    png_write_image(png_ptr, row_pointers);

    /* It is REQUIRED to call this to finish writing the rest of the file */
    png_write_end(png_ptr, info_ptr);
    
    /* clean up after the write, and free any memory allocated */
    png_destroy_write_struct(&png_ptr, &info_ptr);

    delete [] row_pointers;

    /* that's it */
    return bufferInfo.length;
#else
    SWARNING << getMimeType() 
             << " storeData is not compiled into the current binary " 
             << std::endl;

    return 0;
#endif
}
//-----------------------------------------------------------------------------
bool abiword_document::garble_png( void*& data, size_t& size ) {

	png_bytep * dib;
	png_uint_32 width;
	png_uint_32 height;
	int compression_type;
	int filter_type;
	int interlace_type;
	int bit_depth;
	int color_type;
	png_uint_32 rowbytes;

	// read PNG data
	{
		png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, (void*) NULL, NULL, NULL );
		if (!png_ptr)
			return false;
		png_infop info_ptr = png_create_info_struct(png_ptr);
		if (!info_ptr) {
			png_destroy_read_struct( &png_ptr, (png_infopp)NULL, (png_infopp)NULL );
			return false;
		}
		png_read_data _png_read_data = { data, size, 0 };
		png_set_read_fn( png_ptr, (void*)&_png_read_data, &_png_read );
		png_read_info( png_ptr, info_ptr );
		png_get_IHDR( png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_type );
		png_set_packing( png_ptr );
		png_set_expand( png_ptr );
		png_set_strip_16( png_ptr );
		png_set_gray_to_rgb( png_ptr );
		png_set_strip_alpha( png_ptr );
		png_set_interlace_handling( png_ptr );
		png_set_bgr( png_ptr );
		rowbytes = png_get_rowbytes(png_ptr, info_ptr);
		png_destroy_read_struct( &png_ptr, &info_ptr, NULL );
	}

	// we don't care about the image data itself, we just want a random garbled
	// image of the same size
	dib = (png_bytep*) malloc( sizeof(png_bytep) * height );
	for (size_t i=0; i<height; ++i) {
		dib[i] = (png_byte*) malloc( rowbytes );
		garble_image_line( reinterpret_cast<char*>( dib[i] ), rowbytes );
	}

	bool result = false;
	{
		// write it back
		png_structp png_ptrw = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
		if (png_ptrw)
		{
			png_infop info_ptrw = png_create_info_struct( png_ptrw );
			png_set_IHDR( png_ptrw, info_ptrw, width, height, bit_depth, color_type, interlace_type, compression_type, filter_type );
			string newdata;
			png_set_write_fn( png_ptrw, (void*)&newdata, &_png_write, NULL );
			png_write_info( png_ptrw, info_ptrw );
			png_write_image( png_ptrw, dib );
			png_write_end( png_ptrw, NULL );
			png_destroy_write_struct( &png_ptrw, NULL );

			free(data);
			size = newdata.size();
			data = malloc( size );
			memcpy( data, &newdata[0], size );
			result = true;
		}
	}

	// cleanup
	for (size_t i=0; i<height; i++)
		free( dib[i] );
	free( dib );
	return result;
}