Exemplo n.º 1
0
unsigned char *readPngToBuffer(const char *fileName, unsigned int *bmpWidth, unsigned int *bmpHeight)
{
    png_image image;
    png_bytep buffer = NULL;
    
    memset(&image, 0, (sizeof image));
    image.version = PNG_IMAGE_VERSION;
    
    if (0 == png_image_begin_read_from_file(&image, fileName)) {
        DEBUG_LOG("begin read png: error: %s\n", fileName);
        return NULL;
    }

    image.format = PNG_FORMAT_RGBA;
    
    buffer = malloc(PNG_IMAGE_SIZE(image));
    
    if (buffer != NULL) {
        if (png_image_finish_read(&image, NULL, buffer, 0, NULL) != 0) {
            *bmpWidth = image.width;
            *bmpHeight = image.height;
            return buffer;
        }
    }
    if (buffer != NULL) {
        free(buffer);
        buffer = NULL;
    }
    
    DEBUG_LOG("read png: error: %s filename %s\n", image.message, fileName);
    
    return NULL;
}
Exemplo n.º 2
0
bool Texture::LoadFromSTDIO(FILE* a_pFile)
{
	if(!a_pFile)
		return false;

	png_image image;
	memset(&image, 0, (sizeof image));
	image.version = PNG_IMAGE_VERSION;

	png_image_begin_read_from_stdio(&image, a_pFile);

	if(image.format == PNG_FORMAT_RGBA)
		m_Format = GL_RGBA;
	else
		m_Format = GL_RGB;

	m_pData = new unsigned char[PNG_IMAGE_SIZE(image)];
	png_image_finish_read(&image, NULL, m_pData, 0, NULL);

	m_Width = image.width;
	m_Height = image.height;

	m_Type = GL_UNSIGNED_BYTE;

	return true;
}
Exemplo n.º 3
0
void png_test(){
	png_image image;

	memset(&image, 0, (sizeof image));
	image.version = PNG_IMAGE_VERSION;

	
	if(png_image_begin_read_from_file(&image, "data/hex.png")){
		png_bytep buffer;
		image.format = PNG_FORMAT_RGBA;
		buffer = (png_bytep)malloc(PNG_IMAGE_SIZE(image));

	
		if(buffer != NULL &&  png_image_finish_read(&image, NULL, buffer, 0, NULL)){
			if(png_image_write_to_file(&image, "data/hex.jordan.png",0, buffer, 0, NULL)){
				printf("Write was successful. F**k freeing memory\n");
				char c;
				int rs = scanf("%c", &c);
				exit(0);
			}
		} else{
			if(buffer == NULL){
				png_image_free(&image);
			} else{
				free(buffer);
			}

		}
	}	
	
	printf("You've f****d up\n");
	char c;
	int rs = scanf("%c", &c);
}
Exemplo n.º 4
0
unsigned char *readMemPngToBmpBuff(const unsigned char *memPng, long memPngLen, unsigned int *bmpWidth, unsigned int *bmpHeight)
{
    png_image image;
    png_bytep buffer = NULL;
    
    memset(&image, 0, (sizeof image));
    image.version = PNG_IMAGE_VERSION;
    
    if (!png_image_begin_read_from_memory(&image, memPng, memPngLen) != 0) {
        DEBUG_LOG("begin read mem png: error\n");
        return NULL;
    }
    
    image.format = PNG_FORMAT_RGBA;
    
    buffer = malloc(PNG_IMAGE_SIZE(image));
    
    if (buffer != NULL) {
        if (png_image_finish_read(&image, NULL, buffer, 0, NULL) != 0) {
            *bmpWidth = image.width;
            *bmpHeight = image.height;
            return buffer;
        }
    }
    if (buffer != NULL) {
        free(buffer);
        buffer = NULL;
    }
    
    DEBUG_LOG("read png: error: %s from mem png\n", image.message);
    
    return NULL;
}
Exemplo n.º 5
0
bool Texture::LoadFromPNG()
{
	if(m_Source.empty())
		return false;

	png_image image;
	memset(&image, 0, (sizeof image));
	image.version = PNG_IMAGE_VERSION;

	if(!png_image_begin_read_from_file(&image, m_Source.c_str()))
		return false;

	if(image.format == PNG_FORMAT_RGBA)
		m_Format = GL_RGBA;
	else
		m_Format = GL_RGB;

	m_pData = new unsigned char[PNG_IMAGE_SIZE(image)];
	png_image_finish_read(&image, NULL, m_pData, 0, NULL);

	m_Width = image.width;
	m_Height = image.height;

	m_Type = GL_UNSIGNED_BYTE;

	return true;
}
Exemplo n.º 6
0
/* Loads PNG using libpng */
static TLN_Bitmap LoadPNG (char *filename)
{
    png_image image;
    TLN_Bitmap bitmap = NULL;

    /* Only the image structure version number needs to be set. */
    memset (&image, 0, sizeof image);
    image.version = PNG_IMAGE_VERSION;

    if (png_image_begin_read_from_file (&image, filename))
    {
        int src_line_size = image.width * PNG_IMAGE_PIXEL_SIZE(image.format);
        int lut_size = PNG_IMAGE_COLORMAP_SIZE(image);
        BYTE* data = malloc (src_line_size * image.height);
        BYTE* lut = malloc (lut_size);

        bitmap = TLN_CreateBitmap (image.width, image.height, PNG_IMAGE_PIXEL_SIZE(image.format)<<3);

        /* Change this to try different formats!  If you set a colormap format
        * then you must also supply a colormap below.
        */
        image.format = PNG_FORMAT_RGB_COLORMAP;
        if (png_image_finish_read (&image, NULL, data, 0, lut))
        {
            BYTE *src, *dst;
            unsigned int c;

            png_image_free (&image);

            /* copy scanlines */
            src = data;
            for (c=0; c<image.height; c++)
            {
                dst = TLN_GetBitmapPtr (bitmap, 0, c);
                memcpy (dst, src, src_line_size);
                src += src_line_size;
            }

            /* get palette */
            {
                BYTE *src = lut;
                png_uint_32 c;
                TLN_Palette palette;
                palette = TLN_CreatePalette (image.colormap_entries);
                for (c=0; c<image.colormap_entries; c++)
                {
                    TLN_SetPaletteColor (palette, c, src[0], src[1], src[2]);
                    src += 3;
                }
                TLN_SetBitmapPalette (bitmap, palette);
            }
        }
        free (lut);
        free (data);
    }
    return bitmap;
}
Exemplo n.º 7
0
    PixelData decodePNGData(const Data &data, bool shouldPremultiplyAlpha) {
        png_image image;
        memset(&image, 0, (sizeof image));
        image.version = PNG_IMAGE_VERSION;

        if (!png_image_begin_read_from_memory(&image, (void *)data.getBytes(), data.getSize())) {
            throw std::runtime_error("Not PNG data");
        }

        /*
         * According to the example.c file for version 1.6 of libpng, converting 8 bit images to
         * 16 bit images is currently lossy. However, the reverse is hopelessly lossy.  It is
         * also useful to have linear RGB values to correctly premultiply the alpha channel.
         * Therefore all PNG data will be interpreted as 16 bit images, no exceptions.
         */
        image.format = PNG_FORMAT_LINEAR_RGB_ALPHA;

        png_size_t bufferSize = PNG_IMAGE_SIZE(image);
        png_byte *buffer = new png_byte[bufferSize];
        if (buffer == nullptr) {
            throw std::runtime_error("Out of memeory");
        }

        png_image_finish_read(&image, NULL/*background*/, buffer, 0/*row_stride*/, NULL/*colormap*/);

        /*
         * PNGs are internally stored with non-premultiplied alpha channels.  It is often more
         * useful for their values to be premultiplied.  Since the PNG data was interpreted as
         * a 16 bit image, the byte array must be reinterpreted as an array of 16 bit natural
         * numbers.
         */
        if (shouldPremultiplyAlpha) {
            natural_16bit *pixels = reinterpret_cast<natural_16bit *>(buffer);
            for (unsigned int i = 0; i < bufferSize / sizeof(natural_16bit); i += 4) {
                pixels[i + 0] *= pixels[i + 3] / float(0xFFFF);
				pixels[i + 1] *= pixels[i + 3] / float(0xFFFF);
				pixels[i + 2] *= pixels[i + 3] / float(0xFFFF);
            }
        }

        natural_8bit numberOfBitsPerChannel = 16;
        PixelChannel channels[] {
            {PixelChannelName::RED, PixelChannelType::UNSIGNED_INTEGER, numberOfBitsPerChannel},
            {PixelChannelName::GREEN, PixelChannelType::UNSIGNED_INTEGER, numberOfBitsPerChannel},
            {PixelChannelName::BLUE, PixelChannelType::UNSIGNED_INTEGER, numberOfBitsPerChannel},
            {PixelChannelName::ALPHA, PixelChannelType::UNSIGNED_INTEGER, numberOfBitsPerChannel},
        };
        PixelFormat format {sizeof(channels) / sizeof(PixelChannel), channels};
        PixelData imageData {image.width, image.height, format, Data(bufferSize, buffer)};
        
        delete [] buffer;
        
        return imageData;
    }
Exemplo n.º 8
0
int mergePng(char * fileBack, char * fileFront, char * fileOut)
{
	//fileBackΪ±³¾°Í¼Æ¬£¬É«²Ê¿Õ¼äΪRGB
	//fileFrontΪǰ¾°Í¼Æ¬£¬É«²Ê¿Õ¼äΪRGBA
	//fileOutΪµþ¼ÓͼƬ£¬É«²Ê¿Õ¼äΪRGBA
	int height = 480;
	int width = 640;
	png_image image;
	memset(&image, 0, sizeof image);
	image.version = PNG_IMAGE_VERSION;
	image.format = PNG_FORMAT_RGBA;

	png_image_begin_read_from_file(&image, fileBack);
	png_bytep bufBack = (png_bytep)malloc(PNG_IMAGE_SIZE(image));
	png_image_finish_read(&image, NULL/*background*/, bufBack, 0/*row_stride*/, NULL/*colormap*/);
	
	png_image_begin_read_from_file(&image, fileFront);
	png_bytep bufFront = (png_bytep)malloc(PNG_IMAGE_SIZE(image));
	png_image_finish_read(&image, NULL/*background*/, bufFront, 0/*row_stride*/, NULL/*colormap*/);
	
	png_bytep bufOut = (png_bytep)malloc(PNG_IMAGE_SIZE(image));
	
	int countRgb = 0;
	for(int i = 0; i < height; i++) {
		for(int j = 0; j < width * 4; j += 4) {
			bufOut[i * width * 4 + j] = bufBack[countRgb++];
			bufOut[i * width * 4 + j + 1] = bufBack[countRgb++];
			bufOut[i * width * 4 + j + 2] = bufBack[countRgb++];
			bufOut[i * width * 4 + j + 3] = 255 - bufFront[i * width * 4 + j + 3];
		}
	}
	
	png_image_write_to_file(&image, fileOut, 0/*convert_to_8bit*/, bufOut, 0/*row_stride*/, NULL/*colormap*/);
	free(bufBack);
	free(bufFront);
	free(bufOut);
	return 0;
}
Exemplo n.º 9
0
void ReplacedTexture::Load(int level, void *out, int rowPitch) {
	_assert_msg_(G3D, (size_t)level < levels_.size(), "Invalid miplevel");
	_assert_msg_(G3D, out != nullptr && rowPitch > 0, "Invalid out/pitch");

	const ReplacedTextureLevel &info = levels_[level];

#ifdef USING_QT_UI
	ERROR_LOG(G3D, "Replacement texture loading not implemented for Qt");
#else
	png_image png = {};
	png.version = PNG_IMAGE_VERSION;

	FILE *fp = File::OpenCFile(info.file, "rb");
	if (!png_image_begin_read_from_stdio(&png, fp)) {
		ERROR_LOG(G3D, "Could not load texture replacement info: %s - %s", info.file.c_str(), png.message);
		return;
	}

	bool checkedAlpha = false;
	if ((png.format & PNG_FORMAT_FLAG_ALPHA) == 0) {
		// Well, we know for sure it doesn't have alpha.
		if (level == 0) {
			alphaStatus_ = ReplacedTextureAlpha::FULL;
		}
		checkedAlpha = true;
	}
	png.format = PNG_FORMAT_RGBA;

	if (!png_image_finish_read(&png, nullptr, out, rowPitch, nullptr)) {
		ERROR_LOG(G3D, "Could not load texture replacement: %s - %s", info.file.c_str(), png.message);
		return;
	}

	if (!checkedAlpha) {
		// This will only check the hashed bits.
		CheckAlphaResult res = CheckAlphaRGBA8888Basic((u32 *)out, rowPitch / sizeof(u32), png.width, png.height);
		if (res == CHECKALPHA_ANY || level == 0) {
			alphaStatus_ = ReplacedTextureAlpha(res);
		} else if (res == CHECKALPHA_ZERO && alphaStatus_ == ReplacedTextureAlpha::FULL) {
			alphaStatus_ = ReplacedTextureAlpha(res);
		}
	}

	fclose(fp);
	png_image_free(&png);
#endif
}
Exemplo n.º 10
0
bool Interface::load_tex(const char *buf, uint32_t sz, int idx)
{
    png_image image;
    memset(&image, 0, sizeof(png_image));
    image.version = PNG_IMAGE_VERSION;

    if (png_image_begin_read_from_memory(&image, buf, sz))
    {
        image.format = PNG_FORMAT_RGBA;

        png_bytep buffer = (png_bytep)malloc(PNG_IMAGE_SIZE(image));

        if (buffer != NULL)
        {
            if (png_image_finish_read(&image, NULL, buffer, 0, NULL))
            {
                if (idx == TEXTURE_BLACK_IDX)
                {
                    glGenTextures(1, &this->m_texture_black);
                    glBindTexture(GL_TEXTURE_2D, this->m_texture_black);
                }
                else if (idx == TEXTURE_WHITE_IDX)
                {
                    glGenTextures(1, &this->m_texture_white);
                    glBindTexture(GL_TEXTURE_2D, this->m_texture_white);
                }
                else
                {
                    glGenTextures(1, &this->m_textures[idx]);
                    glBindTexture(GL_TEXTURE_2D, this->m_textures[idx]);
                }
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Linear Filtering
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear Filtering
                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width,
                             image.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
            }
            free(buffer);
        }
    }
    else
    {
        ERROR_MESSAGE("Interface: Texture load error: %s\n", image.message);
        return false;
    }

    return true;
}
Exemplo n.º 11
0
HL_PRIM bool HL_NAME(png_decode)( vbyte *data, int dataLen, vbyte *out, int width, int height, int stride, int format, int flags ) {
#	ifdef PNG_IMAGE_VERSION
	png_image img;
	memset(&img, 0, sizeof(img));
	img.version = PNG_IMAGE_VERSION;
	if( png_image_begin_read_from_memory(&img,data,dataLen) == 0 ) {
		png_image_free(&img);
		return false;
	}
	switch( format ) {
	case 0:
		img.format = PNG_FORMAT_RGB;
		break;
	case 1:
		img.format = PNG_FORMAT_BGR;
		break;
	case 7:
		img.format = PNG_FORMAT_RGBA;
		break;
	case 8:
		img.format = PNG_FORMAT_BGRA;
		break;
	case 9:
		img.format = PNG_FORMAT_ABGR;
		break;
	case 10:
		img.format = PNG_FORMAT_ARGB;
		break;
	default:
		png_image_free(&img);
		hl_error("Unsupported format");
		break;
	}
	if( img.width != width || img.height != height ) {
		png_image_free(&img);
		return false;
	}
	if( png_image_finish_read(&img,NULL,out,stride * (flags & 1 ? -1 : 1),NULL) == 0 ) {
		png_image_free(&img);
		return false;
	}
	png_image_free(&img);
#	else
	hl_error("PNG support is missing for this libPNG version");
#	endif
	return true;
}
Exemplo n.º 12
0
void opengl_texture::load_PNG()
{
	png_image png;
	memset(&png, 0, sizeof(png_image));
	png.version = PNG_IMAGE_VERSION;

	png_image_begin_read_from_file(&png, (name + type).c_str());
	if (png.warning_or_error)
	{
		data_state = resource_state::failed;
		ErrorLog(name + " error: " + std::string(png.message));
		return;
	}

	if (png.format & PNG_FORMAT_FLAG_ALPHA)
	{
		data_format = GL_RGBA;
		data_components = GL_RGBA;
		png.format = PNG_FORMAT_RGBA;
	}
	else
	{
		data_format = GL_RGB;
		data_components = GL_RGB;
		png.format = PNG_FORMAT_RGB;
	}
	data_width = png.width;
	data_height = png.height;

	data.resize(PNG_IMAGE_SIZE(png));

	png_image_finish_read(&png, nullptr,
		(void*)&data[0], -data_width * PNG_IMAGE_PIXEL_SIZE(png.format), nullptr);
	// we're storing texture data internally with bottom-left origin
	// so use negative stride

    if (png.warning_or_error)
    {
        data_state = resource_state::failed;
        ErrorLog(name + " error: " + std::string(png.message));
        return;
    }

    data_mapcount = 1;
    data_state = resource_state::good;
}
Exemplo n.º 13
0
bool PngHandler::TransPngFormat(const string& srcFilePath, const string& desFilePath, PNG_FORMAT pngFormat)
{
	bool result = false;

	// 初始化变量
	png_image image;
	memset(&image, 0, (sizeof image));
	image.version = PNG_IMAGE_VERSION;

	// 加载源文件
	if (png_image_begin_read_from_file(&image, srcFilePath.c_str()) != 0)
	{
		// 设置图片格式
		switch (pngFormat)
		{
		case PF_GRAY_8BIT:
			image.format = PNG_FORMAT_GRAY;
			break;
		case PF_GRAYALPHA_8BIT:
			image.format = PNG_FORMAT_GA;
			break;
		case PF_RGB_16BIT:
			image.format = PNG_FORMAT_RGB;
			break;
		case PF_RGBALPHA_16BIT:
			image.format = PNG_FORMAT_RGBA;
			break;
		}

		// 创建buffer
		png_bytep buffer = NULL;
		size_t bufferSize = PNG_IMAGE_SIZE(image);
		buffer = new png_byte[bufferSize];

		if (buffer != NULL 
			&& png_image_finish_read(&image, NULL, buffer, 0, NULL) != 0)
		{
			result = (png_image_write_to_file(&image, desFilePath.c_str(), 0, buffer, 0, NULL) != 0);
        }

		delete[] buffer;
	}

	return result;
}
Exemplo n.º 14
0
Arquivo: main.cpp Projeto: nyaxt/dmix
  PNGLoader(const std::string& filename) {
    png_image png;
    memset(&png, 0, sizeof(png_image));
    png.version = PNG_IMAGE_VERSION;

    if (!png_image_begin_read_from_file(&png, filename.c_str()))
      throw std::runtime_error("png_image_begin_read_from_file failed");

    png.format = PNG_FORMAT_RGBA;
    m_buffer.reset(new char[PNG_IMAGE_SIZE(png)]);

    m_width = png.width;
    m_height = png.height;

    if (!png_image_finish_read(&png, /*bg=*/nullptr, m_buffer.get(),
                               /*row_stride=*/0, /*colormap=*/nullptr))
      throw std::runtime_error("png_image_finish_read failed");
  }
Exemplo n.º 15
0
int gfwx_PngReadFile(const char* filename, uint8_t** pData, uint32_t* pWidth, uint32_t* pHeight, uint32_t bytesPerPixel)
{
	int status = -1;
	int png_status;
	png_image image;
	int row_stride;
	uint8_t* buffer = NULL;

	memset(&image, 0, sizeof(png_image));
	image.version = PNG_IMAGE_VERSION;

	png_status = png_image_begin_read_from_file(&image, filename);

	if (!png_status)
		goto exit;

	image.format = (bytesPerPixel == 4) ? PNG_FORMAT_BGRA : PNG_FORMAT_BGR;
	row_stride = PNG_IMAGE_ROW_STRIDE(image);

	buffer = malloc(PNG_IMAGE_SIZE(image));

	if (!buffer)
		goto exit;

	png_status = png_image_finish_read(&image, NULL, buffer, row_stride, NULL);

	if (!png_status)
		goto exit;

	*pWidth = image.width;
	*pHeight = image.height;
	*pData = buffer;

	status = 1;

exit:
	if (status < 1)
		free(buffer);

	png_image_free(&image);
	return status;
}
Exemplo n.º 16
0
static int read_png(const char *fname, image *image, gradient *g)
{
	int result = 0;
	memset(&image->image, 0, sizeof image->image);
	image->image.version = PNG_IMAGE_VERSION;

	if (png_image_begin_read_from_file(&image->image, image->file_name))
	{
		image->image.format = PNG_FORMAT_RGBA;
		image->stride = PNG_IMAGE_ROW_STRIDE(image->image);
		image->buffer = malloc(PNG_IMAGE_SIZE(image->image));
		image->pixel_bytes = PNG_IMAGE_PIXEL_SIZE(image->image.format);

		if (image->buffer != NULL) {
			if(png_image_finish_read(&image->image, NULL /*background*/,
									 image->buffer, (png_int_32)image->stride,
									 image->colormap)) {

				if(calculate_gradient(image, g))
					result = 1;
				else
					printf("pngtocss: Gradient type not supported\n");
			}
			else {
				fprintf(stderr, "pngtocss: read %s: %s\n", fname,
						image->image.message);

				png_image_free(&image->image);
			}
		}
		else
			fprintf(stderr, "pngtocss: out of memory: %lu bytes\n",
					(unsigned long)PNG_IMAGE_SIZE(image->image));
	}
	else
		/* Failed to read the argument: */
		fprintf(stderr, "pngtocss: %s: %s\n", fname, image->image.message);

	return result;
}
Exemplo n.º 17
0
bool Texture::LoadFromCache()
{
	if(m_Source.empty())
		return false;

	__ResourceLocation& t_Location = __ResourceLocations[m_Source];

	FILE* t_pFile;
	t_pFile = fopen(t_Location.File.c_str(), "rb");
	if(!t_pFile)
		return false;

	fseek(t_pFile, t_Location.Position, SEEK_SET);

	png_image image;
	memset(&image, 0, (sizeof image));
	image.version = PNG_IMAGE_VERSION;

	png_image_begin_read_from_stdio(&image, t_pFile);

	if(image.format == PNG_FORMAT_RGBA)
		m_Format = GL_RGBA;
	else
		m_Format = GL_RGB;

	m_pData = new unsigned char[PNG_IMAGE_SIZE(image)];
	png_image_finish_read(&image, NULL, m_pData, 0, NULL);

	m_Width = image.width;
	m_Height = image.height;

	m_Type = GL_UNSIGNED_BYTE;

	fclose(t_pFile);

	return true;
}
Exemplo n.º 18
0
int main(int argc, char **argv)
{
	png_image image;
	png_bytep buffer;
	unsigned int size;
	bool format_initialized = false;
	png_uint_32 format = 0;
	const char *ipath = NULL;
	const char *opath = NULL;
	const char *prefix = NULL;
	char c;

	program_name = argv[0];

	while ((c = getopt_long(argc, argv, "i:o:f:p:h", long_options, NULL)) != -1) {
		switch (c) {
		case 'i':
			ipath = optarg;
			break;
		case 'o':
			opath = optarg;
			break;
		case 'p':
			prefix = optarg;
			break;
		case 'f':
			format = get_format_from_string(optarg);
			format_initialized = true;
			break;
		case 'h':
			usage(EXIT_SUCCESS);
			break;
		default:
			usage(EXIT_FAILURE);
			break;
		}
	}

	if (!format_initialized || !opath || !ipath || !prefix)
		usage(EXIT_FAILURE);

	memset(&image, 0, sizeof(image));
	image.version = PNG_IMAGE_VERSION;

	if (!png_image_begin_read_from_file(&image, ipath))
		error("Failed to open PNG file.");

	image.format = format;
	size = PNG_IMAGE_SIZE(image);

	buffer = malloc(size);
	if (!buffer)
		error("Failed to allocate buffer.");

	if (!png_image_finish_read(&image, NULL, buffer, 0, NULL))
		error("Failed to read  PNG file.");

	write_to_c_source(prefix, buffer, size, opath);

	png_image_free(&image);
	free(buffer);

	return EXIT_SUCCESS;
}
Exemplo n.º 19
0
int main(int argc, const char **argv)
{
   if (argc == 3)
   {
      png_image image; /* The control structure used by libpng */

      /* Initialize the 'png_image' structure. */
      memset(&image, 0, (sizeof image));
      image.version = PNG_IMAGE_VERSION;

      /* The first argument is the file to read: */
      if (png_image_begin_read_from_file(&image, argv[1]))
      {
         png_bytep buffer;

         /* Set the format in which to read the PNG file; this code chooses a
          * simple sRGB format with a non-associated alpha channel, adequate to
          * store most images.
          */
         image.format = PNG_FORMAT_RGBA;

         /* Now allocate enough memory to hold the image in this format; the
          * PNG_IMAGE_SIZE macro uses the information about the image (width,
          * height and format) stored in 'image'.
          */
         buffer = malloc(PNG_IMAGE_SIZE(image));

         /* If enough memory was available read the image in the desired format
          * then write the result out to the new file.  'background' is not
          * necessary when reading the image because the alpha channel is
          * preserved; if it were to be removed, for example if we requested
          * PNG_FORMAT_RGB, then either a solid background color would have to
          * be supplied or the output buffer would have to be initialized to the
          * actual background of the image.
          *
          * The fourth argument to png_image_finish_read is the 'row_stride' -
          * this is the number of components allocated for the image in each
          * row.  It has to be at least as big as the value returned by
          * PNG_IMAGE_ROW_STRIDE, but if you just allocate space for the
          * default, minimum, size using PNG_IMAGE_SIZE as above you can pass
          * zero.
          *
          * The final argument is a pointer to a buffer for the colormap;
          * colormaps have exactly the same format as a row of image pixels (so
          * you choose what format to make the colormap by setting
          * image.format).  A colormap is only returned if
          * PNG_FORMAT_FLAG_COLORMAP is also set in image.format, so in this
          * case NULL is passed as the final argument.  If you do want to force
          * all images into an index/color-mapped format then you can use:
          *
          *    PNG_IMAGE_COLORMAP_SIZE(image)
          *
          * to find the maximum size of the colormap in bytes.
          */
         if (buffer != NULL &&
            png_image_finish_read(&image, NULL/*background*/, buffer,
               0/*row_stride*/, NULL/*colormap*/))
         {
            /* Now write the image out to the second argument.  In the write
             * call 'convert_to_8bit' allows 16-bit data to be squashed down to
             * 8 bits; this isn't necessary here because the original read was
             * to the 8-bit format.
             */
            if (png_image_write_to_file(&image, argv[2], 0/*convert_to_8bit*/,
               buffer, 0/*row_stride*/, NULL/*colormap*/))
            {
               /* The image has been written successfully. */
               exit(0);
            }
         }

         else
         {
            /* Calling png_free_image is optional unless the simplified API was
             * not run to completion.  In this case if there wasn't enough
             * memory for 'buffer' we didn't complete the read, so we must free
             * the image:
             */
            if (buffer == NULL)
               png_free_image(&image);

            else
               free(buffer);
      }

      /* Something went wrong reading or writing the image.  libpng stores a
       * textual message in the 'png_image' structure:
       */
      fprintf(stderr, "pngtopng: error: %s\n", image.message);
      exit (1);
   }

   fprintf(stderr, "pngtopng: usage: pngtopng input-file output-file\n");
   exit(1);
}

/* That's it ;-)  Of course you probably want to do more with PNG files than
 * just converting them all to 32-bit RGBA PNG files; you can do that between
 * the call to png_image_finish_read and png_image_write_to_file.  You can also
 * ask for the image data to be presented in a number of different formats.  You
 * do this by simply changing the 'format' parameter set before allocating the
 * buffer.
 *
 * The format parameter consists of five flags that define various aspects of
 * the image, you can simply add these together to get the format or you can use
 * one of the predefined macros from png.h (as above):
 *
 * PNG_FORMAT_FLAG_COLOR: if set the image will have three color components per
 *    pixel (red, green and blue), if not set the image will just have one
 *    luminance (grayscale) component.
 *
 * PNG_FORMAT_FLAG_ALPHA: if set each pixel in the image will have an additional
 *    alpha value; a linear value that describes the degree the image pixel
 *    covers (overwrites) the contents of the existing pixel on the display.
 *
 * PNG_FORMAT_FLAG_LINEAR: if set the components of each pixel will be returned
 *    as a series of 16-bit linear values, if not set the components will be
 *    returned as a series of 8-bit values encoded according to the 'sRGB'
 *    standard.  The 8-bit format is the normal format for images intended for
 *    direct display, because almost all display devices do the inverse of the
 *    sRGB transformation to the data they receive.  The 16-bit format is more
 *    common for scientific data and image data that must be further processed;
 *    because it is linear simple math can be done on the component values.
 *    Regardless of the setting of this flag the alpha channel is always linear,
 *    although it will be 8 bits or 16 bits wide as specified by the flag.
 *
 * PNG_FORMAT_FLAG_BGR: if set the components of a color pixel will be returned
 *    in the order blue, then green, then red.  If not set the pixel components
 *    are in the order red, then green, then blue.
 *
 * PNG_FORMAT_FLAG_AFIRST: if set the alpha channel (if present) precedes the
 *    color or grayscale components.  If not set the alpha channel follows the
 *    components.
 *
 * You do not have to read directly from a file.  You can read from memory or,
 * on systems that support it, from a <stdio.h> FILE*.  This is controlled by
 * the particular png_image_read_from_ function you call at the start.  Likewise
 * on write you can write to a FILE* if your system supports it.  Check the
 * macro PNG_STDIO_SUPPORTED to see if stdio support has been included in your
 * libpng build.
 *
 * If you read 16-bit (PNG_FORMAT_FLAG_LINEAR) data you may need to write it in
 * the 8-bit format for display.  You do this by setting the convert_to_8bit
 * flag to 'true'.
 *
 * Don't repeatedly convert between the 8-bit and 16-bit forms.  There is
 * significant data loss when 16-bit data is converted to the 8-bit encoding and
 * the current libpng implementation of convertion to 16-bit is also
 * significantly lossy.  The latter will be fixed in the future, but the former
 * is unavoidable - the 8-bit format just doesn't have enough resolution.
 */

/* If your program needs more information from the PNG data it reads, or if you
 * need to do more complex transformations, or minimise transformations, on the
 * data you read, then you must use one of the several lower level libpng
 * interfaces.
 *
 * All these interfaces require that you do your own error handling - your
 * program must be able to arrange for control to return to your own code any
 * time libpng encounters a problem.  There are several ways to do this, but the
 * standard way is to use the ANSI-C (C90) <setjmp.h> interface to establish a
 * return point within your own code.  You must do this if you do not use the
 * simplified interface (above).
 *
 * The first step is to include the header files you need, including the libpng
 * header file.  Include any standard headers and feature test macros your
 * program requires before including png.h:
 */
#include <png.h>

 /* The png_jmpbuf() macro, used in error handling, became available in
  * libpng version 1.0.6.  If you want to be able to run your code with older
  * versions of libpng, you must define the macro yourself (but only if it
  * is not already defined by libpng!).
  */

#ifndef png_jmpbuf
#  define png_jmpbuf(png_ptr) ((png_ptr)->png_jmpbuf)
#endif

/* Check to see if a file is a PNG file using png_sig_cmp().  png_sig_cmp()
 * returns zero if the image is a PNG and nonzero if it isn't a PNG.
 *
 * The function check_if_png() shown here, but not used, returns nonzero (true)
 * if the file can be opened and is a PNG, 0 (false) otherwise.
 *
 * If this call is successful, and you are going to keep the file open,
 * you should call png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); once
 * you have created the png_ptr, so that libpng knows your application
 * has read that many bytes from the start of the file.  Make sure you
 * don't call png_set_sig_bytes() with more than 8 bytes read or give it
 * an incorrect number of bytes read, or you will either have read too
 * many bytes (your fault), or you are telling libpng to read the wrong
 * number of magic bytes (also your fault).
 *
 * Many applications already read the first 2 or 4 bytes from the start
 * of the image to determine the file type, so it would be easiest just
 * to pass the bytes to png_sig_cmp() or even skip that if you know
 * you have a PNG file, and call png_set_sig_bytes().
 */
#define PNG_BYTES_TO_CHECK 4
int check_if_png(char *file_name, FILE **fp)
{
   char buf[PNG_BYTES_TO_CHECK];

   /* Open the prospective PNG file. */
   if ((*fp = fopen(file_name, "rb")) == NULL)
      return 0;

   /* Read in some of the signature bytes */
   if (fread(buf, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK)
      return 0;

   /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature.
      Return nonzero (true) if they match */

   return(!png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK));
}