//saves the given SDL structure into a given filename.
void save_image(surface surf, const std::string &filename)
{
	//opens the actual file
	const util::scoped_FILE file(fopen(filename.c_str(),"wb"));

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

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

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

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

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

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

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

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

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

	//cleans everything
	png_write_end(png_ptr, info_ptr);
	png_destroy_write_struct(&png_ptr, &info_ptr);
	delete [] row_pointers;
}
Пример #2
0
/* Save the two dimensional array as a png image */
int save_png(double *data, const int nx, const int ny, const char *fname)
{
    FILE *fp;
    png_structp pngstruct_ptr = NULL;
    png_infop pnginfo_ptr = NULL;
    png_byte **row_pointers = NULL;
    int i, j;

    /* Default return status is failure */
    int status = -1;

    int pixel_size = 3;
    int depth = 8;

    if ((fp = fopen(fname, "wb")) != NULL) {

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

        if (pngstruct_ptr != NULL) {

            pnginfo_ptr = png_create_info_struct(pngstruct_ptr);

            if (pnginfo_ptr != NULL) {

                if (!setjmp(png_jmpbuf(pngstruct_ptr))) {

                    png_set_IHDR(pngstruct_ptr, pnginfo_ptr, (size_t) ny,
                                 (size_t) nx, depth, PNG_COLOR_TYPE_RGB,
                                 PNG_INTERLACE_NONE,
                                 PNG_COMPRESSION_TYPE_DEFAULT,
                                 PNG_FILTER_TYPE_DEFAULT);

                    row_pointers = png_malloc(pngstruct_ptr,
                                              ny * sizeof(png_byte *));
                    for (i = 0; i < nx; i++) {
                        png_byte *row = png_malloc(pngstruct_ptr,
                                                   sizeof(uint8_t) * ny *
                                                   pixel_size);
                        row_pointers[i] = row;
                        for (j = 0; j < ny; j++) {
                            pixel_t pixel;
                            // Scale the values so that values between
                            // 0 and 100 degrees are mapped to values
                            // between 0 and 255
                            cmap(data[j + i * ny], 2.55, 0.0, &pixel);
                            *row++ = pixel.red;
                            *row++ = pixel.green;
                            *row++ = pixel.blue;
                        }
                    }

                    png_init_io(pngstruct_ptr, fp);
                    png_set_rows(pngstruct_ptr, pnginfo_ptr, row_pointers);
                    png_write_png(pngstruct_ptr, pnginfo_ptr,
                                  PNG_TRANSFORM_IDENTITY, NULL);

                    status = 0;

                    for (i = 0; i < ny; i++) {
                        png_free(pngstruct_ptr, row_pointers[i]);
                    }
                    png_free(pngstruct_ptr, row_pointers);


                }
            }
            png_destroy_write_struct(&pngstruct_ptr, &pnginfo_ptr);
        }
        fclose(fp);
    }
    return status;
}
Пример #3
0
//void save_png(GLfloat* pix)
void save_png(GLuint* pix, int width, int height)
{
  FILE * fp;
  png_structp png_ptr = NULL;
  png_infop info_ptr = NULL;
  size_t x, y;
  png_byte ** row_pointers = NULL;
  /* "status" contains the return value of this function. At first
     it is set to a value which means 'failure'. When the routine
     has finished its work, it is set to a value which means
     'success'. */
  int status = -1;
  /* The following number is set by trial and error only. I cannot
     see where it it is documented in the libpng manual.
     */
  int pixel_size = 3;
  int depth = 8;

  fp = fopen ("testdepth.png", "wb");
  if (! fp) {
    printf("cannot open\n");
    return;
  }

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

  info_ptr = png_create_info_struct (png_ptr);
  if (info_ptr == NULL) {
    printf("error 1\n");
    return;
  }

  /* Set up error handling. */

  if (setjmp (png_jmpbuf (png_ptr))) {
    printf("error 2\n");
    return;
  }

  /* Set image attributes. */
  //int width = 1200;
  //int height = 400;

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

    /* Initialize rows of PNG. */

  row_pointers = png_malloc (png_ptr, height * sizeof (png_byte *));
    for (y = 0; y < height; ++y) {
        png_byte *row = 
            png_malloc (png_ptr, sizeof (uint8_t) * width * pixel_size);
        row_pointers[y] = row;
        for (x = 0; x < width; ++x) {
          //float f = pix[y*width +x]*255;
          //float f = (pix[y*width +x]>>8) / 16777215.0f * 255.0f ;
          //float f = (pix[y*width +x]>>8);
          //float f = (pix[y*width +x]>>8) / 65536.0f * 255.0f ;
          float f = (pix[y*width +x]&0xff)*255;
          //float f = (pix[y*width +x]&0xff);
          uint32_t utest = (pix[y*width +x]&0xff);
          if (y*width +x == 0)  {
          //printf(" the value u : %u \n", pix[0]&0xff);
          printf(" the value f : %f \n", f);
          printf(" the value utest : %x \n", utest);
                }
            pixel_t yep = { f,f,f};
            pixel_t * pixel = &yep;
            *row++ = pixel->red;
            *row++ = pixel->green;
            *row++ = pixel->blue;
        }
    }
    
    /* Write the image data to "fp". */

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

    /* The routine has successfully written the file, so we set
       "status" to a value which indicates success. */

    status = 0;
    
    for (y = 0; y < height; y++) {
        png_free (png_ptr, row_pointers[y]);
    }
    png_free (png_ptr, row_pointers);
    
    return;
}
Пример #4
0
/** 保存指定图像的Mipmap
@Param 要保存图像文件的路径
@Param 指向图像对象的指针
@Param 指定的Mipmap层级
*/
void F3DPNGCodec::SaveMipmap( const char* filename,F3DImage* image,size_t level )
{
    FBYTE* destBuf;
    EPixelFormat destFormat;
    size_t destSize,pxSize;

    // 创建一个PNG文件
	FVFile file;
	if( file.Open(filename,FVFile::VFILE_CREATENEW|FVFile::VFILE_BINARY) )
    {
		FLOG_WARNINGF( "F3DPNGCodec::SaveMipMap, Create the PNG file (%s) failed!",filename );
        return;
    }

    // 分配一个PNG写对象
    png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING,
        NULL,NULL,NULL);

    // 分配一个PNG信息结构体
    png_infop info_ptr = png_create_info_struct( png_ptr );

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

		FLOG_ERROR("F3DPNGCodec::SaveMipmap, An error occurs when writing...");
		return;
    }

    // 设置PNG的写入回调函数
    png_set_write_fn( png_ptr,&file,PNGWriteFunc,NULL );

    // 获取源图像的一些信息
    size_t width = image->GetWidth( level );
    size_t height = image->GetHeight( level );
    EPixelFormat srcFormat = image->GetPixelFormat();

    if( F3D_HaveAlpha(srcFormat) )
        destFormat = PFT_A8R8G8B8;
    else
        destFormat = PFT_R8G8B8;

    // 将数据转换为指定像素格式
    pxSize = F3D_PixelSize( destFormat );
    destSize = width*height*pxSize;
    destBuf = new FBYTE[destSize];
    F3D_ConvertPixelFormat( image->GetImageData(level),srcFormat,destBuf,destFormat,width,height );

    // 设置PNG图像的信息
    if( destFormat == PFT_A8R8G8B8 )
    {
        png_set_IHDR( png_ptr,info_ptr,(png_uint_32)image->GetWidth(level),
            (png_uint_32)image->GetHeight(level),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,(png_uint_32)image->GetWidth(level),
            (png_uint_32)image->GetHeight(level),8,PNG_COLOR_TYPE_RGB,PNG_INTERLACE_NONE,
            PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT );
    }

    FBYTE** row_pointers = new png_bytep[height];

    FBYTE* data = destBuf;
    for( size_t i=0;i<height;i++ )
    {
        row_pointers[i] = data;
        data += width * pxSize;
    }

    if( setjmp(png_jmpbuf(png_ptr)) )
    {
        png_destroy_write_struct( &png_ptr,&info_ptr );
        delete[] row_pointers;
        delete[] destBuf;

		FLOG_ERROR("F3DPNGCodec::SaveMipmap, An error occurs when writing...");
		return;
    }

    png_set_rows( png_ptr,info_ptr,row_pointers );

    if( destFormat == PFT_A8R8G8B8 )
        png_write_png( png_ptr,info_ptr,PNG_TRANSFORM_BGR,NULL );
    else
        png_write_png( png_ptr,info_ptr,PNG_TRANSFORM_IDENTITY,NULL );

    // 关闭PNG文件
    png_destroy_write_struct( &png_ptr,&info_ptr );
    file.Close();
    delete[] row_pointers;
    delete[] destBuf;
}
Пример #5
0
bool CImageWriterPNG::writeImage(io::IWriteFile* file, IImage* image,u32 param) const
{
#ifdef _IRR_COMPILE_WITH_LIBPNG_
	if (!file || !image)
		return false;

	// Allocate the png write struct
	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
		NULL, (png_error_ptr)png_cpexcept_error, NULL);
	if (!png_ptr)
	{
		os::Printer::log("PNGWriter: Internal PNG create write struct failure\n", file->getFileName(), ELL_ERROR);
		return false;
	}

	// Allocate the png info struct
	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr)
	{
		os::Printer::log("PNGWriter: Internal PNG create info struct failure\n", file->getFileName(), ELL_ERROR);
		png_destroy_write_struct(&png_ptr, NULL);
		return false;
	}

	// for proper error handling
	if (setjmp(png_jmpbuf(png_ptr)))
	{
		png_destroy_write_struct(&png_ptr, &info_ptr);
		return false;
	}

	png_set_write_fn(png_ptr, file, user_write_data_fcn, NULL);

	// Set info
	switch(image->getColorFormat())
	{
		case ECF_A8R8G8B8:
		case ECF_A1R5G5B5:
			png_set_IHDR(png_ptr, info_ptr,
				image->getDimension().Width, image->getDimension().Height,
				8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
				PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
		break;
		default:
			png_set_IHDR(png_ptr, info_ptr,
				image->getDimension().Width, image->getDimension().Height,
				8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
				PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
	}

	s32 lineWidth=image->getDimension().Width;
	switch(image->getColorFormat())
	{
	case ECF_R8G8B8:
	case ECF_R5G6B5:
		lineWidth*=3;
		break;
	case ECF_A8R8G8B8:
	case ECF_A1R5G5B5:
		lineWidth*=4;
		break;
	}
	u8* tmpImage = new u8[image->getDimension().Height*lineWidth];
	if (!tmpImage)
	{
		os::Printer::log("PNGWriter: Internal PNG create image failure\n", file->getFileName(), ELL_ERROR);
		png_destroy_write_struct(&png_ptr, &info_ptr);
		return false;
	}

	u8* data = (u8*)image->lock();
	switch(image->getColorFormat())
	{
	case ECF_R8G8B8:
		CColorConverter::convert_R8G8B8toR8G8B8(data,image->getDimension().Height*image->getDimension().Width,tmpImage);
		break;
	case ECF_A8R8G8B8:
		CColorConverter::convert_A8R8G8B8toA8R8G8B8(data,image->getDimension().Height*image->getDimension().Width,tmpImage);
		break;
	case ECF_R5G6B5:
		CColorConverter::convert_R5G6B5toR8G8B8(data,image->getDimension().Height*image->getDimension().Width,tmpImage);
		break;
	case ECF_A1R5G5B5:
		CColorConverter::convert_A1R5G5B5toA8R8G8B8(data,image->getDimension().Height*image->getDimension().Width,tmpImage);
		break;
	}
	image->unlock();

	// Create array of pointers to rows in image data

	//Used to point to image rows
	u8** RowPointers = new png_bytep[image->getDimension().Height];
	if (!RowPointers)
	{
		os::Printer::log("PNGWriter: Internal PNG create row pointers failure\n", file->getFileName(), ELL_ERROR);
		png_destroy_write_struct(&png_ptr, &info_ptr);
		delete [] tmpImage;
		return false;
	}

	data=tmpImage;
	// Fill array of pointers to rows in image data
	for (u32 i=0; i<image->getDimension().Height; ++i)
	{
		RowPointers[i]=data;
		data += lineWidth;
	}
	// for proper error handling
	if (setjmp(png_jmpbuf(png_ptr)))
	{
		png_destroy_write_struct(&png_ptr, &info_ptr);
		delete [] RowPointers;
		delete [] tmpImage;
		return false;
	}

	png_set_rows(png_ptr, info_ptr, RowPointers);

	if (image->getColorFormat()==ECF_A8R8G8B8 || image->getColorFormat()==ECF_A1R5G5B5)
		png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_BGR, NULL);
	else
	{
		png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
	}

	delete [] RowPointers;
	delete [] tmpImage;
	png_destroy_write_struct(&png_ptr, &info_ptr);
	return true;
#else
	return false;
#endif
}
    // lecture de l'image...
    void VideoGen::read_image()
    {
        char filename[1024]; //grmpf, il vaudrait mieux faire un malloc... 
        FILE           *file;
        png_structp     png_ptr;
        png_infop       info_ptr;
        png_uint_32     width, height;
        int             bit_depth, color_type; 
        png_bytep      *row_pointers;
        unsigned int             i;  

        // Calcul du nom de la prochaine image.
        // Si ce nom ne correspond a aucun fichier, on remet l'index a zero
        sprintf(filename, "%s%02d.png", base_name, current_image_number);


        // on désalloue l'espace mémoire occupé par l'image précédente
        if (image.pixel)
            free(image.pixel);
        image.pixel = NULL;

        // on ouvre l'image
        file = fopen(filename, "rb");
        if(file == NULL) {
            // On reessaye la première image
            current_image_number = 0;
            sprintf(filename, "%s%02d.png", base_name, current_image_number);
            file = fopen(filename, "rb");
            // Si la première image n'existe pas on quite
            if(file == NULL) {
                cerr << name()
                    << " read_image : impossible d'ouvrir l'image source " 
                    << filename << endl;
                exit(-1);
            }
        }

        // Les structures de l'image png
        png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
        assert((png_ptr != NULL) && "png_create_read_struct...");

        info_ptr = png_create_info_struct(png_ptr);
        assert((info_ptr != NULL) && "png_create_info_struct...");

        if (setjmp(png_jmpbuf(png_ptr)))
        {
            png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
            fclose(file);
            exit(-1);
        }

        png_init_io(png_ptr, file);

        png_read_info(png_ptr, info_ptr);
        png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
                NULL, NULL, NULL);
        assert((bit_depth == 8) && "bit_depth!=8");
        if(color_type != PNG_COLOR_TYPE_GRAY) {
            cerr << name()
                << " Erreur sur le format de l'image d'entrée" << endl
                << "Le seul format PNG supporté est : "
                << "niveaux de gris, 8bpp, sans canal alpha" << endl;
            png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
            fclose(file);
            exit(-1);
        }

        // on recupère la taille de l'image
        if(( width != p_WIDTH ) || ( height != p_HEIGHT ))
        {
            cerr <<  name() 
                << " l'image " << filename << " n'a pas les bonnes dimensions ("
                << p_WIDTH << "x" << p_HEIGHT << ")"<< endl;
            exit(-1);
        }

        image.width = width;
        image.height = height;
        // on alloue l'espace necessaire à l'image
        image.pixel = (unsigned char *)malloc(width * height * sizeof(unsigned char));
        assert( (image.pixel != NULL) && "alloc image failed");

        row_pointers = (png_bytep*) png_malloc(png_ptr, height * sizeof(png_bytep));
        assert((row_pointers != NULL) && "row_pointer");
        for (i = 0; i < height; i++)
            row_pointers[i] = (png_bytep)(&image.pixel[i*width]);
        png_set_rows(png_ptr, info_ptr, row_pointers);

        png_read_image(png_ptr, row_pointers);

        png_free(png_ptr, row_pointers);

        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

#ifdef SOCLIB_MODULE_DEBUG
        cout << name()
            << " Lecture de l'image " << filename << endl;
#endif
        fclose(file);
    }
Пример #7
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;

}
Пример #8
0
static void internal_saveImage_PNG(const char *fileName, const iV_Image *image, int color_type)
{
	unsigned char** scanlines = NULL;
	png_infop info_ptr = NULL;
	png_structp png_ptr = NULL;
	PHYSFS_file* fileHandle;

	ASSERT(image->depth != 0, "Bad depth");

	fileHandle = PHYSFS_openWrite(fileName);
	if (fileHandle == NULL)
	{
		debug(LOG_ERROR, "pie_PNGSaveFile: PHYSFS_openWrite failed (while opening file %s) with error: %s\n", fileName, PHYSFS_getLastError());
		return;
	}

	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (png_ptr == NULL)
	{
		debug(LOG_ERROR, "pie_PNGSaveFile: Unable to create png struct\n");
		PNGWriteCleanup(&info_ptr, &png_ptr, fileHandle);
		return;
	}

	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL)
	{
		debug(LOG_ERROR, "pie_PNGSaveFile: Unable to create png info struct\n");
		PNGWriteCleanup(&info_ptr, &png_ptr, fileHandle);
		return;
	}

	// If libpng encounters an error, it will jump into this if-branch
	if (setjmp(png_jmpbuf(png_ptr)))
	{
		debug(LOG_ERROR, "pie_PNGSaveFile: Error encoding PNG data\n");
	}
	else
	{
		unsigned int channelsPerPixel = 3;
		unsigned int currentRow, row_stride;

		if (color_type == PNG_COLOR_TYPE_GRAY)
		{
			channelsPerPixel = 1;
		}
		row_stride = image->width * channelsPerPixel * image->depth / 8;

		scanlines = (unsigned char **)malloc(sizeof(unsigned char *) * image->height);
		if (scanlines == NULL)
		{
			debug(LOG_ERROR, "pie_PNGSaveFile: Couldn't allocate memory\n");
			PNGWriteCleanup(&info_ptr, &png_ptr, fileHandle);
			return;
		}

		png_set_write_fn(png_ptr, fileHandle, wzpng_write_data, wzpng_flush_data);

		// Set the compression level of ZLIB
		// Right now we stick with the default, since that one is the
		// fastest which still produces acceptable filesizes.
		// The highest compression level hardly produces smaller files than default.
		//
		// Below are some benchmarks done while taking screenshots at 1280x1024
		// Z_NO_COMPRESSION:
		// black (except for GUI): 398 msec
		// 381, 391, 404, 360 msec
		//
		// Z_BEST_SPEED:
		// black (except for GUI): 325 msec
		// 611, 406, 461, 608 msec
		//
		// Z_DEFAULT_COMPRESSION:
		// black (except for GUI): 374 msec
		// 1154, 1121, 627, 790 msec
		//
		// Z_BEST_COMPRESSION:
		// black (except for GUI): 439 msec
		// 1600, 1078, 1613, 1700 msec

		// Not calling this function is equal to using the default
		// so to spare some CPU cycles we comment this out.
		// png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION);

		png_set_IHDR(png_ptr, info_ptr, image->width, image->height, image->depth,
		             color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

		// Create an array of scanlines
		for (currentRow = 0; currentRow < image->height; ++currentRow)
		{
			// We're filling the scanline from the bottom up here,
			// otherwise we'd have a vertically mirrored image.
			scanlines[currentRow] = &image->bmp[row_stride * (image->height - currentRow - 1)];
		}

		png_set_rows(png_ptr, info_ptr, (png_bytepp)scanlines);

		png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
	}

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

  unsigned int i,j;

  /* open the file */
  fp = fopen(file_name, "wb");
  if (fp == NULL)
    return;
  
  /* Create and initialize the png_struct with the desired error handler
   * functions.  If you want to use the default stderr and longjump method,
   * you can supply NULL for the last three parameters.  We also check that
   * the library version is compatible with the one used at compile time,
   * in case we are using dynamically linked libraries.  REQUIRED.
   */
  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp) NULL,
				    user_error_fn, user_warning_fn);
  
  if (png_ptr == NULL)
    {
      fclose(fp);
      return;
    }
  
  /* Allocate/initialize the image information data.  REQUIRED */
  info_ptr = png_create_info_struct(png_ptr);
  if (info_ptr == NULL)
    {
      fclose(fp);
      png_destroy_write_struct(&png_ptr,  (png_infopp)NULL);
      return;
    }
  
  /* Set error handling.  REQUIRED if you aren't supplying your own
   * error handling functions in the png_create_write_struct() call.
   */
  if (setjmp(png_ptr->jmpbuf))
    {
      /* If we get here, we had a problem writing the file */
      fclose(fp);
      png_destroy_write_struct(&png_ptr,  (png_infopp) &info_ptr);
      return;
   }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

   fclose(fp);

   return;
}
Пример #10
0
int writepng(const void * buffer, char * filename, int width, int height)
{
  // Open a file to write the png for
  FILE * fp = fopen(filename, "wb");
  if (!fp) {
    fprintf(stderr, "capture: Couln't open output file \"%s\"", filename);
    return 1;
  }

  // Initialize PNG write structure
  png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
                                                NULL, NULL, NULL); 
  if (!png_ptr) {
    fprintf(stderr, "capture: Can't initialize png_ptr");
    return 1;
  }
  // Initialize PNG info pointer
  png_infop info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr) {
     png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
     fprintf(stderr, "capture: Can't initialze info_ptr");
     return 1;
  }
  // Initialize PNG error jump
  if (setjmp(png_jmpbuf(png_ptr))) {
    png_destroy_write_struct(&png_ptr, &info_ptr);
    fclose(fp);
    fprintf(stderr, "capture: Unknown error");
    return 1;
  }

  // Give PNG the file handle
  png_init_io(png_ptr, fp);

  // Set PNG Header
  png_set_IHDR(png_ptr, info_ptr, 
      width,                          // Width
      height,                         // Height
      8,                              // Bit depth
      PNG_COLOR_TYPE_RGB_ALPHA,       // Color type
      PNG_INTERLACE_NONE,             // Interlacing
      PNG_COMPRESSION_TYPE_DEFAULT,   // Compression
      PNG_FILTER_TYPE_DEFAULT);       // Filter method


  // Allocate a pointer to an array of png_byte pointers
  png_bytep * row_pointers = png_malloc(png_ptr, height * png_sizeof(png_bytep));

  // OpenGL stores pixel data in row major format, from bottom of image to top.
  // PNG's are stored row major, top to bottom.
  int i;
  for (i = 0; i < height; ++i)
    row_pointers[i] = &((png_bytep) buffer)[(height - i - 1) * width * 4];

  // Set the rows
  png_set_rows(png_ptr, info_ptr, row_pointers);
  // Write the png
  png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);


  free(row_pointers);
  png_destroy_write_struct(&png_ptr, &info_ptr);
  fclose(fp);

  return 0;
} // writepng()
Пример #11
0
void Metafile::toPNG(PMEMPNG accum, int width, int height, const char *px){
    bitmap_t bmStore;
    bitmap_t *bitmap = &bmStore;
    accum->buffer=NULL;  // PNG constructed in memory will end up here, caller must free().
    accum->size=0;
    bitmap->pixels=(pixel_t *)px;
    bitmap->width  = width;
    bitmap->height = height;

    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL;
    size_t x, y;
    png_byte ** row_pointers = NULL;
    /*  The following number is set by trial and error only. I cannot
        see where it it is documented in the libpng manual.
    */
    int pixel_size = 3;
    int depth = 8;

    png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (png_ptr == NULL){
        accum->buffer=NULL;
        return;
    }

    info_ptr = png_create_info_struct (png_ptr);
    if (info_ptr == NULL){
        png_destroy_write_struct (&png_ptr, &info_ptr);
        accum->buffer=NULL;
        return;
    }

    /* Set up error handling. */

    if (setjmp (png_jmpbuf (png_ptr))) {
        png_destroy_write_struct (&png_ptr, &info_ptr);
        accum->buffer=NULL;
        return;
    }

    /* Set image attributes. */

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

    /* Initialize rows of PNG. */

    row_pointers = (png_byte **) png_malloc (png_ptr, bitmap->height * sizeof (png_byte *));
    for (y = 0; y < bitmap->height; ++y) {
        png_byte *row =
            (png_byte *) png_malloc (png_ptr, sizeof (uint8_t) * bitmap->width * pixel_size);
        row_pointers[bitmap->height - y - 1] = row;  // Row order in EMF is reversed.
        for (x = 0; x < bitmap->width; ++x) {
            pixel_t * pixel = pixel_at (bitmap, x, y);
            *row++ = pixel->red;   // R & B channels were set correctly by DIB_to_RGB
            *row++ = pixel->green;
            *row++ = pixel->blue;
        }
    }

    /* Write the image data to memory */

    png_set_rows (png_ptr, info_ptr, row_pointers);

    png_set_write_fn(png_ptr, accum, my_png_write_data, NULL);

    png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

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

}
Пример #12
0
        void impl_save_png (
            const std::string& file_name,
            std::vector<unsigned char*>& row_pointers,
            const long width,
            const png_type type,
            const int bit_depth
        )
        {

            FILE *fp;
            png_structp png_ptr;
            png_infop info_ptr;

            /* Open the file */
            fp = fopen(file_name.c_str(), "wb");
            if (fp == NULL)
                throw image_save_error("Unable to open " + file_name + " for writing.");

            /* 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, NULL, &png_reader_user_error_fn_silent, &png_reader_user_warning_fn_silent);

            if (png_ptr == NULL)
            {
                fclose(fp);
                throw image_save_error("Error while writing PNG file " + file_name);
            }

            /* Allocate/initialize the image information data.  REQUIRED */
            info_ptr = png_create_info_struct(png_ptr);
            if (info_ptr == NULL)
            {
                fclose(fp);
                png_destroy_write_struct(&png_ptr,  NULL);
                throw image_save_error("Error while writing PNG file " + file_name);
            }

            /* Set error handling.  REQUIRED if you aren't supplying your own
            * error handling functions in the png_create_write_struct() call.
            */
            if (setjmp(png_jmpbuf(png_ptr)))
            {
                /* If we get here, we had a problem writing the file */
                fclose(fp);
                png_destroy_write_struct(&png_ptr, &info_ptr);
                throw image_save_error("Error while writing PNG file " + file_name);
            }

            int color_type = 0;
            switch(type)
            {
                case png_type_rgb:       color_type = PNG_COLOR_TYPE_RGB; break;
                case png_type_rgb_alpha: color_type = PNG_COLOR_TYPE_RGB_ALPHA; break;
                case png_type_gray:      color_type = PNG_COLOR_TYPE_GRAY; break;
                default:
                    {
                        fclose(fp);
                        png_destroy_write_struct(&png_ptr, &info_ptr);
                        throw image_save_error("Invalid color type");
                    }
            }


            /* Set up the output control if you are using standard C streams */
            png_init_io(png_ptr, fp);


            int png_transforms = PNG_TRANSFORM_IDENTITY;
            byte_orderer bo;
            if (bo.host_is_little_endian())
                png_transforms |= PNG_TRANSFORM_SWAP_ENDIAN;

            const long height = row_pointers.size();


            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_set_rows(png_ptr, info_ptr, &row_pointers[0]);
            png_write_png(png_ptr, info_ptr, png_transforms, NULL);

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

            /* Close the file */
            fclose(fp);
        }
Пример #13
0
int filter_png(struct media_info const *info, int out_fd, int in_fd)
{
	FILE			*fp = fdopen(out_fd, "wb");
	struct png_struct_def	*png_ptr = NULL;
	struct png_info_def	*png_info = NULL;
	volatile int		rc = EX_SOFTWARE;
	png_bytep		row_pointers[info->height];
	void * volatile		raw_data = NULL;
	void * volatile		rgb_data = NULL;
	size_t			rgb_stride =
		info->width * ((info->bpp + 7) / 8) * 3;

	if (!fp) {
		perror("fdopen()");
		return EX_OSERR;
	}

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

	if (setjmp(png_jmpbuf(png_ptr)))
		goto out;

	/* allocate memory for raw (YCbCr) image data */
	raw_data = png_malloc(png_ptr, info->stride * info->height);
	if (!raw_data)
		goto out;

	rgb_data = png_malloc(png_ptr, rgb_stride * info->height);
	if (!rgb_data)
		goto out;

	for (size_t y = 0; y < info->height; ++y)
		row_pointers[y] = rgb_data + y * rgb_stride;

	png_info = png_create_info_struct(png_ptr);
	if (!png_info)
		goto out;

	png_init_io(png_ptr, fp);
	png_set_user_limits(png_ptr, info->width, info->height);
	png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);

	/* atm, only 8bpp support is implemented */
	assert(info->bpp == 8);

	for (;;) {
		bool	eof = false;

		if (read_all(in_fd, raw_data, info->stride * info->height, &eof))
			;		/* noop */
		else if (!eof)
			goto out;
		else
			break;

		convert_yuv422_rgb888(rgb_data, raw_data, info->bpp,
				      info->width, info->height);

		png_set_rows(png_ptr, png_info, row_pointers);

		png_set_IHDR(png_ptr, png_info, info->width, info->height,
			     info->bpp, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
			     PNG_COMPRESSION_TYPE_DEFAULT,
			     PNG_FILTER_TYPE_DEFAULT);
		png_write_png(png_ptr, png_info, PNG_TRANSFORM_IDENTITY, NULL);
		fflush(fp);
		break;
	}

	rc = 0;

out:
	png_free(png_ptr, rgb_data);
	png_free(png_ptr, raw_data);
	png_destroy_write_struct(&png_ptr, &png_info);
	fclose(fp);

	return rc;
}
Пример #14
0
int main(int argc, char **argv) {
	extern int optind;
	extern char *optarg;
	int i;

	char *outfile = NULL;
	int de = 0;

	while ((i = getopt(argc, argv, "o:d")) != -1) {
		switch (i) {
		case 'o':
			outfile = optarg;
			break;

		case 'd':
			de = 1;
			break;

		default:
			usage(argv);
			exit(EXIT_FAILURE);
		}
	}

	if (argc - optind != 1) {
		usage(argv);
		exit(EXIT_FAILURE);
	}

	if (outfile == NULL && isatty(1)) {
		fprintf(stderr, "Didn't specify -o and standard output is a terminal\n");
		exit(EXIT_FAILURE);
	}
	FILE *outfp = stdout;
	if (outfile != NULL) {
		outfp = fopen(outfile, "wb");
		if (outfp == NULL) {
			perror(outfile);
			exit(EXIT_FAILURE);
		}
	}

	int width, height;
	unsigned char *buf;

	{
		{
			{
				char *url = argv[optind];

				CURL *curl = curl_easy_init();
				if (curl == NULL) {
					fprintf(stderr, "Curl won't start\n");
					exit(EXIT_FAILURE);
				}

				struct data data;
				data.buf = NULL;
				data.len = 0;
				data.nalloc = 0;

				curl_easy_setopt(curl, CURLOPT_URL, url);
				curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
				curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
				curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_receive);

				CURLcode res = curl_easy_perform(curl);
				if (res != CURLE_OK) {
					fprintf(stderr, "Can't retrieve %s: %s\n", url,
						curl_easy_strerror(res));
					exit(EXIT_FAILURE);
				}

				struct image *i;

				if (data.len >= 4 && memcmp(data.buf, "\x89PNG", 4) == 0) {
					i = read_png(data.buf, data.len);
				} else if (data.len >= 2 && memcmp(data.buf, "\xFF\xD8", 2) == 0) {
					i = read_jpeg(data.buf, data.len);
				} else {
					fprintf(stderr, "Don't recognize file format\n");

					free(data.buf);
					curl_easy_cleanup(curl);
					exit(EXIT_FAILURE);
				}

				free(data.buf);
				curl_easy_cleanup(curl);

				width = i->width;
				height = i->height;
				buf = malloc(i->width * i->height * 4);

				int x, y;
				for (y = 0; y < i->height; y++) {
					for (x = 0; x < i->width; x++) {
						if (i->depth == 4) {
							double as = buf[((y) * width + x) * 4 + 3] / 255.0;
							double rs = buf[((y) * width + x) * 4 + 0] / 255.0 * as;
							double gs = buf[((y) * width + x) * 4 + 1] / 255.0 * as;
							double bs = buf[((y) * width + x) * 4 + 2] / 255.0 * as;

							double ad = i->buf[(y * i->width + x) * 4 + 3] / 255.0;
							double rd = i->buf[(y * i->width + x) * 4 + 0] / 255.0 * ad;
							double gd = i->buf[(y * i->width + x) * 4 + 1] / 255.0 * ad;
							double bd = i->buf[(y * i->width + x) * 4 + 2] / 255.0 * ad;

							// https://code.google.com/p/pulpcore/wiki/TutorialBlendModes
							double ar = as * (1 - ad) + ad;
							double rr = rs * (1 - ad) + rd;
							double gr = gs * (1 - ad) + gd;
							double br = bs * (1 - ad) + bd;

							buf[((y) * width + x) * 4 + 3] = ar * 255.0;
							buf[((y) * width + x) * 4 + 0] = rr / ar * 255.0;
							buf[((y) * width + x) * 4 + 1] = gr / ar * 255.0;
							buf[((y) * width + x) * 4 + 2] = br / ar * 255.0;
						} else if (i->depth == 3) {
							buf[((y) * width + x) * 4 + 0] = i->buf[(y * i->width + x) * 3 + 0];
							buf[((y) * width + x) * 4 + 1] = i->buf[(y * i->width + x) * 3 + 1];
							buf[((y) * width + x) * 4 + 2] = i->buf[(y * i->width + x) * 3 + 2];
							buf[((y) * width + x) * 4 + 3] = 255;
						} else {
							buf[((y) * width) * 4 + 0] = i->buf[(y * i->width + x) * i->depth + 0];
							buf[((y) * width) * 4 + 1] = i->buf[(y * i->width + x) * i->depth + 0];
							buf[((y) * width) * 4 + 2] = i->buf[(y * i->width + x) * i->depth + 0];
							buf[((y) * width) * 4 + 3] = 255;
						}
					}
				}

				free(i->buf);
				free(i);
			}
		}
	}

	unsigned char *rows[height];
	for (i = 0; i < height; i++) {
		rows[i] = buf + i * (4 * width);
	}

	convert(buf, width, height, de);

	png_structp png_ptr;
	png_infop info_ptr;

	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, fail, fail, fail);
	if (png_ptr == NULL) {
		fprintf(stderr, "PNG failure (write struct)\n");
		exit(EXIT_FAILURE);
	}
	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL) {
		png_destroy_write_struct(&png_ptr, NULL);
		fprintf(stderr, "PNG failure (info struct)\n");
		exit(EXIT_FAILURE);
	}

	png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
	png_set_rows(png_ptr, info_ptr, rows);
	png_init_io(png_ptr, outfp);
	png_write_png(png_ptr, info_ptr, 0, NULL);
	png_destroy_write_struct(&png_ptr, &info_ptr);

	if (outfile != NULL) {
		fclose(outfp);
	}

	return 0;
}
Пример #15
0
int main(int argc, char **argv)
{
	if (argc != 4)
	{
		fprintf(stderr, "usage: %s <input.png> <output_basename> <jpeg-quality>\n", *argv);
		return 1;
	}

	const char *infile = argv[1];
	const char *outfile = argv[2];
	int jpeg_quality = atoi(argv[3]);

	FILE *fpin = fopen(infile, "rb");
	if (!fpin)
	{
		perror(infile);
		return 1;
	}

	unsigned char header[8];
	fread(header, 1, 8, fpin);
	if (png_sig_cmp(header, 0, 8))
	{
		fprintf(stderr, "this is not a PNG file\n");
		fclose(fpin);
		return 1;
	}
	png_structp png_ptr = png_create_read_struct
		(PNG_LIBPNG_VER_STRING, 0, 0, 0);
	assert(png_ptr);

	png_infop info_ptr = png_create_info_struct(png_ptr);
	assert(info_ptr);

	png_infop end_info = png_create_info_struct(png_ptr);
	assert (end_info);

	if (setjmp(png_jmpbuf(png_ptr)))
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		fclose(fpin);
		fprintf(stderr, "failed.\n");
		return 1;
	}

	png_init_io(png_ptr, fpin);
	png_set_sig_bytes(png_ptr, 8);
	png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, 0);
	png_bytep * row_pointers = png_get_rows(png_ptr, info_ptr);

	png_uint_32 width, height;
	int bit_depth, color_type;
	png_get_IHDR(png_ptr, info_ptr, &width, &height, 
		&bit_depth, &color_type, 0, 0, 0);

	if (color_type != PNG_COLOR_TYPE_RGB_ALPHA)
	{
		fprintf(stderr, "input PNG must be RGB+Alpha\n");
		fclose(fpin);
		return 1;
	}
	if (bit_depth != 8)
	{
		fprintf(stderr, "input bit depth must be 8bit!\n");
		fclose(fpin);
		return 1;
	}
	printf("png is %ldx%ld\n", width, height);
	int channels = png_get_channels(png_ptr, info_ptr);
	if (channels != 4)
	{
		fprintf(stderr, "channels must be 4.\n");
		fclose(fpin);
		return 1;
	}

	fclose(fpin);

	/* now write jpeg */
	struct jpeg_compress_struct cinfo;
	struct jpeg_error_mgr jerr;
	JSAMPROW jrow_pointer[1];
	FILE *outfp;

	char filename[strlen(outfile) + 10];
	strcpy(filename, outfile);
	strcat(filename, ".rgb.jpg");

	outfp = fopen(filename, "wb");
	if (!outfp)
	{
		perror(filename);
		return 1;
	}

	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_compress(&cinfo);
	jpeg_stdio_dest(&cinfo, outfp);

	cinfo.image_width = width;
	cinfo.image_height = height;
	cinfo.input_components = 3;
	cinfo.in_color_space = JCS_RGB;
	jpeg_set_defaults(&cinfo);
	jpeg_set_quality(&cinfo, jpeg_quality, 1);
	jpeg_start_compress(&cinfo, 1);

	unsigned char *row = malloc(width * 3);
	while (cinfo.next_scanline < cinfo.image_height)
	{
		int x;
		jrow_pointer[0] = row;
		unsigned char *source = row_pointers[cinfo.next_scanline];
		for (x = 0; x < width; ++x)
		{
			row[x * 3 + 0] = source[0];
			row[x * 3 + 1] = source[1];
			row[x * 3 + 2] = source[2];
			source += 4;
		}
		jpeg_write_scanlines(&cinfo, jrow_pointer, 1);
	}

	jpeg_finish_compress(&cinfo);
	fclose(outfp);
	jpeg_destroy_compress(&cinfo);

	/* and write png */
	strcpy(filename, outfile);
	strcat(filename, ".a.png");

	outfp = fopen(filename, "wb");
	if (!outfp)
	{
		perror(filename);
		return 1;
	}

	png_structp png_ptr_w = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
	png_infop info_ptr_w = png_create_info_struct(png_ptr_w);
	if (setjmp(png_jmpbuf(png_ptr_w)))
	{
		png_destroy_write_struct(&png_ptr_w, &info_ptr_w);
		fclose(outfp);
		return 1;
	}
	png_init_io(png_ptr_w, outfp);
	png_set_IHDR(png_ptr_w, info_ptr_w, width, height, 8, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

		/* turn RGBA into A, in-place */
	int x, y;
	for (y=0; y < height; ++y)
	{
		unsigned char *source = row_pointers[y];
		unsigned char *dst = source;
		for (x=0; x < width; ++x)
		{
			*dst++ = source[3];
			source += 4;
		}
	}
	png_set_rows(png_ptr_w, info_ptr_w, row_pointers);
	png_write_png(png_ptr_w, info_ptr_w, PNG_TRANSFORM_IDENTITY, 0);
	png_write_end(png_ptr_w, info_ptr_w);
	png_destroy_write_struct(&png_ptr_w, &info_ptr_w);
	fclose(outfp);
	return 0;
}
Пример #16
0
void image_read(Image * image, char *filename)
{
    FILE           *file;
    png_structp     png_ptr;
    png_infop       info_ptr;
    png_uint_32     width, height;
    int             bit_depth, color_type; 
    png_bytep      *row_pointers;
    int             i;  
    
    if(image->pixel)
        free(image->pixel);
    image->pixel = NULL;

    file = fopen(filename, "rb");
    assert(file != NULL);

    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    assert(png_ptr != NULL);

    info_ptr = png_create_info_struct(png_ptr);
    assert(info_ptr != NULL);

    if (setjmp(png_jmpbuf(png_ptr)))
    {
        png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
        fclose(file);
        exit(-1);
    }

    png_init_io(png_ptr, file);

    png_read_info(png_ptr, info_ptr);
    png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
             NULL, NULL, NULL);
    assert(bit_depth == 8);
    if(color_type != PNG_COLOR_TYPE_GRAY) {
        fprintf(stderr, "Erreur sur le format de l'image d'entrée.\n");
        fprintf(stderr, "Le seul format PNG supporté est : niveaux de gris, 8bpp, sans canal alpha\n");
        png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
        fclose(file);
        exit(-1);
    }

    image->width = width;
    image->height = height;
    image->pixel = (unsigned char *)malloc(width * height * sizeof(unsigned char));
    assert(image->pixel != NULL);

    row_pointers = png_malloc(png_ptr, height * sizeof(png_bytep));
    assert(row_pointers != NULL);
    for (i = 0; i < height; i++)
        row_pointers[i] = (png_bytep)(&image->pixel[i*width]);
    png_set_rows(png_ptr, info_ptr, row_pointers);

    png_read_image(png_ptr, row_pointers);

    png_free(png_ptr, row_pointers);

    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

    fclose(file);
}
Пример #17
0
bool StreamerPNG::saveBitmap(const Bitmap & bitmap, std::ostream & output) {
	volatile int colorType = 0; // volatile is needed because of the setjmp later on.
	volatile int transforms = 0;

	const PixelFormat & pixelFormat = bitmap.getPixelFormat();
	if(pixelFormat == PixelFormat::RGBA) {
		colorType = PNG_COLOR_TYPE_RGB_ALPHA;
		transforms = PNG_TRANSFORM_IDENTITY;
	} else if(pixelFormat == PixelFormat::BGRA) {
		colorType = PNG_COLOR_TYPE_RGB_ALPHA;
		transforms = PNG_TRANSFORM_BGR;
	} else if(pixelFormat == PixelFormat::RGB) {
		colorType = PNG_COLOR_TYPE_RGB;
		transforms = PNG_TRANSFORM_IDENTITY;
	} else if(pixelFormat == PixelFormat::BGR) {
		colorType = PNG_COLOR_TYPE_RGB;
		transforms = PNG_TRANSFORM_BGR;
	} else if(pixelFormat == PixelFormat::MONO) {
		colorType = PNG_COLOR_TYPE_GRAY;
		transforms = PNG_TRANSFORM_IDENTITY;
	} else if(pixelFormat == PixelFormat::MONO_FLOAT) {
		Reference<Bitmap> tmp = BitmapUtils::convertBitmap(bitmap, PixelFormat::MONO);
		return saveBitmap(*tmp.get(), output);
	} else {
		WARN("Unable to save PNG file. Unsupported color type.");
		return false;
	}

	// Set up the necessary structures for libpng.
	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
	if (!png_ptr) {
		return false;
	}

	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr) {
		png_destroy_write_struct(&png_ptr, nullptr);
		return false;
	}
	if (setjmp(png_jmpbuf(png_ptr))) {
		png_destroy_write_struct(&png_ptr, &info_ptr);
		return false;
	}

	struct PNGFunctions {
			static void writeData(png_structp write_ptr, png_bytep data, png_size_t length) {
				std::ostream * out = reinterpret_cast<std::ostream *>(png_get_io_ptr(write_ptr));
				out->write(reinterpret_cast<const char*>(data), static_cast<std::streamsize>(length));
			}
			static void flushData(png_structp flush_ptr) {
				std::ostream * out = reinterpret_cast<std::ostream *>(png_get_io_ptr(flush_ptr));
				out->flush();
			}
	};

	png_set_write_fn(png_ptr, reinterpret_cast<png_voidp>(&output), PNGFunctions::writeData, PNGFunctions::flushData);

	const uint32_t width = bitmap.getWidth();
	const uint32_t height = bitmap.getHeight();

	png_set_IHDR(png_ptr, info_ptr, width, height, 8, colorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

	// Write the image.
	std::vector<png_bytep> row_pointers;
	row_pointers.reserve(height);
	const uint8_t bytes = pixelFormat.getBytesPerPixel();
	for (uint_fast32_t row = 0; row < height; ++row) {
		// Take over rows in the same order.
		row_pointers.push_back(reinterpret_cast<png_bytep>(const_cast<uint8_t *>(bitmap.data()) + row * width * bytes));
	}
	png_set_rows(png_ptr, info_ptr, row_pointers.data());

	png_write_png(png_ptr, info_ptr, transforms, nullptr);

	// Clean up.
	png_destroy_write_struct(&png_ptr, &info_ptr);

	return true;
}
Пример #18
0
void saveCorePNG  (FILE * writer, GLuint texture, int w, int h) {
	GLint tw, th;

	glBindTexture (GL_TEXTURE_2D, texture);
	getTextureDimensions(texture, &tw, &th);

	GLubyte* image = new GLubyte [tw*th*4];
	if (! checkNew (image)) return;

	glPixelStorei (GL_PACK_ALIGNMENT, 1);
//	glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, image);

	#ifdef HAVE_GLES2
	GLuint old_fbo, new_fbo;
	GLint old_vp[4];
	glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&old_fbo);
	glGetIntegerv(GL_VIEWPORT, old_vp);
	glGenFramebuffers(1, &new_fbo);
	glBindFramebuffer(GL_FRAMEBUFFER, new_fbo);
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
	glViewport(0, 0, tw, th);
	glReadPixels(0, 0, tw, th, GL_RGBA, GL_UNSIGNED_BYTE, image);
	glBindFramebuffer(GL_FRAMEBUFFER, old_fbo);
	glViewport(old_vp[0], old_vp[1], old_vp[2], old_vp[3]);
	glDeleteFramebuffers(1, &new_fbo);
	#else
	setPixelCoords (true);
		

	//glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

	const GLfloat texCoords[] = { 
		0.0f, 0.0f,
		1.0f, 0.0f,
		0.0f, 1.0f,
		1.0f, 1.0f
	}; 

	int xoffset = 0;
	while (xoffset < tw) {
		int w = (tw-xoffset < viewportWidth) ? tw-xoffset : viewportWidth;

		int yoffset = 0;
		while (yoffset < th) {
			int h = (th-yoffset < viewportHeight) ? th-yoffset : viewportHeight;
			
			glClear(GL_COLOR_BUFFER_BIT);	// Clear The Screen

			const GLfloat vertices[] = { 
				(GLfloat)-xoffset, (GLfloat)-yoffset, 0., 
				(GLfloat)tw-xoffset, (GLfloat)-yoffset, 0., 
				(GLfloat)-xoffset, (GLfloat)-yoffset+th, 0.,
				(GLfloat)tw-xoffset, (GLfloat)-yoffset+th, 0.
			};

			glUseProgram(shader.texture);
			setPMVMatrix(shader.texture);

			drawQuad(shader.texture, vertices, 1, texCoords);

			glUseProgram(0);

			for (int i = 0; i<h; i++)	{
				glReadPixels(viewportOffsetX, viewportOffsetY+i, w, 1, GL_RGBA, GL_UNSIGNED_BYTE, image+xoffset*4+(yoffset+i)*4*tw);
			}
			
			yoffset += viewportHeight;
		}
		
		xoffset += viewportWidth;
	}
	setPixelCoords (false);
	#endif
	
	
	
	png_structp png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (!png_ptr) {
		fatal ("Error saving image!");
		return;
	}

	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr){
		png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
		fatal ("Error saving image!");
		return;
	}

	png_init_io(png_ptr, writer);

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

	unsigned char * row_pointers[h];

	for (int i = 0; i < h; i++) {
		row_pointers[i] = image + 4*i*tw;
	}

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

	delete [] image;
	image = NULL;
}
Пример #19
0
int RE_SavePNG( const char *filename, byte *buf, size_t width, size_t height, int byteDepth ) {
	fileHandle_t fp;
	png_structp png_ptr = NULL;
	png_infop info_ptr = NULL;
	unsigned int x, y;
	png_byte ** row_pointers = NULL;
	/* "status" contains the return value of this function. At first
	it is set to a value which means 'failure'. When the routine
	has finished its work, it is set to a value which means
	'success'. */
	int status = -1;
	/* The following number is set by trial and error only. I cannot
	see where it it is documented in the libpng manual.
	*/
	int depth = 8;

	fp = ri->FS_FOpenFileWrite( filename, qtrue );
	if ( !fp ) {
		goto fopen_failed;
	}

	png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (png_ptr == NULL) {
		goto png_create_write_struct_failed;
	}

	info_ptr = png_create_info_struct (png_ptr);
	if (info_ptr == NULL) {
		goto png_create_info_struct_failed;
	}

	/* Set up error handling. */

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

	/* Set image attributes. */

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

	/* Initialize rows of PNG. */

	row_pointers = (png_byte **)png_malloc (png_ptr, height * sizeof (png_byte *));
	for ( y=0; y<height; ++y ) {
		png_byte *row = (png_byte *)png_malloc (png_ptr, sizeof (uint8_t) * width * byteDepth);
		row_pointers[height-y-1] = row;
		for (x = 0; x < width; ++x) {
			byte *px = buf + (width * y + x)*3;
			*row++ = px[0];
			*row++ = px[1];
			*row++ = px[2];
		}
	}

	/* Write the image data to "fp". */

//	png_init_io (png_ptr, fp);
	png_set_write_fn( png_ptr, (png_voidp)&fp, user_write_data, user_flush_data );
	png_set_rows (png_ptr, info_ptr, row_pointers);
	png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

	/* The routine has successfully written the file, so we set
	"status" to a value which indicates success. */

	status = 0;

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

png_failure:
png_create_info_struct_failed:
	png_destroy_write_struct (&png_ptr, &info_ptr);
png_create_write_struct_failed:
	ri->FS_FCloseFile( fp );
fopen_failed:
	return status;
}
Пример #20
0
static	BOOL SaveBmpToPNGfile(HBITMAP hbmp,LPTSTR file)
{
	BITMAP	bmp;
	FILE * fp = NULL;
	
	if(!GetObject(hbmp,sizeof(BITMAP),&bmp))return FALSE;

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

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

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

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

	png_infop png_info_ptr =  png_create_info_struct(png_ptr);

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

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

	row_length =bmp.bmHeight * bmp.bmWidthBytes;

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

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

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

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

				WORD   Color;//存16bit的颜色 

				double   Red,Green,Blue; 

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


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

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

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

	png_init_io(png_ptr,fp);

	png_set_rows(png_ptr,png_info_ptr,rows_bytes);

	png_set_bgr(png_ptr);

	//crc32(0, Z_NULL, 0);

	png_write_png(png_ptr, png_info_ptr,0,0);

	png_write_end(png_ptr,png_info_ptr);

	png_destroy_write_struct(&png_ptr, &png_info_ptr);

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

	free(rows_bytes);
	free(row_bytes);	
	DeleteObject(hbmp);
	fclose(fp);
	return TRUE;
}
Пример #21
0
/**
 * @short Writes an image as png to the response object
 * 
 * @param image flat buffer with all pixels
 * @param Bpp Bytes per pixel: 1 grayscale, 2 grayscale with alpha, 3 RGB, 4 RGB with alpha. Negative if in BGR format (cairo)
 * @param width The width of the image
 * @param height The height of the image
 * @param res where to write the image, it sets the necessary structs
 */
int onion_png_response(unsigned char *image, int Bpp, int width, int height, onion_response *res){
	// Many copied from example.c from libpng source code.
	png_structp png_ptr;
	png_infop info_ptr;

	/* 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, NULL, error, warning);

	if (png_ptr == NULL)
	{
		return OCS_INTERNAL_ERROR;
	}

	/* 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 OCS_INTERNAL_ERROR;
	}

	onion_png_data opd;
	opd.res=res;
	opd.sent=0;
	png_set_write_fn(png_ptr, (void *)&opd, onion_png_write, onion_png_flush);
	/* where user_io_ptr is a structure you want available to the callbacks */

	onion_response_set_header(res, "Content-Type", "image/png");
	if (onion_response_write_headers(res)==OR_SKIP_CONTENT) // Maybe it was HEAD.
		return OCS_PROCESSED;
	 
	/* Set the image information here.  Width and height are up to 2^31,
	* bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
	* the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
	* PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
	* or PNG_COLOR_TYPE_RGB_ALPHA.  interlace is either PNG_INTERLACE_NONE or
	* PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
	* currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
	*/
	if (Bpp<0){
		png_set_bgr(png_ptr);
		Bpp=-Bpp;
	}

	switch(Bpp){
		case 1:
			png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_GRAY,
					PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
		break;
		case 2:
			png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_GRAY_ALPHA,
					PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
		break;
		case 3:
			png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB,
					PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
		break;
		case 4:
			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);
		break;
		default:
			png_error(png_ptr, "Wrong bytes per pixel");
			break;
	}
	
	png_uint_32 k;
	png_bytep row_pointers[height];

	if (height > PNG_UINT_32_MAX/png_sizeof(png_bytep))
		png_error (png_ptr, "Image is too tall to process in memory");

	for (k = 0; k < height; k++)
		row_pointers[k] = (png_byte *) (image + k*width*Bpp);

	// Sets the rows to save at the image
	png_set_rows(png_ptr, info_ptr, row_pointers);
	 
	// If header already sent, then there was an error.
	if (opd.sent){
		return OCS_PROCESSED;
	}
	opd.sent=1;
	// Finally WRITE the image. Uses the onion_response_write via onion_png_write helper.
	png_write_png(png_ptr, info_ptr, 0, NULL);
	
	/* Clean up after the write, and free any memory allocated */
	png_destroy_write_struct(&png_ptr, &info_ptr);

	/* That's it */
	return OCS_PROCESSED;
}
Пример #22
0
int png_utils_write_png_image(const char *filename, unsigned char *pixels, int w, int h, int has_alpha, int invert)
{
	png_structp png_ptr;
	png_infop info_ptr;
	png_byte **row;
	int x, y, rc, colordepth = 8;
	int bytes_per_pixel = has_alpha ? 4 : 3;
	FILE *f;

	f = fopen(filename, "w");
	if (!f) {
		fprintf(stderr, "fopen: %s:%s\n", filename, strerror(errno));
		return -1;
	}
	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (!png_ptr)
		goto cleanup1;
	info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr)
		goto cleanup2;
	if (setjmp(png_jmpbuf(png_ptr))) /* oh libpng, you're old as dirt, aren't you. */
		goto cleanup2;

	png_set_IHDR(png_ptr, info_ptr, (size_t) w, (size_t) h, colordepth,
			has_alpha ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB,
			PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
			PNG_FILTER_TYPE_DEFAULT);

	row = png_malloc(png_ptr, h * sizeof(*row));
	if (!invert) {
		for (y = 0; y < h; y++) {
			row[y] = png_malloc(png_ptr, w * bytes_per_pixel);
			for (x = 0; x < w; x++) {
				unsigned char *r = (unsigned char *) row[y];
				unsigned char *src = (unsigned char *)
					&pixels[y * w * bytes_per_pixel + x * bytes_per_pixel];
				unsigned char *dest = &r[x * bytes_per_pixel];
				memcpy(dest, src, bytes_per_pixel);
			}
		}
	} else {
		for (y = 0; y < h; y++) {
			row[h - y - 1] = png_malloc(png_ptr, w * bytes_per_pixel);
			for (x = 0; x < w; x++) {
				unsigned char *r = (unsigned char *) row[h - y - 1];
				unsigned char *src = (unsigned char *)
					&pixels[y * w * bytes_per_pixel + x * bytes_per_pixel];
				unsigned char *dest = &r[x * bytes_per_pixel];
				memcpy(dest, src, bytes_per_pixel);
			}
		}
	}

	png_init_io(png_ptr, f);
	png_set_rows(png_ptr, info_ptr, row);
	png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_PACKING, NULL);

	for (y = 0; y < h; y++)
		png_free(png_ptr, row[y]);
	png_free(png_ptr, row);
	rc = 0;
cleanup2:
	png_destroy_write_struct(&png_ptr, &info_ptr);
cleanup1:
	fclose(f);
	return rc;
}
Пример #23
0
int main(int argc, char *argv[])
{
	if (argc != 3)
	{
		fprintf(stderr, "Usage: %s file_in.dat result.png\n", argv[0]);

		return 1;
	}

	char *file_in = argv[1];
	char *file_out = argv[2];

	int bytes = 256 * 256 * sizeof(int);
	unsigned int *points = (unsigned int *)calloc(1, bytes);

	FILE *fhi = fopen(file_in, "rb");
	if (!fhi)
	{
		fprintf(stderr, "Failed to open %s\n", file_in);
		return 1;
	}

	FILE *fho = fopen(file_out, "wb");
	if (!fho)
	{
		fprintf(stderr, "Failed to create %s\n", file_out);
		return 1;
	}

	while(!feof(fhi))
	{
		int x = fgetc(fhi);
		int y = fgetc(fhi);

		if (x < 0 || y < 0) // EOF probably
			break;

		points[y * 256 + x]++;
	}

	fclose(fhi);

	unsigned int c_max = 0, c_min = 1 << 31;
	for(int index=0; index<(256*256); index++)
	{
		if (points[index] > c_max)
			c_max = points[index];
		if (points[index] < c_min)
			c_min = points[index];
	}
	double div = double(c_max) - double(c_min);

	bytes = 256 * 256 * 3;
	unsigned char *result = (unsigned char *)calloc(1, bytes);

	for(int y=0; y<256; y++)
	{
		for(int x=0; x<256; x++)
		{
			if (points[y * 256 + x] == 0)
				continue;

			double val = double(points[y * 256 + x] - c_min) / div;

			result[y * 256 * 3 + x * 3 + 0] = result[y * 256 * 3 + x * 3 + 2] = 0;
			result[y * 256 * 3 + x * 3 + 1] = (unsigned char)maxval(minval(255.0, val * 255.0), 0.0);
		}
	}

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

	png_infop info_ptr = png_create_info_struct(png_ptr);

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

	unsigned char *row_pointers[256];
	for(int y=0; y<256; y++)
		row_pointers[y] = &result[y * 256 * 3];

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

	fclose(fho);

	return 0;
}
Пример #24
0
int enc_png(char *data,g2int width,g2int height,g2int nbits,char *pngbuf)
{
 
    int color_type;
    g2int j,bytes,pnglen,bit_depth;
    png_structp png_ptr;
    png_infop info_ptr;
//    png_bytep *row_pointers[height];
    png_bytep **row_pointers;
    png_stream write_io_ptr;

/* create and initialize png_structs  */

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

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

/*     Set Error callback   */

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

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

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

/*    Set new custom write functions    */

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

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

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

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

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

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

    png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

/*     Clean up   */

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

}
Пример #25
0
	void write( Image& img, const char* filename ) {

		if ( !( img.get_width() > 0 && img.get_height() > 0 && img.get_num_channels() > 0 ) ) {
			throw std::exception( "This is not a valid image to write." );
		}

		FILE* fp = fopen( filename, "wb" );
		if ( !fp ) {
			throw std::exception( "Failed to open file." );
		}

		boost::shared_ptr<void> fp_cleanup( static_cast<void*>(0), boost::bind( fclose, fp ) );

		png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
		if (!png_ptr) {
		   throw std::exception( "png_create_write_struct failed." );
		}

		png_infop info_ptr = 0;

		boost::shared_ptr<void> png_cleanup( static_cast<void*>(0), boost::bind( png_destroy_write_struct, &png_ptr, &info_ptr ) );

		info_ptr = png_create_info_struct(png_ptr);
		if (!info_ptr) {
		   throw std::exception( "png_create_info_struct failed." );
		}

		if ( setjmp(png_jmpbuf(png_ptr)) ) {
		   throw std::exception( "libpng returned an error." );
		}

	   png_init_io(png_ptr, fp);

		// optional: call png_set_filter to control compression

		// fill png_info structure

		typedef boost::scoped_array< Image::channel* > Channel_array;
		Channel_array row_pointers( new Image::channel* [ img.get_height() ] );

		for ( int row = 0; row < img.get_height(); ++row ) {
			row_pointers[ row ] = img.get_row_ptr( row );
		}

		png_set_rows( png_ptr, info_ptr, row_pointers.get() );

		png_set_IHDR(
			png_ptr,
			info_ptr,
		   	img.get_width(),
		   	img.get_height(),
		   	8,
		   	PNG_COLOR_TYPE_RGB,
		   	PNG_INTERLACE_NONE,
		   	PNG_COMPRESSION_TYPE_DEFAULT,
		   	PNG_FILTER_TYPE_DEFAULT );

		png_write_png(
			png_ptr,
		   	info_ptr,
		   	PNG_TRANSFORM_IDENTITY,
		   	NULL );
	}
Пример #26
0
static int save_png_to_file (bitmap_t *bitmap, const char *path)
{
    FILE * fp;
    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL;
    size_t x, y;
    png_byte ** row_pointers = NULL;
    /* "status" contains the return value of this function. At first
       it is set to a value which means 'failure'. When the routine
       has finished its work, it is set to a value which means
       'success'. */
    int status = -1;
    /* The following number is set by trial and error only. I cannot
       see where it it is documented in the libpng manual.
    */
    int pixel_size = 3;
    int depth = 8;

    fp = fopen (path, "wb");
    if (! fp) {
        goto fopen_failed;
    }

    png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (png_ptr == NULL) {
        goto png_create_write_struct_failed;
    }

    info_ptr = png_create_info_struct (png_ptr);
    if (info_ptr == NULL) {
        goto png_create_info_struct_failed;
    }

    /* Set up error handling. */

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

    /* Set image attributes. */

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

    /* Initialize rows of PNG. */

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

    /* Write the image data to "fp". */

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

    /* The routine has successfully written the file, so we set
       "status" to a value which indicates success. */

    status = 0;

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

png_failure:
png_create_info_struct_failed:
    png_destroy_write_struct (&png_ptr, &info_ptr);
png_create_write_struct_failed:
    fclose (fp);
fopen_failed:
    return status;
}
Пример #27
0
void TCOD_sys_write_png(const SDL_Surface *surf, const char *filename) {
	png_structp png_ptr;
	png_infop info_ptr;
	png_bytep *row_pointers;
	int y,x;
	FILE *fp=fopen(filename,"wb");
	if (!fp) return;

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

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

	/* Allocate/initialize the memory for image information.  REQUIRED. */
	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL)
	{
		fclose(fp);
		png_destroy_write_struct(&png_ptr, png_infopp_NULL);
		return;
	}

	if (setjmp(png_jmpbuf(png_ptr)))
	{
		/* Free all of the memory associated with the png_ptr and info_ptr */
		png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
		fclose(fp);
		/* If we get here, we had a problem reading the file */
		return;
	}

	png_init_io(png_ptr, fp);

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

	// get row data
	row_pointers=(png_bytep *)malloc(sizeof(png_bytep)*surf->h);
	for (y=0; y<  surf->h; y++ ) {
//		TODO : we should be able to use directly the surface data...
//		row_pointers[y]=(png_bytep)(Uint8 *)(surf->pixels) + y * surf->pitch;
		row_pointers[y]=(png_bytep)malloc(sizeof(png_byte)*surf->w*3);
		for (x=0; x < surf->w; x++ ) {
			Uint8 *pixel=(Uint8 *)(surf->pixels) + y * surf->pitch + x * surf->format->BytesPerPixel;
			row_pointers[y][x*3]=*((pixel)+surf->format->Rshift/8);
			row_pointers[y][x*3+1]=*((pixel)+surf->format->Gshift/8);
			row_pointers[y][x*3+2]=*((pixel)+surf->format->Bshift/8);
		}
	}
	png_set_rows(png_ptr,info_ptr,row_pointers);

	png_write_png(png_ptr,info_ptr,PNG_TRANSFORM_IDENTITY,NULL);

	fclose(fp);
	/* clean up, and free any memory allocated - REQUIRED */
	png_destroy_write_struct(&png_ptr, &info_ptr);

	for (y=0; y<  surf->h; y++ ) {
		free(row_pointers[y]);
	}
	free(row_pointers);
}
Пример #28
0
void save_as_png(T1 & file,
                T2 const& image,
                png_options const& opts)

{
    if (opts.use_miniz)
    {
        MiniZ::PNGWriter writer(opts.compression,opts.strategy);
        if (opts.trans_mode == 0)
        {
            writer.writeIHDR(image.width(), image.height(), 24);
            writer.writeIDATStripAlpha(image);
        }
        else
        {
            writer.writeIHDR(image.width(), image.height(), 32);
            writer.writeIDAT(image);
        }
        writer.writeIEND();
        writer.toStream(file);
        return;
    }
    png_voidp error_ptr=0;
    png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING,
                                                error_ptr,0, 0);

    if (!png_ptr) return;

    // switch on optimization only if supported
#if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200) && defined(PNG_MMX_CODE_SUPPORTED)
    png_uint_32 mask, flags;
    flags = png_get_asm_flags(png_ptr);
    mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE);
    png_set_asm_flags(png_ptr, flags | mask);
#endif
    png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_FILTER_NONE);
    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
    {
        png_destroy_write_struct(&png_ptr,(png_infopp)0);
        return;
    }
    jmp_buf* jmp_context = (jmp_buf*) png_get_error_ptr(png_ptr);
    if (jmp_context)
    {
        png_destroy_write_struct(&png_ptr, &info_ptr);
        return;
    }
    png_set_write_fn (png_ptr, &file, &write_data<T1>, &flush_data<T1>);

    png_set_compression_level(png_ptr, opts.compression);
    png_set_compression_strategy(png_ptr, opts.strategy);
    png_set_compression_buffer_size(png_ptr, 32768);

    png_set_IHDR(png_ptr, info_ptr,image.width(),image.height(),8,
                 (opts.trans_mode == 0) ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGB_ALPHA,PNG_INTERLACE_NONE,
                 PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT);
    const std::unique_ptr<png_bytep[]> row_pointers(new png_bytep[image.height()]);
    for (unsigned int i = 0; i < image.height(); i++)
    {
        row_pointers[i] = (png_bytep)image.getRow(i);
    }
    png_set_rows(png_ptr, info_ptr, row_pointers.get());
    png_write_png(png_ptr, info_ptr, (opts.trans_mode == 0) ? PNG_TRANSFORM_STRIP_FILLER_AFTER : PNG_TRANSFORM_IDENTITY, nullptr);
    png_destroy_write_struct(&png_ptr, &info_ptr);
}
Пример #29
0
bool ScreenshotManager::encode_png(std::shared_ptr<uint8_t> pxdata,
                                   coord::viewport_delta size) {
	std::FILE *fout = NULL;
	coord::pixel_t width = size.x,
	               height = size.y;
	auto warn_fn = [] (png_structp /*png_ptr*/, png_const_charp message) {
		log::log(MSG(err) << "Creating screenshot failed: libpng error: " << message);
	};
	auto err_fn = [] (png_structp png_ptr, png_const_charp message) {
		log::log(MSG(err) << "Creating screenshot failed: libpng error: " << message);
		longjmp(png_jmpbuf(png_ptr), 1);
	};

	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
	                                              (png_voidp) NULL,
	                                              err_fn, warn_fn);
	if (!png_ptr)
		return false;

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

	if (setjmp(png_jmpbuf(png_ptr))) {
		std::fclose(fout);
		png_destroy_write_struct(&png_ptr, &info_ptr);
		return false;
	}

	std::string filename = this->gen_next_filename();
	fout = std::fopen(filename.c_str(), "wb");
	if (fout == NULL) {
		png_destroy_write_struct(&png_ptr, &info_ptr);
		log::log(MSG(err) << "Could not open '"<< filename << "': "
		         << std::string(strerror(errno)));
		return false;
	}

	png_init_io(png_ptr, fout);

	png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB,
	             PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
	             PNG_FILTER_TYPE_DEFAULT);

	// Put image row pointer into info_ptr so that we can use the high-level
	// write interface.
	std::vector<png_bytep> row_ptrs;

	// Invert rows.
	row_ptrs.reserve(height);
	for (int i = 1; i <= height; i++) {
		row_ptrs.push_back(pxdata.get() + (height - i) * 4 * width);
	}
	png_set_rows(png_ptr, info_ptr, &row_ptrs[0]);

	//TODO: print ingame message.
	log::log(MSG(info) << "Saving screenshot to '" << filename << "'.");

	png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_FILLER_AFTER, NULL);

	std::fclose(fout);
	png_destroy_write_struct(&png_ptr, &info_ptr);
	return true;
}
void PngEncoder::write(const char *name)
{
   FILE           * file               = NULL;
   unsigned char ** rows               = 0;
   unsigned char  * cmap               = 0;
   short            numOfColors        = (1<<depth);
   short            bit_depth          = 4;
   long             i                  = 0;
   long             j                  = 0;
   png_structp      png_ptr;
   png_infop        info_ptr;
   char             user_error_ptr[]   = "PngEncoder";
   png_colorp       png_palette;
   png_byte         ti[1];

   png_ptr = png_create_write_struct
             ( PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
               user_error_fn, user_warning_fn);
   if (!png_ptr) 
   {
      err("Can not allocate writing structure!\n");
      return;
   }

   info_ptr = png_create_info_struct(png_ptr);
   if (!info_ptr) 
   {
      png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
      err("Can not allocate writing structure!\n");
      return;
   }

   if (setjmp(png_jmpbuf(png_ptr))) 
   {
     png_destroy_write_struct(&png_ptr, &info_ptr);
     return;
   }
   else
   {
     png_palette = (png_colorp) png_malloc(png_ptr,
         PNG_MAX_PALETTE_LENGTH*sizeof(png_color));
     memset(png_palette,0,PNG_MAX_PALETTE_LENGTH*sizeof(png_color));
     for (i=0; i<numOfColors; i++) 
     {
       png_palette[i].red   = palette[i].red;
       png_palette[i].green = palette[i].green;
       png_palette[i].blue  = palette[i].blue;
     }
     png_set_PLTE(png_ptr, info_ptr, png_palette, numOfColors);
     png_set_IHDR( png_ptr, info_ptr, width, height, bit_depth,
         PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
         PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE
                 );
     free(png_palette);
     ti[0] = transIndex;
     png_set_tRNS(png_ptr,info_ptr,ti,1,NULL);
     rows    = (unsigned char **) calloc(sizeof(unsigned char*),height);
     rows[0] = (unsigned char  *) calloc(sizeof(unsigned char),height*width);
     for (i=1; i<height; i++) 
     {
       rows[i] = rows[i-1] + width;
     }
     for (i=0, dataPtr=data; i<height; i++) 
     {
       for (j=0; j<width; j++) 
       {
         if (j%2)
         {
           rows[i][j/2] = ( rows[i][j/2] | *dataPtr );
         }
         else
         {
           rows[i][j/2] = (*dataPtr) << 4;
         }
         dataPtr++;
       }
     }
     png_set_rows(png_ptr,info_ptr,rows);

     file = fopen(name,"wb");
     if (file==0)
     {
       err("Error opening png file %s for writing: %s!\n",name,strerror(errno));
     }
     else
     {
       png_init_io(png_ptr,file);
       png_write_png(png_ptr,info_ptr,PNG_TRANSFORM_IDENTITY,NULL);
     }
   }

   png_destroy_write_struct(&png_ptr, &info_ptr);

   if (file)
   {
      fclose (file);
   }
   if (cmap)
   {
      free(cmap);
   }
   if (rows) 
   {
      if (rows[0])
      {
         free(rows[0]);
      }
      free(rows);
   }
   return;
}