<commit_before>
#include "png_image.h"

#include <vector>
#include <png.h>
#include <base/contract.h>
#include <base/scope_guard.h>


namespace gl
{

////////////////////////////////////////

void png_write( const char *file_name, size_t w, size_t h, size_t c )
{
	GLenum fmt;
	int png_ctype;
	switch ( c )
	{
		case 1: fmt = GL_RED; png_ctype = PNG_COLOR_TYPE_GRAY; break;
		case 3: fmt = GL_RGB; png_ctype = PNG_COLOR_TYPE_RGB; break;
		case 4: fmt = GL_RGBA; png_ctype = PNG_COLOR_TYPE_RGB_ALPHA; break;
		default: throw_runtime( "invalid number of channels ({0})", c );
	}

	std::unique_ptr<uint8_t[]> img( new uint8_t[w*h*c] );
	glReadPixels( 0, 0, static_cast<GLsizei>( w ), static_cast<GLsizei>( h ), fmt, GL_UNSIGNED_BYTE, img.get() );

	FILE *fp = fopen( file_name, "wb" );
	if ( fp == nullptr )
		throw_errno( "error opening file {0}", file_name );
	on_scope_exit
	{
		fclose( fp );
	};

	// Initialize write structure
	auto png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
	if ( png_ptr == NULL )
		throw_runtime( "could not allocate write structure" );
	on_scope_exit
	{
		png_destroy_write_struct( &png_ptr, nullptr );
	};

	// Initialize info structure
	auto info_ptr = png_create_info_struct( png_ptr );
	if (info_ptr == NULL)
		throw_runtime( "could not allocate info structure" );
	on_scope_exit
	{
		png_free_data( png_ptr, info_ptr, PNG_FREE_ALL, -1 );
	};

	// Setup Exception handling
	if ( setjmp( png_jmpbuf( png_ptr ) ) )
		throw_runtime( "error during PNG creation" );

	png_init_io( png_ptr, fp );

	// Write header (8 bit colour depth)
	png_set_IHDR( png_ptr, info_ptr, static_cast<png_uint_32>( w ), static_cast<png_uint_32>( h ), 8, png_ctype, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE );
	png_write_info( png_ptr, info_ptr );

	// Write image data
	for ( size_t y = 0; y < h; ++y )<commit_msg>Added extra checks for png_image writing.<commit_after>
#include "png_image.h"

#include <vector>
#include <png.h>
#include <base/contract.h>
#include <base/scope_guard.h>


namespace gl
{

////////////////////////////////////////

void png_write( const char *file_name, size_t w, size_t h, size_t c )
{
	precondition( w > 0, "width must be larger than 0" );
	precondition( h > 0, "height must be larger than 0" );
	GLenum fmt;
	int png_ctype;
	switch ( c )
	{
		case 1: fmt = GL_RED; png_ctype = PNG_COLOR_TYPE_GRAY; break;
		case 3: fmt = GL_RGB; png_ctype = PNG_COLOR_TYPE_RGB; break;
		case 4: fmt = GL_RGBA; png_ctype = PNG_COLOR_TYPE_RGB_ALPHA; break;
		default: throw_runtime( "invalid number of channels ({0})", c );
	}

	std::unique_ptr<uint8_t[]> img( new uint8_t[w*h*c] );
	glReadPixels( 0, 0, static_cast<GLsizei>( w ), static_cast<GLsizei>( h ), fmt, GL_UNSIGNED_BYTE, img.get() );

	FILE *fp = fopen( file_name, "wb" );
	if ( fp == nullptr )
		throw_errno( "error opening file {0}", file_name );
	on_scope_exit
	{
		fclose( fp );
	};

	// Initialize write structure
	auto png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
	if ( png_ptr == NULL )
		throw_runtime( "could not allocate write structure" );
	on_scope_exit
	{
		png_destroy_write_struct( &png_ptr, nullptr );
	};

	// Initialize info structure
	auto info_ptr = png_create_info_struct( png_ptr );
	if (info_ptr == NULL)
		throw_runtime( "could not allocate info structure" );
	on_scope_exit
	{
		png_free_data( png_ptr, info_ptr, PNG_FREE_ALL, -1 );
	};

	// Setup Exception handling
	if ( setjmp( png_jmpbuf( png_ptr ) ) != 0 )
		throw_runtime( "error during PNG creation" );

	png_init_io( png_ptr, fp );

	// Write header (8 bit colour depth)
	png_set_IHDR( png_ptr, info_ptr, static_cast<png_uint_32>( w ), static_cast<png_uint_32>( h ), 8, png_ctype, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE );
	png_write_info( png_ptr, info_ptr );

	// Write image data
	for ( size_t y = 0; y < h; ++y )
{'fraction_non_alphanumeric': 0.14333333333333334, 'fraction_numerical': 0.01, 'mean_word_length': 4.072821846553966, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1640643', 'n_tokens_mistral': 1598, 'n_tokens_neox': 1467, 'n_words': 386}