Beispiel #1
0
	size_t ImageEncoderPNG::encode( const void * _buffer, size_t _size, const CodecDataInfo* _bufferDataInfo )
	{
		(void)_size;

		const ImageCodecDataInfo* dataInfo = static_cast<const ImageCodecDataInfo*>( _bufferDataInfo );
			
		// allocate/initialize the image information data.
		png_infop info_ptr = png_create_info_struct( m_png_ptr );

		if( info_ptr == nullptr )  
		{
			LOGGER_ERROR(m_serviceProvider)("PNG encoder error: Can't create info structure" 
				);

			return 0;
		}

		int color_type;
		if( dataInfo->channels == 1 )
		{
			color_type = PNG_COLOR_TYPE_GRAY;
		}
		else if( dataInfo->channels == 3 )
		{
			color_type = PNG_COLOR_TYPE_RGB;
		}
		else if( dataInfo->channels == 4 )
		{
			color_type = PNG_COLOR_TYPE_RGB_ALPHA;
		}
		else
		{
			LOGGER_ERROR(m_serviceProvider)("PNG codec error: unsupported image format channels %d"
                , dataInfo->channels
                );

			png_destroy_info_struct( m_png_ptr, &info_ptr );

			return 0;
		}

		png_uint_32 width = (png_uint_32)dataInfo->width;
		png_uint_32 height = (png_uint_32)dataInfo->height;
		int pixel_depth = 8;
		
		png_set_IHDR( m_png_ptr, info_ptr, width, height, pixel_depth, color_type, PNG_INTERLACE_NONE,
			PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE );

		png_set_bgr( m_png_ptr );

		// Write the file header information.
		png_write_info( m_png_ptr, info_ptr );

		size_t pitch = m_options.pitch;

        png_bytep png_buffer = (png_bytep)_buffer;

        for( png_uint_32 k = 0; k < height; ++k) 
        {
            png_write_row( m_png_ptr, png_buffer );
            png_buffer += pitch;
        }
		//}
		// It is REQUIRED to call this to finish writing the rest of the file
		// Bug with png_flush
		png_write_end( m_png_ptr, info_ptr );

		png_destroy_info_struct( m_png_ptr, &info_ptr );

        size_t writeBytes = pitch * height;

		return writeBytes;
	}
Beispiel #2
0
void GBMapView::savePNG(LPCTSTR name)
{
  u8 writeBuffer[1024 * 3];

  FILE *fp = _tfopen(name,_T("wb"));

  if(!fp) {
    systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name);
    return;
  }

  png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
                                                NULL,
                                                NULL,
                                                NULL);
  if(!png_ptr) {
    fclose(fp);
    return;
  }

  png_infop info_ptr = png_create_info_struct(png_ptr);

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

  if(setjmp(png_ptr->jmpbuf)) {
    png_destroy_write_struct(&png_ptr,NULL);
    fclose(fp);
    return;
  }

  png_init_io(png_ptr,fp);

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

  u8 *b = writeBuffer;

  int sizeX = w;
  int sizeY = h;

  u8 *pixU8 = (u8 *)data;
  for(int y = 0; y < sizeY; y++) {
    for(int x = 0; x < sizeX; x++) {
      int blue = *pixU8++;
      int green = *pixU8++;
      int red = *pixU8++;

      *b++ = red;
      *b++ = green;
      *b++ = blue;
    }
    png_write_row(png_ptr,writeBuffer);

    b = writeBuffer;
  }

  png_write_end(png_ptr, info_ptr);

  png_destroy_write_struct(&png_ptr, &info_ptr);

  fclose(fp);
}
Beispiel #3
0
static gint
export_png (GeglOperation       *operation,
            GeglBuffer          *input,
            const GeglRectangle *result,
            png_structp          png,
            png_infop            info,
            gint                 compression,
            gint                 bit_depth)
{
  gint           i, src_x, src_y;
  png_uint_32    width, height;
  guchar        *pixels;
  png_color_16   white;
  int            png_color_type;
  gchar          format_string[16];
  const Babl    *format;

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

  {
    const Babl *babl = gegl_buffer_get_format (input);

    if (bit_depth != 16)
      bit_depth = 8;

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

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

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

  png_set_compression_level (png, compression);

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

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

  png_write_info (png, info);

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

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

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

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

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

      png_write_rows (png, &pixels, 1);
    }

  png_write_end (png, info);

  g_free (pixels);

  return 0;
}
Beispiel #4
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 #5
0
static int savePNGto(FILE *fp, gPixmap *pixmap)
{
	gUnmanagedSurface *surface = pixmap->surface;
	if (!surface)
		return -2;

	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
	if (!png_ptr)
	{
		eDebug("[ePNG] couldn't allocate write struct");
		return -2;
	}
	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr)
	{
		eDebug("[ePNG] failed to allocate info struct");
		png_destroy_write_struct(&png_ptr, 0);
		return -3;
	}

	png_set_IHDR(png_ptr, info_ptr, surface->x, surface->y, surface->bpp/surface->bypp,
		PNG_COLOR_TYPE_RGB_ALPHA,
		PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

	if (setjmp(png_jmpbuf(png_ptr)))
	{
		eDebug("[ePNG] png setjump failed or activated");
		png_destroy_write_struct(&png_ptr, &info_ptr);
		return -4;
	}
	png_init_io(png_ptr, fp);
	png_set_filter(png_ptr, 0, PNG_FILTER_NONE|PNG_FILTER_SUB|PNG_FILTER_PAETH);
	png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);

	png_write_info(png_ptr, info_ptr);
	png_set_packing(png_ptr);

	png_byte *row_pointer;
	png_byte *cr = new png_byte[surface->y * surface->stride];
	if (cr == NULL)
	{
		eDebug("[ePNG] failed to allocate memory image");
		return -5;
	}
	for (int i = 0; i < surface->y; ++i)
	{
		row_pointer = ((png_byte*)surface->data) + i * surface->stride;
		if (surface->bypp == 4)
		{
			memcpy(cr, row_pointer, surface->stride);
			for (int j = 0; j < surface->stride; j += 4)
			{
				unsigned char tmp = cr[j];
				cr[j] = cr[j+2];
				cr[j+2] = tmp;
			}
			png_write_row(png_ptr, cr);
		}
		else
			png_write_row(png_ptr, row_pointer);
	}
	delete [] cr;

	png_write_end(png_ptr, info_ptr);
	png_destroy_write_struct(&png_ptr, &info_ptr);
	return 0;
}
Beispiel #6
0
CAMLprim value write_png_rgb_to_buffer(value buffer, value width, value height,
                                       value with_alpha) {
    CAMLparam4(buffer, width, height, with_alpha);
    CAMLlocal1(vres);

    png_structp png_ptr;
    png_infop info_ptr;
    /* static */
    struct mem_buffer state;

    int w, h, a;

    /* initialise - put this before png_write_png() call */
    state.buffer = NULL;
    state.size = 0;

    w = Int_val(width);
    h = Int_val(height);
    a = Bool_val(with_alpha);

    if ((png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
                                           NULL, NULL, NULL)) == NULL )
        failwith("png_create_write_struct");

    if((info_ptr = png_create_info_struct(png_ptr)) == NULL ) {
        png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
        failwith("png_create_info_struct");
    }

    /* error handling */
    if (setjmp(png_jmpbuf(png_ptr))) {
        /* Free all of the memory associated with the png_ptr and info_ptr */
        png_destroy_write_struct(&png_ptr, &info_ptr);
        failwith("png write error");
    }

    /* the final arg is NULL because we dont need in flush() */
    png_set_write_fn(png_ptr, &state, png_write_data_to_buffer, NULL);

    /* we use system default compression */
    /* png_set_filter(png_ptr, 0, PNG_FILTER_NONE |
       PNG_FILTER_SUB | PNG_FILTER_PAETH ); */
    /* png_set_compression...() */

    png_set_IHDR(png_ptr, info_ptr, w, h,
                 8 /* fixed */,
                 a ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB, /* fixed */
                 PNG_INTERLACE_ADAM7,
                 PNG_COMPRESSION_TYPE_DEFAULT,
                 PNG_FILTER_TYPE_DEFAULT );

    /* infos... */

    png_write_info(png_ptr, info_ptr);

    {
        int rowbytes, i;
        png_bytep *row_pointers;
        char *buf = String_val(buffer);

        row_pointers = (png_bytep*)stat_alloc(sizeof(png_bytep) * h);

        rowbytes= png_get_rowbytes(png_ptr, info_ptr);
        for(i=0; i< h; i++) {
            row_pointers[i] = (png_bytep)(buf + rowbytes * i);
        }

        png_write_image(png_ptr, row_pointers);
        stat_free((void*)row_pointers);
    }

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

    vres = caml_alloc_string(state.size);
    memcpy(String_val(vres), state.buffer, state.size);
    free(state.buffer);
    CAMLreturn(vres);
}
Beispiel #7
0
// this code is heavily adapted from the paint license, which is in
// the file paint.license (BSD compatible) included in this
// distribution.  TODO, add license file to MANIFEST.in and CVS
Py::Object _png_module::write_png(const Py::Tuple& args)
{
    args.verify_length(4, 5);

    FILE *fp = NULL;
    bool close_file = false;
    Py::Object buffer_obj = Py::Object(args[0]);
    PyObject* buffer = buffer_obj.ptr();
    if (!PyObject_CheckReadBuffer(buffer))
    {
        throw Py::TypeError("First argument must be an rgba buffer.");
    }

    const void* pixBufferPtr = NULL;
    Py_ssize_t pixBufferLength = 0;
    if (PyObject_AsReadBuffer(buffer, &pixBufferPtr, &pixBufferLength))
    {
        throw Py::ValueError("Couldn't get data from read buffer.");
    }

    png_byte* pixBuffer = (png_byte*)pixBufferPtr;
    int width = (int)Py::Int(args[1]);
    int height = (int)Py::Int(args[2]);

    if (pixBufferLength < width * height * 4)
    {
        throw Py::ValueError("Buffer and width, height don't seem to match.");
    }

    Py::Object py_fileobj = Py::Object(args[3]);
#if PY3K
    int fd = PyObject_AsFileDescriptor(py_fileobj.ptr());
    PyErr_Clear();
#endif
    if (py_fileobj.isString())
    {
        std::string fileName = Py::String(py_fileobj);
        const char *file_name = fileName.c_str();
        if ((fp = fopen(file_name, "wb")) == NULL)
        {
            throw Py::RuntimeError(
                Printf("Could not open file %s", file_name).str());
        }
        close_file = true;
    }
#if PY3K
    else if (fd != -1)
    {
        fp = fdopen(fd, "w");
    }
#else
    else if (PyFile_CheckExact(py_fileobj.ptr()))
    {
        fp = PyFile_AsFile(py_fileobj.ptr());
    }
#endif
    else
    {
        PyObject* write_method = PyObject_GetAttrString(
            py_fileobj.ptr(), "write");
        if (!(write_method && PyCallable_Check(write_method)))
        {
            Py_XDECREF(write_method);
            throw Py::TypeError(
                "Object does not appear to be a 8-bit string path or a Python file-like object");
        }
        Py_XDECREF(write_method);
    }

    png_bytep *row_pointers = NULL;
    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL;

    try
    {
        struct png_color_8_struct sig_bit;
        png_uint_32 row;

        row_pointers = new png_bytep[height];
        for (row = 0; row < (png_uint_32)height; ++row)
        {
            row_pointers[row] = pixBuffer + row * width * 4;
        }

        png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
        if (png_ptr == NULL)
        {
            throw Py::RuntimeError("Could not create write struct");
        }

        info_ptr = png_create_info_struct(png_ptr);
        if (info_ptr == NULL)
        {
            throw Py::RuntimeError("Could not create info struct");
        }

        if (setjmp(png_jmpbuf(png_ptr)))
        {
            throw Py::RuntimeError("Error building image");
        }

        if (fp)
        {
            png_init_io(png_ptr, fp);
        }
        else
        {
            png_set_write_fn(png_ptr, (void*)py_fileobj.ptr(),
                             &write_png_data, &flush_png_data);
        }
        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);

        // Save the dpi of the image in the file
        if (args.size() == 5)
        {
            double dpi = Py::Float(args[4]);
            size_t dots_per_meter = (size_t)(dpi / (2.54 / 100.0));
            png_set_pHYs(png_ptr, info_ptr, dots_per_meter, dots_per_meter, PNG_RESOLUTION_METER);
        }

        // this a a color image!
        sig_bit.gray = 0;
        sig_bit.red = 8;
        sig_bit.green = 8;
        sig_bit.blue = 8;
        /* if the image has an alpha channel then */
        sig_bit.alpha = 8;
        png_set_sBIT(png_ptr, info_ptr, &sig_bit);

        png_write_info(png_ptr, info_ptr);
        png_write_image(png_ptr, row_pointers);
        png_write_end(png_ptr, info_ptr);
    }
    catch (...)
    {
        if (png_ptr && info_ptr)
        {
            png_destroy_write_struct(&png_ptr, &info_ptr);
        }
        delete [] row_pointers;
        if (fp && close_file)
        {
            fclose(fp);
        }
        /* Changed calls to png_destroy_write_struct to follow
           http://www.libpng.org/pub/png/libpng-manual.txt.
           This ensures the info_ptr memory is released.
        */
        throw;
    }

    png_destroy_write_struct(&png_ptr, &info_ptr);
    delete [] row_pointers;
#if PY3K
    if (fp)
    {
        fflush(fp);
    }
#endif
    if (fp && close_file)
    {
        fclose(fp);
    }

    if (PyErr_Occurred()) {
        throw Py::Exception();
    } else {
        return Py::Object();
    }
}
Beispiel #8
0
int main(int argc, char *argv[])
{
	int result;
	TIFF *tiff;
	u_long width, height;
	int bwidth;
	u_char *raster = 0;
	int r;
	int i;
	png_structp png_ptr;
	png_infop info_ptr;
	png_bytep row_pointer, row;
	int page = 0;
	int angle = 0;
	int nwidth = -1;
	int lr = 0;
	int tb = 0;
	int antialias = 0;
	int xisy = 0;
	int xisflipped = 0;
	int yisflipped = 0;
	uint16 bitsPerSample;
	char *tiffFile = 0;
	char *pngFile = 0;	
	FILE *out;
	int y;
	u_long num;
	u_long denom;
	char error[1024];
	for (i = 1; (i < argc); i++) {
		if (!strcmp(argv[i], "-p")) {
			if (argc == (i + 1)) {
				die("-p expects a page number");
			}
			page = atoi(argv[i + 1]) - 1;
			i++;
			if (page < 0) {
				die("-p expects a page number >= 1");
			}
		} else if (!strcmp(argv[i], "-r")) {
			if (argc == (i + 1)) {
				die("-r expects an angle");
			}
			angle = atoi(argv[i + 1]);
			i++;	
			if ((angle < 0) || (angle > 270) ||
				(angle % 90))
			{
				die("-a expects an angle of 0, 90, 180, or 270 degrees");
			}
		} else if (!strcmp(argv[i], "-w")) {
			if (argc == (i + 1)) {
				die("-w expects a width in pixels");
			}
			nwidth = atoi(argv[i + 1]);
			i++;
			if (nwidth <= 0) {
				die("-w expects a positive width in pixels");
			}
		} else if (!strcmp(argv[i], "-lr")) {
			lr = 1;
		} else if (!strcmp(argv[i], "-tb")) {		
			tb = 1;
		} else if (!strcmp(argv[i], "-a")) {		
			antialias = 1;
		} else if ((!tiffFile) && (argv[i][0] != '-')) {
			tiffFile = argv[i];
		} else if ((!pngFile) && (argv[i][0] != '-')) {
			pngFile = argv[i];
		} else {
			usage("unknown parameter");
		}
	}
	if (!tiffFile) {
		usage("tiff filename is required");
	}
	tiff = TIFFOpen(tiffFile, "rb");
	if (!tiff) {
		die("Can't open file");
	}	
	if (!TIFFSetDirectory(tiff, page)) {
		die("Can't access page number requested");
	}
	(void) TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &width);
	if (nwidth == -1) {
		num = 1;
		denom = 1;
	} else {
		if (!xisy) {
			num = width;
			denom = nwidth;
		} else {
			num = height;
			denom = nwidth;
		}
	}	
	if ((!num) || (!denom)) {
		die("Width and height must both be nonzero");
	}
	(void) TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &height);
	(void) TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bitsPerSample);
	if (bitsPerSample != 1) {
		die("Sorry, only 1-bit (scan/fax) TIFFs are supported");
	}
	bwidth = (int) TIFFScanlineSize(tiff);
	raster = calloc(1, bwidth * height);
	if (!raster) {
		die("Memory allocation error");
	}
	for (y = 0; (y < height); y++) {
		TIFFReadScanline(tiff, raster + bwidth * y, y, 0);
	}
	switch (angle) {
		case 0:
		break;
		case 90:
		xisy = !xisy;
		yisflipped = !yisflipped;
		break;
		case 180:
		xisflipped = !xisflipped;
		yisflipped = !yisflipped;
		break;
		case 270:
		xisy = !xisy;
		xisflipped = !xisflipped;
		break;
	}
	if (lr) {
		xisflipped = !xisflipped;
	}
	if (tb) {
		yisflipped = !yisflipped;
	}
	row = calloc(sizeof(u_char), (xisy) ? height : width);
	if (!row) {
		die("Memory allocation error");
	}	
	png_ptr = png_create_write_struct(
		PNG_LIBPNG_VER_STRING, 0, 0, 0);		
	if (!png_ptr) {
		die("Cannot allocate png_structp");
	}
	info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr) {
		die("Cannot allocate png_infop");
	}
	if (setjmp(png_jmpbuf(png_ptr))) {
		die("Error on png write");
	}
	if (pngFile) {
		out = fopen(pngFile, "wb");
		if (!out) {
			die("Cannot create output file");
		}
	} else {
		out = stdout;
		SET_BINARY(STDOUT_FILENO);		
	}
	png_init_io(png_ptr, out);
	/* Turning off filtering yields a large speed improvement at a 
		modest price in file size */
	png_set_filter(png_ptr, 0, PNG_FILTER_NONE);
	if (nwidth == -1) {
		nwidth = width;
	}
	png_set_IHDR(png_ptr, info_ptr, ((xisy) ? height : width) * denom / num,
		((xisy) ? width : height) * denom / num,
		8, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE,
		PNG_COMPRESSION_TYPE_DEFAULT,
		PNG_FILTER_TYPE_DEFAULT);
	png_write_info(png_ptr, info_ptr);
	for (y = 0; (y < info_ptr->height); y++) {
		int x;
		u_char *p;
		row_pointer = row;
		p = row;
		for (x = 0; (x < info_ptr->width); x++) {
			int tx, ty;
			int accum = 0, total = 0;
			int ty1 = (xisy ? x : y) * num / denom;
			int tx1 = (xisy ? y : x) * num / denom;
			int tx2, ty2;
			int xsteps, ysteps;
			if (!antialias) {
				tx2 = tx1 + 1;
				ty2 = ty1 + 1;
			} else {
				ty2 = (xisy ? (x + 1) : (y + 1)) * num / denom;
				tx2 = (xisy ? (y + 1) : (x + 1)) * num / denom;
			}
			ysteps = abs(ty2 - ty1);
			xsteps = abs(tx2 - tx1);
			if (xisflipped) {
				tx1 = width - 1 - tx1;
				tx2 = width - 1 - tx2;
			}	
			if (yisflipped) {
				ty1 = height - 1 - ty1;
				ty2 = height - 1 - ty2;
			}	
			ty = ty1;	
			while (ty != ty2) {
				tx = tx1;
				while (tx != tx2) {
					accum += GetBWPixel(raster, ty, tx);
					total++;
					tx += sign(tx2 - tx1);
				}
				ty += sign(ty2 - ty1);
			}
			if (total > 0) {
				*p = accum / total;	
			}
			p++;
		}
		png_write_row(png_ptr, row_pointer);	
		
	}
	png_write_end(png_ptr, info_ptr);
	png_destroy_write_struct(&png_ptr, &info_ptr);
	if (out != stdout) {
		fclose(out);
	}
	return 0;
}
static BOOL DLL_CALLCONV
Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
	png_structp png_ptr;
	png_infop info_ptr;
	png_colorp palette = NULL;
	png_uint_32 width, height;
	BOOL has_alpha_channel = FALSE;

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

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

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

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

			if (!png_ptr)  {
				return FALSE;
			}

			// allocate/initialize the image information data.

			info_ptr = png_create_info_struct(png_ptr);

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

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

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

				png_destroy_write_struct(&png_ptr, &info_ptr);

				return FALSE;
			}

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

			// set physical resolution

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

			if ((res_x > 0) && (res_y > 0))  {
				png_set_pHYs(png_ptr, info_ptr, res_x, res_y, 1);
			}
	
			// Set the image information here.  Width and height are up to 2^31,
			// bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
			// the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
			// PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
			// or PNG_COLOR_TYPE_RGB_ALPHA.  interlace is either PNG_INTERLACE_NONE or
			// PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
			// currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED

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

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

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

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

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

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

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

					break;

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

					// set the palette

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

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

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

					break;
				}

				case FIC_RGBALPHA :
					has_alpha_channel = TRUE;

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

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

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

			// write possible ICC profile

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

			// write metadata

			WriteMetadata(png_ptr, info_ptr, dib);

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

			// set the transparency table

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

			// set the background color

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

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

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

			png_write_info(png_ptr, info_ptr);

			// write out the image data

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

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

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

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

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

			png_write_end(png_ptr, info_ptr);

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

			png_destroy_write_struct(&png_ptr, &info_ptr);

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

	return FALSE;
}
Beispiel #10
0
int IMG_SavePNG_RW(SDL_RWops *src, SDL_Surface *surf,int compression){
	png_structp png_ptr;
	png_infop info_ptr;
	SDL_PixelFormat *fmt=NULL;
	SDL_Surface *tempsurf=NULL;
	int ret,funky_format,used_alpha;
	unsigned int i,temp_alpha;
	png_colorp palette;
	Uint8 *palette_alpha=NULL;
	png_byte **row_pointers=NULL;
	png_ptr=NULL;info_ptr=NULL;palette=NULL;ret=-1;
	funky_format=0;
	
	if( !src || !surf) {
		goto savedone; /* Nothing to do. */
	}

	row_pointers=(png_byte **)malloc(surf->h * sizeof(png_byte*));
	if (!row_pointers) { 
		SDL_SetError("Couldn't allocate memory for rowpointers");
		goto savedone;
	}
	
	png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,NULL,NULL);
	if (!png_ptr){
		SDL_SetError("Couldn't allocate memory for PNG file");
		goto savedone;
	}
	info_ptr= png_create_info_struct(png_ptr);
	if (!info_ptr){
		SDL_SetError("Couldn't allocate image information for PNG file");
		goto savedone;
	}
	/* setup custom writer functions */
	png_set_write_fn(png_ptr,(voidp)src,png_write_data,NULL);

	if (setjmp(png_jmpbuf(png_ptr))){
		SDL_SetError("Unknown error writing PNG");
		goto savedone;
	}

	if(compression>Z_BEST_COMPRESSION)
		compression=Z_BEST_COMPRESSION;

	if(compression == Z_NO_COMPRESSION) // No compression
	{
		png_set_filter(png_ptr,0,PNG_FILTER_NONE);
		png_set_compression_level(png_ptr,Z_NO_COMPRESSION);
	}
        else if(compression<0) // Default compression
		png_set_compression_level(png_ptr,Z_DEFAULT_COMPRESSION);
        else
		png_set_compression_level(png_ptr,compression);

	fmt=surf->format;
	if(fmt->BitsPerPixel==8){ /* Paletted */
		png_set_IHDR(png_ptr,info_ptr,
			surf->w,surf->h,8,PNG_COLOR_TYPE_PALETTE,
			PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT,
			PNG_FILTER_TYPE_DEFAULT);
		palette=(png_colorp) malloc(fmt->palette->ncolors * sizeof(png_color));
		if (!palette) {
			SDL_SetError("Couldn't create memory for palette");
			goto savedone;
		}
		for (i=0;i<fmt->palette->ncolors;i++) {
			palette[i].red=fmt->palette->colors[i].r;
			palette[i].green=fmt->palette->colors[i].g;
			palette[i].blue=fmt->palette->colors[i].b;
		}
		png_set_PLTE(png_ptr,info_ptr,palette,fmt->palette->ncolors);
		if (surf->flags&SDL_SRCCOLORKEY) {
			palette_alpha=(Uint8 *)malloc((fmt->colorkey+1)*sizeof(Uint8));
			if (!palette_alpha) {
				SDL_SetError("Couldn't create memory for palette transparency");
				goto savedone;
			}
			/* FIXME: memset? */
			for (i=0;i<(fmt->colorkey+1);i++) {
				palette_alpha[i]=255;
			}
			palette_alpha[fmt->colorkey]=0;
			png_set_tRNS(png_ptr,info_ptr,palette_alpha,fmt->colorkey+1,NULL);
		}
	}else{ /* Truecolor */
		if (fmt->Amask) {
			png_set_IHDR(png_ptr,info_ptr,
				surf->w,surf->h,8,PNG_COLOR_TYPE_RGB_ALPHA,
				PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT,
				PNG_FILTER_TYPE_DEFAULT);
		} else {
			png_set_IHDR(png_ptr,info_ptr,
				surf->w,surf->h,8,PNG_COLOR_TYPE_RGB,
				PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT,
				PNG_FILTER_TYPE_DEFAULT);
		}
	}
	png_write_info(png_ptr, info_ptr);

	if (fmt->BitsPerPixel==8) { /* Paletted */
		for(i=0;i<surf->h;i++){
			row_pointers[i]= ((png_byte*)surf->pixels) + i*surf->pitch;
		}
		if(SDL_MUSTLOCK(surf)){
			SDL_LockSurface(surf);
		}
		png_write_image(png_ptr, row_pointers);
		if(SDL_MUSTLOCK(surf)){
			SDL_UnlockSurface(surf);
		}
	}else{ /* Truecolor */
		if(fmt->BytesPerPixel==3){
			if(fmt->Amask){ /* check for 24 bit with alpha */
				funky_format=1;
			}else{
				/* Check for RGB/BGR/GBR/RBG/etc surfaces.*/
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
				if(fmt->Rmask!=0xFF0000 
				|| fmt->Gmask!=0x00FF00
				|| fmt->Bmask!=0x0000FF){
#else
				if(fmt->Rmask!=0x0000FF 
				|| fmt->Gmask!=0x00FF00
				|| fmt->Bmask!=0xFF0000){
#endif
					funky_format=1;
				}
			}
		}else if (fmt->BytesPerPixel==4){
			if (!fmt->Amask) { /* check for 32bit but no alpha */
				funky_format=1; 
			}else{
				/* Check for ARGB/ABGR/GBAR/RABG/etc surfaces.*/
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
				if(fmt->Rmask!=0xFF000000
				|| fmt->Gmask!=0x00FF0000
				|| fmt->Bmask!=0x0000FF00
				|| fmt->Amask!=0x000000FF){
#else
				if(fmt->Rmask!=0x000000FF
				|| fmt->Gmask!=0x0000FF00
				|| fmt->Bmask!=0x00FF0000
				|| fmt->Amask!=0xFF000000){
#endif
					funky_format=1;
				}
			}
		}else{ /* 555 or 565 16 bit color */
			funky_format=1;
		}
		if (funky_format) {
			/* Allocate non-funky format, and copy pixeldata in*/
			if(fmt->Amask){
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
				tempsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, surf->w, surf->h, 24,
										0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
#else
				tempsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, surf->w, surf->h, 24,
										0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
#endif
			}else{
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
				tempsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, surf->w, surf->h, 24,
										0xff0000, 0x00ff00, 0x0000ff, 0x00000000);
#else
				tempsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, surf->w, surf->h, 24,
										0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000);
#endif
			}
			if(!tempsurf){
				SDL_SetError("Couldn't allocate temp surface");
				goto savedone;
			}
			if(surf->flags&SDL_SRCALPHA){
				temp_alpha=fmt->alpha;
				used_alpha=1;
				SDL_SetAlpha(surf,0,255); /* Set for an opaque blit */
			}else{
				used_alpha=0;
			}
			if(SDL_BlitSurface(surf,NULL,tempsurf,NULL)!=0){
				SDL_SetError("Couldn't blit surface to temp surface");
				SDL_FreeSurface(tempsurf);
				goto savedone;
			}
			if (used_alpha) {
				SDL_SetAlpha(surf,SDL_SRCALPHA,(Uint8)temp_alpha); /* Restore alpha settings*/
			}
			for(i=0;i<tempsurf->h;i++){
				row_pointers[i]= ((png_byte*)tempsurf->pixels) + i*tempsurf->pitch;
			}
			if(SDL_MUSTLOCK(tempsurf)){
				SDL_LockSurface(tempsurf);
			}
			png_write_image(png_ptr, row_pointers);
			if(SDL_MUSTLOCK(tempsurf)){
				SDL_UnlockSurface(tempsurf);
			}
			SDL_FreeSurface(tempsurf);
		} else {
			for(i=0;i<surf->h;i++){
				row_pointers[i]= ((png_byte*)surf->pixels) + i*surf->pitch;
			}
			if(SDL_MUSTLOCK(surf)){
				SDL_LockSurface(surf);
			}
			png_write_image(png_ptr, row_pointers);
			if(SDL_MUSTLOCK(surf)){
				SDL_UnlockSurface(surf);
			}
		}
	}

	png_write_end(png_ptr, NULL);
	ret=0; /* got here, so nothing went wrong. YAY! */

savedone: /* clean up and return */
	png_destroy_write_struct(&png_ptr,&info_ptr);
	if (palette) {
		free(palette);
	}
	if (palette_alpha) {
		free(palette_alpha);
	}
	if (row_pointers) {
		free(row_pointers);
	}
	return ret;
}
Beispiel #11
0
unsigned char *
pngconv_lossless2png(void *image_data,
                     unsigned short width, unsigned short height,
                     void *index_data,
                     unsigned short index_data_count,
                     int tag_no, int format,
                     unsigned long *length) {
    volatile png_structp png_ptr = NULL;
    volatile png_infop png_info_ptr = NULL;
    volatile my_png_buffer png_buff;
    png_uint_32 png_width = 0, png_height = 0;
    int bpp, color_type;
    volatile png_bytepp png_image_data = NULL;
    png_uint_32 x, y;
    volatile png_colorp png_palette = NULL;
    if (image_data == NULL) {
        fprintf(stderr, "pngconv_lossless2png: image_data == NULL\n");
        return NULL;
    }
    if ((format != 3) && (format != 5)) {
        fprintf(stderr, "jpegconv_lossless2png: format=%d not implemented yes.\n", format);
        return NULL;
    }
    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,NULL,NULL);
    if (! png_ptr) {
        fprintf(stderr, "jpegconv_lossless2png: can't create write_struct\n");
        return NULL;
    }
    if (setjmp(png_jmpbuf(png_ptr))) {
        fprintf(stderr, "pngconv_lossless2png: libpng error jump occured\n");
        free(png_palette);
        if (png_image_data) {
            for (y=0 ; y < png_height ; y++) {
                free(png_image_data[y]);
            }
            free(png_image_data);
        }
        free(png_buff.data);
        png_destroy_write_struct((png_structpp) &png_ptr,
                                 (png_infopp) &png_info_ptr);
        return NULL;
    }
    png_info_ptr = png_create_info_struct(png_ptr);
    if (! png_info_ptr) {
        fprintf(stderr, "jpegconv_lossless2png: can't create info_struct\n");
        png_destroy_write_struct((png_structpp) &png_ptr, NULL);
        return NULL;
    }
    //
    png_width = width;
    png_height = height;
    bpp = 8;
    if (format == 3) {
        color_type =  PNG_COLOR_TYPE_PALETTE;
    } else if (tag_no == 20) { /* DefineBitsLossless */
        color_type = PNG_COLOR_TYPE_RGB;
    } else if (tag_no == 36) { /* DefineBitsLossless2 */
        color_type = PNG_COLOR_TYPE_RGB_ALPHA;
    } else {
        fprintf(stderr, "jpegconv_lossless2png: format!=3 and tag_no=%d not implemented.\n",
                tag_no);
        png_destroy_write_struct((png_structpp) &png_ptr,
                                 (png_infopp) &png_info_ptr);
        return NULL;
    }
    png_set_filter(png_ptr, 0, PNG_ALL_FILTERS);
    png_set_IHDR(png_ptr, png_info_ptr,
                 png_width, png_height, bpp, color_type,
                 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
                 PNG_FILTER_TYPE_DEFAULT);
    if (format == 3) {
        register int i;
        if (index_data_count == 0) {
            fprintf(stderr, "jpegconv_lossless2png: index_data_count == 0 at line(%d)\n", __LINE__);
            png_destroy_write_struct((png_structpp) &png_ptr,
                                     (png_infopp) &png_info_ptr);
            return NULL;
        }
        png_palette = (png_colorp) malloc(sizeof(png_color)*index_data_count);
        png_set_packing(png_ptr);
        if (tag_no == 20) {
            swf_rgb_t *rgb_list  = index_data;
            for (i=0 ; i < index_data_count ; i++) {
                png_palette[i].red   = rgb_list[i].red;
                png_palette[i].green = rgb_list[i].green;
                png_palette[i].blue  = rgb_list[i].blue;
            }
        } else {
            swf_rgba_t *rgba_list  = index_data;
            png_bytep trans = NULL;
            int num_trans = 0;
            png_color_16p trans_values = NULL;
            for (i=0 ; i < index_data_count ; i++) {
                png_palette[i].red   = rgba_list[i].red;
                png_palette[i].green = rgba_list[i].green;
                png_palette[i].blue  = rgba_list[i].blue;
            }
            // scanning to end of transparent pixel
            for (i = index_data_count - 1 ; 0 <= i ; i--) {
                if (rgba_list[i].alpha < 254) { // 254 XXX
                    break;
                }
            }
            num_trans = i + 1;
            if (num_trans > 0) {
                trans = malloc(num_trans);
                for (i = 0 ; i < num_trans ; i++) {
                    trans[i] = rgba_list[i].alpha;
                }
                png_set_tRNS(png_ptr, png_info_ptr, trans, num_trans,
                             trans_values);
                free(trans);
            }

        }
        png_set_PLTE( png_ptr, png_info_ptr, png_palette, index_data_count);
        free(png_palette);
    }
    png_image_data = (png_bytepp) malloc(png_height * sizeof(png_bytep));
    if (color_type == PNG_COLOR_TYPE_PALETTE) {
        for (y=0 ; y < png_height ; y++) {
            png_image_data[y] = (png_bytep) malloc(png_get_rowbytes(png_ptr, png_info_ptr));
            for (x=0 ; x < png_width ; x++) {
                unsigned char *data = image_data;
                png_image_data[y][x] = data[x + y*((png_width +3) & -4)];
            }
        }
        
    } else if (color_type == PNG_COLOR_TYPE_RGB) {
        swf_xrgb_t *xrgb_list = image_data;
        for (y=0 ; y < png_height ; y++) {
            png_image_data[y] = (png_bytep) malloc(png_get_rowbytes(png_ptr, png_info_ptr));
            for (x=0 ; x < png_width ; x++) {
                png_image_data[y][3*x]   =  xrgb_list[x+y*png_width].red;
                png_image_data[y][3*x+1] =  xrgb_list[x+y*png_width].green;
                png_image_data[y][3*x+2] =  xrgb_list[x+y*png_width].blue;
            }
        }
    } else {
        swf_argb_t *argb_list = image_data;
        for (y=0 ; y < png_height ; y++) {
            png_image_data[y] = (png_bytep) malloc(png_get_rowbytes(png_ptr, png_info_ptr));
            for (x=0 ; x < png_width ; x++) {
                png_image_data[y][4*x]   = argb_list[x+y*png_width].red;
                png_image_data[y][4*x+1] = argb_list[x+y*png_width].green;
                png_image_data[y][4*x+2] = argb_list[x+y*png_width].blue;
                png_image_data[y][4*x+3] = argb_list[x+y*png_width].alpha;
            }
        }
        
    }
    png_buff.data = NULL;
    png_buff.data_len = 0;
    png_buff.data_offset = 0;
    png_data_write((png_structp) png_ptr, (my_png_buffer*) &png_buff);

    png_write_info(png_ptr, png_info_ptr);
    png_write_image(png_ptr, png_image_data);
    png_write_end(png_ptr, png_info_ptr);
    //
    for (y=0 ; y < png_height ; y++) {
        free(png_image_data[y]);
    }
    free(png_image_data);
    png_destroy_write_struct((png_structpp) &png_ptr,
                             (png_infopp) &png_info_ptr);
    *length = png_buff.data_offset;
    return png_buff.data;
}
//saves the given SDL structure into a given filename.
void save_image(surface surf, const std::string &filename)
{
	//opens the actual file
	const util::scoped_FILE file(fopen(filename.c_str(),"wb"));

	//initializes PNG write structures
	//TODO: review whether providing NULL error handlers is something
	//sensible
	png_struct* png_ptr = png_create_write_struct
		(PNG_LIBPNG_VER_STRING, reinterpret_cast<png_voidp>(png_voidp_NULL),
		 png_error_ptr_NULL, png_error_ptr_NULL);
	if(!png_ptr)
		throw exploder_failure("Unable to initialize the png write structure");

	png_info* info_ptr = png_create_info_struct(png_ptr);
	if(!info_ptr) {
		png_destroy_write_struct(&png_ptr,
				static_cast<png_infopp>(NULL));
		throw exploder_failure("Unable to initialize the png info structure");
	}

	//instructs the PNG library to use the open file
	png_init_io(png_ptr, file);

	//sets compression level to the maximum
	png_set_compression_level(png_ptr,
			Z_BEST_COMPRESSION);

	//configures the header
	png_set_IHDR(png_ptr, info_ptr, surf->w, surf->h,
			8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
			PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

	//puts the actual image data in the row_pointers array
	png_byte **row_pointers = new png_byte *[surf->h];
	surface_lock lock(surf);

	//converts the data to the RGBA format. We cannot pass SDL data
	//directly to the png lib, even if we know its pixel format, because of
	//endianness problems.
	util::scoped_array<rgba> rgba_data(new rgba[surf->w * surf->h]);

	Uint32 *surf_data = lock.pixels();
	int pos = 0;
	for(int y = 0; y < surf->h; ++y) {
		row_pointers[y] = reinterpret_cast<png_byte*>(rgba_data + pos);
		for(int x = 0; x < surf->w; ++x) {
			Uint8 red, green, blue, alpha;
			SDL_GetRGBA(*surf_data, surf->format, &red, &green, &blue, &alpha);
			rgba_data[pos].r = red;
			rgba_data[pos].g = green;
			rgba_data[pos].b = blue;
			rgba_data[pos].a = alpha;
			pos++;
			surf_data++;
		}
	}
	png_set_rows(png_ptr, info_ptr, row_pointers);

	//writes the actual image data
	png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

	//cleans everything
	png_write_end(png_ptr, info_ptr);
	png_destroy_write_struct(&png_ptr, &info_ptr);
	delete [] row_pointers;
}
Beispiel #13
0
int image_png_compress(MediaScanImage *i, MediaScanThumbSpec *spec) {
  int j, x, y;
  int color_space = PNG_COLOR_TYPE_RGB_ALPHA;
  volatile unsigned char *ptr = NULL;
  png_structp png_ptr;
  png_infop info_ptr;
  Buffer *buf;

  if (!i->_pixbuf_size) {
    LOG_WARN("PNG compression requires pixbuf data (%s)\n", i->path);
    return 0;
  }

  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (!png_ptr) {
    FATAL("Could not initialize libpng\n");
  }

  info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr) {
    png_destroy_write_struct(&png_ptr, NULL);
    FATAL("Could not initialize libpng\n");
  }

  // Initialize buffer for compressed data
  buf = (Buffer *)malloc(sizeof(Buffer));
  buffer_init(buf, BUF_SIZE);
  i->_dbuf = (void *)buf;

  png_set_write_fn(png_ptr, buf, image_png_write_buf, image_png_flush_buf);

  if (setjmp(png_jmpbuf(png_ptr))) {
    if (ptr != NULL)
      free((void *)ptr);
    return 0;
  }

  // Match output color space with input file
  switch (i->channels) {
    case 4:
    case 3:
      LOG_DEBUG("PNG output color space set to RGBA\n");
      color_space = PNG_COLOR_TYPE_RGB_ALPHA;
      break;
    case 2:
    case 1:
      LOG_DEBUG("PNG output color space set to gray alpha\n");
      color_space = PNG_COLOR_TYPE_GRAY_ALPHA;
      break;
  }

  png_set_IHDR(png_ptr, info_ptr, spec->width, spec->height, 8, color_space,
               PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

  png_write_info(png_ptr, info_ptr);

  ptr = (unsigned char *)malloc(png_get_rowbytes(png_ptr, info_ptr));

  j = 0;

  if (color_space == PNG_COLOR_TYPE_GRAY_ALPHA) {
    for (y = 0; y < spec->height; y++) {
      for (x = 0; x < spec->width; x++) {
        ptr[x * 2] = COL_BLUE(i->_pixbuf[j]);
        ptr[x * 2 + 1] = COL_ALPHA(i->_pixbuf[j]);
        j++;
      }
      png_write_row(png_ptr, (png_bytep) ptr);
    }
  }
  else {                        // RGB
    for (y = 0; y < spec->height; y++) {
      for (x = 0; x < spec->width; x++) {
        ptr[x * 4] = COL_RED(i->_pixbuf[j]);
        ptr[x * 4 + 1] = COL_GREEN(i->_pixbuf[j]);
        ptr[x * 4 + 2] = COL_BLUE(i->_pixbuf[j]);
        ptr[x * 4 + 3] = COL_ALPHA(i->_pixbuf[j]);
        j++;
      }
      png_write_row(png_ptr, (png_bytep) ptr);
    }
  }

  free((void *)ptr);

  png_write_end(png_ptr, info_ptr);

  png_destroy_write_struct(&png_ptr, &info_ptr);

  return 1;
}
Beispiel #14
0
// this code is heavily adapted from the paint license, which is in
// the file paint.license (BSD compatible) included in this
// distribution.  TODO, add license file to MANIFEST.in and CVS
Py::Object 
RendererAgg::write_png(const Py::Tuple& args)
{
  //small memory leak in this function - JDH 2004-06-08
  _VERBOSE("RendererAgg::write_png");
  
  args.verify_length(1);
  
  FILE *fp;
  Py::Object o = Py::Object(args[0]);
  bool fpclose = true;
  if (o.isString()) {
    std::string fileName = Py::String(o);
    const char *file_name = fileName.c_str();
    fp = fopen(file_name, "wb");
  }
  else {
    if ((fp = PyFile_AsFile(o.ptr())) == NULL) 
      throw Py::TypeError("Could not convert object to file pointer");
    fpclose = false;
  }

  png_structp png_ptr;
  png_infop info_ptr;
  struct        png_color_8_struct sig_bit;
  png_uint_32 row;
  
  png_bytep row_pointers[height];
  for (row = 0; row < height; ++row) {
    row_pointers[row] = pixBuffer + row * width * 4;
  }
  

  if (fp == NULL) 
    throw Py::RuntimeError("could not open file");
  
  
  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (png_ptr == NULL) {
    if (fpclose) fclose(fp);
    throw Py::RuntimeError("could not create write struct");
  }
  
  info_ptr = png_create_info_struct(png_ptr);
  if (info_ptr == NULL) {
    if (fpclose) fclose(fp);
    png_destroy_write_struct(&png_ptr, &info_ptr);
    throw Py::RuntimeError("could not create info struct");
  }
  
  if (setjmp(png_ptr->jmpbuf)) {
    if (fpclose) fclose(fp);
    png_destroy_write_struct(&png_ptr, &info_ptr);
    throw Py::RuntimeError("error building image");
  }
  
  png_init_io(png_ptr, fp);
  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);
  
  // this a a color image!
  sig_bit.gray = 0;
  sig_bit.red = 8;
  sig_bit.green = 8;
  sig_bit.blue = 8;
  /* if the image has an alpha channel then */
  sig_bit.alpha = 8;
  png_set_sBIT(png_ptr, info_ptr, &sig_bit);
  
  png_write_info(png_ptr, info_ptr);
  png_write_image(png_ptr, row_pointers);
  png_write_end(png_ptr, info_ptr);

  /* Changed calls to png_destroy_write_struct to follow
     http://www.libpng.org/pub/png/libpng-manual.txt.  
     This ensures the info_ptr memory is released.  
  */

  png_destroy_write_struct(&png_ptr, &info_ptr);

 
  if (fpclose) fclose(fp);
  
  return Py::Object();
}
Beispiel #15
0
CAMLprim value write_png_index_to_buffer(value buffer, value cmap, value
        width, value height) {
    CAMLparam4(buffer, cmap, width, height);
    CAMLlocal1(vres);

    png_structp png_ptr;
    png_infop info_ptr;
    /* static */
    struct mem_buffer state;

    int w, h;

    /* initialise - put this before png_write_png() call */
    state.buffer = NULL;
    state.size = 0;

    w = Int_val(width);
    h = Int_val(height);

    if ((png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
                                           NULL, NULL, NULL)) == NULL ) {
        failwith("png_create_write_struct");
    }

    if((info_ptr = png_create_info_struct(png_ptr)) == NULL ) {
        png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
        failwith("png_create_info_struct");
    }

    /* error handling */
    if (setjmp(png_jmpbuf(png_ptr))) {
        /* Free all of the memory associated with the png_ptr and info_ptr */
        png_destroy_write_struct(&png_ptr, &info_ptr);
        /* If we get here, we had a problem writing the file */
        failwith("png write error");
    }

    /* the final arg is NULL because we dont need in flush() */
    png_set_write_fn(png_ptr, &state, png_write_data_to_buffer, NULL);

    /* we use system default compression */
    /* png_set_filter(png_ptr, 0, PNG_FILTER_NONE |
       PNG_FILTER_SUB | PNG_FILTER_PAETH ); */
    /* png_set_compression...() */

    png_set_IHDR(png_ptr, info_ptr, w, h,
                 8 /* fixed */,
                 PNG_COLOR_TYPE_PALETTE, /* fixed */
                 PNG_INTERLACE_ADAM7,
                 PNG_COMPRESSION_TYPE_DEFAULT,
                 PNG_FILTER_TYPE_DEFAULT );

    {
        png_colorp palette;
        int num_palette;

        PngPalette_val(cmap, &palette, &num_palette );

        if(num_palette <= 0 ) {
            png_destroy_write_struct(&png_ptr, &info_ptr);
            failwith("png write error (null colormap)");
        }
        png_set_PLTE(png_ptr, info_ptr, palette, num_palette );
    }

    /* infos... */

    png_write_info(png_ptr, info_ptr);

    {
        int rowbytes, i;
        png_bytep *row_pointers;
        char *buf = String_val(buffer);

        row_pointers = (png_bytep*)stat_alloc(sizeof(png_bytep) * h);

        rowbytes= png_get_rowbytes(png_ptr, info_ptr);
#if 0
        printf("rowbytes= %d width=%d\n", rowbytes, w);
#endif

        if(rowbytes != w && rowbytes != w * 2) {
            png_destroy_write_struct(&png_ptr, &info_ptr);
            failwith("png write error (illegal byte/pixel)");
        }
        for(i=0; i< h; i++) {
            row_pointers[i] = (png_bytep)(buf + rowbytes * i);
        }

        png_write_image(png_ptr, row_pointers);
        stat_free((void*)row_pointers);
    }

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

    vres = caml_alloc_string(state.size);
    memcpy(String_val(vres), state.buffer, state.size);
    free(state.buffer);
    CAMLreturn(vres);
}
// Method to write raw image into PNG at dest. The raw scanline begins
// at the bottom of the image per SecondLife conventions.
BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest)
{
	try
	{
		S8 numComponents = rawImage->getComponents();
		switch (numComponents)
		{
		case 1:
			mColorType = PNG_COLOR_TYPE_GRAY;
			break;
		case 2:
			mColorType = PNG_COLOR_TYPE_GRAY_ALPHA;
			break;
		case 3:
			mColorType = PNG_COLOR_TYPE_RGB;
			break;
		case 4:
			mColorType = PNG_COLOR_TYPE_RGB_ALPHA;
			break;
		default:
			mColorType = -1;
		}

		if (mColorType == -1)
		{
			throw "Unsupported image: unexpected number of channels";
		}

		mWritePngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
			NULL, &errorHandler, NULL);
		if (!mWritePngPtr)
		{
			throw "Problem creating png write structure";
		}

		mWriteInfoPtr = png_create_info_struct(mWritePngPtr);

		// Setup write function
		PngDataInfo dataPtr;
		dataPtr.mData = dest;
		dataPtr.mOffset = 0;
		png_set_write_fn(mWritePngPtr, &dataPtr, &writeDataCallback, &writeFlush);

		// Setup image params
		mWidth = rawImage->getWidth();
		mHeight = rawImage->getHeight();
		mBitDepth = 8;	// Fixed to 8-bpp in SL
		mChannels = numComponents;
		mInterlaceType = PNG_INTERLACE_NONE;
		mCompressionType = PNG_COMPRESSION_TYPE_DEFAULT;
		mFilterMethod = PNG_FILTER_TYPE_DEFAULT;

		// Write header
		png_set_IHDR(mWritePngPtr, mWriteInfoPtr, mWidth, mHeight,
			mBitDepth, mColorType, mInterlaceType,
			mCompressionType, mFilterMethod);

		// Get data and compute row size
		const U8* data = rawImage->getData();
		int offset = mWidth * mChannels;

		// Ready to write, start with the header
		png_write_info(mWritePngPtr, mWriteInfoPtr);

		// Write image (sorry, must const-cast for libpng)
		const U8 * rowPointer;
		for (U32 i=0; i < mHeight; i++)
		{
			rowPointer = &data[(mHeight-1-i)*offset];
			png_write_row(mWritePngPtr, const_cast<png_bytep>(rowPointer));
		}

		// Finish up
		png_write_end(mWritePngPtr, mWriteInfoPtr);
		mFinalSize = dataPtr.mOffset;
	}
	catch (png_const_charp msg)
	{
		mErrorMessage = msg;
		releaseResources();
		return (FALSE);
	}

	releaseResources();
	return TRUE;
}
Beispiel #17
0
CAMLprim value write_png_file_index(value fd, value buffer, value cmap,
                                    value width, value height) {
    CAMLparam5(fd, buffer, cmap, width, height);

    FILE *fp;
    png_structp png_ptr;
    png_infop info_ptr;

    int w, h;

    w = Int_val(width);
    h = Int_val(height);

    if ((fp = fdopen(Int_val(fd), "wb")) == NULL ) {
        failwith("png file open failed");
    }

    if ((png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
                                           NULL, NULL, NULL)) == NULL ) {
        fclose(fp);
        failwith("png_create_write_struct");
    }

    if((info_ptr = png_create_info_struct(png_ptr)) == NULL ) {
        fclose(fp);
        png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
        failwith("png_create_info_struct");
    }

    /* error handling */
    if (setjmp(png_jmpbuf(png_ptr))) {
        /* Free all of the memory associated with the png_ptr and info_ptr */
        png_destroy_write_struct(&png_ptr, &info_ptr);
        fclose(fp);
        /* If we get here, we had a problem writing the file */
        failwith("png write error");
    }

    /* use standard C stream */
    png_init_io(png_ptr, fp);

    /* we use system default compression */
    /* png_set_filter(png_ptr, 0, PNG_FILTER_NONE |
       PNG_FILTER_SUB | PNG_FILTER_PAETH ); */
    /* png_set_compression...() */

    png_set_IHDR(png_ptr, info_ptr, w, h,
                 8 /* fixed */,
                 PNG_COLOR_TYPE_PALETTE, /* fixed */
                 PNG_INTERLACE_ADAM7,
                 PNG_COMPRESSION_TYPE_DEFAULT,
                 PNG_FILTER_TYPE_DEFAULT );

    {
        png_colorp palette;
        int num_palette;

        PngPalette_val(cmap, &palette, &num_palette );

        if(num_palette <= 0 ) {
            png_destroy_write_struct(&png_ptr, &info_ptr);
            fclose(fp);
            /* If we get here, we had a problem writing the file */
            failwith("png write error (null colormap)");
        }
        png_set_PLTE(png_ptr, info_ptr, palette, num_palette );
    }

    /* infos... */

    png_write_info(png_ptr, info_ptr);

    {
        int rowbytes, i;
        png_bytep *row_pointers;
        char *buf = String_val(buffer);

        row_pointers = (png_bytep*)stat_alloc(sizeof(png_bytep) * h);

        rowbytes= png_get_rowbytes(png_ptr, info_ptr);
#if 0
        printf("rowbytes= %d width=%d\n", rowbytes, w);
#endif

        if(rowbytes != w && rowbytes != w * 2) {
            png_destroy_write_struct(&png_ptr, &info_ptr);
            fclose(fp);
            /* If we get here, we had a problem writing the file */
            failwith("png write error (illegal byte/pixel)");
        }
        for(i=0; i< h; i++) {
            row_pointers[i] = (png_bytep)(buf + rowbytes * i);
        }

        png_write_image(png_ptr, row_pointers);
        stat_free((void*)row_pointers);
    }

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

    fclose(fp);

    CAMLreturn(Val_unit);
}
Beispiel #18
0
bool CCImage::_saveImageToPNG(const char * pszFilePath, bool bIsToRGB)
{
	bool bRet = false;

	do 
	{
		CC_BREAK_IF(NULL == pszFilePath);

		FILE *fp;
		png_structp png_ptr;
		png_infop info_ptr;
		png_colorp palette;
		png_bytep *row_pointers;

		FILE_STANDARD_INFO fileStandardInfo = { 0 };
		HANDLE hFile;
		std::wstring path = CCUtf8ToUnicode(pszFilePath);

		CREATEFILE2_EXTENDED_PARAMETERS extendedParams = {0};
		extendedParams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
		extendedParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
		extendedParams.dwFileFlags = FILE_FLAG_SEQUENTIAL_SCAN;
		extendedParams.dwSecurityQosFlags = SECURITY_ANONYMOUS;
		extendedParams.lpSecurityAttributes = nullptr;
		extendedParams.hTemplateFile = nullptr;

		// read the file from hardware
		hFile = ::CreateFile2(path.c_str(), GENERIC_WRITE, 0, CREATE_ALWAYS, &extendedParams);
		if (INVALID_HANDLE_VALUE == hFile)
		{
			break;
		}

		int CrtFileHandle;
		/* convert OS file handle to CRT file pointer */ 
		if ( (CrtFileHandle=_open_osfhandle ((long)hFile,_O_RDONLY))==-1){ 
			//printf( "_open_osfhandle Failed "); 
			break;
		} 
		/* Change handle access to stream access. */ 
		if( (fp = _fdopen( CrtFileHandle, "wb")) == NULL ) { 
			//printf( "_fdopen Failed "); 
			break;
		} 


		CC_BREAK_IF(NULL == fp);

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

		if (NULL == png_ptr)
		{
			fclose(fp);
			break;
		}

		info_ptr = png_create_info_struct(png_ptr);
		if (NULL == info_ptr)
		{
			fclose(fp);
			png_destroy_write_struct(&png_ptr, NULL);
			break;
		}
#if (CC_TARGET_PLATFORM != CC_PLATFORM_BADA)
		if (setjmp(png_jmpbuf(png_ptr)))
		{
			fclose(fp);
			png_destroy_write_struct(&png_ptr, &info_ptr);
			break;
		}
#endif
		png_init_io(png_ptr, fp);

		if (!bIsToRGB && m_bHasAlpha)
		{
			png_set_IHDR(png_ptr, info_ptr, m_nWidth, m_nHeight, 8, PNG_COLOR_TYPE_RGB_ALPHA,
				PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
		} 
		else
		{
			png_set_IHDR(png_ptr, info_ptr, m_nWidth, m_nHeight, 8, PNG_COLOR_TYPE_RGB,
				PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
		}

		palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH * sizeof (png_color));
		png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH);

		png_write_info(png_ptr, info_ptr);

		png_set_packing(png_ptr);

		row_pointers = (png_bytep *)malloc(m_nHeight * sizeof(png_bytep));
		if(row_pointers == NULL)
		{
			fclose(fp);
			png_destroy_write_struct(&png_ptr, &info_ptr);
			break;
		}

		if (!m_bHasAlpha)
		{
			for (int i = 0; i < (int)m_nHeight; i++)
			{
				row_pointers[i] = (png_bytep)m_pData + i * m_nWidth * 3;
			}

			png_write_image(png_ptr, row_pointers);

			free(row_pointers);
			row_pointers = NULL;
		}
		else
		{
			if (bIsToRGB)
			{
				unsigned char *pTempData = new unsigned char[m_nWidth * m_nHeight * 3];
				if (NULL == pTempData)
				{
					fclose(fp);
					png_destroy_write_struct(&png_ptr, &info_ptr);
					break;
				}

				for (int i = 0; i < m_nHeight; ++i)
				{
					for (int j = 0; j < m_nWidth; ++j)
					{
						pTempData[(i * m_nWidth + j) * 3] = m_pData[(i * m_nWidth + j) * 4];
						pTempData[(i * m_nWidth + j) * 3 + 1] = m_pData[(i * m_nWidth + j) * 4 + 1];
						pTempData[(i * m_nWidth + j) * 3 + 2] = m_pData[(i * m_nWidth + j) * 4 + 2];
					}
				}

				for (int i = 0; i < (int)m_nHeight; i++)
				{
					row_pointers[i] = (png_bytep)pTempData + i * m_nWidth * 3;
				}

				png_write_image(png_ptr, row_pointers);

				free(row_pointers);
				row_pointers = NULL;

				CC_SAFE_DELETE_ARRAY(pTempData);
			} 
			else
			{
				for (int i = 0; i < (int)m_nHeight; i++)
				{
					row_pointers[i] = (png_bytep)m_pData + i * m_nWidth * 4;
				}

				png_write_image(png_ptr, row_pointers);

				free(row_pointers);
				row_pointers = NULL;
			}
		}

		png_write_end(png_ptr, info_ptr);

		png_free(png_ptr, palette);
		palette = NULL;

		png_destroy_write_struct(&png_ptr, &info_ptr);

		fclose(fp);

		bRet = true;
	} while (0);
	return bRet;
}
Beispiel #19
0
bool  PngEncoder::write( const Mat& img, const vector<int>& params )
{
    png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 );
    png_infop info_ptr = 0;
    FILE* f = 0;
    int y, width = img.cols, height = img.rows;
    int depth = img.depth(), channels = img.channels();
    bool result = false;
    AutoBuffer<uchar*> buffer;

    if( depth != CV_8U && depth != CV_16U )
        return false;

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

        if( info_ptr )
        {
            if( setjmp( png_jmpbuf ( png_ptr ) ) == 0 )
            {
                if( m_buf )
                {
                    png_set_write_fn(png_ptr, this,
                        (png_rw_ptr)writeDataToBuf, (png_flush_ptr)flushBuf);
                }
                else
                {
                    f = fopen( m_filename.c_str(), "wb" );
                    if( f )
                        png_init_io( png_ptr, f );
                }

                int compression_level = -1; // Invalid value to allow setting 0-9 as valid
                int compression_strategy = Z_RLE; // Default strategy
                bool isBilevel = false;

                for( size_t i = 0; i < params.size(); i += 2 )
                {
                    if( params[i] == CV_IMWRITE_PNG_COMPRESSION )
                    {
                        compression_level = params[i+1];
                        compression_level = MIN(MAX(compression_level, 0), Z_BEST_COMPRESSION);
                    }
                    if( params[i] == CV_IMWRITE_PNG_STRATEGY )
                    {
                        compression_strategy = params[i+1];
                        compression_strategy = MIN(MAX(compression_strategy, 0), Z_FIXED);
                    }
                    if( params[i] == CV_IMWRITE_PNG_BILEVEL )
                    {
                        isBilevel = params[i+1] != 0;
                    }
                }

                if( m_buf || f )
                {
                    if( compression_level >= 0 )
                    {
                        png_set_compression_level( png_ptr, compression_level );
                    }
                    else
                    {
                        // tune parameters for speed
                        // (see http://wiki.linuxquestions.org/wiki/Libpng)
                        png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_FILTER_SUB);
                        png_set_compression_level(png_ptr, Z_BEST_SPEED);
                    }
                    png_set_compression_strategy(png_ptr, compression_strategy);

                    png_set_IHDR( png_ptr, info_ptr, width, height, depth == CV_8U ? isBilevel?1:8 : 16,
                        channels == 1 ? PNG_COLOR_TYPE_GRAY :
                        channels == 3 ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGBA,
                        PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
                        PNG_FILTER_TYPE_DEFAULT );

                    png_write_info( png_ptr, info_ptr );

                    if (isBilevel)
                        png_set_packing(png_ptr);

                    png_set_bgr( png_ptr );
                    if( !isBigEndian() )
                        png_set_swap( png_ptr );

                    buffer.allocate(height);
                    for( y = 0; y < height; y++ )
                        buffer[y] = img.data + y*img.step;

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

                    result = true;
                }
            }
        }
    }

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

    return result;
}
Beispiel #20
0
bool wxPNGHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbose )
{
    wxPNGInfoStruct wxinfo;

    wxinfo.verbose = verbose;
    wxinfo.stream.out = &stream;

    png_structp png_ptr = png_create_write_struct
                          (
                            PNG_LIBPNG_VER_STRING,
                            NULL,
                            wx_png_error,
                            wx_png_warning
                          );
    if (!png_ptr)
    {
        if (verbose)
           wxLogError(_("Couldn't save PNG image."));
        return false;
    }

    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL)
    {
        png_destroy_write_struct( &png_ptr, (png_infopp)NULL );
        if (verbose)
           wxLogError(_("Couldn't save PNG image."));
        return false;
    }

    if (setjmp(wxinfo.jmpbuf))
    {
        png_destroy_write_struct( &png_ptr, (png_infopp)NULL );
        if (verbose)
           wxLogError(_("Couldn't save PNG image."));
        return false;
    }

    // NB: please see the comment near wxPNGInfoStruct declaration for
    //     explanation why this line is mandatory
    png_set_write_fn( png_ptr, &wxinfo, wx_PNG_stream_writer, NULL);

    const int iColorType = image->HasOption(wxIMAGE_OPTION_PNG_FORMAT)
                            ? image->GetOptionInt(wxIMAGE_OPTION_PNG_FORMAT)
                            : wxPNG_TYPE_COLOUR;
    const int iBitDepth = image->HasOption(wxIMAGE_OPTION_PNG_BITDEPTH)
                            ? image->GetOptionInt(wxIMAGE_OPTION_PNG_BITDEPTH)
                            : 8;

    wxASSERT_MSG( iBitDepth == 8 || iBitDepth == 16,
                    _T("PNG bit depth must be 8 or 16") );

    bool bHasAlpha = image->HasAlpha();
    bool bHasMask = image->HasMask();
    bool bUseAlpha = bHasAlpha || bHasMask;

    int iPngColorType;
    if ( iColorType==wxPNG_TYPE_COLOUR )
    {
        iPngColorType = bUseAlpha ? PNG_COLOR_TYPE_RGB_ALPHA
                                  : PNG_COLOR_TYPE_RGB;
    }
    else
    {
        iPngColorType = bUseAlpha ? PNG_COLOR_TYPE_GRAY_ALPHA
                                  : PNG_COLOR_TYPE_GRAY;
    }

    png_set_IHDR( png_ptr, info_ptr, image->GetWidth(), image->GetHeight(),
                  iBitDepth, iPngColorType,
                  PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
                  PNG_FILTER_TYPE_BASE);

    int iElements;
    png_color_8 sig_bit;

    if ( iPngColorType & PNG_COLOR_MASK_COLOR )
    {
        sig_bit.red =
        sig_bit.green =
        sig_bit.blue = (png_byte)iBitDepth;
        iElements = 3;
    }
    else // grey
    {
        sig_bit.gray = (png_byte)iBitDepth;
        iElements = 1;
    }

    if ( iPngColorType & PNG_COLOR_MASK_ALPHA )
    {
        sig_bit.alpha = (png_byte)iBitDepth;
        iElements++;
    }

    if ( iBitDepth == 16 )
        iElements *= 2;

    png_set_sBIT( png_ptr, info_ptr, &sig_bit );
    png_write_info( png_ptr, info_ptr );
    png_set_shift( png_ptr, &sig_bit );
    png_set_packing( png_ptr );

    unsigned char *
        data = (unsigned char *)malloc( image->GetWidth() * iElements );
    if ( !data )
    {
        png_destroy_write_struct( &png_ptr, (png_infopp)NULL );
        return false;
    }

    unsigned char *
        pAlpha = (unsigned char *)(bHasAlpha ? image->GetAlpha() : NULL);
    int iHeight = image->GetHeight();
    int iWidth = image->GetWidth();

    unsigned char uchMaskRed = 0, uchMaskGreen = 0, uchMaskBlue = 0;

    if ( bHasMask )
    {
        uchMaskRed = image->GetMaskRed();
        uchMaskGreen = image->GetMaskGreen();
        uchMaskBlue = image->GetMaskBlue();
    }

    unsigned char *pColors = image->GetData();

    for (int y = 0; y != iHeight; ++y)
    {
        unsigned char *pData = data;
        for (int x = 0; x != iWidth; x++)
        {
            unsigned char uchRed = *pColors++;
            unsigned char uchGreen = *pColors++;
            unsigned char uchBlue = *pColors++;

            switch ( iColorType )
            {
                default:
                    wxFAIL_MSG( _T("unknown wxPNG_TYPE_XXX") );
                    // fall through

                case wxPNG_TYPE_COLOUR:
                    *pData++ = uchRed;
                    if ( iBitDepth == 16 )
                        *pData++ = 0;
                    *pData++ = uchGreen;
                    if ( iBitDepth == 16 )
                        *pData++ = 0;
                    *pData++ = uchBlue;
                    if ( iBitDepth == 16 )
                        *pData++ = 0;
                    break;

                case wxPNG_TYPE_GREY:
                    {
                        // where do these coefficients come from? maybe we
                        // should have image options for them as well?
                        unsigned uiColor =
                            (unsigned) (76.544*(unsigned)uchRed +
                                        150.272*(unsigned)uchGreen +
                                        36.864*(unsigned)uchBlue);

                        *pData++ = (unsigned char)((uiColor >> 8) & 0xFF);
                        if ( iBitDepth == 16 )
                            *pData++ = (unsigned char)(uiColor & 0xFF);
                    }
                    break;

                case wxPNG_TYPE_GREY_RED:
                    *pData++ = uchRed;
                    if ( iBitDepth == 16 )
                        *pData++ = 0;
                    break;
            }

            if ( bUseAlpha )
            {
                unsigned char uchAlpha = 255;
                if ( bHasAlpha )
                    uchAlpha = *pAlpha++;

                if ( bHasMask )
                {
                    if ( (uchRed == uchMaskRed)
                            && (uchGreen == uchMaskGreen)
                                && (uchBlue == uchMaskBlue) )
                        uchAlpha = 0;
                }

                *pData++ = uchAlpha;
                if ( iBitDepth == 16 )
                    *pData++ = 0;
            }
        }

        png_bytep row_ptr = data;
        png_write_rows( png_ptr, &row_ptr, 1 );
    }

    free(data);
    png_write_end( png_ptr, info_ptr );
    png_destroy_write_struct( &png_ptr, (png_infopp)&info_ptr );

    return true;
}
void fr_io_png_dump(fr_t * fr, FILE *fp) {
    log_debug("png io dump started");

    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL;

    // Initialize write structure
    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (png_ptr == NULL) {
        log_error("Couldn't create PNG write struct");
    }

    // Initialize info structure
    info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL) {
        log_error("Couldn't create PNG info struct");
    }

    // Setup Exception handling
    if (setjmp(png_jmpbuf(png_ptr))) {
        log_error("Error during PNG creation");
    }

    png_init_io(png_ptr, fp);

    log_trace("png header writing started");

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

    log_trace("png header ended started");


    char * title = "fractalrender";

    // Set title
    if (title != NULL) {
        png_text title_text;
        title_text.compression = PNG_TEXT_COMPRESSION_NONE;
        title_text.key = "Title";
        title_text.text = title;
        png_set_text(png_ptr, info_ptr, &title_text, 1);
    }

    log_trace("png info writing started");

    png_write_info(png_ptr, info_ptr);

    log_trace("png info writing ended");

    log_trace("png pixel writing started");

    int y;
    for (y = 0; y < fr->dim.height; y++) {
        png_write_row(png_ptr, fr->bitmap + 4 * fr->dim.width * y);
    }
    
    log_trace("png pixel writing ended");


    // End write
    png_write_end(png_ptr, NULL);

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

    log_debug("png io dump ended");

}
int
main(
    int argc,
    char *argv[])
{
    int opt = 0;

    bool writeToStdout = false;
    char *pngName = DEFAULT_NAME;
    int32_t requestedWidth = 0;
    int32_t requestedHeight = 0;
    uint32_t displayNumber = DEFAULT_DISPLAY_NUMBER;
    int compression = Z_DEFAULT_COMPRESSION;
    int delay = DEFAULT_DELAY;

    VC_IMAGE_TYPE_T imageType = VC_IMAGE_RGBA32;
    int8_t dmxBytesPerPixel  = 4;

    int result = 0;

    program = basename(argv[0]);

    //-------------------------------------------------------------------

    char *sopts = "c:d:D:Hh:p:w:s";

    struct option lopts[] =
    {
        { "compression", required_argument, NULL, 'c' },
        { "delay", required_argument, NULL, 'd' },
        { "display", required_argument, NULL, 'D' },
        { "height", required_argument, NULL, 'h' },
        { "help", no_argument, NULL, 'H' },
        { "pngname", required_argument, NULL, 'p' },
        { "width", required_argument, NULL, 'w' },
        { "stdout", no_argument, NULL, 's' },
        { NULL, no_argument, NULL, 0 }
    };

    while ((opt = getopt_long(argc, argv, sopts, lopts, NULL)) != -1)
    {
        switch (opt)
        {
        case 'c':

            compression = atoi(optarg);

            if ((compression < 0) || (compression > 9))
            {
                compression = Z_DEFAULT_COMPRESSION;
            }

            break;

        case 'd':

            delay = atoi(optarg);
            break;

        case 'D':

            displayNumber = atoi(optarg);
            break;

        case 'h':

            requestedHeight = atoi(optarg);
            break;

        case 'p':

            pngName = optarg;
            break;

        case 'w':

            requestedWidth = atoi(optarg);
            break;

        case 's':

            writeToStdout = true;
            break;

        case 'H':
        default:

            usage();

            if (opt == 'H')
            {
                exit(EXIT_SUCCESS);
            }
            else
            {
                exit(EXIT_FAILURE);
            }

            break;
        }
    }

    //-------------------------------------------------------------------

    bcm_host_init();

    //-------------------------------------------------------------------
    //
    // When the display is rotate (either 90 or 270 degrees) we need to
    // swap the width and height of the snapshot
    //

    char response[1024];
    int displayRotated = 0;

    if (vc_gencmd(response, sizeof(response), "get_config int") == 0)
    {
        vc_gencmd_number_property(response,
                                  "display_rotate",
                                  &displayRotated);
    }

    //-------------------------------------------------------------------

    if (delay)
    {
        sleep(delay);
    }

    //-------------------------------------------------------------------

    DISPMANX_DISPLAY_HANDLE_T displayHandle
        = vc_dispmanx_display_open(displayNumber);

    if (displayHandle == 0)
    {
        fprintf(stderr,
                "%s: unable to open display %d\n",
                program,
                displayNumber);

        exit(EXIT_FAILURE);
    }

    DISPMANX_MODEINFO_T modeInfo;
    result = vc_dispmanx_display_get_info(displayHandle, &modeInfo);

    if (result != 0)
    {
        fprintf(stderr, "%s: unable to get display information\n", program);
        exit(EXIT_FAILURE);
    }

    int32_t pngWidth = modeInfo.width;
    int32_t pngHeight = modeInfo.height;

    if (requestedWidth > 0)
    {
        pngWidth = requestedWidth;

        if (requestedHeight == 0)
        {
            double numerator = modeInfo.height * requestedWidth;
            double denominator = modeInfo.width;

            pngHeight = (int32_t)ceil(numerator / denominator);
        }
    }

    if (requestedHeight > 0)
    {
        pngHeight = requestedHeight;

        if (requestedWidth == 0)
        {
            double numerator = modeInfo.width * requestedHeight;
            double denominator = modeInfo.height;

            pngWidth = (int32_t)ceil(numerator / denominator);
        }
    }

    //-------------------------------------------------------------------
    // only need to check low bit of displayRotated (value of 1 or 3).
    // If the display is rotated either 90 or 270 degrees (value 1 or 3)
    // the width and height need to be transposed.

    int32_t dmxWidth = pngWidth;
    int32_t dmxHeight = pngHeight;

    if (displayRotated & 1)
    {
        dmxWidth = pngHeight;
        dmxHeight = pngWidth;
    }

    int32_t dmxPitch = dmxBytesPerPixel * ALIGN_TO_16(dmxWidth);

    void *dmxImagePtr = malloc(dmxPitch * dmxHeight);

    if (dmxImagePtr == NULL)
    {
        fprintf(stderr, "%s: unable to allocated image buffer\n", program);
        exit(EXIT_FAILURE);
    }

    //-------------------------------------------------------------------

    uint32_t vcImagePtr = 0;
    DISPMANX_RESOURCE_HANDLE_T resourceHandle;
    resourceHandle = vc_dispmanx_resource_create(imageType,
                                                 dmxWidth,
                                                 dmxHeight,
                                                 &vcImagePtr);

    result = vc_dispmanx_snapshot(displayHandle,
                                  resourceHandle,
                                  DISPMANX_NO_ROTATE);

    if (result != 0)
    {
        vc_dispmanx_resource_delete(resourceHandle);
        vc_dispmanx_display_close(displayHandle);

        fprintf(stderr, "%s: vc_dispmanx_snapshot() failed\n", program);
        exit(EXIT_FAILURE);
    }

    VC_RECT_T rect;
    result = vc_dispmanx_rect_set(&rect, 0, 0, dmxWidth, dmxHeight);

    if (result != 0)
    {
        vc_dispmanx_resource_delete(resourceHandle);
        vc_dispmanx_display_close(displayHandle);

        fprintf(stderr, "%s: vc_dispmanx_rect_set() failed\n", program);
        exit(EXIT_FAILURE);
    }

    result = vc_dispmanx_resource_read_data(resourceHandle,
                                            &rect,
                                            dmxImagePtr,
                                            dmxPitch);


    if (result != 0)
    {
        vc_dispmanx_resource_delete(resourceHandle);
        vc_dispmanx_display_close(displayHandle);

        fprintf(stderr,
                "%s: vc_dispmanx_resource_read_data() failed\n",
                program);

        exit(EXIT_FAILURE);
    }

    vc_dispmanx_resource_delete(resourceHandle);
    vc_dispmanx_display_close(displayHandle);

    //-------------------------------------------------------------------
    // Convert from RGBA (32 bit) to RGB (24 bit)

    int8_t pngBytesPerPixel = 3;
    int32_t pngPitch = pngBytesPerPixel * pngWidth;
    void *pngImagePtr = malloc(pngPitch * pngHeight);

    int32_t j = 0;
    for (j = 0 ; j < pngHeight ; j++)
    {
        int32_t dmxXoffset = 0;
        int32_t dmxYoffset = 0;

        switch (displayRotated & 3)
        {
        case 0: // 0 degrees

            if (displayRotated & 0x20000) // flip vertical
            {
                dmxYoffset = (dmxHeight - j - 1) * dmxPitch;
            }
            else
            {
                dmxYoffset = j * dmxPitch;
            }

            break;

        case 1: // 90 degrees


            if (displayRotated & 0x20000) // flip vertical
            {
                dmxXoffset = j * dmxBytesPerPixel;
            }
            else
            {
                dmxXoffset = (dmxWidth - j - 1) * dmxBytesPerPixel;
            }

            break;

        case 2: // 180 degrees

            if (displayRotated & 0x20000) // flip vertical
            {
                dmxYoffset = j * dmxPitch;
            }
            else
            {
                dmxYoffset = (dmxHeight - j - 1) * dmxPitch;
            }

            break;

        case 3: // 270 degrees

            if (displayRotated & 0x20000) // flip vertical
            {
                dmxXoffset = (dmxWidth - j - 1) * dmxBytesPerPixel;
            }
            else
            {
                dmxXoffset = j * dmxBytesPerPixel;
            }

            break;
        }

        int32_t i = 0;
        for (i = 0 ; i < pngWidth ; i++)
        {
            uint8_t *pngPixelPtr = pngImagePtr
                                 + (i * pngBytesPerPixel)
                                 + (j * pngPitch);

            switch (displayRotated & 3)
            {
            case 0: // 0 degrees

                if (displayRotated & 0x10000) // flip horizontal
                {
                    dmxXoffset = (dmxWidth - i - 1) * dmxBytesPerPixel;
                }
                else
                {
                    dmxXoffset = i * dmxBytesPerPixel;
                }

                break;

            case 1: // 90 degrees

                if (displayRotated & 0x10000) // flip horizontal
                {
                    dmxYoffset = (dmxHeight - i - 1) * dmxPitch;
                }
                else
                {
                    dmxYoffset = i * dmxPitch;
                }

                break;

            case 2: // 180 degrees

                if (displayRotated & 0x10000) // flip horizontal
                {
                    dmxXoffset = i * dmxBytesPerPixel;
                }
                else
                {
                    dmxXoffset = (dmxWidth - i - 1) * dmxBytesPerPixel;
                }

                break;

            case 3: // 270 degrees

                if (displayRotated & 0x10000) // flip horizontal
                {
                    dmxYoffset = i * dmxPitch;
                }
                else
                {
                    dmxYoffset = (dmxHeight - i - 1) * dmxPitch;
                }

                break;
            }

            uint8_t *dmxPixelPtr = dmxImagePtr + dmxXoffset + dmxYoffset;

            memcpy(pngPixelPtr, dmxPixelPtr, 3);
        }
    }

    free(dmxImagePtr);
    dmxImagePtr = NULL;

    //-------------------------------------------------------------------

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

    if (pngPtr == NULL)
    {
        fprintf(stderr,
                "%s: unable to allocated PNG write structure\n",
                program);

        exit(EXIT_FAILURE);
    }

    png_infop infoPtr = png_create_info_struct(pngPtr);

    if (infoPtr == NULL)
    {
        fprintf(stderr,
                "%s: unable to allocated PNG info structure\n",
                program);

        exit(EXIT_FAILURE);
    }

    if (setjmp(png_jmpbuf(pngPtr)))
    {
        fprintf(stderr, "%s: unable to create PNG\n", program);
        exit(EXIT_FAILURE);
    }

    FILE *pngfp = NULL;

    if (writeToStdout)
    {
        pngfp = stdout;
    }
    else
    {
        pngfp = fopen(pngName, "wb");

        if (pngfp == NULL)
        {
            fprintf(stderr,
                    "%s: unable to create %s - %s\n",
                    program,
                    pngName,
                    strerror(errno));

            exit(EXIT_FAILURE);
        }
    }

    png_init_io(pngPtr, pngfp);

    png_set_IHDR(
        pngPtr,
        infoPtr,
        pngWidth,
        pngHeight,
        8,
        PNG_COLOR_TYPE_RGB,
        PNG_INTERLACE_NONE,
        PNG_COMPRESSION_TYPE_BASE,
        PNG_FILTER_TYPE_BASE);

    if (compression != Z_DEFAULT_COMPRESSION)
    {
        png_set_compression_level(pngPtr, compression);
    }

    png_write_info(pngPtr, infoPtr);

    int y = 0;
    for (y = 0; y < pngHeight; y++)
    {
        png_write_row(pngPtr, pngImagePtr + (pngPitch * y));
    }

    png_write_end(pngPtr, NULL);
    png_destroy_write_struct(&pngPtr, &infoPtr);

    if (pngfp != stdout)
    {
        fclose(pngfp);
    }

    //-------------------------------------------------------------------

    free(pngImagePtr);
    pngImagePtr = NULL;

    return 0;
}
Beispiel #23
0
static	BOOL SaveBmpToPNGfile(HBITMAP hbmp,LPTSTR file)
{
	BITMAP	bmp;
	FILE * fp = NULL;
	
	if(!GetObject(hbmp,sizeof(BITMAP),&bmp))return FALSE;

	fp = _tfopen(file,TEXT("wb"));

	if(!fp)
	{
		DeleteObject(hbmp);
		return FALSE;
	}

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

	if(!png_ptr)
	{
		DeleteObject(hbmp);
		return FALSE;
	}

	png_infop png_info_ptr =  png_create_info_struct(png_ptr);

	if(!png_info_ptr)
	{
		DeleteObject(hbmp);
		png_destroy_write_struct(&png_ptr,NULL);
		return FALSE;
	}
	
	if(setjmp(png_jmpbuf(png_ptr)))
	{
		png_destroy_write_struct(&png_ptr,&png_info_ptr);
		fclose(fp);
		DeleteFile(file);
		DeleteObject(hbmp);
		return FALSE;
	}

	int color = PNG_COLOR_TYPE_RGB_ALPHA;
	if(bmp.bmBitsPixel < 32)
		color = PNG_COLOR_TYPE_RGB;
	
	LONG	row_length;
	BYTE * row_bytes;
	PBYTE * rows_bytes  =(PBYTE*) malloc( bmp.bmHeight * sizeof(png_byte *));

	row_length =bmp.bmHeight * bmp.bmWidthBytes;

	row_bytes = (PBYTE) png_malloc(png_ptr,row_length);
		
	GetBitmapBits(hbmp,row_length,row_bytes);	

	if(bmp.bmBitsPixel >=24)
	{
		for ( LONG i=0 ,j=0; i < bmp.bmHeight ; i ++ ,j +=bmp.bmWidthBytes )
		{
			rows_bytes[i] = row_bytes + j;
			if(color & PNG_COLOR_MASK_ALPHA)		
				for(LONG k=0; k < bmp.bmWidthBytes ; k+= 4)
					rows_bytes[i][k+3] = 255;		
		}
	}else //16 bit
	{

		for (int i =0; i < bmp.bmHeight ; i ++)
		{
			rows_bytes[i] =(PBYTE) malloc(bmp.bmWidth * 3);

			for(int  j=0,k=0; j < bmp.bmWidthBytes; j+=2, k+=3)
			{

				WORD   Color;//存16bit的颜色 

				double   Red,Green,Blue; 

				Color = *(PWORD)(row_bytes + i * bmp.bmWidthBytes + j );


				Blue=(Color&0xF800)>> 11; 

				Green=(Color&0x7e0)>> 5; 
				
				Red=(Color&0x1F);

				rows_bytes[i][k] = (BYTE)(Red * 256  / 32 +0.5);
				rows_bytes[i][k+1] = (BYTE)(Green * 256  / 64 +0.5);
				rows_bytes[i][k+2] = (BYTE)(Blue * 256  / 32 +0.5);
			}
		}
	}
	
	png_set_IHDR(png_ptr,png_info_ptr,bmp.bmWidth,bmp.bmHeight,8,
		color, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
		PNG_FILTER_TYPE_BASE);

	png_init_io(png_ptr,fp);

	png_set_rows(png_ptr,png_info_ptr,rows_bytes);

	png_set_bgr(png_ptr);

	//crc32(0, Z_NULL, 0);

	png_write_png(png_ptr, png_info_ptr,0,0);

	png_write_end(png_ptr,png_info_ptr);

	png_destroy_write_struct(&png_ptr, &png_info_ptr);

	if(!(color & PNG_COLOR_MASK_ALPHA))
	{
		for(int i = 0; i < bmp.bmHeight ; i++)
		{
			free(rows_bytes[i]);
		}
	}

	free(rows_bytes);
	free(row_bytes);	
	DeleteObject(hbmp);
	fclose(fp);
	return TRUE;
}
Beispiel #24
0
int writePNG(struct opj_res *res, char *title, unsigned xPos, unsigned yPos, unsigned w, unsigned h, unsigned num_comps) {
	int code = 0;

	if(w == 0) { w = res->image->comps[0].w; }
	if(h == 0) { h = res->image->comps[0].h; }
	if(xPos >= res->image->comps[0].w) { xPos = 0; }
	if(yPos >= res->image->comps[0].h) { yPos = 0; }
	if(xPos + w >= res->image->comps[0].w) { w =	res->image->comps[0].w - xPos; }
	if(yPos + h >= res->image->comps[0].h) { h =	res->image->comps[0].h - yPos; }

	png_structp png_ptr;
	png_infop info_ptr;
	png_bytep row;

	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (png_ptr == NULL) {
		code = 1;
		goto finalise;
	}

	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL) {
		code = 1;
		goto finalise;
	}

	if (setjmp(png_jmpbuf(png_ptr))) {
		code = 1;
		goto finalise;
	}


	png_init_io(png_ptr, stdout);


	png_set_IHDR(png_ptr, info_ptr, w, h,
			8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
			PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);


	if (title != NULL) {
		png_text title_text;
		title_text.compression = PNG_TEXT_COMPRESSION_NONE;
		title_text.key = "Title";
		title_text.text = title;
		png_set_text(png_ptr, info_ptr, &title_text, 1);
	}

	png_write_info(png_ptr, info_ptr);

	row = (png_bytep) malloc(3 * w * sizeof(png_byte));


	unsigned x, y;
	for (y = yPos ; y < yPos + h ; y++) {
		for (x = xPos ; x < xPos + w ; x++) {
			int i = y * res->image->comps[0].w + x;
			if(num_comps < 3) {
				setRGB(&(row[(x-xPos)*3]), res->image->comps[0].data[i], res->image->comps[0].data[i], res->image->comps[0].data[i]);
			} else {
				setRGB(&(row[(x-xPos)*3]), res->image->comps[0].data[i], res->image->comps[1].data[i], res->image->comps[2].data[i]);
			}
		}
		png_write_row(png_ptr, row);
	}

	png_write_end(png_ptr, NULL);

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

	return code;
}
Beispiel #25
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 #26
0
/**
 * Write png to file
 * Return:
 *		0		 OK
 *		negative ERROR
 */
int write_png(const char *path, const Bitmap_t *mem)
{
    VALIDATE_NOT_NULL2(path, mem);
    FILE *fp;
    png_structp png_ptr;
    png_infop info_ptr;
    png_colorp palette;

    fp = fopen(path, "wb");
    if (NULL == fp) {
        LogE("Failed open file\n");
        return -1;
    }

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

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

    if (setjmp(png_jmpbuf(png_ptr))) {
        LogE("write file occur error");
        fclose(fp);
        png_destroy_write_struct(&png_ptr, &info_ptr);
        return -1;
    }

    int form = PNG_COLOR_TYPE_RGB_ALPHA;
    int depth = 8;
    switch (mem->form) {
        case RGBA32:
            form = PNG_COLOR_TYPE_RGBA;
            break;

        case RGB24:
            form = PNG_COLOR_TYPE_RGB;
            break;

        case GRAY:
            form = PNG_COLOR_TYPE_GRAY;
            depth = 1;
            break;
    }

    png_init_io(png_ptr, fp);
    png_set_IHDR(png_ptr, info_ptr, mem->width, mem->height, depth, form, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
    png_write_info(png_ptr, info_ptr);
    png_bytep row_pointers[mem->height];
    int k;
    for (k = 0; k < mem->height; ++k) {
        row_pointers[k] = mem->base + k * mem->width * mem->form;
    }
    png_write_image(png_ptr, row_pointers);
    png_write_end(png_ptr, info_ptr);
    png_destroy_write_struct(&png_ptr, &info_ptr);
    fclose (fp);

    return 0;
}
Beispiel #27
0
static GstFlowReturn
gst_pngenc_chain (GstPad * pad, GstBuffer * buf)
{
  GstPngEnc *pngenc;
  gint row_index;
  gint color_type;
  png_byte *row_pointers[MAX_HEIGHT];
  GstFlowReturn ret = GST_FLOW_OK;
  GstBuffer *encoded_buf = NULL;

  pngenc = GST_PNGENC (gst_pad_get_parent (pad));

  GST_DEBUG_OBJECT (pngenc, "BEGINNING");

  /* initialize png struct stuff */
  pngenc->png_struct_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING,
      (png_voidp) NULL, user_error_fn, user_warning_fn);
  if (pngenc->png_struct_ptr == NULL) {
    gst_buffer_unref (buf);
    GST_ELEMENT_ERROR (pngenc, LIBRARY, INIT, (NULL),
        ("Failed to initialize png structure"));
    ret = GST_FLOW_ERROR;
    goto done;
  }

  pngenc->png_info_ptr = png_create_info_struct (pngenc->png_struct_ptr);
  if (!pngenc->png_info_ptr) {
    gst_buffer_unref (buf);
    png_destroy_write_struct (&(pngenc->png_struct_ptr), (png_infopp) NULL);
    GST_ELEMENT_ERROR (pngenc, LIBRARY, INIT, (NULL),
        ("Failed to initialize the png info structure"));
    ret = GST_FLOW_ERROR;
    goto done;
  }

  /* non-0 return is from a longjmp inside of libpng */
  if (setjmp (png_jmpbuf (pngenc->png_struct_ptr)) != 0) {
    gst_buffer_unref (buf);
    png_destroy_write_struct (&pngenc->png_struct_ptr, &pngenc->png_info_ptr);
    GST_ELEMENT_ERROR (pngenc, LIBRARY, FAILED, (NULL),
        ("returning from longjmp"));
    ret = GST_FLOW_ERROR;
    goto done;
  }

  png_set_filter (pngenc->png_struct_ptr, 0,
      PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE);
  png_set_compression_level (pngenc->png_struct_ptr, pngenc->compression_level);

  if (pngenc->bpp == 32)
    color_type = PNG_COLOR_TYPE_RGBA;
  else if (pngenc->bpp == 8)
    color_type = PNG_COLOR_TYPE_GRAY;
  else
    color_type = PNG_COLOR_TYPE_RGB;

  png_set_IHDR (pngenc->png_struct_ptr,
      pngenc->png_info_ptr,
      pngenc->width,
      pngenc->height,
      8,
      color_type,
      PNG_INTERLACE_NONE,
      PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

  png_set_write_fn (pngenc->png_struct_ptr, pngenc,
      (png_rw_ptr) user_write_data, user_flush_data);

  for (row_index = 0; row_index < pngenc->height; row_index++) {
    row_pointers[row_index] = GST_BUFFER_DATA (buf) +
        (row_index * pngenc->stride);
  }

  /* allocate the output buffer */
  pngenc->buffer_out =
      gst_buffer_new_and_alloc (pngenc->height * pngenc->stride);
  pngenc->written = 0;

  png_write_info (pngenc->png_struct_ptr, pngenc->png_info_ptr);
  png_write_image (pngenc->png_struct_ptr, row_pointers);
  png_write_end (pngenc->png_struct_ptr, NULL);

  encoded_buf = gst_buffer_create_sub (pngenc->buffer_out, 0, pngenc->written);

  png_destroy_info_struct (pngenc->png_struct_ptr, &pngenc->png_info_ptr);
  png_destroy_write_struct (&pngenc->png_struct_ptr, (png_infopp) NULL);
  gst_buffer_copy_metadata (encoded_buf, buf, GST_BUFFER_COPY_TIMESTAMPS);
  gst_buffer_unref (buf);
  gst_buffer_set_caps (encoded_buf, GST_PAD_CAPS (pngenc->srcpad));

  if ((ret = gst_pad_push (pngenc->srcpad, encoded_buf)) != GST_FLOW_OK)
    goto done;

  if (pngenc->snapshot) {
    GstEvent *event;

    GST_DEBUG_OBJECT (pngenc, "snapshot mode, sending EOS");
    /* send EOS event, since a frame has been pushed out */
    event = gst_event_new_eos ();

    gst_pad_push_event (pngenc->srcpad, event);
    ret = GST_FLOW_UNEXPECTED;
  }

done:
  GST_DEBUG_OBJECT (pngenc, "END, ret:%d", ret);

  if (pngenc->buffer_out != NULL) {
    gst_buffer_unref (pngenc->buffer_out);
    pngenc->buffer_out = NULL;
  }

  gst_object_unref (pngenc);
  return ret;
}
Beispiel #28
0
/* 
   Dump an image to a Portable Network Graphics (PNG) file. File_name
   is where the file goes, i_height and i_width are the height and
   width in pixels of the image. The data for the image is stored as a
   linear array of one byte for each of red, green, and blue
   components of an RGB pixel. Thus row[i] will begin at rgb_image +
   i*(i_width*3) and the blue pixel at image[i][0] would be rgb_image +
   i*(i_width*3) + 1.
   
 */
void 
write_png(const char *file_name, png_uint_32 i_height, png_uint_32 i_width,
	  void *rgb_image, /*in*/ png_text *text_ptr, int i_text_count )
{
  FILE *fp;
  png_structp png_ptr;
  png_infop info_ptr;
  png_color_8 sig_bit;
  png_bytep *row_pointers;

  unsigned int i,j;

  /* open the file */
  fp = fopen(file_name, "wb");
  if (fp == NULL)
    return;
  
  /* 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, (png_voidp) NULL,
				    user_error_fn, user_warning_fn);
  
  if (png_ptr == NULL)
    {
      fclose(fp);
      return;
    }
  
  /* Allocate/initialize the image information data.  REQUIRED */
  info_ptr = png_create_info_struct(png_ptr);
  if (info_ptr == NULL)
    {
      fclose(fp);
      png_destroy_write_struct(&png_ptr,  (png_infopp)NULL);
      return;
    }
  
  /* Set error handling.  REQUIRED if you aren't supplying your own
   * error handling functions in the png_create_write_struct() call.
   */
  if (setjmp(png_ptr->jmpbuf))
    {
      /* If we get here, we had a problem writing the file */
      fclose(fp);
      png_destroy_write_struct(&png_ptr,  (png_infopp) &info_ptr);
      return;
   }

   /* Set up the output control using standard C streams. This
      is required. */
   png_init_io(png_ptr, fp);

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

   /* For color images: */
   sig_bit.red   = 8;
   sig_bit.green = 8;
   sig_bit.blue  = 8;

   if (text_ptr)
     png_set_text(png_ptr, info_ptr, text_ptr, i_text_count);

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

   /* Once we write out the header, the compression type on the text
    * chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or
    * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again
    * at the end.
    */

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

   row_pointers = png_malloc(png_ptr, i_height*sizeof(png_bytep *));
   for (i=0, j=0; i<i_height; i++, j+=i_width*3) {
     row_pointers[i] = rgb_image + j; 
   }
   
   png_set_rows   (png_ptr, info_ptr, row_pointers);
   png_write_image(png_ptr, row_pointers);

   /* You can write optional chunks like tEXt, zTXt, and tIME at the end
    * as well.
    */

   /* It is REQUIRED to call this to finish writing the rest of the file */
   png_write_end(png_ptr, info_ptr);

   /* if you allocated any text comments, free them here */
   /* free image data if allocated. */

   /* clean up after the write, and free any memory allocated */
   png_destroy_info_struct(png_ptr, &info_ptr);

   /* clean up after the write, and free any memory allocated */
   png_destroy_write_struct(&png_ptr, (png_infopp)NULL);

   fclose(fp);

   return;
}
Beispiel #29
0
static void
gst_snapshot_chain (GstPad * pad, GstData * _data)
{
  GstBuffer *buf = GST_BUFFER (_data);
  GstSnapshot *snapshot;
  guchar *data;
  gulong size;
  gint i;
  png_byte *row_pointers[MAX_HEIGHT];
  FILE *fp;

  g_return_if_fail (pad != NULL);
  g_return_if_fail (GST_IS_PAD (pad));
  g_return_if_fail (buf != NULL);

  snapshot = GST_SNAPSHOT (GST_OBJECT_PARENT (pad));

  data = GST_BUFFER_DATA (buf);
  size = GST_BUFFER_SIZE (buf);

  GST_DEBUG ("snapshot: have buffer of %d\n", GST_BUFFER_SIZE (buf));

  snapshot->cur_frame++;
  if (snapshot->cur_frame == snapshot->frame ||
      snapshot->snapshot_asked == TRUE) {
    snapshot->snapshot_asked = FALSE;

    GST_INFO ("dumpfile : %s\n", snapshot->location);
    fp = fopen (snapshot->location, "wb");
    if (fp == NULL)
      g_warning (" Can not open %s\n", snapshot->location);
    else {
      snapshot->png_struct_ptr =
          png_create_write_struct (PNG_LIBPNG_VER_STRING, (png_voidp) NULL,
          user_error_fn, user_warning_fn);
      if (snapshot->png_struct_ptr == NULL)
        g_warning ("Failed to initialize png structure");

      snapshot->png_info_ptr =
          png_create_info_struct (snapshot->png_struct_ptr);

      if (setjmp (snapshot->png_struct_ptr->jmpbuf))
        png_destroy_write_struct (&snapshot->png_struct_ptr,
            &snapshot->png_info_ptr);

      png_set_filter (snapshot->png_struct_ptr, 0,
          PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE);
      png_init_io (snapshot->png_struct_ptr, fp);
      png_set_compression_level (snapshot->png_struct_ptr, 9);
      png_set_IHDR (snapshot->png_struct_ptr,
          snapshot->png_info_ptr,
          snapshot->width,
          snapshot->height,
          snapshot->to_bpp / 3,
          PNG_COLOR_TYPE_RGB,
          PNG_INTERLACE_NONE,
          PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

      for (i = 0; i < snapshot->height; i++)
        row_pointers[i] = data + (snapshot->width * i * snapshot->to_bpp / 8);

      png_write_info (snapshot->png_struct_ptr, snapshot->png_info_ptr);
      png_write_image (snapshot->png_struct_ptr, row_pointers);
      png_write_end (snapshot->png_struct_ptr, NULL);
      png_destroy_info_struct (snapshot->png_struct_ptr,
          &snapshot->png_info_ptr);
      png_destroy_write_struct (&snapshot->png_struct_ptr, (png_infopp) NULL);
      fclose (fp);
    }
  }

  gst_pad_push (snapshot->srcpad, GST_DATA (buf));
}
Beispiel #30
0
	void
GPC_Canvas::
MakeScreenShot(
	const char* filename
){
	png_structp png_ptr;
	png_infop info_ptr;
	unsigned char *pixels = 0;
	png_bytepp row_pointers = 0;
	int i, bytesperpixel = 3, color_type = PNG_COLOR_TYPE_RGB;
	FILE *fp = 0;

	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (!png_ptr) 
	{
		std::cout << "Cannot png_create_write_struct." << std::endl;
		return;
	}

	info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr) 
	{
		png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
		std::cout << "Cannot png_create_info_struct." << std::endl;
		return;
	}

	if (setjmp(png_jmpbuf(png_ptr))) {
		png_destroy_write_struct(&png_ptr, &info_ptr);
		delete [] pixels;
		delete [] row_pointers;
		// printf("Aborting\n");
		if (fp) {
			fflush(fp);
			fclose(fp);
		}
		return;
	}

	// copy image data

	pixels = new unsigned char[GetWidth() * GetHeight() * bytesperpixel * sizeof(unsigned char)];
	if (!pixels) {
		std::cout << "Cannot allocate pixels array" << std::endl;
		return;
	}

	glReadPixels(0, 0, GetWidth(), GetHeight(), GL_RGB, GL_UNSIGNED_BYTE, pixels);

	fp = fopen(filename, "wb");
	if (!fp)
	{
		std::cout << "Couldn't open " << filename << " for writing." << std::endl;
		longjmp(png_jmpbuf(png_ptr), 1);
	}

	png_init_io(png_ptr, fp);

	/*
	png_set_filter(png_ptr, 0,
		PNG_FILTER_NONE  | PNG_FILTER_VALUE_NONE |
		PNG_FILTER_SUB   | PNG_FILTER_VALUE_SUB  |
		PNG_FILTER_UP    | PNG_FILTER_VALUE_UP   |
		PNG_FILTER_AVG   | PNG_FILTER_VALUE_AVG  |
		PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH|
		PNG_ALL_FILTERS);

	png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
	*/

	// png image settings
	png_set_IHDR(png_ptr,
		 info_ptr,
		 GetWidth(),
		 GetHeight(),
		 8,
		 color_type,
		 PNG_INTERLACE_NONE,
		 PNG_COMPRESSION_TYPE_DEFAULT,
		 PNG_FILTER_TYPE_DEFAULT);

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

	// allocate memory for an array of row-pointers
	row_pointers = new png_bytep [(GetHeight() * sizeof(png_bytep))];
	if (!row_pointers) 
	{
		std::cout << "Cannot allocate row-pointers array" << std::endl;
		longjmp(png_jmpbuf(png_ptr), 1);
	}

	// set the individual row-pointers to point at the correct offsets
	for (i = 0; i < GetHeight(); i++) {
		row_pointers[GetHeight()-1-i] = (png_bytep)
			((unsigned char *)pixels + (i * GetWidth()) * bytesperpixel * sizeof(unsigned char));
	}

	// write out the entire image data in one call
	png_write_image(png_ptr, row_pointers);

	// write the additional chunks to the PNG file (not really needed)
	png_write_end(png_ptr, info_ptr);

	// clean up
	delete [] (pixels);
	delete [] (row_pointers);
	png_destroy_write_struct(&png_ptr, &info_ptr);

	if (fp) 
	{
		fflush(fp);
		fclose(fp);
	}
}