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