Exemplo n.º 1
0
//
// initialize PNG writing
//
static void s_PngWriteInit(png_structp& png_ptr,
                           png_infop&   info_ptr,
                           size_t width, size_t height, size_t depth,
                           CImageIO::ECompress compress)
{
    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,
                                      s_PngWriteErrorHandler,
                                      s_PngWarningHandler);
    if ( !png_ptr ) {
        NCBI_THROW(CImageException, eWriteError,
                   "CImageIOPng::WriteImage(): png_create_read_struct() failed");
    }

    info_ptr = png_create_info_struct(png_ptr);
    if ( !info_ptr ) {
        NCBI_THROW(CImageException, eWriteError,
                   "CImageIOPng::WriteImage(): png_create_info_struct() failed");
    }

    png_byte color_type = PNG_COLOR_TYPE_RGB;
    if (depth == 4) {
        color_type = PNG_COLOR_TYPE_RGBA;
    }
    png_set_IHDR(png_ptr, info_ptr,
                 width, height, 8, color_type,
                 PNG_INTERLACE_NONE,
                 PNG_COMPRESSION_TYPE_BASE,
                 PNG_FILTER_TYPE_BASE);

    // set our compression quality
    switch (compress) {
    case CImageIO::eCompress_None:
        png_set_filter(png_ptr, 0, PNG_FILTER_NONE);
        png_set_compression_level(png_ptr, Z_NO_COMPRESSION);
        break;
    case CImageIO::eCompress_Low:
        png_set_filter(png_ptr, 0, PNG_FILTER_NONE);
        png_set_compression_level(png_ptr, Z_BEST_SPEED);
        break;
    case CImageIO::eCompress_Medium:
        png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION);
        break;
    case CImageIO::eCompress_High:
        png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
        break;
    default:
        LOG_POST_X(26, Error << "unknown compression type: " << (int)compress);
        break;
    }

}
Exemplo n.º 2
0
static size_t rgb2png(ss_t **png, const ss_t *rgb, const struct RGB_Info *ri)
{
	RETURN_IF(!valid_rgbi(ri) ||!rgb, 0);
	size_t out_size = 0;
	png_structp s = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
	png_infop pi = png_create_info_struct(s);
	if (png)
		ss_set_size(*png, 0);
	png_set_write_fn(s, (png_voidp)png, aux_png_write, NULL);
	int ctype = (ri->chn > 1 ? PNG_COLOR_MASK_COLOR : 0) |
		    (ri->chn == 2 || ri->chn == 4 ? PNG_COLOR_MASK_ALPHA : 0);
	png_set_IHDR(s, pi, (png_uint_32)ri->width, (png_uint_32)ri->height,
		     ri->bpc, ctype, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
		     PNG_FILTER_TYPE_BASE);
	png_set_filter(s, PNG_FILTER_TYPE_BASE, PNG_ALL_FILTERS);
	png_set_compression_level(s, Z_BEST_COMPRESSION);
	png_write_info(s, pi);
	png_bytep *rows = (png_bytep *)alloca(sizeof(png_bytep) * pi->height);
	if (aux_png_set_rows(rows, pi, ss_get_buffer_r(rgb))) {
		png_write_image(s, rows);
		png_write_end(s, pi);
		out_size = ss_size(*png);
	}
	png_destroy_info_struct(s, &pi);
	png_destroy_write_struct(&s, &pi);
	return out_size;
}
Exemplo n.º 3
0
std::unique_ptr<PNGImageEncoderState> PNGImageEncoderState::create(const IntSize& imageSize, Vector<unsigned char>* output)
{
    if (imageSize.width() <= 0 || imageSize.height() <= 0)
        return nullptr;

    png_struct* png = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
    png_info* info = png_create_info_struct(png);
    if (!png || !info || setjmp(png_jmpbuf(png))) {
        png_destroy_write_struct(png ? &png : 0, info ? &info : 0);
        return nullptr;
    }

    // Optimize compression for speed.
    // The parameters are the same as what libpng uses by default for RGB and RGBA images, except:
    // The zlib compression level is set to 3 instead of 6, to avoid the lazy Ziv-Lempel match searching.
    png_set_compression_level(png, 3);

    // The zlib memory level is set to 8.  This actually matches the default, we are just future-proofing.
    png_set_compression_mem_level(png, 8);

    // The zlib strategy is set to Z_FILTERED, which does not match the default.
    // Avoid the zlib strategies Z_HUFFMAN_ONLY or Z_RLE.
    // Although they are the fastest for poorly-compressible images (e.g. photographs),
    // they are very slow for highly-compressible images (e.g. text, drawings or business graphics)
    png_set_compression_strategy(png, Z_FILTERED);

    // The delta filter is PNG_FILTER_SUB instead of PNG_ALL_FILTERS, to reduce the filter computations.
    png_set_filter(png, PNG_FILTER_TYPE_BASE, PNG_FILTER_SUB);

    png_set_write_fn(png, output, writeOutput, 0);
    png_set_IHDR(png, info, imageSize.width(), imageSize.height(), 8, PNG_COLOR_TYPE_RGB_ALPHA, 0, 0, 0);
    png_write_info(png, info);

    return wrapUnique(new PNGImageEncoderState(png, info));
}
Exemplo n.º 4
0
static void write_png(const png_bytep rgba, png_uint_32 width, png_uint_32 height, SkWStream& out) {
    png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    SkASSERT(png != nullptr);
    png_infop info_ptr = png_create_info_struct(png);
    SkASSERT(info_ptr != nullptr);
    if (setjmp(png_jmpbuf(png))) {
        SkFAIL("png encode error");
    }
    png_set_IHDR(png, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
    png_set_compression_level(png, 1);
    png_bytepp rows = (png_bytepp) sk_malloc_throw(height * sizeof(png_byte*));
    png_bytep pixels = (png_bytep) sk_malloc_throw(width * height * 3);
    for (png_size_t y = 0; y < height; ++y) {
        const png_bytep src = rgba + y * width * 4;
        rows[y] = pixels + y * width * 3;
        // convert from RGBA to RGB
        for (png_size_t x = 0; x < width; ++x) {
            rows[y][x * 3] = src[x * 4];
            rows[y][x * 3 + 1] = src[x * 4 + 1];
            rows[y][x * 3 + 2] = src[x * 4 + 2];
        }
    }
    png_set_filter(png, 0, PNG_NO_FILTERS);
    png_set_rows(png, info_ptr, &rows[0]);
    png_set_write_fn(png, &out, write_png_callback, NULL);
    png_write_png(png, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
    png_destroy_write_struct(&png, NULL);
    sk_free(rows);
}
Exemplo n.º 5
0
errort	WritePNG( FILE * fp , unsigned char * data, unsigned int sizeX, unsigned int sizeY, int img_depth, int img_alpha)
{
  png_structp png_ptr = png_create_write_struct
    (PNG_LIBPNG_VER_STRING, (png_voidp)NULL,NULL,NULL);
  if (!png_ptr)
    return BadFormat;
  
  png_infop info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr) {
    png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
    return BadFormat;
  }
  if (setjmp(png_ptr->jmpbuf)) {
    png_destroy_write_struct(&png_ptr, &info_ptr);
    return BadFormat;
  }

  png_init_io(png_ptr, fp);

  png_set_filter(png_ptr, 0, PNG_FILTER_NONE);
  png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);

  /* set other zlib parameters */
  png_set_compression_mem_level(png_ptr, 8);
  png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY);
  png_set_compression_window_bits(png_ptr, 15);
  png_set_compression_method(png_ptr, 8);
  
  png_set_IHDR(png_ptr, 
	       info_ptr, 
	       sizeX,
	       sizeY,
	       img_depth, 
	       img_alpha?PNG_COLOR_TYPE_RGB_ALPHA:PNG_COLOR_TYPE_RGB, 
	       PNG_INTERLACE_NONE,
	       PNG_COMPRESSION_TYPE_DEFAULT, 
	       PNG_FILTER_TYPE_DEFAULT);
  
  png_write_info(png_ptr, info_ptr);
# if __BYTE_ORDER != __BIG_ENDIAN  
  if (img_depth==16) {
    png_set_swap(png_ptr);
  }
#endif
  int stride = (img_depth/8)*(img_alpha?4:3);
  png_byte **row_pointers = new png_byte*[sizeY];
  for (unsigned int i=0;i<sizeY;i++) {
    row_pointers[i]= (png_byte *)&data[stride*i*sizeX];
  }
  png_write_image (png_ptr,row_pointers);
  png_write_end(png_ptr, info_ptr);
  png_write_flush(png_ptr);
  png_destroy_write_struct(&png_ptr, &info_ptr);

  //free (data);
  delete [] row_pointers;
  return Ok;
}
Exemplo n.º 6
0
void write_png(FileSystem::FileSourceFS &fs, const std::string &path, const Uint8 *bytes, int width, int height, int stride, int bytes_per_pixel) {
	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
	if (!png_ptr) {
		fprintf(stderr, "Couldn't create png_write_struct\n");
		return;
	}

	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr) {
		png_destroy_write_struct(&png_ptr, 0);
		fprintf(stderr, "Couldn't create png_info_struct\n");
		return;
	}

	//http://www.libpng.org/pub/png/libpng-1.2.5-manual.html#section-3.1
	if (setjmp(png_jmpbuf(png_ptr))) {
		png_destroy_write_struct(&png_ptr, &info_ptr);
		fprintf(stderr, "Couldn't set png jump buffer\n");
		return;
	}

	FILE *out = fs.OpenWriteStream(path);
	if (!out) {
		png_destroy_write_struct(&png_ptr, &info_ptr);
		fprintf(stderr, "Couldn't open '%s/%s' for writing\n", fs.GetRoot().c_str(), path.c_str());
		return;
	}

	int colour_type;
	switch (bytes_per_pixel) {
		case 1: colour_type = PNG_COLOR_TYPE_GRAY; break;
		case 2: colour_type = PNG_COLOR_TYPE_GRAY_ALPHA; break;
		case 3: colour_type = PNG_COLOR_TYPE_RGB; break;
		case 4: colour_type = PNG_COLOR_TYPE_RGB_ALPHA; break;
		default: assert(0); return;
	}

	png_init_io(png_ptr, out);
	png_set_filter(png_ptr, 0, PNG_FILTER_NONE);
	png_set_IHDR(png_ptr, info_ptr, width, height, 8, colour_type,
		PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
		PNG_FILTER_TYPE_DEFAULT);

	png_bytepp rows = new png_bytep[height];

	for (int i = 0; i < height; ++i) {
		const Uint8 *row = bytes + ((height-i-1) * stride);
		rows[i] = const_cast<Uint8*>(row);
	}
	png_set_rows(png_ptr, info_ptr, rows);
	png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, 0);

	png_destroy_write_struct(&png_ptr, &info_ptr);

	delete[] rows;

	fclose(out);
}
Exemplo n.º 7
0
int
main(int argc, char **argv)
{
    int i;
    unsigned char *scanbuf;
    unsigned char **rows;
    png_structp png_p;
    png_infop info_p;

    if ( !get_args( argc, argv ) )  {
	(void)fputs(usage, stderr);
	bu_exit ( 1, NULL );
    }

    /* autosize input? */
    if ( fileinput && autosize ) {
	unsigned long int	w, h;
	if ( fb_common_file_size(&w, &h, file_name, 1) ) {
	    file_width = (long)w;
	    file_height = (long)h;
	} else {
	    fprintf(stderr, "bw-png: unable to autosize\n");
	}
    }

    png_p = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
    if ( !png_p )
	bu_exit( EXIT_FAILURE, "Could not create PNG write structure\n" );

    info_p = png_create_info_struct( png_p );
    if ( !info_p )
	bu_exit( EXIT_FAILURE, "Could not create PNG info structure\n" );

    /* allocate space for the image */
    scanbuf = (unsigned char *)bu_calloc( SIZE, sizeof( unsigned char ), "scanbuf" );

    /* create array of pointers to rows for libpng */
    rows = (unsigned char **)bu_calloc( file_height, sizeof( unsigned char *), "rows" );
    for ( i=0; i<file_height; i++ )
	rows[i] = scanbuf + ((file_height-i-1)*ROWSIZE);

    /* read the bw file */
    if ( fread( scanbuf, SIZE, 1, infp ) != 1 )
	bu_exit( EXIT_FAILURE, "bw-png: Short read\n");

    png_init_io( png_p, stdout );
    png_set_filter( png_p, 0, PNG_FILTER_NONE );
    png_set_compression_level( png_p, Z_BEST_COMPRESSION );
    png_set_IHDR( png_p, info_p, file_width, file_height, 8,
		  PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE,
		  PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT );

    png_write_info( png_p, info_p );
    png_write_image( png_p, rows );
    png_write_end( png_p, NULL );
    return 0;
}
Exemplo n.º 8
0
bool CPNGFile::Save(const char *szFilename)
{
	// regular file saving - first, there has to be a buffer
	if (!pImageData) return false;
	// open the file
	fp = fopen(szFilename, "wb"); if (!fp) return false;
	// clear any previously initialized png-structs (e.g. by reading)
	ClearPngStructs();
	// reinit them for writing
	fWriteMode=true;
	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (!png_ptr) { Clear(); return false; }
	info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr) { Clear(); return false; }
	// error handling
	if (setjmp(png_jmpbuf(png_ptr))) { Clear(); return false; }
	// io initialization
	png_init_io(png_ptr, fp);
	// compression stuff
	png_set_filter(png_ptr, 0, PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_PAETH);
	png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
	png_set_compression_mem_level(png_ptr, 8);
	png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY);
	png_set_compression_window_bits(png_ptr, 15);
	png_set_compression_method(png_ptr, 8);
	// set header
	png_set_IHDR(png_ptr, info_ptr, iWdt, iHgt, iBPC, iClrType, iIntrlcType, iCmprType, iFltrType);
	// double-check our calculated row size
	int iRealRowSize=png_get_rowbytes(png_ptr, info_ptr);
	if (iRealRowSize != iRowSize)
	{
		// this won't go well, so better abort
		Clear(); return false;
	}
	// write png header
	png_write_info(png_ptr, info_ptr);
	// image data is given as bgr...
	png_set_bgr(png_ptr);
	// create row array
	unsigned char **ppRowBuf = new unsigned char *[iHgt];
	unsigned char **ppRows=ppRowBuf; unsigned char *pRow=pImageData;
	for (unsigned int i=0; i<iHgt; ++i,pRow+=iRowSize) *ppRows++=pRow;
	// write image
	png_write_image(png_ptr, ppRowBuf);
	// free row buffer
	delete [] ppRowBuf;
	// write end struct
	png_write_end(png_ptr, info_ptr);
	// finally, close the file
	fclose(fp); fp = NULL;
	// clear png structs
	ClearPngStructs();
	// success!
	return true;
}
void png_write( const char *myfile, unsigned char *data, unsigned int width, unsigned int height, bool alpha, char bpp )
{
    FILE *fp = VSFileSystem::vs_open( myfile, "wb" );
    png_structp png_ptr = png_create_write_struct
                              ( PNG_LIBPNG_VER_STRING, (png_voidp) NULL, NULL, NULL );
    if (!png_ptr)
        return;
    png_infop info_ptr = png_create_info_struct( png_ptr );
    if (!info_ptr) {
        png_destroy_write_struct( &png_ptr, (png_infopp) NULL );
        return;
    }
    if ( setjmp( png_ptr->jmpbuf ) ) {
        png_destroy_write_struct( &png_ptr, &info_ptr );
        VSFileSystem::vs_close( fp );
        return;
    }
    png_init_io( png_ptr, fp );
    png_set_filter( png_ptr, 0, PNG_FILTER_NONE );
    png_set_compression_level( png_ptr, Z_BEST_COMPRESSION );

    /* set other zlib parameters */
    png_set_compression_mem_level( png_ptr, 8 );
    png_set_compression_strategy( png_ptr, Z_DEFAULT_STRATEGY );
    png_set_compression_window_bits( png_ptr, 15 );
    png_set_compression_method( png_ptr, 8 );

    png_set_IHDR( png_ptr,
                  info_ptr,
                  width,
                  height,
                  bpp,
                  alpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB,
                  PNG_INTERLACE_NONE,
                  PNG_COMPRESSION_TYPE_DEFAULT,
                  PNG_FILTER_TYPE_DEFAULT );

    png_write_info( png_ptr, info_ptr );
# if __BYTE_ORDER != __BIG_ENDIAN
    if (bpp == 16)
        png_set_swap( png_ptr );
#endif
    int stride = (bpp/8)*(alpha ? 4 : 3);
    png_byte **row_pointers = new png_byte*[height];
    for (unsigned int i = 0; i < height; i++)
        row_pointers[i] = (png_byte*) &data[stride*i*width];
    png_write_image( png_ptr, row_pointers );
    png_write_end( png_ptr, info_ptr );
    png_write_flush( png_ptr );
    png_destroy_write_struct( &png_ptr, &info_ptr );

    VSFileSystem::vs_close( fp );
    free( data );
    delete[] row_pointers;
}
Exemplo n.º 10
0
void PNGImageWriter::beginOfImage(int cols, int rows) {
    _png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

    _info_ptr = png_create_info_struct(_png_ptr);
    if (!_info_ptr) {
        png_destroy_write_struct(&_png_ptr, NULL);
        exit(1);
    }

    png_set_IHDR(_png_ptr,
		 _info_ptr,
		 cols,
		 rows,
		 16,
		 PNG_COLOR_TYPE_GRAY,
		 PNG_INTERLACE_NONE,
		 NULL/*PNG_COMPRESSION_TYPE_DEFAULT*/,
		 PNG_FILTER_TYPE_DEFAULT);
    //png_set_filter(_png_ptr, 0, PNG_FILTER_NONE);
    //png_set_packing(_png_ptr);
    png_set_compression_level(_png_ptr, 0); // No compression
    png_set_filter(_png_ptr, 0 /* method */, PNG_NO_FILTERS);

    png_color_8 sig_bit;
    sig_bit.gray  = 16;
    sig_bit.red   = 0;
    sig_bit.green = 0;
    sig_bit.blue  = 0;
    sig_bit.alpha = 0;
    png_set_sBIT(_png_ptr, _info_ptr, &sig_bit);
    //png_set_shift(_png_ptr, &sig_bit);

    //png_set_gamma(_png_ptr, 1., 1.);
    png_set_strip_16(_png_ptr);

    //if (lsb)
    //png_set_swap(_png_ptr);

    // flush output after every row
    if (_lineBuffered)
	png_set_flush(_png_ptr, 1);

    //png_set_filler(_png_ptr, 0, PNG_FILLER_BEFORE);

    // Represent black as 1 and white as 0 instead of the PNG default.
    //png_set_invert_mono(_png_ptr);

    png_init_io(_png_ptr, _output);

    /* write the file information */
    png_write_info(_png_ptr, _info_ptr);
}
Exemplo n.º 11
0
Arquivo: gdpng.c Projeto: blair/orca
void gdImagePng(gdImagePtr im, FILE *out)
{
    int i;
    png_colorp palette;
    png_structp png_write_ptr =
        png_create_write_struct(PNG_LIBPNG_VER_STRING,
                                (png_voidp)NULL,
                                /* we would need to point to error handlers
                                   here to do it properly */
                                (png_error_ptr)NULL, (png_error_ptr)NULL);
    png_infop info_ptr = png_create_info_struct(png_write_ptr);

    if (setjmp(gdPngJmpbufStruct.jmpbuf)) {
        png_destroy_write_struct(&png_write_ptr, &info_ptr);
        return;
    }

    palette = (png_colorp)png_malloc (png_write_ptr,
                                      im->colorsTotal*sizeof(png_color));
    if (palette == NULL) {
        png_destroy_write_struct(&png_write_ptr, &info_ptr);
        return;
    }


    png_init_io(png_write_ptr, out);
    png_set_write_status_fn(png_write_ptr, NULL);
    png_set_IHDR(png_write_ptr,info_ptr,
                 im->sx,im->sy,im->colorsTotal > 16 ? 8:4,
                 PNG_COLOR_TYPE_PALETTE,
                 im->interlace ? PNG_INTERLACE_ADAM7: PNG_INTERLACE_NONE ,
                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
    for(i=0; i<im->colorsTotal; i++) {
        palette[i].red = im->red[i];
        palette[i].green = im->green[i];
        palette[i].blue = im->blue[i];
    }
    png_set_PLTE(png_write_ptr, info_ptr, palette, im->colorsTotal);

    /* choose between speed (1) and space (9) optimization */
    /* we want to be fast ... */
    png_set_compression_level(png_write_ptr,1);
    png_set_filter(png_write_ptr,PNG_FILTER_TYPE_BASE,PNG_NO_FILTERS);
    /* store file info */
    png_write_info(png_write_ptr, info_ptr);
    png_set_packing(png_write_ptr);
    png_write_image(png_write_ptr, im->pixels);
    png_write_end(png_write_ptr, info_ptr);
    png_free(png_write_ptr, palette);
    png_destroy_write_struct(&png_write_ptr, &info_ptr);
}
Exemplo n.º 12
0
bool
PNGOutput::open (const std::string &name, const ImageSpec &userspec,
                 OpenMode mode)
{
    if (mode != Create) {
        error ("%s does not support subimages or MIP levels", format_name());
        return false;
    }

    close ();  // Close any already-opened file
    m_spec = userspec;  // Stash the spec

    m_file = Filesystem::fopen (name, "wb");
    if (! m_file) {
        error ("Could not open file \"%s\"", name.c_str());
        return false;
    }

    std::string s = PNG_pvt::create_write_struct (m_png, m_info,
                                                  m_color_type, m_spec);
    if (s.length ()) {
        close ();
        error ("%s", s.c_str ());
        return false;
    }

	png_init_io (m_png, m_file);
	
	int compression_level = 6; /* medium speed vs size tradeoff */

	// RTT MOD: CVI use incoming compression values
	const ImageIOParameter *compParameter = m_spec.find_attribute ("CompressionQuality",TypeDesc::INT);
	if (compParameter)
	{
		compression_level = *(const int *)compParameter->data();
		compression_level = std::min( std::max( compression_level, 0 ), 9 ); // compression 0-9
	}
	png_set_compression_level (m_png, compression_level);

	const ImageIOParameter *filterParameter = m_spec.find_attribute ("png:Filters",TypeDesc::INT);
	if (filterParameter)
	{
		int filters = *(const int *)filterParameter->data();
		filters &= PNG_ALL_FILTERS;
		png_set_filter(m_png, 0, filters);
	}
	
    PNG_pvt::write_info (m_png, m_info, m_color_type, m_spec, m_pngtext);

    return true;
}
Exemplo n.º 13
0
void CSnapShot::WriteImageToFile(CThread * pThread)
{
	m_threadData.bWriting = true;

	D3DDISPLAYMODE displayMode;
	g_pCore->GetGraphics()->GetDevice()->GetDisplayMode(0, &displayMode);

	UINT uiScreenWidth = displayMode.Width;
	UINT uiScreenHeight = displayMode.Height;
	BYTE* mem = new BYTE[SCREEN_SHOT_FORMAT_BYTES_PER_PIXEL * uiScreenWidth * uiScreenWidth];

	GetFrontBufferPixels(uiScreenWidth, uiScreenHeight, mem);

	BYTE** ScreenData = nullptr;
	ScreenData = new BYTE* [uiScreenHeight];
	for (unsigned short y = 0; y < uiScreenHeight; y++) {
		ScreenData[y] = new BYTE[uiScreenWidth * SCREEN_SHOT_FORMAT_BYTES_PER_PIXEL];
	}

	UINT uiLinePitch = uiScreenWidth * SCREEN_SHOT_FORMAT_BYTES_PER_PIXEL;
	unsigned long ulLineWidth = uiScreenWidth * SCREEN_SHOT_FORMAT_BYTES_PER_PIXEL;
	for (unsigned int i = 0; i < uiScreenHeight; i++) {
		memcpy(ScreenData[i], (BYTE*) mem + i* uiLinePitch, ulLineWidth);
		for(unsigned int j = 3; j < ulLineWidth; j += SCREEN_SHOT_FORMAT_BYTES_PER_PIXEL) {
			ScreenData[i][j] = 0xFF;
		}
	}

	CString strPath = GetScreenShotPath();
	FILE *file = fopen(strPath, "wb");
	png_struct* png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	png_info* info_ptr = png_create_info_struct(png_ptr);
	png_init_io(png_ptr, file);
	png_set_filter(png_ptr, 0, PNG_FILTER_NONE);
	png_set_compression_level(png_ptr, 9);
	png_set_IHDR(png_ptr, info_ptr, uiScreenWidth, uiScreenHeight, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
	png_set_rows(png_ptr, info_ptr, ScreenData);
	png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_BGR | PNG_TRANSFORM_STRIP_ALPHA, NULL);
	png_write_end(png_ptr, info_ptr);
	png_destroy_write_struct(&png_ptr, &info_ptr);
	fclose(file);

	for (unsigned short y = 0; y < uiScreenHeight; y++) {
		delete []ScreenData[y];
	}

	delete []ScreenData;
	delete []mem;
	m_threadData.bWriting = false;
}
Exemplo n.º 14
0
void save_as_png(T1 & file,
                T2 const& image,
                png_options const& opts)

{
    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,static_cast<png_infopp>(0));
        return;
    }
    jmp_buf* jmp_context = static_cast<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] = const_cast<png_bytep>(reinterpret_cast<const unsigned char *>(image.get_row(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);
}
Exemplo n.º 15
0
void
open_png(void)
{
 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,of);
 png_set_filter(png_ptr,0,PNG_FILTER_NONE|PNG_FILTER_SUB|PNG_FILTER_UP
  |PNG_FILTER_AVG|PNG_FILTER_PAETH);
 png_set_compression_level(png_ptr,Z_BEST_COMPRESSION);
 png_set_IHDR(png_ptr,info_ptr,ox,oy,8,PNG_COLOR_TYPE_GRAY,PNG_INTERLACE_NONE,
  PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT);
 png_set_gAMA(png_ptr,info_ptr,1.0);
 png_set_pHYs(png_ptr,info_ptr,ppm,ppm,PNG_RESOLUTION_METER);
 png_write_info(png_ptr,info_ptr);
}
Exemplo n.º 16
0
void writePNG (png_bytepp imageBuffer, png_uint_32 width, png_uint_32 height, int iteration) {
  const char *fname = "out.png";
  
  FILE *fp = fopen(fname, "wb");
  if (!fp) return;
  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_init_io(png_ptr, fp);
  png_set_filter(png_ptr, PNG_FILTER_TYPE_DEFAULT, PNG_FILTER_NONE);
  png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
  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);
  png_set_rows(png_ptr, info_ptr, imageBuffer);
  png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
  png_destroy_write_struct(&png_ptr, &info_ptr);
  fclose(fp);
}
Exemplo n.º 17
0
static bool encodePixels(IntSize imageSize, const unsigned char* inputPixels, bool premultiplied, Vector<unsigned char>* output)
{
    if (imageSize.width() <= 0 || imageSize.height() <= 0)
        return false;

    Vector<unsigned char> row;

    png_struct* png = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
    png_info* info = png_create_info_struct(png);
    if (!png || !info || setjmp(png_jmpbuf(png))) {
        png_destroy_write_struct(png ? &png : 0, info ? &info : 0);
        return false;
    }

    // Optimize compression for speed.
    // The parameters are the same as what libpng uses by default for RGB and RGBA images, except:
    // - the zlib compression level is 3 instead of 6, to avoid the lazy Ziv-Lempel match searching;
    // - the delta filter is 1 ("sub") instead of 5 ("all"), to reduce the filter computations.
    // The zlib memory level (8) and strategy (Z_FILTERED) will be set inside libpng.
    //
    // Avoid the zlib strategies Z_HUFFMAN_ONLY or Z_RLE.
    // Although they are the fastest for poorly-compressible images (e.g. photographs),
    // they are very slow for highly-compressible images (e.g. text, drawings or business graphics).
    png_set_compression_level(png, 3);
    png_set_filter(png, PNG_FILTER_TYPE_BASE, PNG_FILTER_SUB);

    png_set_write_fn(png, output, writeOutput, 0);
    png_set_IHDR(png, info, imageSize.width(), imageSize.height(),
                 8, PNG_COLOR_TYPE_RGB_ALPHA, 0, 0, 0);
    png_write_info(png, info);

    unsigned char* pixels = const_cast<unsigned char*>(inputPixels);
    row.resize(imageSize.width() * sizeof(SkPMColor));
    const size_t pixelRowStride = imageSize.width() * 4;
    for (int y = 0; y < imageSize.height(); ++y) {
        if (premultiplied) {
            preMultipliedBGRAtoRGBA(pixels, imageSize.width(), row.data());
            png_write_row(png, row.data());
        } else
            png_write_row(png, pixels);
        pixels += pixelRowStride;
    }

    png_write_end(png, info);
    png_destroy_write_struct(&png, &info);
    return true;
}
Exemplo n.º 18
0
// Callback for threaded save
// Static function
DWORD CScreenShot::ThreadProc ( LPVOID lpdwThreadParam )
{
    unsigned long ulScreenHeight = ms_ScreenSize.bottom - ms_ScreenSize.top;
    unsigned long ulScreenWidth = ms_ScreenSize.right - ms_ScreenSize.left;

    // Create the screen data buffer
    BYTE** ppScreenData = NULL;
    ppScreenData = new BYTE* [ ulScreenHeight ];
    for ( unsigned short y = 0; y < ulScreenHeight; y++ ) {
        ppScreenData[y] = new BYTE [ ulScreenWidth * 4 ];
    }

    // Copy the surface data into a row-based buffer for libpng
    #define BYTESPERPIXEL 4
    unsigned long ulLineWidth = ulScreenWidth * 4;
    for ( unsigned int i = 0; i < ulScreenHeight; i++ ) {
        memcpy ( ppScreenData[i], (BYTE*) ms_pBits + i* ms_ulPitch, ulLineWidth );
        for ( unsigned int j = 3; j < ulLineWidth; j += BYTESPERPIXEL ) {
            ppScreenData[i][j] = 0xFF;
        }
    }

    FILE *file = fopen (ms_strFileName, "wb");
        png_struct* png_ptr = png_create_write_struct ( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
        png_info* info_ptr = png_create_info_struct ( png_ptr );
        png_init_io ( png_ptr, file );
        png_set_filter ( png_ptr, 0, PNG_FILTER_NONE );
        png_set_compression_level ( png_ptr, 1 );
        png_set_IHDR ( png_ptr, info_ptr, ulScreenWidth, ulScreenHeight, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT );
        png_set_rows ( png_ptr, info_ptr, ppScreenData );
        png_write_png ( png_ptr, info_ptr, PNG_TRANSFORM_BGR | PNG_TRANSFORM_STRIP_ALPHA, NULL );
        png_write_end ( png_ptr, info_ptr );
        png_destroy_write_struct ( &png_ptr, &info_ptr );
    fclose(file);

    // Clean up the screen data buffer
    if ( ppScreenData ) {
        for ( unsigned short y = 0; y < ulScreenHeight; y++ ) {
            delete [] ppScreenData[y];
        }
        delete [] ppScreenData;
    }

    ms_bIsSaving = false;
    return 0;
}
Exemplo n.º 19
0
void save_as_png(T1 & file , T2 const& image, int compression = Z_DEFAULT_COMPRESSION, int strategy = Z_DEFAULT_STRATEGY)
{
    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, compression);
    png_set_compression_strategy(png_ptr, strategy);
    png_set_compression_buffer_size(png_ptr, 32768);

    png_set_IHDR(png_ptr, info_ptr,image.width(),image.height(),8,
                 PNG_COLOR_TYPE_RGB_ALPHA,PNG_INTERLACE_NONE,
                 PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT);
    png_write_info(png_ptr, info_ptr);
    for (unsigned i=0;i<image.height();i++)
    {
        png_write_row(png_ptr,(png_bytep)image.getRow(i));
    }

    png_write_end(png_ptr, info_ptr);
    png_destroy_write_struct(&png_ptr, &info_ptr);
}
Exemplo n.º 20
0
int png_write_data(const char *filename, uint8 *data, uint32 width, uint32 height)
{
  FILE *fp;
  uint32_t i;

  fp = fopen(filename, "wb");
  if (!fp) return -1;
   
  png_structp png_ptr = png_create_write_struct
    (PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
     NULL, NULL);
  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;
  }

  png_init_io(png_ptr, fp);
  
  png_set_filter(png_ptr, 0, PNG_FILTER_VALUE_NONE);
  png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
  
  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);
  
  png_bytepp row_pointers = (png_bytepp)malloc(sizeof(png_bytep)*height);
  
  for(i = 0; i < height; i++)
      row_pointers[i] = &data[3*i*width];

  png_set_rows(png_ptr, info_ptr, row_pointers);

  png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

  png_destroy_write_struct(&png_ptr, &info_ptr);
  
  free(row_pointers);
  fclose(fp);   
  return 0;
}
Exemplo n.º 21
0
/*
 * Encodes an image to a PNG file stream.
 */
int opng_encode_image(struct opng_codec_context *context, int filtered, FILE *stream, const char *fname, int level)
{
    const char * volatile err_msg;  /* volatile is required by cexcept */

    context->libpng_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, opng_write_error, opng_write_warning);
    context->info_ptr = png_create_info_struct(context->libpng_ptr);
    if (!context->libpng_ptr || !context->info_ptr)
    {
        opng_error(0, "Out of memory");
        png_destroy_write_struct(&context->libpng_ptr, &context->info_ptr);
        exit(1);
    }

    struct opng_encoding_stats * stats = context->stats;
    opng_init_stats(stats);
    context->stream = stream;
    context->fname = fname;

    Try
    {

        png_set_filter(context->libpng_ptr, PNG_FILTER_TYPE_BASE, filtered ? PNG_ALL_FILTERS : PNG_FILTER_NONE);
        if (level != 6) {
            png_set_compression_level(context->libpng_ptr, level);
        }
        png_set_compression_mem_level(context->libpng_ptr, 8);
        png_set_compression_window_bits(context->libpng_ptr, 15);
        png_set_compression_strategy(context->libpng_ptr, 0);
        png_set_keep_unknown_chunks(context->libpng_ptr, PNG_HANDLE_CHUNK_ALWAYS, 0, 0);
        opng_store_image(context->image, context->libpng_ptr, context->info_ptr);

        /* Write the PNG stream. */
        png_set_write_fn(context->libpng_ptr, context, opng_write_data, 0);
        png_write_png(context->libpng_ptr, context->info_ptr, 0, 0);
    }
    Catch (err_msg)
    {
        stats->idat_size = OPTK_INT64_MAX;
        opng_error(fname, err_msg);
        return -1;
    }
    png_data_freer(context->libpng_ptr, context->info_ptr, PNG_USER_WILL_FREE_DATA, PNG_FREE_ALL);
    png_destroy_write_struct(&context->libpng_ptr, &context->info_ptr);
    return 0;
}
Exemplo n.º 22
0
pngquant_error rwpng_write_image8(FILE *outfile, png8_image *mainprog_ptr)
{
    png_structp png_ptr;
    png_infop info_ptr;

    pngquant_error retval = rwpng_write_image_init((png_image*)mainprog_ptr, &png_ptr, &info_ptr, outfile);
    if (retval) return retval;

    // Palette images generally don't gain anything from filtering
    png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_FILTER_VALUE_NONE);

    rwpng_set_gamma(info_ptr, png_ptr, mainprog_ptr->gamma);

    /* set the image parameters appropriately */
    int sample_depth;
    if (mainprog_ptr->num_palette <= 2)
        sample_depth = 1;
    else if (mainprog_ptr->num_palette <= 4)
        sample_depth = 2;
    else if (mainprog_ptr->num_palette <= 16)
        sample_depth = 4;
    else
        sample_depth = 8;

    png_set_IHDR(png_ptr, info_ptr, mainprog_ptr->width, mainprog_ptr->height,
      sample_depth, PNG_COLOR_TYPE_PALETTE,
      0, PNG_COMPRESSION_TYPE_DEFAULT,
      PNG_FILTER_TYPE_BASE);

    png_set_PLTE(png_ptr, info_ptr, &mainprog_ptr->palette[0], mainprog_ptr->num_palette);

    if (mainprog_ptr->num_trans > 0)
        png_set_tRNS(png_ptr, info_ptr, mainprog_ptr->trans, mainprog_ptr->num_trans, NULL);


    png_bytepp row_pointers = rwpng_create_row_pointers(info_ptr, png_ptr, mainprog_ptr->indexed_data, mainprog_ptr->height, mainprog_ptr->width);

    rwpng_write_end(&info_ptr, &png_ptr, row_pointers);

    free(row_pointers);

    return SUCCESS;
}
Exemplo n.º 23
0
pngquant_error rwpng_write_image_init(png_image *mainprog_ptr, png_structpp png_ptr_p, png_infopp info_ptr_p, FILE *outfile)
{
    /* could also replace libpng warning-handler (final NULL), but no need: */

    *png_ptr_p = png_create_write_struct(PNG_LIBPNG_VER_STRING, mainprog_ptr, rwpng_error_handler, NULL);

    if (!(*png_ptr_p)) {
        return LIBPNG_INIT_ERROR;   /* out of memory */
    }

    *info_ptr_p = png_create_info_struct(*png_ptr_p);
    if (!(*info_ptr_p)) {
        png_destroy_write_struct(png_ptr_p, NULL);
        return LIBPNG_INIT_ERROR;   /* out of memory */
    }


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

    if (setjmp(mainprog_ptr->jmpbuf)) {
        png_destroy_write_struct(png_ptr_p, info_ptr_p);
        return LIBPNG_INIT_ERROR;   /* libpng error (via longjmp()) */
    }

    png_init_io(*png_ptr_p, outfile);

    png_set_compression_level(*png_ptr_p, Z_BEST_COMPRESSION);

    // Palette images generally don't gain anything from filtering
    png_set_filter(*png_ptr_p, PNG_FILTER_TYPE_BASE, PNG_FILTER_VALUE_NONE);

    if (mainprog_ptr->png8.gamma > 0.0) {
        png_set_gAMA(*png_ptr_p, *info_ptr_p, mainprog_ptr->png8.gamma);
    }

    return SUCCESS;
}
Exemplo n.º 24
0
// Note: Calls req.Respond().  Other data can be added afterward.
static bool StreamBufferToDataURI(DebuggerRequest &req, const GPUDebugBuffer &buf, bool includeAlpha, int stackWidth) {
#ifdef USING_QT_UI
	req.Fail("Not supported on Qt yet, pull requests accepted");
	return false;
#else
	u8 *flipbuffer = nullptr;
	u32 w = (u32)-1;
	u32 h = (u32)-1;
	const u8 *buffer = ConvertBufferToScreenshot(buf, includeAlpha, flipbuffer, w, h);
	if (!buffer) {
		req.Fail("Internal error converting buffer for PNG encode");
		return false;
	}

	if (stackWidth > 0) {
		u32 totalPixels = w * h;
		w = stackWidth;
		while ((totalPixels % w) != 0)
			--w;
		h = totalPixels / w;
	}

	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
	if (!png_ptr) {
		req.Fail("Internal error setting up PNG encoder (png_ptr)");
		return false;
	}
	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr) {
		png_destroy_write_struct(&png_ptr, nullptr);
		req.Fail("Internal error setting up PNG encoder (info_ptr)");
		return false;
	}

	// Speed.  Wireless N should give 35 KB/ms.  For most devices, zlib/filters will cost more.
	png_set_compression_strategy(png_ptr, Z_RLE);
	png_set_compression_level(png_ptr, 1);
	png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_FILTER_NONE);

	auto &json = req.Respond();
	json.writeInt("width", w);
	json.writeInt("height", h);

	// Start a value...
	json.writeRaw("uri", "");
	req.Flush();
	// Now we'll write it directly to the stream.
	req.ws->AddFragment(false, "\"data:image/png;base64,");

	struct Context {
		DebuggerRequest *req;
		uint8_t buf[3];
		size_t bufSize;
	};
	Context ctx = { &req, {}, 0 };

	auto write = [](png_structp png_ptr, png_bytep data, png_size_t length) {
		auto ctx = (Context *)png_get_io_ptr(png_ptr);
		auto &req = *ctx->req;

		// If we buffered some bytes, fill to 3 bytes for a clean base64 encode.
		// This way we don't have padding.
		while (length > 0 && ctx->bufSize > 0 && ctx->bufSize != 3) {
			ctx->buf[ctx->bufSize++] = data[0];
			data++;
			length--;
		}

		if (ctx->bufSize == 3) {
			req.ws->AddFragment(false, Base64Encode(ctx->buf, ctx->bufSize));
			ctx->bufSize = 0;
		}
		assert(ctx->bufSize == 0 || length == 0);

		// Save bytes that would result in padding for next time.
		size_t toBuffer = length % 3;
		for (size_t i = 0; i < toBuffer; ++i) {
			ctx->buf[i] = data[length - toBuffer + i];
			ctx->bufSize++;
		}

		if (length > toBuffer) {
			req.ws->AddFragment(false, Base64Encode(data, length - toBuffer));
		}
	};
	auto flush = [](png_structp png_ptr) {
		// Nothing, just here to prevent stdio flush.
	};

	png_bytep *row_pointers = new png_bytep[h];
	u32 stride = includeAlpha ? w * 4 : w * 3;
	for (u32 i = 0; i < h; ++i) {
		row_pointers[i] = (u8 *)buffer + stride * i;
	}

	png_set_write_fn(png_ptr, &ctx, write, flush);
	int colorType = includeAlpha ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB;
	png_set_IHDR(png_ptr, info_ptr, w, h, 8, colorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
	png_set_rows(png_ptr, info_ptr, row_pointers);
	png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, nullptr);

	png_destroy_write_struct(&png_ptr, &info_ptr);
	delete [] row_pointers;
	delete [] flipbuffer;

	if (ctx.bufSize > 0) {
		req.ws->AddFragment(false, Base64Encode(ctx.buf, ctx.bufSize));
		ctx.bufSize = 0;
	}

	// End the string.
	req.ws->AddFragment(false, "\"");
	return true;
#endif
}
Exemplo n.º 25
0
void Screendump(const char* destFile, const int width, const int height)
{
	std::string dir = FileSystem::GetUserDir("screenshots");
	FileSystem::rawFileSystem.MakeDirectory(dir);
	std::string fname = FileSystem::JoinPathBelow(dir, destFile);

	// pad rows to 4 bytes, which is the default row alignment for OpenGL
	const int stride = (3*width + 3) & ~3;

	std::vector<png_byte> pixel_data(stride * height);
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
	glPixelStorei(GL_PACK_ALIGNMENT, 4); // never trust defaults
	glReadBuffer(GL_FRONT);
	glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, &pixel_data[0]);
	glFinish();

	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
	if (!png_ptr) {
		fprintf(stderr, "Couldn't create png_write_struct\n");
		return;
	}

	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr) {
		png_destroy_write_struct(&png_ptr, 0);
		fprintf(stderr, "Couldn't create png_info_struct\n");
		return;
	}

	//http://www.libpng.org/pub/png/libpng-1.2.5-manual.html#section-3.1
	if (setjmp(png_jmpbuf(png_ptr))) {
		png_destroy_write_struct(&png_ptr, &info_ptr);
		fprintf(stderr, "Couldn't set png jump buffer\n");
		return;
	}

	FILE *out = fopen(fname.c_str(), "wb");
	if (!out) {
		png_destroy_write_struct(&png_ptr, &info_ptr);
		fprintf(stderr, "Couldn't open %s for writing\n", fname.c_str());
		return;
	}

	png_init_io(png_ptr, out);
	png_set_filter(png_ptr, 0, PNG_FILTER_NONE);
	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);

	png_bytepp rows = new png_bytep[height];

	for (int i = 0; i < height; ++i) {
		rows[i] = reinterpret_cast<png_bytep>(&pixel_data[(height-i-1) * stride]);
	}
	png_set_rows(png_ptr, info_ptr, rows);
	png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, 0);

	png_destroy_write_struct(&png_ptr, &info_ptr);

	delete[] rows;

	fclose(out);
	printf("Screenshot %s saved\n", fname.c_str());
}
Exemplo n.º 26
0
void save_as_png(T & file, std::vector<mapnik::rgb> const& palette,
                 mapnik::image_gray8 const& image,
                 unsigned width,
                 unsigned height,
                 unsigned color_depth,
                 std::vector<unsigned> const&alpha,
                 png_options const& opts)
{
    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,static_cast<png_infopp>(0));
        return;
    }
    jmp_buf* jmp_context = static_cast<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<T>, &flush_data<T>);

    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,width,height,color_depth,
                 PNG_COLOR_TYPE_PALETTE,PNG_INTERLACE_NONE,
                 PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT);

    png_color* pal = const_cast<png_color*>(reinterpret_cast<const png_color*>(&palette[0]));
    png_set_PLTE(png_ptr, info_ptr, pal, static_cast<unsigned>(palette.size()));

    // make transparent lowest indexes, so tRNS is small
    if (alpha.size()>0)
    {
        std::vector<png_byte> trans(alpha.size());
        unsigned alphaSize=0;//truncate to nonopaque values
        for(unsigned i=0; i < alpha.size(); i++)
        {
            trans[i]=alpha[i];
            if (alpha[i]<255)
            {
                alphaSize = i+1;
            }
        }
        if (alphaSize>0)
        {
            png_set_tRNS(png_ptr, info_ptr, static_cast<png_bytep>(&trans[0]), alphaSize, 0);
        }
    }

    png_write_info(png_ptr, info_ptr);
    for (unsigned i=0;i<height;i++)
    {
        png_write_row(png_ptr,const_cast<png_bytep>(image.get_row(i)));
    }

    png_write_end(png_ptr, info_ptr);
    png_destroy_write_struct(&png_ptr, &info_ptr);
}
Exemplo n.º 27
0
bool  PngEncoder::write( const Mat& img, const vector<int>& params )
{
    png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 );
    png_infop info_ptr = 0;
    FILE* f = 0;
    int y, width = img.cols, height = img.rows;
    int depth = img.depth(), channels = img.channels();
    bool result = false;
    AutoBuffer<uchar*> buffer;

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

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

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

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

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

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

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

                    png_write_info( png_ptr, info_ptr );

                    if (isBilevel)
                        png_set_packing(png_ptr);

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

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

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

                    result = true;
                }
            }
        }
    }

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

    return result;
}
Exemplo n.º 28
0
static BOOL DLL_CALLCONV
Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
	png_structp png_ptr;
	png_infop info_ptr;
	png_colorp palette = NULL;
	png_uint_32 width, height;
	BOOL has_alpha_channel = FALSE;

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

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

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

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

			if (!png_ptr)  {
				return FALSE;
			}

			// allocate/initialize the image information data.

			info_ptr = png_create_info_struct(png_ptr);

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

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

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

				png_destroy_write_struct(&png_ptr, &info_ptr);

				return FALSE;
			}

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

			// set physical resolution

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

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

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

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

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

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

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

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

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

					break;

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

					// set the palette

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

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

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

					break;
				}

				case FIC_RGBALPHA :
					has_alpha_channel = TRUE;

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

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

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

			// write possible ICC profile

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

			// write metadata

			WriteMetadata(png_ptr, info_ptr, dib);

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

			// set the transparency table

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

			// set the background color

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

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

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

			png_write_info(png_ptr, info_ptr);

			// write out the image data

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

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

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

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

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

			png_write_end(png_ptr, info_ptr);

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

			png_destroy_write_struct(&png_ptr, &info_ptr);

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

	return FALSE;
}
Exemplo n.º 29
0
int begin(char* base_file_name, unsigned char *png_buf, long long png_length) {

  MY_PNG_READ_OFFSET = 0;
  PNG_LENGTH = png_length; 
  ENTIRE_PNG_BUF = png_buf;

  if (png_sig_cmp(ENTIRE_PNG_BUF, 0, 8) != 0) {
    error(-1, "png_sig_cmp", E_INVALID);
    return -1;
  }

  DEBUG_PRINT(("Initial png size is %lld bytes\n", PNG_LENGTH));

  my_png_meta *pm = calloc(1, sizeof(my_png_meta));
  my_init_libpng(pm);

  //If libpng errors, we end up here
  if (setjmp(png_jmpbuf(pm->read_ptr))) {
    DEBUG_PRINT(("libpng called setjmp!\n"));
    my_deinit_libpng(pm);
    free(ENTIRE_PNG_BUF);
    error(-1, "libpng", "libpng encountered an error\n");
    return -1;
  }

  //Normally a file, but instead make it our buffer
  void *read_io_ptr = png_get_io_ptr(pm->read_ptr);
  png_set_read_fn(pm->read_ptr, read_io_ptr, my_png_read_fn);

  //Transform all PNG image types to RGB
  int transforms = 
    PNG_TRANSFORM_GRAY_TO_RGB |
    PNG_TRANSFORM_STRIP_ALPHA | 
    PNG_TRANSFORM_EXPAND;

  png_read_png(pm->read_ptr, pm->info_ptr, transforms, NULL);

  //Now that it was read and transformed, its size will differ
  PNG_LENGTH = 0; 

  //Lets collect our metadata
  struct ihdr_infos_s ihdr_infos;
  ihdr_infos.bit_depth        = png_get_bit_depth(pm->read_ptr, pm->info_ptr);
  ihdr_infos.color_type       = png_get_color_type(pm->read_ptr, pm->info_ptr);
  ihdr_infos.filter_method    = png_get_filter_type(pm->read_ptr, pm->info_ptr);
  ihdr_infos.compression_type = png_get_compression_type(pm->read_ptr, pm->info_ptr);
  ihdr_infos.interlace_type   = png_get_interlace_type(pm->read_ptr, pm->info_ptr);
  ihdr_infos.height           = png_get_image_height(pm->read_ptr, pm->info_ptr);
  ihdr_infos.width            = png_get_image_width(pm->read_ptr, pm->info_ptr);

  if (ihdr_infos.color_type != 2) {
    DEBUG_PRINT((E_INVALID));
    free(ENTIRE_PNG_BUF);
    my_deinit_libpng(pm);
    DEBUG_PRINT(("Looks like libpng could not correctly convert to RGB\n"));
    return -1;
  }

  //Just in case we want to enable alpha, etc
  switch(ihdr_infos.color_type) {
    case 0:  //greyscale
    case 3:  //indexed
      ihdr_infos.bytes_per_pixel = 1;
      break;
    case 4: ihdr_infos.bytes_per_pixel = 2; break; //greyscale w/ alpha 
    case 2: ihdr_infos.bytes_per_pixel = 3; break; //Truecolour (RGB)
    case 6: ihdr_infos.bytes_per_pixel = 4; break; //Truecolour w/ alpha
    default: error_fatal(1, "ihdr_infos", "Unknown image type"); //should never happen
  }

  ihdr_infos.scanline_len = (ihdr_infos.bytes_per_pixel * ihdr_infos.width) + 1;

  DEBUG_PRINT(("HEIGHT: %u\n", ihdr_infos.height));
  DEBUG_PRINT(("WIDTH: %u\n", ihdr_infos.width));
  DEBUG_PRINT(("BIT_DEPTH: %u\n", ihdr_infos.bit_depth));

  // Don't compress, since we are merely copying it to memory,
  // we will be decompressing it again anyway
  png_set_compression_level(pm->write_ptr, Z_NO_COMPRESSION);

  void *write_io_ptr = png_get_io_ptr(pm->write_ptr);
  png_set_write_fn(pm->write_ptr, write_io_ptr, my_png_write_fn, my_png_dummy_flush);

  //Make sure we use all filters
  png_set_filter(pm->write_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);

  //Set our comment
  struct png_text_struct comment_struct;

  comment_struct.compression = -1;
  comment_struct.key = " Glitched by pnglitch.xyz ";
  comment_struct.text = NULL;
  comment_struct.text_length = 0;
  
  png_set_text(pm->write_ptr, pm->info_ptr, &comment_struct, 1);

  //Buffer is Written using callback my_png_write_fn to buffer
  //ENTIRE_PNG_BUF. PNG_LENGTH will be updated automatically by it
  png_write_png(pm->write_ptr, pm->info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

  my_deinit_libpng(pm);

  DEBUG_PRINT(("libpng output buf is %lld bytes\n", PNG_LENGTH));

  //Now that libpng has converted the image
  //and we have it in a buffer, we process it by hand with zlib
  struct z_stream_s inflate_stream;
  my_init_zlib(&inflate_stream);
  inflateInit(&inflate_stream);

  //Pointer to keep track of where we are
  unsigned char *pngp = ENTIRE_PNG_BUF;

  //Skip PNG Signature
  pngp += 8; 

  //Get Header
  unsigned char ihdr_bytes_buf[4+4+13+4]; // size + label + content + crc
  buf_read(ihdr_bytes_buf, &pngp, 4+4+13+4);

  //When we run into non-idat chunks, we will want to preserve them.
  //The spec says there's no chunk that needs to go after IDAT,
  //so we can simply concatenate all of these chunks into a buffer
  //then write them all at once after the IHDR
  
  //ancillary chunks, eg comments
  unsigned char *ancil_chunks_buf = calloc(1,1);
  long long ancil_chunks_len = 0;

  unsigned char *unzip_idats_buf = calloc(1, 1);
  long unzip_buf_len = 1;
  long unzip_buf_offset = 0;

  long long zipped_idats_len = 0; //Length of all idats as we read them

  unsigned long accum_png_len = 8 + (4+4+13+4);

  int chunk_count = 0;

  printf("Uncompressing image data...\n");
  while (1) {
    unsigned char chunk_label[4];
    unsigned char chunk_len_buf[4];

    buf_read(chunk_len_buf, &pngp, 4);

    //first 4 bytes are the length of data section
    long chunk_len = four_bytes_to_int(chunk_len_buf);

    accum_png_len += chunk_len + 4 + 4 + 4; // plus len, crc, label
    DEBUG_PRINT(("at %lu --> %lld\n", accum_png_len, PNG_LENGTH));

    //leave at end of buffer
    if (accum_png_len >= PNG_LENGTH)
      break;

    //read the chunk label (name of this header)
    buf_read(chunk_label, &pngp, 4);

    DEBUG_PRINT(("Reading chunk %d with label '%c%c%c%c', size %ld\n",
          chunk_count, chunk_label[0], chunk_label[1], chunk_label[2],
          chunk_label[3], chunk_len));

    chunk_count += 1;

    if (memcmp(chunk_label, "IDAT", 4) == 0) {

      zipped_idats_len += chunk_len;

      //read the chunk's data section
      unsigned char *raw_chunk_buf = calloc(chunk_len, 1);
      buf_read(raw_chunk_buf, &pngp, chunk_len);

      //Tell inflate to uncompress it
      inflate_stream.next_in = raw_chunk_buf; 
      inflate_stream.avail_in = chunk_len; 

      //Now uncompress it (resizes buffer automatically)
      unsigned char *check_uncompress = uncompress_buffer(&inflate_stream, 
          unzip_idats_buf, &unzip_buf_len, &unzip_buf_offset);

      //Stop if error
      if (check_uncompress == NULL) {
        DEBUG_PRINT((E_GLITCH));
        free(ancil_chunks_buf);
        free(raw_chunk_buf);
        free(unzip_idats_buf);
        free(ENTIRE_PNG_BUF);
        return -1;
      }

      //Moving on
      unzip_idats_buf = check_uncompress;
      free(raw_chunk_buf);
      pngp += 4; // skip CRC

    } else { //This is not an idat

      ancil_chunks_buf = realloc(ancil_chunks_buf, 
          ancil_chunks_len + 4 + 4 + chunk_len + 4); //make room for new data

      //append length and label bytes
      append_bytes(ancil_chunks_buf, chunk_len_buf, &ancil_chunks_len, 4);
      append_bytes(ancil_chunks_buf, chunk_label, &ancil_chunks_len, 4);

      //append chunk data
      unsigned char *raw_chunk_buf = calloc(chunk_len, 1);
      buf_read(raw_chunk_buf, &pngp, chunk_len);
      append_bytes(ancil_chunks_buf, raw_chunk_buf, &ancil_chunks_len, chunk_len );

      //append chunk crc
      unsigned char chunk_crc_buf[4];
      buf_read(chunk_crc_buf, &pngp, 4);
      append_bytes(ancil_chunks_buf, chunk_crc_buf, &ancil_chunks_len, 4);

      free(raw_chunk_buf);

      DEBUG_PRINT(("ancillary chunks length: %lld\n", ancil_chunks_len));

    }
  }

  //buf contains all idats uncompressed, concatenated
  unsigned long unzipped_idats_len = inflate_stream.total_out; 
  unzip_idats_buf = realloc(unzip_idats_buf, unzipped_idats_len);

  //we already have ancillary chunks and idats, don't need the original
  free(ENTIRE_PNG_BUF);
  inflateEnd(&inflate_stream);

  printf("Uncompressed %lld bytes to %ld bytes\n", zipped_idats_len, unzipped_idats_len);

  printf("Glitching image data...\n");

  for (int g=0;g<NUM_OUTPUT_FILES;g++) {

    //do glitches
    switch(g) {
      case 5:
        glitch_random(unzip_idats_buf, unzipped_idats_len,
            ihdr_infos.scanline_len, 0.0005);
        break;
      case 6:
        glitch_random_filter(unzip_idats_buf, unzipped_idats_len,
            ihdr_infos.scanline_len);
        break;
      default:
        glitch_filter(unzip_idats_buf, unzipped_idats_len,
            ihdr_infos.scanline_len, g);
    }

    //recompress so we can write them to file
    long long glitched_idats_len = 0;
    unsigned char *glitched_idats = zip_idats(unzip_idats_buf,
        unzipped_idats_len, &glitched_idats_len);

    if (glitched_idats == NULL) {
      DEBUG_PRINT((E_GLITCH));
      free (unzip_idats_buf);
      free (ancil_chunks_buf);
      return -1;
    }

    char path[MAX_PATH_LENGTH];
    bzero(path, MAX_PATH_LENGTH);

    snprintf(path, MAX_PATH_LENGTH, "%s%s%s-%d.png", OUTPUT_DIRECTORY, DIR_SEP,
        base_file_name, g);

    DEBUG_PRINT(("Output file name is %s\n", path));

    FILE *outfp = fopen(path, "wb");

    write_glitched_image(glitched_idats, glitched_idats_len, ihdr_bytes_buf,
        ancil_chunks_buf, ancil_chunks_len, outfp);

    printf("%s\n", path);
    fflush(stdout);

    fclose(outfp);
    free(glitched_idats);
  }

  free(ancil_chunks_buf);
  free(unzip_idats_buf);
  return 0;
}
Exemplo n.º 30
0
    void write_header( const View& view )
    {
        using png_rw_info_t = detail::png_write_support
            <
                typename channel_type<typename get_pixel_type<View>::type>::type,
                typename color_space_type<View>::type
            >;

        // Set the image information here.  Width and height are up to 2^31,
        // bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
        // the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
        // PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
        // or PNG_COLOR_TYPE_RGB_ALPHA.  interlace is either PNG_INTERLACE_NONE or
        // PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
        // currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
        png_set_IHDR( get_struct()
                    , get_info()
                    , static_cast< png_image_width::type  >( view.width()  )
                    , static_cast< png_image_height::type >( view.height() )
                    , static_cast< png_bitdepth::type     >( png_rw_info_t::_bit_depth )
                    , static_cast< png_color_type::type   >( png_rw_info_t::_color_type )
                    , _info._interlace_method
                    , _info._compression_type
                    , _info._filter_method
                    );

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

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

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

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

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

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

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

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

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

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

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

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

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

#ifndef BOOST_GIL_IO_PNG_1_4_OR_LOWER

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

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

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

                texts[i] = pt;
            }

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

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

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

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

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

        png_set_compression_mem_level( get_struct()
                                     , _info._compression_mem_level
                                     );

        png_set_compression_strategy( get_struct()
                                    , _info._compression_strategy
                                    );

        png_set_compression_window_bits( get_struct()
                                       , _info._compression_window_bits
                                       );

        png_set_compression_method( get_struct()
                                  , _info._compression_method
                                  );

        png_set_compression_buffer_size( get_struct()
                                       , _info._compression_buffer_size
                                       );

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

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

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

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

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

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

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


        png_write_info( get_struct()
                      , get_info()
                      );
    }