UInt64 PNGImageFileType::storeData(const Image  *OSG_PNG_ARG  (pImage  ), 
                                         UChar8 *OSG_PNG_ARG  (buffer ),
                                         Int32   OSG_CHECK_ARG(memSize))
{
#ifdef OSG_WITH_PNG

    png_structp png_ptr;
    png_infop info_ptr;

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

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

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

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

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

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

    /* This is the hard way */

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

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

            return 0;
    }
    
    Int32 bit_depth;

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

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

    /* Write the file header information.  REQUIRED */

    png_write_info(png_ptr, info_ptr);

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

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

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

    delete [] row_pointers;

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

    return 0;
#endif
}
Example #2
0
//--------------------------------------------------------------------------------
bool SavePNG(const Path& in_file, BitmapData* in_pData)
{
	PROFILE_BLOCK;

	if (in_pData == nullptr)
		return false;

	FILE *fp = nullptr;
	FOPEN(&fp, in_file.GetData(), L("wb"));	
	if (!fp)
	{
		AssertMsg(false, L("File %s could not be opened for writing"), in_file.GetData());
		return false;
	}

	png_struct* png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);

	if (!png_ptr)
	{
		AssertMsg(false, L("png_create_write_struct failed"));
		return false;
	}

	png_info* info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr)
	{
		AssertMsg(false, L("png_create_info_struct failed"));
		return false;
	}

	if (setjmp(png_jmpbuf(png_ptr)))
	{
		AssertMsg(false, L("Error during init_io"));
		return false;
	}

	png_init_io(png_ptr, fp);

	if (setjmp(png_jmpbuf(png_ptr)))
	{
		AssertMsg(false, L("Error during writing header"));
		return false;
	}

	s32 bit_depth = 0;
	s32 color_type = 0;
	switch (in_pData->GetFormat())
	{
	case BufferFormat::A_U1:
		color_type = ePNG_GrayScale;  bit_depth = 1; break;
	case BufferFormat::A_U8:
		color_type = ePNG_GrayScale;  bit_depth = 8; break;
	case BufferFormat::BGR_U24:
		color_type = ePNG_TrueColor;  bit_depth = 8; break;
	case BufferFormat::ABGR_U32:
		color_type = ePNG_TrueColor | ePNG_Alpha;  bit_depth = 8; break;
	default:
		return false;
	}

	png_set_IHDR(png_ptr, info_ptr, in_pData->GetWidth(), in_pData->GetHeight(), bit_depth, color_type, PNG_INTERLACE_NONE,	PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

	png_write_info(png_ptr, info_ptr);

	if (setjmp(png_jmpbuf(png_ptr)))
		AssertMsg(false, L("Error during writing bytes"));

	u8* pBuffer = (u8*)in_pData->GetBuffer();
	u8** row_pointers = new u8*[in_pData->GetHeight()];
	for (u32 i = 0; i < in_pData->GetHeight(); i++)
	{
		row_pointers[i] = pBuffer;
		pBuffer += in_pData->GetBufferPitch();
	}

	png_write_image(png_ptr, row_pointers);

	if (setjmp(png_jmpbuf(png_ptr)))
	{
		delete[] row_pointers;
		AssertMsg(false, L("Error during end of write"));
		return false;
	}

	png_write_end(png_ptr, nullptr);

	delete[] row_pointers;
	
	fclose(fp);
	return true;
}
Example #3
0
static PoolVector<uint8_t> _lossless_pack_png(const Ref<Image> &p_image) {

	Ref<Image> img = p_image->duplicate();

	if (img->is_compressed())
		img->decompress();

	ERR_FAIL_COND_V(img->is_compressed(), PoolVector<uint8_t>());

	png_structp png_ptr;
	png_infop info_ptr;
	png_bytep *row_pointers;

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

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

	info_ptr = png_create_info_struct(png_ptr);

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

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

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

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

	int pngf = 0;
	int cs = 0;

	switch (img->get_format()) {

		case Image::FORMAT_L8: {

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

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

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

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

			if (img->detect_alpha()) {

				img->convert(Image::FORMAT_RGBA8);
				pngf = PNG_COLOR_TYPE_RGB_ALPHA;
				cs = 4;
			} else {

				img->convert(Image::FORMAT_RGB8);
				pngf = PNG_COLOR_TYPE_RGB;
				cs = 3;
			}
		}
	}

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

	png_write_info(png_ptr, info_ptr);

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

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

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

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

	memfree(row_pointers);

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

		ERR_FAIL_V(PoolVector<uint8_t>());
	}

	png_write_end(png_ptr, NULL);

	return ret;
}
Example #4
0
bool ImageWriter::writePNG(SDL_Surface *surface, const std::string &filename)
{
    // TODO Maybe someone can make this look nice?
    FILE *fp = fopen(filename.c_str(), "wb");
    if (!fp)
    {
        logger->log("could not open file %s for writing", filename.c_str());
        return false;
    }

    png_structp png_ptr;
    png_infop info_ptr;
    png_bytep *row_pointers;
    int colortype;

    if (SDL_MUSTLOCK(surface)) {
        SDL_LockSurface(surface);
    }

    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
    if (!png_ptr)
    {
        logger->log("Had trouble creating png_structp");
        return false;
    }

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
    {
        png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
        logger->log("Could not create png_info");
        return false;
    }

    if (setjmp(png_jmpbuf(png_ptr)))
    {
        png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
        logger->log("problem writing to %s", filename.c_str());
        return false;
    }

    png_init_io(png_ptr, fp);

    colortype = (surface->format->BitsPerPixel == 24) ?
        PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGB_ALPHA;

    png_set_IHDR(png_ptr, info_ptr, surface->w, surface->h, 8, colortype,
            PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

    png_write_info(png_ptr, info_ptr);

    png_set_packing(png_ptr);

    row_pointers = new png_bytep[surface->h];
    if (!row_pointers)
    {
        logger->log("Had trouble converting surface to row pointers");
        return false;
    }

    for (int i = 0; i < surface->h; i++)
    {
        row_pointers[i] = (png_bytep)(Uint8 *)surface->pixels + i * surface->pitch;
    }

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

    fclose(fp);

    delete [] row_pointers;

    png_destroy_write_struct(&png_ptr, (png_infopp)NULL);

    if (SDL_MUSTLOCK(surface)) {
        SDL_UnlockSurface(surface);
    }

    return true;
}
Example #5
0
int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
{
	png_structp png_ptr;
	png_infop info_ptr;

	unsigned char *pixels = NULL;
	unsigned char *from, *to;
	png_bytepp row_pointers = NULL;
	int i, bytesperpixel, color_type = PNG_COLOR_TYPE_GRAY;
	FILE *fp = NULL;

	/* use the jpeg quality setting for compression */
	int compression;
	compression= (int)(((float)(ibuf->ftype & 0xff) / 11.1111f));
	compression= compression < 0 ? 0 : (compression > 9 ? 9 : compression);

	/* for prints */
	if(flags & IB_mem)
		name= "<memory>";

	bytesperpixel = (ibuf->depth + 7) >> 3;
	if ((bytesperpixel > 4) || (bytesperpixel == 2)) {
		printf("imb_savepng: Cunsupported bytes per pixel: %d for file: '%s'\n", bytesperpixel, name);
		return (0);
	}

	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
		NULL, NULL, NULL);
	if (png_ptr == NULL) {
		printf("imb_savepng: Cannot png_create_write_struct for file: '%s'\n", name);
		return 0;
	}

	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL) {
		png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
		printf("imb_savepng: Cannot png_create_info_struct for file: '%s'\n", name);
		return 0;
	}

	if (setjmp(png_jmpbuf(png_ptr))) {
		png_destroy_write_struct(&png_ptr, &info_ptr);
		printf("imb_savepng: Cannot setjmp for file: '%s'\n", name);
		return 0;
	}

	// copy image data

	pixels = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned char), "pixels");
	if (pixels == NULL) {
		png_destroy_write_struct(&png_ptr, &info_ptr);
		printf("imb_savepng: Cannot allocate pixels array of %dx%d, %d bytes per pixel for file: '%s'\n", ibuf->x, ibuf->y, bytesperpixel, name);
		return 0;
	}

	from = (unsigned char *) ibuf->rect;
	to = pixels;

	switch (bytesperpixel) {
	case 4:
		color_type = PNG_COLOR_TYPE_RGBA;
		for (i = ibuf->x * ibuf->y; i > 0; i--) {
			to[0] = from[0];
			to[1] = from[1];
			to[2] = from[2];
			to[3] = from[3];
			to += 4; from += 4;
		}
		break;
	case 3:
		color_type = PNG_COLOR_TYPE_RGB;
		for (i = ibuf->x * ibuf->y; i > 0; i--) {
			to[0] = from[0];
			to[1] = from[1];
			to[2] = from[2];
			to += 3; from += 4;
		}
		break;
	case 1:
		color_type = PNG_COLOR_TYPE_GRAY;
		for (i = ibuf->x * ibuf->y; i > 0; i--) {
			to[0] = from[0];
			to++; from += 4;
		}
		break;
	}

	if (flags & IB_mem) {
		// create image in memory
		imb_addencodedbufferImBuf(ibuf);
		ibuf->encodedsize = 0;

		png_set_write_fn(png_ptr,
			 (png_voidp) ibuf,
			 WriteData,
			 Flush);
	} else {
		fp = fopen(name, "wb");
		if (!fp) {
			png_destroy_write_struct(&png_ptr, &info_ptr);
			MEM_freeN(pixels);
			printf("imb_savepng: Cannot open file for writing: '%s'\n", name);
			return 0;
		}
		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, compression);

	// png image settings
	png_set_IHDR(png_ptr,
		 info_ptr,
		 ibuf->x,
		 ibuf->y,
		 8,
		 color_type,
		 PNG_INTERLACE_NONE,
		 PNG_COMPRESSION_TYPE_DEFAULT,
		 PNG_FILTER_TYPE_DEFAULT);

	/* image text info */
	if (ibuf->metadata) {
		png_text*  metadata;
		ImMetaData* iptr;
		int  num_text = 0;
		iptr = ibuf->metadata;
		while (iptr) {
			num_text++;
			iptr = iptr->next;
		}
		
		metadata = MEM_callocN(num_text*sizeof(png_text), "png_metadata");
		iptr = ibuf->metadata;
		num_text = 0;
		while (iptr) {
			
			metadata[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
			metadata[num_text].key = iptr->key;
			metadata[num_text].text = iptr->value;
			num_text++;
			iptr = iptr->next;
		}
		
		png_set_text(png_ptr, info_ptr, metadata, num_text);
		MEM_freeN(metadata);

	}

	if(ibuf->ppm[0] > 0.0 && ibuf->ppm[1] > 0.0) {
		png_set_pHYs(png_ptr, info_ptr, (unsigned int)(ibuf->ppm[0] + 0.5), (unsigned int)(ibuf->ppm[1] + 0.5), PNG_RESOLUTION_METER);
	}

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

	// allocate memory for an array of row-pointers
	row_pointers = (png_bytepp) MEM_mallocN(ibuf->y * sizeof(png_bytep), "row_pointers");
	if (row_pointers == NULL) {
		printf("imb_savepng: Cannot allocate row-pointers array for file '%s'\n", name);
		png_destroy_write_struct(&png_ptr, &info_ptr);
		MEM_freeN(pixels);
		if (fp) {
			fclose(fp);
		}
		return 0;
	}

	// set the individual row-pointers to point at the correct offsets
	for (i = 0; i < ibuf->y; i++) {
		row_pointers[ibuf->y-1-i] = (png_bytep)
			((unsigned char *)pixels + (i * ibuf->x) * 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
	MEM_freeN(pixels);
	MEM_freeN(row_pointers);
	png_destroy_write_struct(&png_ptr, &info_ptr);

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

	return(1);
}
Example #6
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;
    bool close_dup_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]);
    PyObject* py_file = NULL;
    if (py_fileobj.isString())
    {
        if ((py_file = npy_PyFile_OpenFile(py_fileobj.ptr(), (char *)"wb")) == NULL) {
            throw Py::Exception();
        }
        close_file = true;
    }
    else
    {
        py_file = py_fileobj.ptr();
    }

    if ((fp = npy_PyFile_Dup(py_file, (char *)"wb")))
    {
        close_dup_file = true;
    }
    else
    {
        PyErr_Clear();
        PyObject* write_method = PyObject_GetAttrString(
                py_file, "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_file,
                             &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 (close_dup_file)
        {
            if (npy_PyFile_DupClose(py_file, fp)) {
              throw Py::RuntimeError("Error closing dupe file handle");
            }
        }

        if (close_file)
        {
            npy_PyFile_CloseFile(py_file);
            Py_DECREF(py_file);
        }
        /* 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 (close_dup_file)
    {
        if (npy_PyFile_DupClose(py_file, fp)) {
          throw Py::RuntimeError("Error closing dupe file handle");
        }
    }

    if (close_file)
    {
        npy_PyFile_CloseFile(py_file);
        Py_DECREF(py_file);
    }

    if (PyErr_Occurred()) {
        throw Py::Exception();
    } else {
        return Py::Object();
    }
}
Example #7
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;
	unsigned int i;
	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;
	SDL_BlendMode temp_blend;

	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,(png_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;
			}

			SDL_GetSurfaceBlendMode(surf, &temp_blend);
			SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_NONE);

			if(SDL_BlitSurface(surf,NULL,tempsurf,NULL)!=0){
				SDL_SetError("Couldn't blit surface to temp surface");
				SDL_FreeSurface(tempsurf);
				goto savedone;
			}

			SDL_SetSurfaceBlendMode(surf, temp_blend);

			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;
}
Example #8
0
bool ImageMemory::SaveImage(const std::string &filename)
{
    if(pixels == NULL) {
        IF_PRINT_WARNING(VIDEO_DEBUG) << "pixels member was NULL upon function invocation for file: " << filename << std::endl;
        return false;
    }

    // open up the file for writing
    FILE *fp = fopen(filename.c_str(), "wb");

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

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

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

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

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

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

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

    // write the header
    int32 color_type = rgb_format ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGBA;
    png_set_IHDR(png_ptr, info_ptr, width, height, 8, color_type,
                 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);


    png_write_info(png_ptr, info_ptr);

    png_set_packing(png_ptr);

    // get the row array from our data
    png_bytep *row_pointers = new png_bytep[height];
    if(!row_pointers) {
        IF_PRINT_WARNING(VIDEO_DEBUG) << "Couldn't allocate png row_pointers for: " << filename << std::endl;
        png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
        fclose(fp);
        return false;
    }

    int32 bytes_per_row = rgb_format ? width * 3 : width * 4;
    for(uint32 i = 0; i < height; ++i) {
        row_pointers[i] = (png_bytep)pixels + bytes_per_row * i;
    }

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

    fclose(fp);

    // free the memory
    delete[] row_pointers;
    png_destroy_write_struct(&png_ptr, (png_infopp)NULL);

    return true;
} // bool ImageMemory::SaveImage(const std::string& filename)
Example #9
0
void Openchunk::run()
{
		png_structp png_ptr_read;
    png_infop info_ptr_read;
    png_structp png_ptr_write;
    png_infop info_ptr_write;
	
    png_uint_32 next_frame_width;
    png_uint_32 next_frame_height;
    png_uint_32 next_frame_x_offset;
    png_uint_32 next_frame_y_offset;
    png_uint_16 next_frame_delay_num;
    png_uint_16 next_frame_delay_den;
    png_byte next_frame_dispose_op;
    png_byte next_frame_blend_op;
    png_color_16p Framebg;
	  framlist.clear();
	
  buffer = new StreamFile();
  buffer->LoadFile(subfile);
	qDebug() << "### start read ->" << subfile;
	if (!buffer->isValid()) {
		alert("unvalid buffer fill",__LINE__);
		exit(0);
	}
	validpng = buffer->device()->peek(4).contains("PNG");
	qDebug() << "### ahed  ->" << validpng;
	frame1.loadFromData(buffer->stream()); /* load first frame */
	if (frame1.isNull()) {
		alert("unable find a valid image",__LINE__);
		return;
	}
	png_ptr_read = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if(png_ptr_read == NULL) {
		alert("unable to create read struct",__LINE__);
		return;
	}
	info_ptr_read = png_create_info_struct(png_ptr_read);
	if(info_ptr_read == NULL) {
     alert("unable to create info struct",__LINE__);
		 return;
	}

	png_set_read_fn(png_ptr_read,buffer,EncoderReaderCallback);
	
	if(setjmp(png_ptr_read->jmpbuf)) {
        alert("something didn't work, jump 1",__LINE__);
		    return;
	}
	
	png_read_info(png_ptr_read, info_ptr_read);
	
	if(!png_get_valid(png_ptr_read, info_ptr_read, PNG_INFO_acTL)) {
			alert("source image must be animated",__LINE__);
		  return;
	}
	
	  QRect Frect(0,0,info_ptr_read->width,info_ptr_read->height);
    ////////////qDebug() << "### Frame rect from head ->" << Frect;
    QImage master(Frect.width(),Frect.height(),QImage::Format_ARGB32);
    const uint height = master.height();
    png_bytep *row_pointers = new png_bytep[height];
                        for (uint i = 0; i < height; ++i)  {
                          row_pointers[i] = (png_bytep)master.scanLine(i);
                        }
    int validloop = -1;
    for(int i = 0; i < png_get_num_frames(png_ptr_read, info_ptr_read); i++)
    {
        /////////qDebug() << "### frame read  ------------- " << i;
				png_ptr_write = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
        if(png_ptr_write == NULL)  {
        alert("unable to create write struct");
        return;
        }
        StreamFile *framer = new StreamFile();
        png_set_write_fn(png_ptr_write,framer,EncoderWriteCallback, NULL);
        info_ptr_write = png_create_info_struct(png_ptr_write);
        if(info_ptr_write == NULL)  {
        alert("unable to create write struct");
        return;
        }
        if(setjmp(png_ptr_write->jmpbuf))  {
            alert("something didn't work, jump 2");
            return;
        }
				png_read_frame_head(png_ptr_read, info_ptr_read);
				if(png_get_valid(png_ptr_read, info_ptr_read, PNG_INFO_fcTL))
        {
            png_get_next_frame_fcTL(png_ptr_read, info_ptr_read,
                                    &next_frame_width, &next_frame_height,
                                    &next_frame_x_offset, &next_frame_y_offset,
                                    &next_frame_delay_num, &next_frame_delay_den,
                                    &next_frame_dispose_op, &next_frame_blend_op);
        }
        else
        {
            /* the first frame doesn't have an fcTL so it's expected to be hidden, 
            * but we'll extract it anyway  next_frame_x_offset , next_frame_y_offset */ 
            next_frame_width = png_get_image_width(png_ptr_read, info_ptr_read);
            next_frame_height = png_get_image_height(png_ptr_read, info_ptr_read);
        }
				QRect C_frame_rect(0,0,next_frame_width,next_frame_height);
				
				
				AFRAMES FrameInfo = OneFrameReader(png_ptr_read, info_ptr_read, png_ptr_write, info_ptr_write,
        next_frame_width, next_frame_height);
				png_write_info(png_ptr_write, info_ptr_write);
				png_read_image(png_ptr_read, row_pointers);
        png_write_image(png_ptr_write, row_pointers);
        png_write_end(png_ptr_write, NULL);
				
				            float Fraction = (float)next_frame_delay_num /  (float)next_frame_delay_den + 0.00;
                    ////////qDebug() << "### Fraction  " << Fraction;
                    int PlayGo;
                    if (Fraction < 0.001 ) {
                        PlayGo = 100;
                    } else if (Fraction < 1.010 && Fraction > 0.9) {
                        PlayGo = 1000;
                    } else {
                        PlayGo = Fraction * 1000;
                    }
										
				/* extract frames */
				if ( framer->isValid() && Frect.contains(C_frame_rect) ) {
					 validloop++;
					 int Coalpha = 255;
					 /* prepare image if no background find grab a pixel color! */
					 QImage tmpgd(C_frame_rect.width(),C_frame_rect.height(),QImage::Format_ARGB32);
					 /* compose it files */
					 APNGFRAME one;
					 one.dimg = framer->stream();
					 one.maxframe = Frect;
					 one.pos = validloop;
					 one.point = QPoint(next_frame_x_offset,next_frame_y_offset);
					 one.play = PlayGo;
					 if (!(png_get_valid(png_ptr_read, info_ptr_read, PNG_INFO_bKGD))) {
					 tmpgd.loadFromData(one.dimg);
					 QRgb GrepColor = tmpgd.pixel(QPoint(2,2));
					 one.bg = QColor(GrepColor);
					 one.bg.setAlpha(qAlpha(GrepColor));
					 Coalpha = qAlpha(GrepColor);
					 } else {
					 one.bg = FrameInfo.bg; 
					 }
					 
					       QImage tmpe;
					       QImage Pvidi(one.maxframe.width(),one.maxframe.height(),QImage::Format_ARGB32);
					       if (tmpe.loadFromData(one.dimg)) {
								 QPainter p(&Pvidi);
								 p.setRenderHint(QPainter::Antialiasing, true);
								 p.setBrush(one.bg);
								 p.drawRect(Pvidi.rect());
								 p.drawImage(one.point,tmpe);
								 p.end();
								 one.item = Pvidi; 
                 ////qDebug() << "### isNull() in theard .." << one.item.isNull();									 
								 }
					 
					 
					 //////item tmpe
					 //////qDebug() << "### Frame rect ->" << one.point << ",nr." << validloop << "C." << one.bg.name() << "Al." << Coalpha;
					 framlist.insert(validloop,one);
				}
				framer->~StreamFile();
				png_ptr_write = 0;
        info_ptr_write = 0;
		}
	
	
	qDebug() << "### Frame size() ->" << framlist.size();
	//////alert("end of chunks",__LINE__);
	validpng = true;
	buffer->~StreamFile();
	exit(0);
}
Example #10
0
/* save rgb888 to png format in fp */
int save_png(const char* path, const char* data, int width, int height)
{
    FILE *fp;
    png_byte **volatile rows;
    png_struct *png;
    png_info *info;

    fp = fopen(path, "w");
    if (!fp) {
        int errsv = errno;
        E("Cannot open file %s for writing.\n", path);
        return errsv;
    }

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

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

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

    info = png_create_info_struct (png);
    if (!info) {
        E("png_create_info_struct failed\n");
        png_destroy_write_struct (&png, NULL);
        goto oops;
    }

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

    png_color_16 white;

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

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

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

    png_destroy_write_struct (&png, &info);

    fclose(fp);
    free (rows);
    return 0;

oops:
    fclose(fp);
    free (rows);
    return -1;
}
Example #11
0
int write_png(struct image image, char *filename) {
	int rc = 0, i = 0, x = 0, y = 0, width = 0, height = 0;
	unsigned char *data = NULL;
	FILE *file = NULL;
	png_byte color_type, bit_depth;
	png_structp png_ptr;
	png_infop info_ptr;
	png_bytep *row_pointers;

	file = fopen(filename, "wb");

	if (!file) {
		printf("Could not open %s\n", filename);

		rc = 1;
		goto cleanup;
	}

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

	if (!png_ptr) {
		printf("png_create_write_struct failed\n");

		rc = 1;
		goto cleanup;
	}

	info_ptr = png_create_info_struct(png_ptr);

	if (!info_ptr) {
		printf("png_create_info_struct failed\n");

		rc = 1;
		goto cleanup;
	}

	if (setjmp(png_jmpbuf(png_ptr))) {
		printf("Error initializing write\n");

		rc = 1;
		goto cleanup;
	}

	png_init_io(png_ptr, file);

	if (setjmp(png_jmpbuf(png_ptr))) {
		printf("Error writing header\n");

		rc = 1;
		goto cleanup;
	}

	data = image.data;
	width = image.width;
	height = image.height;
	color_type = 2;
	bit_depth = 8;

	png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
	png_write_info(png_ptr, info_ptr);

	row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * height + 1);

	for (y = 0; y < height; y++) {
		row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png_ptr, info_ptr) + 1);
	}

	for (y = 0, i = 0; y < height; y++) {
		png_byte *row = row_pointers[y];

		for (x = 0; x < width; x++) {
			png_byte *rgb = &(row[x * 3]);

			rgb[0] = data[i++];
			rgb[1] = data[i++];
			rgb[2] = data[i++];
		}
	}

	png_write_image(png_ptr, row_pointers);

	if (setjmp(png_jmpbuf(png_ptr))) {
		printf("Error ending write\n");

		rc = 1;
		goto cleanup;
	}

	png_write_end(png_ptr, NULL);

cleanup:
	if (file) {
		fclose(file);
	}

	return rc;
}
Example #12
0
ImageIO::errorType ImageIO::savePNG(const char * filename)
{
#ifdef ENABLE_PNG
  FILE *file = fopen(filename, "wb");
  if (!file)
  {
    printf("Error in savePNG: Cannot open file %s.\n", filename);
    return IO_ERROR;
  }

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

  if (!png_ptr)
  {
    printf("Error in savePNG: Creating the internal structure failed.\n");
    fclose(file);
    return (IO_ERROR);
  }

  png_infop info_ptr = png_create_info_struct(png_ptr);
  
  if (!info_ptr)
  {
    png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
    printf("Error in savePNG: Creating the information structure failed.\n");
    fclose(file);
    return (IO_ERROR);
  }
  
  if (setjmp(png_jmpbuf(png_ptr)))
  {
    png_destroy_write_struct(&png_ptr, &info_ptr);
    fclose(file);
    printf("Error in savePNG: cannot setup the error handling.\n");
    return (IO_ERROR);
  }

  // setup the output
  png_init_io(png_ptr, file);

  if (setjmp(png_jmpbuf(png_ptr)))
  {
    png_destroy_write_struct(&png_ptr, &info_ptr);
    fclose(file);
    printf("Error in savePNG: cannot write the png header.\n");
    return (IO_ERROR);
  }

  int bit_depth = BITS_PER_CHANNEL_8; // currently we only support 8 bits per channel
  int color_type;

  switch(bytesPerPixel)
  {
  case IMAGE_IO_RGB:
    color_type = PNG_COLOR_TYPE_RGB;
  	break;
  case IMAGE_IO_RGB_ALPHA:
    color_type = PNG_COLOR_TYPE_RGB_ALPHA;
    break;
  default:
    png_destroy_write_struct(&png_ptr, &info_ptr);
    printf("Error in savePNG: cannot handle bytesPerPixel that is not 3 or 4.\n");
    return OTHER_ERROR;
    break;
  }
    
  png_set_IHDR(png_ptr, info_ptr, (png_uint_32)width, (png_uint_32)height,
    bit_depth, color_type, PNG_INTERLACE_NONE,
    PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

  png_write_info(png_ptr, info_ptr);

  if (setjmp(png_jmpbuf(png_ptr)))
  {
    png_destroy_write_struct(&png_ptr, &info_ptr);
    fclose(file);
    printf("Error in savePNG: cannot write the png file.\n");
    return (IO_ERROR);
  }
  unsigned int bytesPerRow = bytesPerPixel * width;
  png_bytep * row_pointers = (png_bytep*) malloc (sizeof(png_bytep) * height);
  for(unsigned int row = 0; row < height; row++)
    row_pointers[row] = (png_byte*)(&pixels[(height - row - 1) * bytesPerRow]);

  png_write_image(png_ptr, row_pointers);

  free(row_pointers);

  if (setjmp(png_jmpbuf(png_ptr)))
  {
    png_destroy_write_struct(&png_ptr, &info_ptr);
    fclose(file);
    printf("Error in savePNG: unknown error occurred during end of file.\n");
    return (IO_ERROR);
  }

  png_write_end(png_ptr, NULL);

  png_destroy_write_struct(&png_ptr, &info_ptr);
  fclose(file);
  
  return OK;

#else
  return INVALID_FILE_FORMAT;
#endif
}
static Bool
writePng (unsigned char *buffer,
	  png_rw_ptr	writeFunc,
	  void		*closure,
	  int		width,
	  int		height,
	  int		stride)
{
    png_struct	 *png;
    png_info	 *info;
    png_byte	 **rows;
    png_color_16 white;
    int		 i;

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

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

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

	return FALSE;
    }

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

	return FALSE;
    }

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

	return FALSE;
    }

    png_set_write_fn (png, closure, writeFunc, NULL);

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

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

    png_set_bKGD (png, info, &white);

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

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

    return TRUE;
}
Example #14
0
File: png.cpp Project: 2asoft/xray
BMMRES
BitmapIO_PNG::Save(const TCHAR *filename, Bitmap *map) 
{
    if(!map)
		return(ProcessImageIOError(&bi,BMMRES_INTERNALERROR));
    
    openMode = BMM_OPEN_W;
    
    if((ostream = _tfopen(filename,_T("wb"))) == NULL)
		return (ProcessImageIOError(&bi));

	BitmapStorage *palettedStorage = NULL;

    png = png_create_write_struct (PNG_VERSION, (void *) this, error_func, warning_func);
    if (setjmp(png->jmpbuf)) {
		if (info)
            for (png_uint_32 i = 0; i < info->height; i++)
			    if (row_pointers[i]) free(row_pointers[i]);
		if (row_pointers) {
			free(row_pointers);
			row_pointers = NULL;
		}

		if (palettedStorage) delete palettedStorage;
        fclose(ostream);
		_tremove(filename);
        png_destroy_write_struct (&png, &info);
        return BMMRES_IOERROR;
    }
    info = png_create_info_struct(png);

    png_init_io(png, ostream);

	switch(cfg.color_type) {
	case PngPalette:
		info->color_type = PNG_COLOR_TYPE_PALETTE;
		info->pixel_depth = 8;
		info->valid |= PNG_INFO_PLTE;
		info->num_palette = 256;
		break;
	case PngRGB:
		info->color_type = PNG_COLOR_TYPE_RGB;
		break;
	case PngRGBA:
		info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
		break;
	case PngGray:
		info->color_type = PNG_COLOR_TYPE_GRAY;
		break;
	case PngGrayA:
		info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
		break;
	}
	info->width = map->Width();
	info->height = map->Height();
	if (OutputGamma() != 1.0f) {
		info->valid |= PNG_INFO_gAMA;
		info->gamma = OutputGamma();
	} else info->gamma = 1.0f;

	if (map->Aspect() != 1.0f) {
		info->valid |= PNG_INFO_pHYs;
		info->x_pixels_per_unit = (png_uint_32)(1024.0f * map->Aspect());
		info->y_pixels_per_unit = 1024;
		info->phys_unit_type = 0;
	}

	if (cfg.interlaced)
		info->interlace_type = 1;
	else
		info->interlace_type = 0;

	switch( info->color_type) {
	case PNG_COLOR_TYPE_PALETTE:
	case PNG_COLOR_TYPE_GRAY:
		info->channels = 1;
		break;
	case PNG_COLOR_TYPE_GRAY_ALPHA:
		info->channels = 2;
		break;
	case PNG_COLOR_TYPE_RGB:
		info->channels = 3;
		break;
	case PNG_COLOR_TYPE_RGB_ALPHA:
		info->channels = 4;
		break;
	}

	info->bit_depth = cfg.bitdepth;
	info->rowbytes = info->width * info->channels * info->bit_depth / 8;

	row_pointers = (png_bytep *)malloc(info->height * sizeof(png_bytep));
	for (png_uint_32 i = 0; i < info->height; i++)
		row_pointers[i] = (png_bytep)malloc(info->rowbytes);

	switch (info->bit_depth) {
	case 16:  // this is only RGB/RGBA/Gray/GrayA
		switch(info->color_type) {
		case PNG_COLOR_TYPE_RGB:
		case PNG_COLOR_TYPE_RGB_ALPHA:
			{
			BMM_Color_64 *line64 = (BMM_Color_64 *) calloc(info->width,sizeof(BMM_Color_64));
			for (png_uint_32 iy = 0; iy < info->height; ++iy) {
				if (GetOutputPixels(0, iy, info->width, line64) != 1) {
					for (png_uint_32 i = 0; i < info->height; i++)
						if (row_pointers[i]) free(row_pointers[i]);
					if (row_pointers) {
						free(row_pointers);
						row_pointers = NULL;
					}

					fclose(ostream);
					_tremove(filename);
					free(line64);
                    png_destroy_write_struct (&png, &info);
					return BMMRES_IOERROR;
				}
				BMM_Color_64 *l64=line64;
				unsigned short *oshort = (unsigned short *)row_pointers[iy];
				for (png_uint_32 ix = 0; ix < info->width; ++l64, ix++) {
					*oshort = (unsigned short)l64->r; oshort++;
					*oshort = (unsigned short)l64->g; oshort++;
					*oshort = (unsigned short)l64->b; oshort++;
					if (info->channels == 4) {
						*oshort = (unsigned short)l64->a; oshort++;
					}
				}
			}
			free(line64);
			}
			break;
		case PNG_COLOR_TYPE_GRAY:
			{
			for (png_uint_32 iy = 0; iy < info->height; ++iy)
				if (map->Get16Gray(0, iy, info->width, (unsigned short *)row_pointers[iy]) != 1) {
					for (png_uint_32 i = 0; i < info->height; i++)
						if (row_pointers[i]) free(row_pointers[i]);
					if (row_pointers) {
						free(row_pointers);
						row_pointers = NULL;
					}

					fclose(ostream);
					_tremove(filename);
                    png_destroy_write_struct (&png, &info);
					return BMMRES_IOERROR;
				}
			}
			break;
		case PNG_COLOR_TYPE_GRAY_ALPHA:
			{
			BMM_Color_64 *line64 = (BMM_Color_64 *) calloc(info->width, sizeof(BMM_Color_64));
			unsigned short *line = (unsigned short *) calloc(info->width, sizeof(unsigned short));
			for (png_uint_32 iy = 0; iy < info->height; ++iy) {
				if (GetOutputPixels(0, iy, info->width, line64) != 1 ||
					map->Get16Gray(0, iy, info->width, line) != 1) {
					for (png_uint_32 i = 0; i < info->height; i++)
						if (row_pointers[i]) free(row_pointers[i]);
					if (row_pointers) {
						free(row_pointers);
						row_pointers = NULL;
					}
					free(line64);
					free(line);
					fclose(ostream);
					_tremove(filename);
                    png_destroy_write_struct (&png, &info);
					return BMMRES_IOERROR;
				}
				BMM_Color_64 *l64 = line64;
				unsigned short *l=line;
				unsigned short *oshort = (unsigned short *)row_pointers[iy];
				for (png_uint_32 ix = 0; ix < info->width; ix++, l64++) {
					*oshort++ = *l++;
					*oshort++ = (unsigned short)l64->a;
				}
			}
			free(line64);
			free(line);
			}
			break;
		}
		break;

	case 8: // this can be any type
		switch(info->color_type) {
		case PNG_COLOR_TYPE_PALETTE: {
			// Set up a palette buffer
			PixelBuf48 palettebuf(info->num_palette);
			BMM_Color_48 *pal = palettebuf.Ptr();
			// Must compute a color palette, and reduce the image to 256 colors!
			// this calculates a palette based on the gamma corrected values, which
			// corresponds to what GetOutputPixels returns.
			if(CalcOutputPalette(256, pal) == 0) {
				for (png_uint_32 i = 0; i < info->height; i++)
					if (row_pointers[i]) free(row_pointers[i]);
				if (row_pointers) {
					free(row_pointers);
					row_pointers = NULL;
				}
				fclose(ostream);
				_tremove(filename);
                png_destroy_write_struct (&png, &info);
				return BMMRES_IOERROR;
			}
			info->palette = (png_color *)malloc(info->num_palette * sizeof(png_color));
			for (int i = 0; i < info->num_palette; i++) {
				info->palette[i].red = (unsigned char)(pal[i].r >> 8);
				info->palette[i].green = (unsigned char)(pal[i].g >> 8);
				info->palette[i].blue = (unsigned char)(pal[i].b >> 8);
			}
			PixelBuf64 line(info->width);
			ColorPacker* cpack = BMMNewColorPacker(info->width, pal, info->num_palette);
			for (png_uint_32 iy=0; iy < info->height; ++iy) {
				if(!GetOutputPixels(0, iy, info->width, line.Ptr())) {
					for (png_uint_32 i = 0; i < info->height; i++)
						if (row_pointers[i]) free(row_pointers[i]);
					if (row_pointers) {
						free(row_pointers);
						row_pointers = NULL;
					}
					fclose(ostream);
					_tremove(filename);
                    png_destroy_write_struct (&png, &info);
					return BMMRES_IOERROR;
				}
				cpack->PackLine(line.Ptr(), row_pointers[iy], info->width);
			}
			cpack->DeleteThis();
			}
			break;
		case PNG_COLOR_TYPE_RGB:
		case PNG_COLOR_TYPE_RGB_ALPHA:
			{
			BMM_Color_32 *line32 = (BMM_Color_32 *) calloc(info->width,sizeof(BMM_Color_32));
			for (png_uint_32 iy = 0; iy < info->height; ++iy) {
				if (GetDitheredOutputPixels(0, iy, info->width, line32) != 1) {
					for (png_uint_32 i = 0; i < info->height; i++)
						if (row_pointers[i]) free(row_pointers[i]);
					if (row_pointers) {
						free(row_pointers);
						row_pointers = NULL;
					}

					fclose(ostream);
					_tremove(filename);
					free(line32);
                    png_destroy_write_struct (&png, &info);
					return BMMRES_IOERROR;
				}
				BMM_Color_32 *l32=line32;
				unsigned char *obyte = (unsigned char *)row_pointers[iy];
				for (png_uint_32 ix = 0; ix < info->width; ++l32, ix++) {
					*obyte = (unsigned char)l32->r; obyte++;
					*obyte = (unsigned char)l32->g; obyte++;
					*obyte = (unsigned char)l32->b; obyte++;
					if (info->channels == 4) {
						*obyte = (unsigned char)l32->a; obyte++;
					}
				}
			}
			free(line32);
			}
			break;
		case PNG_COLOR_TYPE_GRAY:
			{
			unsigned short *line = (unsigned short *) calloc(info->width * info->channels, sizeof(unsigned short));
			for (png_uint_32 iy = 0; iy < info->height; ++iy) {
				if (map->Get16Gray(0, iy, info->width, line) != 1) {
					for (png_uint_32 i = 0; i < info->height; i++)
						if (row_pointers[i]) free(row_pointers[i]);
					if (row_pointers) {
						free(row_pointers);
						row_pointers = NULL;
					}

					fclose(ostream);
					_tremove(filename);
					free(line);
                    png_destroy_write_struct (&png, &info);
					return BMMRES_IOERROR;
				}
				unsigned short *l=line;
				unsigned char *obyte = (unsigned char *)row_pointers[iy];
				for (png_uint_32 ix = 0; ix < info->width; ix++) {
					*obyte++ = (unsigned char)(*l >> 8); l++;
				}
			}
			free(line);
			}
			break;
		case PNG_COLOR_TYPE_GRAY_ALPHA:
			{
			BMM_Color_64 *line64 = (BMM_Color_64 *) calloc(info->width,sizeof(BMM_Color_64));
			unsigned short *line = (unsigned short *) calloc(info->width, sizeof(unsigned short));
			for (png_uint_32 iy = 0; iy < info->height; ++iy) {
				if (GetOutputPixels(0, iy, info->width, line64) != 1 ||
					map->Get16Gray(0, iy, info->width, line) != 1) {
					for (png_uint_32 i = 0; i < info->height; i++)
						if (row_pointers[i]) free(row_pointers[i]);
					if (row_pointers) {
						free(row_pointers);
						row_pointers = NULL;
					}

					fclose(ostream);
					_tremove(filename);
					free(line);
					free(line64);
                    png_destroy_write_struct (&png, &info);
					return BMMRES_IOERROR;
				}
				unsigned short *l=line;
				BMM_Color_64 *l64 = line64;
				unsigned char *obyte = (unsigned char *)row_pointers[iy];
				for (png_uint_32 ix = 0; ix < info->width; ix++, l64++) {
					*obyte++ = (unsigned char)(*l >> 8); l++;
					*obyte++ = (unsigned char)(l64->a >> 8);
				}
			}
			free(line);
			free(line64);
			}
			break;
		}
		break;
#ifdef OUTPUT_1_2_4
	case 4: { // Paletted only
		}
		break;
	case 2: { // Paletted only
		}
		break;
	case 1: { // Paletted only
		}
#endif
		break;
	}

	png_write_info(png, info);

	png_set_swap(png);

	png_write_image(png, row_pointers);

	png_write_end(png, info);
	fclose(ostream);

 	for (i = 0; i < info->height; i++)
		free(row_pointers[i]);

	free(row_pointers);

    png_destroy_write_struct (&png, &info);

    return BMMRES_SUCCESS;
}
Example #15
0
int write_RGBA_to_png(uint16_t width, uint16_t height, uint8_t * array, const char * filename)
{
	int x, y;
	png_structp png_ptr;
	png_infop info_ptr;
	png_bytep * row_pointers;
	FILE * fp = fopen(filename, "wb");
	
	if(fp == NULL)
		return 0;
	
	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	info_ptr = png_create_info_struct(png_ptr);
	
	PNGSETJMP
	
	png_init_io(png_ptr, fp);
	
	PNGSETJMP
	
	png_set_IHDR(png_ptr, info_ptr, width, height,
				 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
				 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
	
	png_write_info(png_ptr, info_ptr);
	
	/* write bytes */
	PNGSETJMP
	
	/* convert uint8_t[] to pngbyte[][] */
	row_pointers = malloc(sizeof(*row_pointers) * height);
	for(y = 0;y < height;y++)
	{
		row_pointers[y] = malloc(png_get_rowbytes(png_ptr, info_ptr));
		for(x = 0;x < width * 4;x += 4)
		{
			row_pointers[y][x] = array[y * width * 4 + x];
			row_pointers[y][x+1] = array[y * width * 4 + x+1];
			row_pointers[y][x+2] = array[y * width * 4 + x+2];
			row_pointers[y][x+3] = array[y * width * 4 + x+3];
		}
	}
	
	png_write_image(png_ptr, row_pointers);
	
	/* end write */
	PNGSETJMP
	
	png_write_end(png_ptr, NULL);
	png_destroy_write_struct(&png_ptr, &info_ptr);
	
	for(y = 0;y < height;y++)
	{
		free(row_pointers[y]);
	}
	free(row_pointers);
	
	fclose(fp);
	
	return 1;
}
Example #16
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;

		fp = fopen(pszFilePath, "wb");
		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 (setjmp(png_jmpbuf(png_ptr)))
		{
			fclose(fp);
			png_destroy_write_struct(&png_ptr, &info_ptr);
			break;
		}

		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;
}
Example #17
0
/* ****************************************************************** */
void WritePNG (double ***Vdbl, char *var_name, char *filename, 
                Grid *grid)
/*
 *
 *
 *
 *
 ******************************************************************** */
{
  int ic, ir, i;
  png_structp     png_ptr;
  png_infop       info_ptr;
  int backgroundcolour_;
  int bit_depth_;
  int colortype_;
  int compressionlevel_;
  int  indx;
  double filegamma_;
  Image *png;
  unsigned char **image;
  FILE   *fp;
    
  png = GetImage (var_name);
  SetColorMap (png->r, png->g, png->b, png->colormap);
  GetSlice (Vdbl, png, grid);
  if (prank != 0) return;

  image = (png_bytepp)malloc(png->nrow*sizeof(png_bytep));
  for (ir = 0; ir < png->nrow; ir++) {
    image[ir] = (png_bytep)malloc(6*png->ncol*sizeof(png_byte));
  }

  for(ic = 0; ic < png->ncol; ic++){
  for(ir = 0; ir < png->nrow; ir++){
    i = 6*ic;
    image[ir][i]   = png->rgb[ir][ic].r;      /* -- red -- */
    image[ir][i+1] = 0;
    image[ir][i+2] = png->rgb[ir][ic].g;     /* -- green -- */
    image[ir][i+3] = 0;
    image[ir][i+4] = png->rgb[ir][ic].b;     /* -- blue -- */
    image[ir][i+5] = 0;
  }}


 /* -- write --- */

  compressionlevel_ = 6;
  backgroundcolour_ = 0;
  bit_depth_ = 16;
  filegamma_ = 0.;
  colortype_ = 2.; 

  fp = fopen(filename, "wb");
  if(fp == NULL){
    printf(" ! error opening file in writing data\n");
    exit(1);
  }

  png_ptr  = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  info_ptr = png_create_info_struct(png_ptr);
  png_init_io(png_ptr, fp);

   /*   if(compressionlevel_ != -2){ */
        png_set_compression_level(png_ptr, compressionlevel_);
   /* }
   else
     {
        png_set_compression_level(png_ptr, PNGWRITER_DEFAULT_COMPRESSION);
   }*/

  png_set_IHDR(png_ptr, info_ptr, png->ncol, png->nrow,
               bit_depth_, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
               PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

  if(filegamma_ < 1.0e-1){
    filegamma_ = 0.7;
  }

  png_set_gAMA(png_ptr, info_ptr, filegamma_);
  
   /*
   time_t          gmt;
   png_time        mod_time;
   png_text        text_ptr[5];
   time(&gmt);
   png_convert_from_time_t(&mod_time, gmt);
   png_set_tIME(png_ptr, info_ptr, &mod_time);
   */

  png_write_info(png_ptr, info_ptr);
  png_write_image(png_ptr, image); 
  png_write_end(png_ptr, info_ptr);
  png_destroy_write_struct(&png_ptr, &info_ptr);
  fclose(fp);

  free((char *) image[0]);
  free((char *) image);

}
Example #18
0
int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
{
	png_structp png_ptr;
	png_infop info_ptr;

	unsigned char *pixels = NULL;
	unsigned char *from, *to;
	unsigned short *pixels16 = NULL, *to16;
	float *from_float, from_straight[4];
	png_bytepp row_pointers = NULL;
	int i, bytesperpixel, color_type = PNG_COLOR_TYPE_GRAY;
	FILE *fp = NULL;

	bool is_16bit  = (ibuf->ftype & PNG_16BIT) != 0;
	bool has_float = (ibuf->rect_float != NULL);
	int channels_in_float = ibuf->channels ? ibuf->channels : 4;

	float (*chanel_colormanage_cb)(float);

	/* use the jpeg quality setting for compression */
	int compression;
	compression = (int)(((float)(ibuf->ftype & 0xff) / 11.1111f));
	compression = compression < 0 ? 0 : (compression > 9 ? 9 : compression);

	if (ibuf->float_colorspace) {
		/* float buffer was managed already, no need in color space conversion */
		chanel_colormanage_cb = channel_colormanage_noop;
	}
	else {
		/* standard linear-to-srgb conversion if float buffer wasn't managed */
		chanel_colormanage_cb = linearrgb_to_srgb;
	}

	/* for prints */
	if (flags & IB_mem)
		name = "<memory>";

	bytesperpixel = (ibuf->planes + 7) >> 3;
	if ((bytesperpixel > 4) || (bytesperpixel == 2)) {
		printf("imb_savepng: Unsupported bytes per pixel: %d for file: '%s'\n", bytesperpixel, name);
		return (0);
	}

	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
	                                  NULL, NULL, NULL);
	if (png_ptr == NULL) {
		printf("imb_savepng: Cannot png_create_write_struct for file: '%s'\n", name);
		return 0;
	}

	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL) {
		png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
		printf("imb_savepng: Cannot png_create_info_struct for file: '%s'\n", name);
		return 0;
	}

	if (setjmp(png_jmpbuf(png_ptr))) {
		png_destroy_write_struct(&png_ptr, &info_ptr);
		printf("imb_savepng: Cannot setjmp for file: '%s'\n", name);
		return 0;
	}

	/* copy image data */

	if (is_16bit)
		pixels16 = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned short), "png 16bit pixels");
	else
		pixels = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned char), "png 8bit pixels");

	if (pixels == NULL && pixels16 == NULL) {
		png_destroy_write_struct(&png_ptr, &info_ptr);
		printf("imb_savepng: Cannot allocate pixels array of %dx%d, %d bytes per pixel for file: '%s'\n", ibuf->x, ibuf->y, bytesperpixel, name);
		return 0;
	}

	from = (unsigned char *) ibuf->rect;
	to = pixels;
	from_float = ibuf->rect_float;
	to16 = pixels16;

	switch (bytesperpixel) {
		case 4:
			color_type = PNG_COLOR_TYPE_RGBA;
			if (is_16bit) {
				if (has_float) {
					if (channels_in_float == 4) {
						for (i = ibuf->x * ibuf->y; i > 0; i--) {
							premul_to_straight_v4_v4(from_straight, from_float);
							to16[0] = ftoshort(chanel_colormanage_cb(from_straight[0]));
							to16[1] = ftoshort(chanel_colormanage_cb(from_straight[1]));
							to16[2] = ftoshort(chanel_colormanage_cb(from_straight[2]));
							to16[3] = ftoshort(chanel_colormanage_cb(from_straight[3]));
							to16 += 4; from_float += 4;
						}
					}
					else if (channels_in_float == 3) {
						for (i = ibuf->x * ibuf->y; i > 0; i--) {
							to16[0] = ftoshort(chanel_colormanage_cb(from_float[0]));
							to16[1] = ftoshort(chanel_colormanage_cb(from_float[1]));
							to16[2] = ftoshort(chanel_colormanage_cb(from_float[2]));
							to16[3] = 65535;
							to16 += 4; from_float += 3;
						}
					}
					else {
						for (i = ibuf->x * ibuf->y; i > 0; i--) {
							to16[0] = ftoshort(chanel_colormanage_cb(from_float[0]));
							to16[2] = to16[1] = to16[0];
							to16[3] = 65535;
							to16 += 4; from_float++;
						}
					}
				}
				else {
					for (i = ibuf->x * ibuf->y; i > 0; i--) {
						to16[0] = UPSAMPLE_8_TO_16(from[0]);
						to16[1] = UPSAMPLE_8_TO_16(from[1]);
						to16[2] = UPSAMPLE_8_TO_16(from[2]);
						to16[3] = UPSAMPLE_8_TO_16(from[3]);
						to16 += 4; from += 4;
					}
				}
			}
			else {
				for (i = ibuf->x * ibuf->y; i > 0; i--) {
					to[0] = from[0];
					to[1] = from[1];
					to[2] = from[2];
					to[3] = from[3];
					to += 4; from += 4;
				}
			}
			break;
		case 3:
			color_type = PNG_COLOR_TYPE_RGB;
			if (is_16bit) {
				if (has_float) {
					if (channels_in_float == 4) {
						for (i = ibuf->x * ibuf->y; i > 0; i--) {
							premul_to_straight_v4_v4(from_straight, from_float);
							to16[0] = ftoshort(chanel_colormanage_cb(from_straight[0]));
							to16[1] = ftoshort(chanel_colormanage_cb(from_straight[1]));
							to16[2] = ftoshort(chanel_colormanage_cb(from_straight[2]));
							to16 += 3; from_float += 4;
						}
					}
					else if (channels_in_float == 3) {
						for (i = ibuf->x * ibuf->y; i > 0; i--) {
							to16[0] = ftoshort(chanel_colormanage_cb(from_float[0]));
							to16[1] = ftoshort(chanel_colormanage_cb(from_float[1]));
							to16[2] = ftoshort(chanel_colormanage_cb(from_float[2]));
							to16 += 3; from_float += 3;
						}
					}
					else {
						for (i = ibuf->x * ibuf->y; i > 0; i--) {
							to16[0] = ftoshort(chanel_colormanage_cb(from_float[0]));
							to16[2] = to16[1] = to16[0];
							to16 += 3; from_float++;
						}
					}
				}
				else {
					for (i = ibuf->x * ibuf->y; i > 0; i--) {
						to16[0] = UPSAMPLE_8_TO_16(from[0]);
						to16[1] = UPSAMPLE_8_TO_16(from[1]);
						to16[2] = UPSAMPLE_8_TO_16(from[2]);
						to16 += 3; from += 4;
					}
				}
			}
			else {
				for (i = ibuf->x * ibuf->y; i > 0; i--) {
					to[0] = from[0];
					to[1] = from[1];
					to[2] = from[2];
					to += 3; from += 4;
				}
			}
			break;
		case 1:
			color_type = PNG_COLOR_TYPE_GRAY;
			if (is_16bit) {
				if (has_float) {
					float rgb[3];
					if (channels_in_float == 4) {
						for (i = ibuf->x * ibuf->y; i > 0; i--) {
							premul_to_straight_v4_v4(from_straight, from_float);
							rgb[0] = chanel_colormanage_cb(from_straight[0]);
							rgb[1] = chanel_colormanage_cb(from_straight[1]);
							rgb[2] = chanel_colormanage_cb(from_straight[2]);
							to16[0] = ftoshort(rgb_to_bw(rgb));
							to16++; from_float += 4;
						}
					}
					else if (channels_in_float == 3) {
						for (i = ibuf->x * ibuf->y; i > 0; i--) {
							rgb[0] = chanel_colormanage_cb(from_float[0]);
							rgb[1] = chanel_colormanage_cb(from_float[1]);
							rgb[2] = chanel_colormanage_cb(from_float[2]);
							to16[0] = ftoshort(rgb_to_bw(rgb));
							to16++; from_float += 3;
						}
					}
					else {
						for (i = ibuf->x * ibuf->y; i > 0; i--) {
							to16[0] = ftoshort(chanel_colormanage_cb(from_float[0]));
							to16++; from_float++;
						}
					}
				}
				else {
					for (i = ibuf->x * ibuf->y; i > 0; i--) {
						to16[0] = UPSAMPLE_8_TO_16(from[0]);
						to16++; from += 4;
					}
				}
			}
			else {
				for (i = ibuf->x * ibuf->y; i > 0; i--) {
					to[0] = from[0];
					to++; from += 4;
				}
			}
			break;
	}

	if (flags & IB_mem) {
		/* create image in memory */
		imb_addencodedbufferImBuf(ibuf);
		ibuf->encodedsize = 0;

		png_set_write_fn(png_ptr,
		                 (png_voidp) ibuf,
		                 WriteData,
		                 Flush);
	}
	else {
		fp = BLI_fopen(name, "wb");
		if (!fp) {
			png_destroy_write_struct(&png_ptr, &info_ptr);
			if (pixels)
				MEM_freeN(pixels);
			if (pixels16)
				MEM_freeN(pixels16);
			printf("imb_savepng: Cannot open file for writing: '%s'\n", name);
			return 0;
		}
		png_init_io(png_ptr, fp);
	}

#if 0
	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);
#endif

	png_set_compression_level(png_ptr, compression);

	/* png image settings */
	png_set_IHDR(png_ptr,
	             info_ptr,
	             ibuf->x,
	             ibuf->y,
	             is_16bit ? 16 : 8,
	             color_type,
	             PNG_INTERLACE_NONE,
	             PNG_COMPRESSION_TYPE_DEFAULT,
	             PNG_FILTER_TYPE_DEFAULT);

	/* image text info */
	if (ibuf->metadata) {
		png_text *metadata;
		ImMetaData *iptr;
		int num_text = 0;
		iptr = ibuf->metadata;
		while (iptr) {
			num_text++;
			iptr = iptr->next;
		}
		
		metadata = MEM_callocN(num_text * sizeof(png_text), "png_metadata");
		iptr = ibuf->metadata;
		num_text = 0;
		while (iptr) {
			
			metadata[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
			metadata[num_text].key = iptr->key;
			metadata[num_text].text = iptr->value;
			num_text++;
			iptr = iptr->next;
		}
		
		png_set_text(png_ptr, info_ptr, metadata, num_text);
		MEM_freeN(metadata);

	}

	if (ibuf->ppm[0] > 0.0 && ibuf->ppm[1] > 0.0) {
		png_set_pHYs(png_ptr, info_ptr, (unsigned int)(ibuf->ppm[0] + 0.5), (unsigned int)(ibuf->ppm[1] + 0.5), PNG_RESOLUTION_METER);
	}

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

#ifdef __LITTLE_ENDIAN__
	png_set_swap(png_ptr);
#endif

	/* allocate memory for an array of row-pointers */
	row_pointers = (png_bytepp) MEM_mallocN(ibuf->y * sizeof(png_bytep), "row_pointers");
	if (row_pointers == NULL) {
		printf("imb_savepng: Cannot allocate row-pointers array for file '%s'\n", name);
		png_destroy_write_struct(&png_ptr, &info_ptr);
		if (pixels)
			MEM_freeN(pixels);
		if (pixels16)
			MEM_freeN(pixels16);
		if (fp) {
			fclose(fp);
		}
		return 0;
	}

	/* set the individual row-pointers to point at the correct offsets */
	if (is_16bit) {
		for (i = 0; i < ibuf->y; i++) {
			row_pointers[ibuf->y - 1 - i] = (png_bytep)
			                                ((unsigned short *)pixels16 + (i * ibuf->x) * bytesperpixel);
		}
	}
	else {
		for (i = 0; i < ibuf->y; i++) {
			row_pointers[ibuf->y - 1 - i] = (png_bytep)
			                                ((unsigned char *)pixels + (i * ibuf->x) * 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 */
	if (pixels)
		MEM_freeN(pixels);
	if (pixels16)
		MEM_freeN(pixels16);
	MEM_freeN(row_pointers);
	png_destroy_write_struct(&png_ptr, &info_ptr);

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

	return(1);
}
Example #19
0
Error ResourceSaverPNG::save_image(const String &p_path, Image &p_img) {

	if (p_img.get_format() > Image::FORMAT_INDEXED_ALPHA)
		p_img.decompress();

	ERR_FAIL_COND_V(p_img.get_format() > Image::FORMAT_INDEXED_ALPHA, ERR_INVALID_PARAMETER);

	png_structp png_ptr;
	png_infop info_ptr;
	png_bytep * row_pointers;


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

	ERR_FAIL_COND_V(!png_ptr,ERR_CANT_CREATE);

	info_ptr = png_create_info_struct(png_ptr);

	ERR_FAIL_COND_V(!info_ptr,ERR_CANT_CREATE);

	if (setjmp(png_jmpbuf(png_ptr))) {
		ERR_FAIL_V(ERR_CANT_OPEN);
	}
	//change this
	Error err;
	FileAccess* f = FileAccess::open(p_path,FileAccess::WRITE,&err);
	if (err) {
		ERR_FAIL_V(err);
	}

	png_set_write_fn(png_ptr,f,_write_png_data,NULL);

	/* write header */
	if (setjmp(png_jmpbuf(png_ptr))) {
		ERR_FAIL_V(ERR_CANT_OPEN);
	}

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


	switch(p_img.get_format()) {

		case Image::FORMAT_GRAYSCALE: {

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

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

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

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

			if (p_img.detect_alpha()) {

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

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

		}
	}

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

	png_write_info(png_ptr, info_ptr);


	/* write bytes */
	if (setjmp(png_jmpbuf(png_ptr))) {
		memdelete(f);
		ERR_FAIL_V(ERR_CANT_OPEN);
	}


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

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

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

	memfree(row_pointers);

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

		memdelete(f);
		ERR_FAIL_V(ERR_CANT_OPEN);
	}

	png_write_end(png_ptr, NULL);
	memdelete(f);

	/* cleanup heap allocation */

	return OK;
}
Example #20
0
int main(int argc, char **argv) {
    if (argc != 4) {
        fprintf(stderr, "usage: %s <filename> <type> <width>\n", argv[0]);
        return 1;
    }

    type = atoi(argv[2]);
    
    fractal = fractals_get(type);

    if (type > 1) {
        abort_("type > 1");
    }

    width = atoi(argv[3]);

    if (width < 1) {
        abort_("width < 1");
    }

    height = (float)(width * fractal->ratio_height) / fractal->ratio_width;

    printf("fractal name: %s\nfractal size: %ux%u\ndest file: %s\n", fractal->name, width, height, argv[1]);
    
    /* create file */
    FILE *fp = fopen(argv[1], "wb");
        
    if (!fp) {
        abort_("[write_png_file] File %s could not be opened for writing", argv[1]);
    }


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

    if (!png_ptr) {
        abort_("[write_png_file] png_create_write_struct failed");
    }

    info_ptr = png_create_info_struct(png_ptr);

    if (!info_ptr) {
        abort_("[write_png_file] png_create_info_struct failed");
    }

    if (setjmp(png_jmpbuf(png_ptr))) {
        abort_("[write_png_file] Error during init_io");
    }

    png_init_io(png_ptr, fp);


    /* write header */
    if (setjmp(png_jmpbuf(png_ptr))) {
        abort_("[write_png_file] Error during writing header");
    }

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

    png_write_info(png_ptr, info_ptr);

    
    /* allocate memory */
    row_pointers = (png_bytep *) malloc(sizeof(png_bytep) * height);
    
    for (y = 0; y < height; ++y) {
        row_pointers[y] = (png_byte*) malloc(width * 4);
    }


    /* render the fractal */
    fractals_write(row_pointers, width, height, type);


    /* write bytes */
    if (setjmp(png_jmpbuf(png_ptr))) {
        abort_("[write_png_file] Error during writing bytes");
    }

    png_write_image(png_ptr, row_pointers);


    /* end write */
    if (setjmp(png_jmpbuf(png_ptr))) {
        abort_("[write_png_file] Error during end of write");
    }

    png_write_end(png_ptr, NULL);

    /* cleanup heap allocation */

    for (y = 0; y < height; y++) {
        free(row_pointers[y]);
    }

    free(row_pointers);

    fclose(fp);

    return 0;
}
Example #21
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;

}
Example #22
0
int main(int argc, char *argv[]) {
	setlocale(LC_ALL, "");
	setvbuf(stdout, (char*)NULL, _IONBF, 0);

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

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

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

	puts(MSG[I_OPEN]);

	FILE *f;

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

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

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

	png_struct *png_ptr;
	png_info *info_ptr, *end_info;

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

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

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

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

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

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

	png_read_info(png_ptr, info_ptr);

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

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

	int num_palette = 0;
	png_color *png_pal_got = NULL;

	if (image_is_pal)

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

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

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

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

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

	long int diff;
	bool vert;

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

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

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

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

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

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

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

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

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

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

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

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

	puts(MSG[I_LOAD]);

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

	png_read_image(png_ptr, (void*)row);

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

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

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

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

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

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

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

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

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

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

//	Bildspeicher erweitern, falls das Bild vergroessert wurde:

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

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

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

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

	sc_eject(image);

	sc_close();

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

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

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

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

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

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

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

   	png_init_io(png_ptr, f);

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

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

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

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

	png_write_info(png_ptr, info_ptr);

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

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

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

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

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

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

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

	puts(MSG[I_FINISHED]);

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

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

	free(trw);
	free(image);
	free(row);
	
	puts(MSG[I_COMPLETED]);
	
	return EXIT_SUCCESS;
}
Example #23
0
File: png.cpp Project: kyuu/azura
    //-----------------------------------------------------------------
    bool WritePNG(Image* image, File* file)
    {
        if (!image || !file) {
            return false;
        }

        Image::Ptr src_image = image;

        switch (src_image->getPixelFormat()) {
            case PixelFormat::RGB_P8:
            case PixelFormat::RGB:
            case PixelFormat::RGBA:
                // ok, we can handle these directly
                break;
            case PixelFormat::BGR:
                // convert to RGB
                src_image = src_image->convert(PixelFormat::RGB);
                break;
            case PixelFormat::BGRA:
                // convert to RGBA
                src_image = src_image->convert(PixelFormat::RGBA);
                break;
            default: // shouldn't happen
                return false;
        }

        // initialize the necessary libpng data structures
        png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
        if (!png_ptr) {
            return false;
        }
        png_infop info_ptr = png_create_info_struct(png_ptr);
        if (!info_ptr) {
            png_destroy_write_struct(&png_ptr, 0);
            return false;
        }

        // libpng uses SJLJ for error handling, so we need to define
        // any automatic variables before the call to setjmp()
        ArrayAutoPtr<png_bytep> rows;

        // establish a return point
        if (setjmp(png_jmpbuf(png_ptr)) != 0) {
            png_destroy_write_struct(&png_ptr, &info_ptr);
            return false;
        }

        // tell libpng that we are going to use our own io functions
        png_set_write_fn(png_ptr, file, write_callback, flush_callback);

        // set the image attributes
        switch (src_image->getPixelFormat())
        {
            case PixelFormat::RGB_P8:
            {
                png_set_IHDR(
                    png_ptr,
                    info_ptr,
                    src_image->getWidth(),
                    src_image->getHeight(),
                    8, /* 8 bits per channel */
                    PNG_COLOR_TYPE_PALETTE,
                    PNG_INTERLACE_NONE,
                    PNG_COMPRESSION_TYPE_DEFAULT,
                    PNG_FILTER_TYPE_DEFAULT
                );
                png_set_PLTE(
                    png_ptr,
                    info_ptr,
                    (png_colorp)src_image->getPalette(),
                    256 /* size of palette */
                );
                break;
            }
            case PixelFormat::RGB:
            {
                png_set_IHDR(
                    png_ptr,
                    info_ptr,
                    src_image->getWidth(),
                    src_image->getHeight(),
                    8, /* 8 bits per channel */
                    PNG_COLOR_TYPE_RGB,
                    PNG_INTERLACE_NONE,
                    PNG_COMPRESSION_TYPE_DEFAULT,
                    PNG_FILTER_TYPE_DEFAULT
                );
                break;
            }
            case PixelFormat::RGBA:
            {
                png_set_IHDR(
                    png_ptr,
                    info_ptr,
                    src_image->getWidth(),
                    src_image->getHeight(),
                    8, /* 8 bits per channel */
                    PNG_COLOR_TYPE_RGB_ALPHA,
                    PNG_INTERLACE_NONE,
                    PNG_COMPRESSION_TYPE_DEFAULT,
                    PNG_FILTER_TYPE_DEFAULT
                );
                break;
            }
            default: // shouldn't happen
                png_destroy_write_struct(&png_ptr, &info_ptr);
                return false;
        }

        // write png header
        png_write_info(png_ptr, info_ptr);

        // prepare an array of row pointers for libpng
        PixelFormatDescriptor pfd = Image::GetPixelFormatDescriptor(src_image->getPixelFormat());
        rows = new png_bytep[src_image->getHeight()];
        for (int i = 0; i < src_image->getHeight(); ++i) {
            rows[i] = (png_bytep)(src_image->getPixels() + i * src_image->getWidth() * pfd.bytesPerPixel);
        }

        // write image data
        png_write_image(png_ptr, rows.get());

        // finish the write process
        png_write_end(png_ptr, 0);

        // clean up
        png_destroy_write_struct(&png_ptr, &info_ptr);

        return true;
    }
Example #24
0
/*
 * write audio block to png file
*/
void frame_loop(size_t frame, char* output_dir, SNDFILE* audio_file, s_dimension d) {

    size_t x, y;
    size_t area = d.width * d.height;
    size_t wsec = ceil(d.width / d.channels);
    sf_count_t req, cnt;
    sf_count_t copy_frames = ceil(area / d.channels);
    png_uint_32 i;
    png_infop info_ptr;
    png_structp png_ptr;
    png_color_8 sig_bit;
    png_byte  pixelbuffer[d.height][d.width * BYTES_PER_PIXEL];
    png_bytep row_pointers[d.height];
    short int audiobuffer[d.channels * area];

    char file_name[11 + strlen(output_dir)];

    // open file for writing
    set_filename(file_name, output_dir, frame);
    FILE *fp = fopen(file_name, "wb");
    if (!fp) {
        exit(ERROR);
    }
    printf("%s\n", file_name);

    // clear pixelbuffer
    memset(&pixelbuffer, 0, area * BYTES_PER_PIXEL);
    // assign row pointers
    for (i = 0; i < d.height; i++) {
        row_pointers[i] = &(pixelbuffer[i][0]);
    }

    req = (size_t)sf_seek(audio_file, d.audio_frames * frame, SEEK_SET);
    if(req == -1) {
        puts("[!] audiofile seek error");
        // skip frame
        return;
    }
    cnt = sf_readf_short(audio_file, audiobuffer, copy_frames);

    // copy block
    for(x=0; x<cnt; x++) {
        //pixelbuffer[ (int) floor(x / width) ][x % width] = (char) audiobuffer[x * channels];
        for(y=0; y<d.channels; y++) {
            size_t ix = min(floor(x / wsec), d.height-1);
            size_t iy = x % wsec + y * wsec;
            pixelbuffer[ix][iy] = abs((audiobuffer[x * d.channels + y]) / 128);
            //printf("%lu ", (audiobuffer[x * channels + y] + sizeof(short int)) / 2);
            //printf("%i ", abs((audiobuffer[x * channels + y]) / 128));
        }
        //printf("\n");
    }


    // generate png from pixelbuffer
    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

    if (!png_ptr) {
        fclose(fp);
        exit(ERROR);
    }

    info_ptr = png_create_info_struct(png_ptr);

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

    if (setjmp(png_jmpbuf(png_ptr))) {
        puts("png error");
        png_destroy_write_struct(&png_ptr, &info_ptr);
        fclose(fp);
        exit(ERROR);
    }

    // write png
    png_init_io(png_ptr, fp);
    png_set_IHDR(png_ptr,
                 info_ptr,
                 d.width,
                 d.height,
                 d.bit_depth,
                 PNG_COLOR_TYPE_GRAY,
                 PNG_INTERLACE_NONE,
                 PNG_COMPRESSION_TYPE_DEFAULT,
                 PNG_FILTER_TYPE_DEFAULT);
    sig_bit.gray = d.bit_depth;
    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);

    png_destroy_write_struct(&png_ptr, &info_ptr);
    fclose(fp);
}
Example #25
0
int main(int argc, char *argv[])
{
  unsigned char header[8];
  if ( argc != 3 )
   {
        printf( "usage: %s filename gamma_value", argv[0] );
    }
  FILE *fp = fopen(argv[1],"rb");
  float gamma ;
  sscanf(argv[2], "%f", &gamma);
  if(!fp)
    printf("not a file");
  fread(header, 1, 8, fp);
  int is_png = !png_sig_cmp(header, 0, 8); //Quite weird. cmp return 0 if bytes match PNG signature
  if(!is_png)
    printf("not a png");
  else
    printf("input file confirmed as png\n");

  //Creating png_structp
  png_structp png_ptr = png_create_read_struct
	(PNG_LIBPNG_VER_STRING, 
	 NULL, //(png_voidp)user_error_ptr, 
	 NULL, //user_error_fn, 
	 NULL); //user_warning_fn);
  
  if(!png_ptr)
    printf("png_ptr construct error\n");

  //Creating png_infop
  png_infop info_ptr = png_create_info_struct(png_ptr);
  if(!info_ptr)
  {
    png_destroy_read_struct(&png_ptr,(png_infopp) NULL,(png_infopp) NULL);
    printf("something wrong with pngInfo\n");
  }
  
  //setjmp for error condition from libpng

  if(setjmp(png_jmpbuf(png_ptr)))
    printf("something wrong with jmp setting\n");

  //eventually, we are reading the file :-)
  png_init_io(png_ptr, fp);
  //since we've sampled 8 byes for testing if it is png, we need to let libpng know 
  png_set_sig_bytes(png_ptr, 8);

  //There're bunch of error handling from the manual... we skip as usual
/*
  //High-level of reading interface, we'll read into memory directly
  png_read_png(png_ptr, info_ptr, 0, NULL); //third para as png_transforms bitwise OR mask
  png_bytep *row_pointers = png_get_rows(png_ptr, info_ptr);
*/

  /* low level of reading, we need it to manipulate more detailed stuff*/
  png_read_info(png_ptr, info_ptr);
  
  int width = png_get_image_width(png_ptr, info_ptr);
  int height = png_get_image_height(png_ptr, info_ptr);
  png_byte color_type = png_get_color_type(png_ptr, info_ptr);
  png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr);
  png_bytep *row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
  int x, y,k;
  k = (int)((log(bit_depth)/log(2)));
  printf("%d\n", k);
  for (y = 0; y < height; y++)
    row_pointers[y] = (png_bytep) malloc(width*k);

  png_read_image(png_ptr, row_pointers);

  printf("color_type:%d\nbit_depth: %d\n",color_type, bit_depth);
  

  //processing image
  for (y = 0; y< height; y++)
  {
    png_byte* row = row_pointers[y];
    for(x = 0; x < width; x ++)
    {
      png_byte* ptr = &(row[x*k]);    
      //ptr[0] = 255 - ptr[0]; //shouldn't invert alpha :)
      //ptr[0] = (int)(pow(ptr[0], 0.9)) ;
      ptr[1] = (int)(255 * pow((ptr[1]/255.0), gamma)) ;
      ptr[2] = (int)(255 * pow((ptr[2]/255.0), gamma)) ;
      ptr[3] = (int)(255 * pow((ptr[3]/255.0), gamma)) ;
    } 

  }
  //output
  FILE *outfp = fopen("gammaout.png", "wb");
  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
  info_ptr = png_create_info_struct(png_ptr);
  png_init_io(png_ptr, outfp);
  png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

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

  free(row_pointers);

  fclose(fp);
  


}
Example #26
0
bool  PngEncoder::write( const Mat& img, const std::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;
}
Example #27
0
void WritePNG(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 = safe_malloc(width * height * numBytes);

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

	png_set_write_fn(png, buffer, png_write_data, png_flush_data);

	if(numBytes == 4)
	{
		png_set_IHDR(png, info, width, height, 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
				 PNG_FILTER_TYPE_DEFAULT);
	}
	else
	{
		// should be 3
		png_set_IHDR(png, info, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
				PNG_FILTER_TYPE_DEFAULT);
	}

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

	row_pointers = safe_malloc(height * sizeof(png_bytep));

	if(setjmp(png_jmpbuf(png)))
	{
		free(row_pointers);
		free(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);

	free(row_pointers);

	SaveFile(name, buffer, png_compressed_size);

	free(buffer);
}
Example #28
0
// Also informed by https://gist.github.com/niw/5963798
bool WritePNG(ImageData* outImage, char* fileName)
{
    // Step 0: Make sure we can open the input file
    FILE* outFile = fopen(fileName, "wb");
    if (!outFile) {
        abort_("WritePNG: Can't open %s for writing\n", fileName);
    }

    int width = outImage->xDim;
    int height = outImage->yDim;

    // The image we get has RGB-only data, in 3-byte pixels
    // We need an array of rows, with pointers to them, each row having RGBA data
    png_bytep row_pointers[height];
    for (int row = 0; row < height; row++) {
        // Output image rows are RGBA
        row_pointers[row] = (png_bytep)malloc(width * 4);
        if (!row_pointers[row]) {
            abort_("WritePNG: Can't allocate memory for row %d\n", row);
        }
    
        // Set all to 0xff, for initializing alpha channel
        memset(row_pointers[row], 0xff, width * 4);

        // Now copy pixels from input image to output
        for (int pixel = 0; pixel < width; pixel++) {
            *(Pixel*)(row_pointers[row] + pixel * 4) =
                *(outImage->pixels + row * width + pixel);
        }
    }

    png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png) abort();

    png_infop info = png_create_info_struct(png);
    if (!info) abort();

    if (setjmp(png_jmpbuf(png))) abort();

    png_init_io(png, outFile);

    // Output is 8bit depth, RGBA format.
    png_set_IHDR(
            png,
            info,
            width, height,
            8,
            PNG_COLOR_TYPE_RGBA,
            PNG_INTERLACE_NONE,
            PNG_COMPRESSION_TYPE_DEFAULT,
            PNG_FILTER_TYPE_DEFAULT
            );
    png_write_info(png, info);

    // To remove the alpha channel for PNG_COLOR_TYPE_RGB format, Use png_set_filler().
    //png_set_filler(png, 0, PNG_FILLER_AFTER);

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

    for(int y = 0; y < height; y++) {
        free(row_pointers[y]);
    }

    fclose(outFile);
    return false;
}
Example #29
0
File: png.c Project: jinjoh/NOOR
short imb_savepng(struct ImBuf *ibuf, char *name, int flags)
{
    png_structp png_ptr;
    png_infop info_ptr;

    unsigned char *pixels = 0;
    unsigned char *from, *to;
    png_bytepp row_pointers = 0;
    int i, bytesperpixel, color_type = PNG_COLOR_TYPE_GRAY;
    FILE *fp = 0;

    bytesperpixel = (ibuf->depth + 7) >> 3;
    if ((bytesperpixel > 4) || (bytesperpixel == 2)) {
        printf("imb_savepng: unsupported bytes per pixel: %d\n", bytesperpixel);
        return (0);
    }

    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
                                      NULL, NULL, NULL);
    if (png_ptr == NULL) {
        printf("Cannot png_create_write_struct\n");
        return 0;
    }

    info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL) {
        png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
        printf("Cannot png_create_info_struct\n");
        return 0;
    }

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

    // copy image data

    pixels = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned char), "pixels");
    if (pixels == NULL) {
        printf("Cannot allocate pixels array\n");
        return 0;
    }

    from = (unsigned char *) ibuf->rect;
    to = pixels;

    switch (bytesperpixel) {
    case 4:
        color_type = PNG_COLOR_TYPE_RGBA;
        for (i = ibuf->x * ibuf->y; i > 0; i--) {
            to[0] = from[0];
            to[1] = from[1];
            to[2] = from[2];
            to[3] = from[3];
            to += 4;
            from += 4;
        }
        break;
    case 3:
        color_type = PNG_COLOR_TYPE_RGB;
        for (i = ibuf->x * ibuf->y; i > 0; i--) {
            to[0] = from[0];
            to[1] = from[1];
            to[2] = from[2];
            to += 3;
            from += 4;
        }
        break;
    case 1:
        color_type = PNG_COLOR_TYPE_GRAY;
        for (i = ibuf->x * ibuf->y; i > 0; i--) {
            to[0] = from[0];
            to++;
            from += 4;
        }
        break;
    }

    if (flags & IB_mem) {
        // create image in memory
        imb_addencodedbufferImBuf(ibuf);
        ibuf->encodedsize = 0;

        png_set_write_fn(png_ptr,
                         (png_voidp) ibuf,
                         WriteData,
                         Flush);
    } else {
        fp = fopen(name, "wb");
        if (!fp) {
            MEM_freeN(pixels);
            return 0;
        }
        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,
                 ibuf->x,
                 ibuf->y,
                 8,
                 color_type,
                 PNG_INTERLACE_NONE,
                 PNG_COMPRESSION_TYPE_DEFAULT,
                 PNG_FILTER_TYPE_DEFAULT);

    /* image text info */
    if (ibuf->img_info) {
        png_text*  imginfo;
        ImgInfo* iptr;
        int  num_text = 0;
        iptr = ibuf->img_info;
        while (iptr) {
            num_text++;
            iptr = iptr->next;
        }

        imginfo = MEM_callocN(num_text*sizeof(png_text), "png_imginfo");
        iptr = ibuf->img_info;
        num_text = 0;
        while (iptr) {

            imginfo[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
            imginfo[num_text].key = iptr->key;
            imginfo[num_text].text = iptr->value;
            num_text++;
            iptr = iptr->next;
        }

        png_set_text(png_ptr, info_ptr, imginfo, num_text);
        MEM_freeN(imginfo);

    }

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

    // allocate memory for an array of row-pointers
    row_pointers = (png_bytepp) MEM_mallocN(ibuf->y * sizeof(png_bytep), "row_pointers");
    if (row_pointers == NULL) {
        printf("Cannot allocate row-pointers array\n");
        MEM_freeN(pixels);
        return 0;
    }

    // set the individual row-pointers to point at the correct offsets
    for (i = 0; i < ibuf->y; i++) {
        row_pointers[ibuf->y-1-i] = (png_bytep)
                                    ((unsigned char *)pixels + (i * ibuf->x) * 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
    MEM_freeN(pixels);
    MEM_freeN(row_pointers);
    png_destroy_write_struct(&png_ptr, &info_ptr);

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

    return(1);
}
bool PNGImageFileType::write(const Image        *OSG_PNG_ARG(pImage  ), 
                                   std::ostream &OSG_PNG_ARG(os      ),
                             const std::string  &OSG_PNG_ARG(mimetype))
{
#ifdef OSG_WITH_PNG

    png_structp png_ptr;
    png_infop info_ptr;

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

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

    if(png_ptr == NULL)
        return false;

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

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

    /* This is the hard way */

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

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

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

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

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

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


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

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

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

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

#if 0
    /* invert monochrome pixels */
    png_set_invert_mono(png_ptr);

    /* Shift the pixels up to a legal bit depth and fill in
    * as appropriate to correctly scale the image.
    */
    png_set_shift(png_ptr, &sig_bit);

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

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

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

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

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

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

    delete [] row_pointers;

    /* that's it */
    return true;

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

    return false;
#endif
}