void png_load_from_memory(aasset_buffer_t& buf, raw_bitmap_t* out_bitmap) { //png header - 8 bytes if (png_sig_cmp(buf.data(), 0, 8)) { my_assert(false && "Couldn't load texture. It isn't png file."); return; } auto png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); my_assert(png_ptr && "Couldn't load texture. Png load error."); MAKE_GUARD(png_ptr, [](decltype(png_ptr) ptr) { png_destroy_read_struct(&ptr, (png_infopp)NULL, (png_infopp)NULL);}); auto info_ptr = png_create_info_struct(png_ptr); my_assert(info_ptr && "Couldn't load texture. Png load error."); auto info_deleter = [png_ptr](decltype(info_ptr) ptr) { png_destroy_info_struct(png_ptr, &ptr);}; MAKE_GUARD(info_ptr, info_deleter); // the code in this if statement gets called if libpng encounters an error if (setjmp((long*) png_jmpbuf(png_ptr))) { my_assert(false && "error from libpng"); return; } png_set_read_fn(png_ptr, &buf, read_from_aasset_buffer); // tell libpng we already read the signature png_set_sig_bytes(png_ptr, 8); buf.seek(8); png_read_info(png_ptr, info_ptr); png_uint_32 width = 0; png_uint_32 height = 0; int bitDepth = 0; int colorType = -1; auto res = png_get_IHDR(png_ptr, info_ptr, &width, &height, &bitDepth, &colorType, NULL, NULL, NULL); my_assert(res == 1); bool transparency = false; if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); transparency = true; } // Expands PNG with less than 8bits per channel to 8bits. if (bitDepth < 8) { png_set_packing(png_ptr); // Shrinks PNG with 16bits per color channel down to 8bits. } else if (bitDepth == 16) { png_set_strip_16(png_ptr); } uint32_t format = 0; switch (colorType) { case PNG_COLOR_TYPE_RGB: format = transparency ? GL_RGBA : GL_RGB; break; case PNG_COLOR_TYPE_RGBA: format = GL_RGBA; break; case PNG_COLOR_TYPE_PALETTE: { png_set_palette_to_rgb(png_ptr); format = transparency ? GL_RGBA : GL_RGB; break; } default: my_assert(false && "Png read error. Uknown color type"); return; } //apply transformations png_read_update_info(png_ptr, info_ptr); out_bitmap->init(width, height, format); auto row_size = png_get_rowbytes(png_ptr, info_ptr); my_assert(row_size > 0); my_assert(row_size == width * out_bitmap->bytes_per_pixel()); auto row_ptrs = new png_bytep[height]; MAKE_GUARD(row_ptrs, [](decltype(row_ptrs) ptr) { delete[] ptr;}); for (int32_t i = 0; i < height; ++i) { row_ptrs[height - (i + 1)] = out_bitmap->get_row(i); } png_read_image(png_ptr, row_ptrs); }
TypedImage LoadPng(const std::string& filename) { #ifdef HAVE_PNG FILE *in = fopen(filename.c_str(), "rb"); if( in ) { //check the header const size_t nBytes = 8; png_byte header[nBytes]; size_t nread = fread(header, 1, nBytes, in); int nIsPNG = png_sig_cmp(header, 0, nread); if ( nIsPNG != 0 ) { throw std::runtime_error( filename + " is not a PNG file" ); } //set up initial png structs png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, &PngWarningsCallback); if (!png_ptr) { throw std::runtime_error( "PNG Init error 1" ); } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); throw std::runtime_error( "PNG Init error 2" ); } png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); throw std::runtime_error( "PNG Init error 3" ); } png_init_io(png_ptr, in); png_set_sig_bytes(png_ptr, nBytes); //read the file png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); if( png_get_bit_depth(png_ptr, info_ptr) == 1) { //Unpack bools to bytes to ease loading. png_set_packing(png_ptr); } else if( png_get_bit_depth(png_ptr, info_ptr) < 8) { //Expand nonbool colour depths up to 8bpp png_set_expand_gray_1_2_4_to_8(png_ptr); } //Get rid of palette, by transforming it to RGB if(png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png_ptr); } if( png_get_interlace_type(png_ptr,info_ptr) != PNG_INTERLACE_NONE) { throw std::runtime_error( "Interlace not yet supported" ); } const size_t w = png_get_image_width(png_ptr,info_ptr); const size_t h = png_get_image_height(png_ptr,info_ptr); const size_t pitch = png_get_rowbytes(png_ptr, info_ptr); TypedImage img; img.Alloc(w, h, PngFormat(png_ptr, info_ptr), pitch); png_bytepp rows = png_get_rows(png_ptr, info_ptr); for( unsigned int r = 0; r < h; r++) { memcpy( img.ptr + pitch*r, rows[r], pitch ); } png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(in); return img; } throw std::runtime_error("Unable to load PNG file, '" + filename + "'"); #else throw std::runtime_error("PNG Support not enabled. Please rebuild Pangolin."); #endif }
void png::load(const std::string& file_name) { // unfortunately, we need to break down to the C-code level here, since // libpng is written in C itself // we need to open the file in binary mode FILE* fp = fopen(file_name.c_str(), "rb"); if (!fp) { throw std::runtime_error{"failed to open " + file_name}; } // read in the header (max size of 8), use it to validate this as a png file png_byte header[8]; fread(header, 1, 8, fp); if (png_sig_cmp(header, 0, 8)) { fclose(fp); throw std::runtime_error{file_name + " is not a valid png file"}; } // set up libpng structs for reading info png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); if (!png_ptr) { fclose(fp); throw std::runtime_error{"Failed to create libpng read struct"}; } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, nullptr, nullptr); fclose(fp); throw std::runtime_error{"Failed to create libpng info struct"}; } // set error handling to not abort the entire program if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); fclose(fp); throw std::runtime_error{"Error reading png metadata"}; } // initialize png reading png_init_io(png_ptr, fp); // let it know we've already read the first 8 bytes png_set_sig_bytes(png_ptr, 8); // read in the basic image info png_read_info(png_ptr, info_ptr); // convert to 8 bits png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr); if (bit_depth == 16) png_set_strip_16(png_ptr); // verify this is in RGBA format, and if not, convert it to RGBA png_byte color_type = png_get_color_type(png_ptr, info_ptr); if (color_type != PNG_COLOR_TYPE_RGBA && color_type != PNG_COLOR_TYPE_RGB) { if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { if (bit_depth < 8) png_set_expand(png_ptr); png_set_gray_to_rgb(png_ptr); } if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); } // convert tRNS to alpha channel if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); size_t width = png_get_image_width(png_ptr, info_ptr); size_t height = png_get_image_height(png_ptr, info_ptr); rgba_pixel* newpix = nullptr; png_byte* row = nullptr; png_read_update_info(png_ptr, info_ptr); // begin reading in the image if (setjmp(png_jmpbuf(png_ptr))) { delete[] newpix; delete[] row; png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); fclose(fp); throw std::runtime_error{"Error reading image with libpng"}; } int bpr = png_get_rowbytes(png_ptr, info_ptr); // number of bytes in a row // initialize our image storage newpix = new rgba_pixel[height * width]; row = new png_byte[bpr]; int numchannels = png_get_channels(png_ptr, info_ptr); for (size_t y = 0; y < height; y++) { png_read_row(png_ptr, row, nullptr); png_byte* pix = row; for (size_t x = 0; x < width; x++) { rgba_pixel& px = newpix[width * y + x]; if (numchannels == 1 || numchannels == 2) { // monochrome unsigned char color = (unsigned char)*pix++; px.red = color; px.green = color; px.blue = color; if (numchannels == 2) px.alpha = (unsigned char)*pix++; else px.alpha = 255; } else if (numchannels == 3 || numchannels == 4) { px.red = (unsigned char)*pix++; px.green = (unsigned char)*pix++; px.blue = (unsigned char)*pix++; if (numchannels == 4) px.alpha = (unsigned char)*pix++; else px.alpha = 255; } } } // replace image delete[] pixels_; pixels_ = newpix; width_ = width; height_ = height; // cleanup delete[] row; png_read_end(png_ptr, nullptr); png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); fclose(fp); }
Py::Object _image_module::readpng(const Py::Tuple& args) { args.verify_length(1); std::string fname = Py::String(args[0]); png_byte header[8]; // 8 is the maximum size that can be checked FILE *fp = fopen(fname.c_str(), "rb"); if (!fp) throw Py::RuntimeError("_image_module::readpng could not open PNG file for reading"); fread(header, 1, 8, fp); if (png_sig_cmp(header, 0, 8)) throw Py::RuntimeError("_image_module::readpng: file not recognized as a PNG file"); /* initialize stuff */ png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) throw Py::RuntimeError("_image_module::readpng: png_create_read_struct failed"); png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) throw Py::RuntimeError("_image_module::readpng: png_create_info_struct failed"); if (setjmp(png_jmpbuf(png_ptr))) throw Py::RuntimeError("_image_module::readpng: error during init_io"); png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); png_uint_32 width = info_ptr->width; png_uint_32 height = info_ptr->height; // convert misc color types to rgb for simplicity if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY || info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); int bit_depth = info_ptr->bit_depth; if (bit_depth == 16) png_set_strip_16(png_ptr); png_set_interlace_handling(png_ptr); png_read_update_info(png_ptr, info_ptr); bool rgba = info_ptr->color_type == PNG_COLOR_TYPE_RGBA; if ( (info_ptr->color_type != PNG_COLOR_TYPE_RGB) && !rgba) { std::cerr << "Found color type " << (int)info_ptr->color_type << std::endl; throw Py::RuntimeError("_image_module::readpng: cannot handle color_type"); } /* read file */ if (setjmp(png_jmpbuf(png_ptr))) throw Py::RuntimeError("_image_module::readpng: error during read_image"); png_bytep row_pointers[height]; for (png_uint_32 row = 0; row < height; row++) row_pointers[row] = new png_byte[png_get_rowbytes(png_ptr,info_ptr)]; png_read_image(png_ptr, row_pointers); int dimensions[3]; dimensions[0] = height; //numrows dimensions[1] = width; //numcols dimensions[2] = 4; PyArrayObject *A = (PyArrayObject *) PyArray_FromDims(3, dimensions, PyArray_FLOAT); for (png_uint_32 y = 0; y < height; y++) { png_byte* row = row_pointers[y]; for (png_uint_32 x = 0; x < width; x++) { png_byte* ptr = (rgba) ? &(row[x*4]) : &(row[x*3]); size_t offset = y*A->strides[0] + x*A->strides[1]; //if ((y<10)&&(x==10)) std::cout << "r = " << ptr[0] << " " << ptr[0]/255.0 << std::endl; *(float*)(A->data + offset + 0*A->strides[2]) = ptr[0]/255.0; *(float*)(A->data + offset + 1*A->strides[2]) = ptr[1]/255.0; *(float*)(A->data + offset + 2*A->strides[2]) = ptr[2]/255.0; *(float*)(A->data + offset + 3*A->strides[2]) = rgba ? ptr[3]/255.0 : 1.0; } } //free the png memory png_read_end(png_ptr, info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); fclose(fp); for (png_uint_32 row = 0; row < height; row++) delete [] row_pointers[row]; return Py::asObject((PyObject*)A); }
uint32_t * load_png(struct load_image *args) { png_structp png; png_infop info; int color_type; void *rgb_data; png_bytep *pointers; int i; png_uint_32 w,h; int depth; struct png_context context; png_uint_32 stride; if(png_sig_cmp(args->data, 0, 8)) { DEBUG_PUTS("not png"); return 0; } png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); info = png_create_info_struct(png); context.data = args->data; context.len = args->length; context.pos = 8; png_set_read_fn(png, &context, &read_callback); png_set_sig_bytes(png, 8); png_read_info(png, info); png_get_IHDR(png, info, &w, &h, &depth, &color_type, 0, 0, 0); DEBUG_PRINTF("w: %d\n", w); DEBUG_PRINTF("h: %d\n", h); switch (color_type) { case PNG_COLOR_TYPE_PALETTE: DEBUG_PUTS("pallete"); png_set_palette_to_rgb(png); break; case PNG_COLOR_TYPE_RGB_ALPHA: DEBUG_PUTS("rgba"); break; default: rgb_data = 0; goto out; }; png_set_filler(png, 0xff, PNG_FILLER_AFTER); pointers = (png_bytep *) malloc(h * sizeof(*pointers)); if (!pointers) { rgb_data = 0; goto out; } stride = png_get_rowbytes(png, info); rgb_data = malloc(stride * 4 * h); if (!rgb_data) { rgb_data = 0; goto out; } for (i = 0; i < h; i++) pointers[i] = rgb_data + w * 4 * i; png_read_image(png, pointers); *args->w = w; *args->h = h; out: png_destroy_read_struct(&png, &info, 0); return rgb_data; }
/* return -2 if file cannot be opened * return -1 if file data is corrupted * return 0 if file format is not valid * return 1 if file successfully loaded */ int read_image_file_png (const char* filename, ImageData *imagedata) { int i, width, height, BPP; unsigned char* pixelArray = NULL; png_bytep* row_pointers; png_byte color_type; png_infop info_ptr; png_structp png_ptr; png_byte header[8]; FILE *fp; /* open file for reading-bytes */ fp = fopen (filename, "rb"); if(!fp) ABORT("Read Error: file '%s' could not be opened for reading.", filename, -2) /* Test if file type is png */ /* 8 bytes is the maximum size that can be checked */ if(fread(header, 1, 8, fp) != 8 || png_sig_cmp(header, 0, 8)) ABORT("Read Error: file '%s' is not recognized as a PNG file.", filename, 0) /* initialise - prepare for parsing */ png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(!png_ptr) ABORT("Read Error: file '%s' is corrupted. png_create_read_struct failed.", filename, -1) info_ptr = png_create_info_struct (png_ptr); if(!info_ptr) ABORT("Read Error: file '%s' is corrupted. png_create_info_struct failed.", filename, -1) if(setjmp(png_jmpbuf(png_ptr))) ABORT("Read Error: file '%s' is corrupted. setjmp(png_jmpbuf(png_ptr)) failed.", filename, -1) png_init_io (png_ptr, fp); png_set_sig_bytes (png_ptr, 8); png_read_info (png_ptr, info_ptr); /* ensure 3-byte colour depth */ color_type = png_get_color_type (png_ptr, info_ptr); if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb (png_ptr); /* ensure Alpha channel present */ png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER); /*png_get_bit_depth(png_ptr, info_ptr) = 8... why so? */ height = png_get_image_height(png_ptr, info_ptr); width = png_get_image_width (png_ptr, info_ptr); BPP = 4; /* ensure BGRA and not ARGB */ png_set_bgr(png_ptr); /* make libpng to handle expansion of the interlaced image */ png_set_interlace_handling (png_ptr); /* reflect requested transformations */ png_read_update_info (png_ptr, info_ptr); /* prepare to read file */ if(setjmp(png_jmpbuf(png_ptr))) ABORT("Read Error: file '%s' is corrupted. setjmp(png_jmpbuf(png_ptr)) failed.", filename, -1) /* allocate memory needed to hold the image */ pixelArray = (unsigned char*) malloc (height*width*BPP); row_pointers = (png_bytep*) malloc (height * sizeof(*row_pointers)); for(i = 0; i < height; i++) row_pointers[i] = (png_bytep) (pixelArray + i*width*BPP); /* finally... read image file... */ png_read_image(png_ptr, row_pointers); /* free resources */ free(row_pointers); fclose(fp); /* success */ imagedata->pixelArray = pixelArray; imagedata->height = height; imagedata->width = width; imagedata->bpp = BPP*8; return 1; }
int res_create_surface_png(const char* name, gr_surface* pSurface) { GGLSurface* surface = NULL; int result = 0; unsigned char header[8]; png_structp png_ptr = NULL; png_infop info_ptr = NULL; FILE* fp = fopen(name, "rb"); if (fp == NULL) { char resPath[256]; snprintf(resPath, sizeof(resPath)-1, "/res/images/%s.png", name); resPath[sizeof(resPath)-1] = '\0'; fp = fopen(resPath, "rb"); if (fp == NULL) { result = -1; goto exit; } } size_t bytesRead = fread(header, 1, sizeof(header), fp); if (bytesRead != sizeof(header)) { result = -2; goto exit; } if (png_sig_cmp(header, 0, sizeof(header))) { result = -3; goto exit; } png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { result = -4; goto exit; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { result = -5; goto exit; } if (setjmp(png_jmpbuf(png_ptr))) { result = -6; goto exit; } png_set_packing(png_ptr); png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, sizeof(header)); png_read_info(png_ptr, info_ptr); size_t width = info_ptr->width; size_t height = info_ptr->height; size_t stride = 4 * width; size_t pixelSize = stride * height; int color_type = info_ptr->color_type; int bit_depth = info_ptr->bit_depth; int channels = info_ptr->channels; if (!(bit_depth == 8 && ((channels == 3 && color_type == PNG_COLOR_TYPE_RGB) || (channels == 4 && color_type == PNG_COLOR_TYPE_RGBA) || (channels == 1 && color_type == PNG_COLOR_TYPE_PALETTE)))) { return -7; goto exit; } surface = malloc(sizeof(GGLSurface) + pixelSize); if (surface == NULL) { result = -8; goto exit; } unsigned char* pData = (unsigned char*) (surface + 1); surface->version = sizeof(GGLSurface); surface->width = width; surface->height = height; surface->stride = width; /* Yes, pixels, not bytes */ surface->data = pData; surface->format = (channels == 3) ? GGL_PIXEL_FORMAT_RGBX_8888 : GGL_PIXEL_FORMAT_RGBA_8888; if (color_type == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png_ptr); } int x; size_t y; if (channels == 3) { for (y = 0; y < height; ++y) { unsigned char* pRow = pData + y * stride; png_read_row(png_ptr, pRow, NULL); for(x = width - 1; x >= 0; x--) { int sx = x * 3; int dx = x * 4; unsigned char r = pRow[sx]; unsigned char g = pRow[sx + 1]; unsigned char b = pRow[sx + 2]; unsigned char a = 0xff; pRow[dx ] = r; // r pRow[dx + 1] = g; // g pRow[dx + 2] = b; // b pRow[dx + 3] = a; } } } else { for (y = 0; y < height; ++y) { unsigned char* pRow = pData + y * stride; png_read_row(png_ptr, pRow, NULL); #ifdef PIXELS_BGRA if (channels == 4) { for (x = width - 1; x >= 0; x--) { int dx = x * 4; unsigned char r = pRow[dx]; pRow[dx] = pRow[dx + 2]; pRow[dx + 2] = r; } } #endif } } *pSurface = (gr_surface) surface; exit: png_destroy_read_struct(&png_ptr, &info_ptr, NULL); if (fp != NULL) { fclose(fp); } if (result < 0) { if (surface) { free(surface); } } return result; }
void* replaceBootImage(AbstractFile* imageWrapper, const unsigned int* key, const unsigned int* iv, AbstractFile* png, size_t *fileSize) { AbstractFile* imageFile; unsigned char header[8]; InfoIBootIM* info; png_uint_32 i; png_bytepp row_pointers; uint8_t* imageBuffer; void* buffer; png->read(png, header, 8); if(png_sig_cmp(header, 0, 8) != 0) { XLOG(0, "error: not a valid png file\n"); return NULL; } png->seek(png, 0); png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, pngError, pngWarn); if (!png_ptr) { return NULL; } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); return NULL; } png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return NULL; } if (setjmp(png_jmpbuf(png_ptr))) { XLOG(0, "error reading png\n"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); free(buffer); return NULL; } png_set_read_fn(png_ptr, png, pngRead); png_read_info(png_ptr, info_ptr); if(info_ptr->bit_depth > 8) { XLOG(0, "warning: bit depth per channel is greater than 8 (%d). Attempting to strip, but image quality will be degraded.\n", info_ptr->bit_depth); } if(info_ptr->color_type == PNG_COLOR_TYPE_GRAY || info_ptr->color_type == PNG_COLOR_TYPE_RGB) { XLOG(0, "notice: attempting to add dummy transparency channel\n"); } if(info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { XLOG(0, "notice: attempting to expand palette into full rgb\n"); } png_set_expand(png_ptr); png_set_strip_16(png_ptr); png_set_bgr(png_ptr); png_set_add_alpha(png_ptr, 0x0, PNG_FILLER_AFTER); png_set_invert_alpha(png_ptr); png_read_update_info(png_ptr, info_ptr); if(info_ptr->width > 320 || info_ptr->height > 480) { XLOG(0, "error: dimensions out of range, must be within 320x480, not %lux%lu\n", info_ptr->width, info_ptr->height); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return NULL; } if(info_ptr->bit_depth != 8) { XLOG(0, "error: bit depth per channel must be 8 not %d!\n", info_ptr->bit_depth); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return NULL; } if(info_ptr->color_type != PNG_COLOR_TYPE_GRAY_ALPHA && info_ptr->color_type != PNG_COLOR_TYPE_RGB_ALPHA) { XLOG(0, "error: incorrect color type, must be greyscale with alpha, or rgb with alpha\n"); if(info_ptr->color_type == PNG_COLOR_TYPE_GRAY || info_ptr->color_type == PNG_COLOR_TYPE_RGB) { XLOG(0, "It appears you're missing an alpha channel. Add transparency to your image\n"); } if(info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { XLOG(0, "This PNG is saved with the palette color type rather than ARGB.\n"); } png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return NULL; } row_pointers = (png_bytepp) malloc(sizeof(png_bytep) * info_ptr->height); imageBuffer = malloc(info_ptr->height * info_ptr->rowbytes); for(i = 0; i < info_ptr->height; i++) { row_pointers[i] = imageBuffer + (info_ptr->rowbytes * i); } png_read_image(png_ptr, row_pointers); png_read_end(png_ptr, end_info); buffer = malloc(1); *fileSize = 0; if(key != NULL) { imageFile = duplicateAbstractFile2(imageWrapper, createAbstractFileFromMemoryFile((void**)&buffer, fileSize), key, iv, NULL); } else { imageFile = duplicateAbstractFile(imageWrapper, createAbstractFileFromMemoryFile((void**)&buffer, fileSize)); } info = (InfoIBootIM*) (imageFile->data); info->header.width = (uint16_t) info_ptr->width; info->header.height = (uint16_t) info_ptr->height; if(info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { info->header.format = IBOOTIM_GREY; } else { info->header.format = IBOOTIM_ARGB; } imageFile->write(imageFile, imageBuffer, info_ptr->height * info_ptr->rowbytes); imageFile->close(imageFile); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); png->close(png); free(row_pointers); free(imageBuffer); return buffer; }
// load in the image data IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const { #ifdef _IRR_COMPILE_WITH_LIBPNG_ if (!file) return 0; video::IImage* image = 0; //Used to point to image rows u8** RowPointers = 0; png_byte buffer[8]; // Read the first few bytes of the PNG file if( file->read(buffer, 8) != 8 ) { os::Printer::log("LOAD PNG: can't read file\n", file->getFileName(), ELL_ERROR); return 0; } // Check if it really is a PNG file if( png_sig_cmp(buffer, 0, 8) ) { os::Printer::log("LOAD PNG: not really a png\n", file->getFileName(), ELL_ERROR); return 0; } // Allocate the png read struct png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, (png_error_ptr)png_cpexcept_error, NULL); if (!png_ptr) { os::Printer::log("LOAD PNG: Internal PNG create read struct failure\n", file->getFileName(), ELL_ERROR); return 0; } // Allocate the png info struct png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { os::Printer::log("LOAD PNG: Internal PNG create info struct failure\n", file->getFileName(), ELL_ERROR); png_destroy_read_struct(&png_ptr, NULL, NULL); return 0; } // for proper error handling if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); if (RowPointers) delete [] RowPointers; return 0; } // changed by zola so we don't need to have public FILE pointers png_set_read_fn(png_ptr, file, user_read_data_fcn); png_set_sig_bytes(png_ptr, 8); // Tell png that we read the signature png_read_info(png_ptr, info_ptr); // Read the info section of the png file u32 Width; u32 Height; s32 BitDepth; s32 ColorType; { // Use temporary variables to avoid passing casted pointers png_uint_32 w,h; // Extract info png_get_IHDR(png_ptr, info_ptr, &w, &h, &BitDepth, &ColorType, NULL, NULL, NULL); Width=w; Height=h; } // Convert palette color to true color if (ColorType==PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); // Convert low bit colors to 8 bit colors if (BitDepth < 8) { if (ColorType==PNG_COLOR_TYPE_GRAY || ColorType==PNG_COLOR_TYPE_GRAY_ALPHA) #if (PNG_LIBPNG_VER_MAJOR > 1) || (PNG_LIBPNG_VER_MINOR > 3) png_set_expand_gray_1_2_4_to_8(png_ptr); #else png_set_gray_1_2_4_to_8(png_ptr); #endif else png_set_packing(png_ptr); }
GLuint png_texture_load(const char * file_name, int width, int height) { png_uint_32 temp_width, temp_height; int bit_depth, color_type, i; png_byte header[8]; GLuint texture; FILE *fp = fopen(file_name, "rb"); if (fp == 0) { perror(file_name); return 0; } // read the header fread(header, 1, 8, fp); if (png_sig_cmp(header, 0, 8)) { fprintf(stderr, "error: %s is not a PNG.\n", file_name); fclose(fp); return 0; } png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { fprintf(stderr, "error: png_create_read_struct returned 0.\n"); fclose(fp); return 0; } // create png info struct info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { fprintf(stderr, "error: png_create_info_struct returned 0.\n"); png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); fclose(fp); return 0; } // create png info struct end_info = png_create_info_struct(png_ptr); if (!end_info) { fprintf(stderr, "error: png_create_info_struct returned 0.\n"); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); fclose(fp); return 0; } // the code in this if statement gets called if libpng encounters an error if (setjmp(png_jmpbuf(png_ptr))) { fprintf(stderr, "error from libpng\n"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fp); return 0; } // init png reading png_init_io(png_ptr, fp); // let libpng know you already read the first 8 bytes png_set_sig_bytes(png_ptr, 8); // read all the info up to the image data png_read_info(png_ptr, info_ptr); // variables to pass to get info // get info about png png_get_IHDR(png_ptr, info_ptr, &temp_width, &temp_height, &bit_depth, &color_type, NULL, NULL, NULL); #if 0 if (width ) { width = temp_width; } if (height ) { height = temp_height; } #endif // Update the png info struct. png_read_update_info(png_ptr, info_ptr); // Row size in bytes. rowbytes = png_get_rowbytes(png_ptr, info_ptr); // glTexImage2d requires rows to be 4-byte aligned rowbytes += 3 - ((rowbytes-1) % 4); // Allocate the image_data as a big block, to be given to opengl image_data = (png_byte*)malloc(rowbytes * temp_height * sizeof(png_byte)+15); if (image_data == NULL) { fprintf(stderr, "error: could not allocate memory for PNG image data\n"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fp); return 0; } // row_pointers is for pointing to image_data for reading the png with libpng row_pointers = (png_bytep*)malloc(temp_height * sizeof(png_bytep)); if (row_pointers == NULL) { fprintf(stderr, "error: could not allocate memory for PNG row pointers\n"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); free(image_data); fclose(fp); return 0; } // set the individual row_pointers to point at the correct offsets of image_data for (i = 0; i < temp_height; i++) { row_pointers[temp_height - 1 - i] = image_data + i * rowbytes; } // read the png into image_data through row_pointers png_read_image(png_ptr, row_pointers); // Generate the OpenGL texture object glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, temp_width, temp_height, 0, GL_RGB, GL_UNSIGNED_BYTE, image_data); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // clean up png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); free(image_data); free(row_pointers); fclose(fp); return texture; }
GLuint read_png_file(char* file_name) { unsigned char header[8]; // 8 is the maximum size that can be checked /* open file and test for it being a png */ FILE *fp = fopen(file_name, "rb"); if (!fp) abort_("[read_png_file] File %s could not be opened for reading", file_name); fread(header, 1, 8, fp); if (png_sig_cmp(header, 0, 8)) abort_("[read_png_file] File %s is not recognized as a PNG file", file_name); /* initialize stuff */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) abort_("[read_png_file] png_create_read_struct failed"); info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) abort_("[read_png_file] png_create_info_struct failed"); end_info = png_create_info_struct(png_ptr); if (!end_info) abort_("[read_png_file] png_create_end_info_struct failed"); if (setjmp(png_jmpbuf(png_ptr))) abort_("[read_png_file] Error during init_io"); png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); width = png_get_image_width(png_ptr, info_ptr); height = png_get_image_height(png_ptr, info_ptr); color_type = png_get_color_type(png_ptr, info_ptr); bit_depth = png_get_bit_depth(png_ptr, info_ptr); number_of_passes = png_set_interlace_handling(png_ptr); png_read_update_info(png_ptr, info_ptr); // Row size in bytes. rowbytes = png_get_rowbytes(png_ptr, info_ptr); // glTexImage2d requires rows to be 4-byte aligned rowbytes += 3 - ((rowbytes-1) % 4); // Allocate the image_data as a big block, to be given to opengl image_data = (png_byte*)malloc(rowbytes * height * sizeof(png_byte)+15); if (image_data == NULL) abort_("[read_png_file] png_create_end_info_struct failed"); if (setjmp(png_jmpbuf(png_ptr))) abort_("[read_png_file] Error during read_image"); row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height); if (bit_depth == 16) rowbytes = width*8; else rowbytes = width*4; for (y=0; y<height; y++) row_pointers[y] = (png_byte*) malloc(rowbytes); png_read_image(png_ptr, row_pointers); glGenTextures(1, &Texture); glBindTexture(GL_TEXTURE_2D, Texture); glTexImage2D(GL_TEXTURE_2D,0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*) image_data ); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // clean up png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); free(image_data); free(row_pointers); fclose(fp); return Texture; }
ImageNode *LoadPNGImage(const char *fileName) { static ImageNode *result; static FILE *fd; static unsigned char **rows; static png_structp pngData; static png_infop pngInfo; static png_infop pngEndInfo; unsigned char header[8]; unsigned long rowBytes; int bitDepth, colorType; unsigned int x, y; png_uint_32 width; png_uint_32 height; Assert(fileName); result = NULL; fd = NULL; rows = NULL; pngData = NULL; pngInfo = NULL; pngEndInfo = NULL; fd = fopen(fileName, "rb"); if(!fd) { return NULL; } x = fread(header, 1, sizeof(header), fd); if(x != sizeof(header) || png_sig_cmp(header, 0, sizeof(header))) { fclose(fd); return NULL; } pngData = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(JUNLIKELY(!pngData)) { fclose(fd); Warning(_("could not create read struct for PNG image: %s"), fileName); return NULL; } if(JUNLIKELY(setjmp(png_jmpbuf(pngData)))) { png_destroy_read_struct(&pngData, &pngInfo, &pngEndInfo); if(fd) { fclose(fd); } if(rows) { ReleaseStack(rows); } DestroyImage(result); Warning(_("error reading PNG image: %s"), fileName); return NULL; } pngInfo = png_create_info_struct(pngData); if(JUNLIKELY(!pngInfo)) { png_destroy_read_struct(&pngData, NULL, NULL); fclose(fd); Warning(_("could not create info struct for PNG image: %s"), fileName); return NULL; } pngEndInfo = png_create_info_struct(pngData); if(JUNLIKELY(!pngEndInfo)) { png_destroy_read_struct(&pngData, &pngInfo, NULL); fclose(fd); Warning("could not create end info struct for PNG image: %s", fileName); return NULL; } png_init_io(pngData, fd); png_set_sig_bytes(pngData, sizeof(header)); png_read_info(pngData, pngInfo); png_get_IHDR(pngData, pngInfo, &width, &height, &bitDepth, &colorType, NULL, NULL, NULL); result = CreateImage(width, height, 0); png_set_expand(pngData); if(bitDepth == 16) { png_set_strip_16(pngData); } else if(bitDepth < 8) { png_set_packing(pngData); } png_set_swap_alpha(pngData); png_set_filler(pngData, 0xFF, PNG_FILLER_BEFORE); if(colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb(pngData); } png_read_update_info(pngData, pngInfo); rowBytes = png_get_rowbytes(pngData, pngInfo); rows = AllocateStack(result->height * sizeof(result->data)); y = 0; for(x = 0; x < result->height; x++) { rows[x] = &result->data[y]; y += rowBytes; } png_read_image(pngData, rows); png_read_end(pngData, pngInfo); png_destroy_read_struct(&pngData, &pngInfo, &pngEndInfo); fclose(fd); ReleaseStack(rows); rows = NULL; return result; }
static void read_png_file_low(const char* file_name, png_image_data_t *png_image_data) { png_structp png_ptr; int number_of_passes; char header[8]; // 8 is the maximum size that can be checked int y; /* open file and test for it being a png */ FILE *fp = fopen(file_name, "rb"); if (!fp) abort_("[read_png_file] File %s could not be opened for reading", file_name); fread(header, 1, 8, fp); if (png_sig_cmp(header, 0, 8)) abort_("[read_png_file] File %s is not recognized as a PNG file", file_name); /* initialize stuff */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) abort_("[read_png_file] png_create_read_struct failed"); png_image_data->info_ptr = png_create_info_struct(png_ptr); if (!png_image_data->info_ptr) abort_("[read_png_file] png_create_info_struct failed"); if (setjmp(png_jmpbuf(png_ptr))) abort_("[read_png_file] Error during init_io"); png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, 8); /* 8 == sig_read ? */ png_read_info(png_ptr, png_image_data->info_ptr); /* set transformations */ /* if ((png_image_data->info_ptr->color_type & PNG_COLOR_TYPE_RGB) == 0) transforms |= PNG_TRANSFORM_BGR; */ if (png_get_valid(png_ptr, png_image_data->info_ptr, PNG_INFO_sBIT)) { png_color_8p sig_bit; png_get_sBIT(png_ptr, png_image_data->info_ptr, &sig_bit); printf("sig_bit: %d\n", sig_bit); png_set_shift(png_ptr, sig_bit); } /* TODO DFG: is this needed? */ number_of_passes = png_set_interlace_handling(png_ptr); png_read_update_info(png_ptr, png_image_data->info_ptr); /* read file */ if (setjmp(png_jmpbuf(png_ptr))) abort_("[read_png_file] Error during read_image"); #if 1 png_image_data->row_pointers = (png_bytep*) qemu_malloc(sizeof(png_bytep) * png_image_data->info_ptr->height); for (y=0; y < png_image_data->info_ptr->height; y++) png_image_data->row_pointers[y] = (png_byte*) qemu_malloc(png_image_data->info_ptr->rowbytes); png_read_image(png_ptr, png_image_data->row_pointers); #endif /* DFG TODO: Cleanup */ /* png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); */ fclose(fp); }
static void read_png_file(const char* file_name, png_image_data_t *png_image_data, int max_width, int max_height) { png_structp png_ptr; png_infop info_ptr; png_bytep *row_pointers; char header[8]; // 8 is the maximum size that can be checked int y; char* dest; /* open file and test for it being a png */ FILE *fp = fopen(file_name, "rb"); if (!fp) abort_("[read_png_file] File %s could not be opened for reading", file_name); fread(header, 1, 8, fp); if (png_sig_cmp(header, 0, 8)) abort_("[read_png_file] File %s is not recognized as a PNG file", file_name); /* initialize stuff */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) abort_("[read_png_file] png_create_read_struct failed"); if (max_width > 0 && max_height > 0) png_set_user_limits(png_ptr, max_width, max_height); info_ptr = png_create_info_struct(png_ptr); if (setjmp(png_jmpbuf(png_ptr))) abort_("[read_png_file] Error during init_io"); png_init_io(png_ptr, fp); if (setjmp(png_jmpbuf(png_ptr))) abort_("[read_png_file] Error during init_io"); png_set_sig_bytes(png_ptr, sizeof(header)); if (setjmp(png_jmpbuf(png_ptr))) abort_("[read_png_file] Error during init_io"); png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_ALPHA, png_voidp_NULL); if (setjmp(png_jmpbuf(png_ptr))) abort_("[read_png_file] Error during init_io"); row_pointers = png_get_rows(png_ptr, info_ptr); png_image_data->height = png_get_image_height(png_ptr, info_ptr); png_image_data->width = png_get_image_width(png_ptr, info_ptr); png_image_data->image4c = (void*)qemu_malloc(png_image_data->width * png_image_data->height * 4); dest = (char*)png_image_data->image4c; /* transform this from 3 channels to a (fake for now) 4 channels */ for (y=0; y < png_image_data->height; y++) { char* src = row_pointers[y]; int x; for (x = 0; x < png_image_data->width; x++) { *dest = *src; dest++, src++; *dest = *src; dest++, src++; *dest = *src; dest++, src++; *dest = 0; dest++; /* alpha channel ignored */ } } png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); fclose(fp); }
/* Read the information before the actual image data. This has been * changed in v0.90 to allow reading a file that already has the magic * bytes read from the stream. You can tell libpng how many bytes have * been read from the beginning of the stream (up to the maximum of 8) * via png_set_sig_bytes(), and we will only check the remaining bytes * here. The application can then have access to the signature bytes we * read if it is determined that this isn't a valid PNG file. */ void PNGAPI png_read_info(png_structp png_ptr, png_infop info_ptr) { png_debug(1, "in png_read_info\n"); /* save jump buffer and error functions */ /* If we haven't checked all of the PNG signature bytes, do so now. */ if (png_ptr->sig_bytes < 8) { png_size_t num_checked = png_ptr->sig_bytes, num_to_check = 8 - num_checked; png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check); png_ptr->sig_bytes = 8; if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) { if (num_checked < 4 && png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) png_error(png_ptr, "Not a PNG file"); else png_error(png_ptr, "PNG file corrupted by ASCII conversion"); } if (num_checked < 3) png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; } for(;;) { #ifdef PNG_USE_LOCAL_ARRAYS PNG_IHDR; PNG_IDAT; PNG_IEND; PNG_PLTE; #if defined(PNG_READ_bKGD_SUPPORTED) PNG_bKGD; #endif #if defined(PNG_READ_cHRM_SUPPORTED) PNG_cHRM; #endif #if defined(PNG_READ_gAMA_SUPPORTED) PNG_gAMA; #endif #if defined(PNG_READ_hIST_SUPPORTED) PNG_hIST; #endif #if defined(PNG_READ_iCCP_SUPPORTED) PNG_iCCP; #endif #if defined(PNG_READ_iTXt_SUPPORTED) PNG_iTXt; #endif #if defined(PNG_READ_oFFs_SUPPORTED) PNG_oFFs; #endif #if defined(PNG_READ_pCAL_SUPPORTED) PNG_pCAL; #endif #if defined(PNG_READ_pHYs_SUPPORTED) PNG_pHYs; #endif #if defined(PNG_READ_sBIT_SUPPORTED) PNG_sBIT; #endif #if defined(PNG_READ_sCAL_SUPPORTED) PNG_sCAL; #endif #if defined(PNG_READ_sPLT_SUPPORTED) PNG_sPLT; #endif #if defined(PNG_READ_sRGB_SUPPORTED) PNG_sRGB; #endif #if defined(PNG_READ_tEXt_SUPPORTED) PNG_tEXt; #endif #if defined(PNG_READ_tIME_SUPPORTED) PNG_tIME; #endif #if defined(PNG_READ_tRNS_SUPPORTED) PNG_tRNS; #endif #if defined(PNG_READ_zTXt_SUPPORTED) PNG_zTXt; #endif #endif /* PNG_GLOBAL_ARRAYS */ png_byte chunk_length[4]; png_uint_32 length; png_read_data(png_ptr, chunk_length, 4); length = png_get_uint_32(chunk_length); png_reset_crc(png_ptr); png_crc_read(png_ptr, png_ptr->chunk_name, 4); png_debug2(0, "Reading %s chunk, length=%lu.\n", png_ptr->chunk_name, length); /* This should be a binary subdivision search or a hash for * matching the chunk name rather than a linear search. */ if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) png_handle_IHDR(png_ptr, info_ptr, length); else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) png_handle_IEND(png_ptr, info_ptr, length); #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name)) { if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) png_ptr->mode |= PNG_HAVE_IDAT; png_handle_unknown(png_ptr, info_ptr, length); if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) png_ptr->mode |= PNG_HAVE_PLTE; else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) { if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before IDAT"); else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && !(png_ptr->mode & PNG_HAVE_PLTE)) png_error(png_ptr, "Missing PLTE before IDAT"); break; } } #endif else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) png_handle_PLTE(png_ptr, info_ptr, length); else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) { if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before IDAT"); else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && !(png_ptr->mode & PNG_HAVE_PLTE)) png_error(png_ptr, "Missing PLTE before IDAT"); png_ptr->idat_size = length; png_ptr->mode |= PNG_HAVE_IDAT; break; } #if defined(PNG_READ_bKGD_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) png_handle_bKGD(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_cHRM_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) png_handle_cHRM(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_gAMA_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) png_handle_gAMA(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_hIST_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) png_handle_hIST(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_oFFs_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) png_handle_oFFs(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_pCAL_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) png_handle_pCAL(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_sCAL_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) png_handle_sCAL(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_pHYs_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) png_handle_pHYs(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_sBIT_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) png_handle_sBIT(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_sRGB_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) png_handle_sRGB(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_iCCP_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) png_handle_iCCP(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_sPLT_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) png_handle_sPLT(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_tEXt_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) png_handle_tEXt(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_tIME_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) png_handle_tIME(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_tRNS_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) png_handle_tRNS(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_zTXt_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) png_handle_zTXt(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_iTXt_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) png_handle_iTXt(png_ptr, info_ptr, length); #endif else png_handle_unknown(png_ptr, info_ptr, length); } }
static int lload(lua_State *L) { int top = lua_gettop(L); FILE *fp; struct png_source source; if (top == 1) { const char *filename = luaL_checkstring(L,1); fp = fopen(filename, "rb"); if (fp == NULL) { return luaL_error(L, strerror(errno)); } unsigned char header[PNGSIGSIZE]; if (fread(header, 1, PNGSIGSIZE, fp) != PNGSIGSIZE) { return luaL_error(L, "png invalid"); } if (png_sig_cmp(header, 0, PNGSIGSIZE)) { return luaL_error(L, "png sig invalid"); } fseek(fp, 0, SEEK_SET); } else if (top == 2) { luaL_checktype(L,1,LUA_TLIGHTUSERDATA); void *data = lua_touserdata(L,1); size_t size = luaL_checkinteger(L,2); if (size < PNGSIGSIZE) { return luaL_error(L, "png invalid"); } if (png_sig_cmp(data, 0, PNGSIGSIZE)) { return luaL_error(L, "png sig invalid"); } source.data = data; source.size = size; source.offset = 0; } else { return luaL_error(L, "invalid argument number"); } png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height; int bit_depth, color_type, interlace_type; int step;//, type; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { return 0; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_read_struct(&png_ptr, NULL, NULL); return 0; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return 0; } if (top == 1) png_init_io(png_ptr, fp); else png_set_read_fn(png_ptr, (void *)&source, png_read_cb); //png_set_sig_bytes(png_ptr, PNGSIGSIZE); png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { bit_depth = 8; png_set_expand_gray_1_2_4_to_8(png_ptr); } if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) != 0) png_set_tRNS_to_alpha(png_ptr); if (bit_depth == 16) png_set_strip_16(png_ptr); if (bit_depth < 8) png_set_packing(png_ptr); png_read_update_info(png_ptr, info_ptr); bit_depth = png_get_bit_depth(png_ptr, info_ptr); color_type = png_get_color_type(png_ptr, info_ptr); switch (color_type) { case PNG_COLOR_TYPE_GRAY: // type = TEXTURE_DEPTH; step = 1; break; case PNG_COLOR_TYPE_RGB: //type = TEXTURE_RGB; step = 3; break; case PNG_COLOR_TYPE_RGB_ALPHA: //type = TEXTURE_RGBA; step = 4; break; default: return luaL_error(L, "png color type %d not support", color_type); } png_bytep *row_pointers = (png_bytep *)malloc(height * sizeof(png_bytep)); png_size_t rowbytes = png_get_rowbytes(png_ptr,info_ptr); size_t bytes = rowbytes * height; uint8_t *buffer = (uint8_t *)malloc(bytes); int i; for (i=0; i<height; ++i) { row_pointers[i] = buffer + i*rowbytes; } png_read_image(png_ptr, row_pointers); png_read_end(png_ptr, info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); free(row_pointers); switch (color_type) { case PNG_COLOR_TYPE_GRAY: lua_pushliteral(L,"GRAY"); break; case PNG_COLOR_TYPE_RGB: lua_pushliteral(L,"RGB8"); break; case PNG_COLOR_TYPE_RGBA: lua_pushliteral(L,"RGBA8"); break; } lua_pushinteger(L,width); lua_pushinteger(L,height); int n = width * height * step; lua_createtable(L,n,0); for (i=0; i<n; ++i) { lua_pushinteger(L, buffer[i]); lua_rawseti(L, -2, i+1); } free(buffer); return 4; }
void png_reader::init() { FILE *fp=fopen(fileName_.c_str(),"rb"); if (!fp) throw image_reader_exception("cannot open image file "+fileName_); png_byte header[8]; memset(header,0,8); if ( fread(header,1,8,fp) != 8) { fclose(fp); throw image_reader_exception("Could not read " + fileName_); } int is_png=!png_sig_cmp(header,0,8); if (!is_png) { fclose(fp); throw image_reader_exception(fileName_ + " is not a png file"); } png_structp png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,0,0,0); if (!png_ptr) { fclose(fp); throw image_reader_exception("failed to allocate png_ptr"); } // catch errors in a custom way to avoid the need for setjmp png_set_error_fn(png_ptr, png_get_error_ptr(png_ptr), user_error_fn, user_warning_fn); png_infop info_ptr; try { info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr,0,0); fclose(fp); throw image_reader_exception("failed to create info_ptr"); } } catch (std::exception const& ex) { png_destroy_read_struct(&png_ptr,0,0); fclose(fp); throw; } png_set_read_fn(png_ptr, (png_voidp)fp, png_read_data); png_set_sig_bytes(png_ptr,8); png_read_info(png_ptr, info_ptr); png_uint_32 width, height; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth_, &color_type_,0,0,0); width_=width; height_=height; MAPNIK_LOG_DEBUG(png_reader) << "png_reader: bit_depth=" << bit_depth_ << ",color_type=" << color_type_; png_destroy_read_struct(&png_ptr,&info_ptr,0); fclose(fp); }
GLuint loadTextureFromPNG(const char* filename, int &width, int &height) { file = zip_fopen(APKArchive, filename, 0); if (!file) { LOGE("Error opening %s from APK", filename); return TEXTURE_LOAD_ERROR; } //header for testing if it is a png png_byte header[8]; //read the header zip_fread(file, header, 8); //test if png int is_png = !png_sig_cmp(header, 0, 8); if (!is_png) { zip_fclose(file); LOGE("Not a png file : %s", filename); return TEXTURE_LOAD_ERROR; } //create png struct png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { zip_fclose(file); LOGE("Unable to create png struct : %s", filename); return (TEXTURE_LOAD_ERROR); } //create png info struct png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL); LOGE("Unable to create png info : %s", filename); zip_fclose(file); return (TEXTURE_LOAD_ERROR); } //create png info struct png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); LOGE("Unable to create png end info : %s", filename); zip_fclose(file); return (TEXTURE_LOAD_ERROR); } //png error stuff, not sure libpng man suggests this. if (setjmp(png_jmpbuf(png_ptr))) { zip_fclose(file); LOGE("Error during setjmp : %s", filename); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return (TEXTURE_LOAD_ERROR); } //init png reading //png_init_io(png_ptr, fp); png_set_read_fn(png_ptr, NULL, png_zip_read); //let libpng know you already read the first 8 bytes png_set_sig_bytes(png_ptr, 8); // read all the info up to the image data png_read_info(png_ptr, info_ptr); //variables to pass to get info int bit_depth, color_type; png_uint_32 twidth, theight; // get info about png png_get_IHDR(png_ptr, info_ptr, &twidth, &theight, &bit_depth, &color_type, NULL, NULL, NULL); //update width and height based on png info width = twidth; height = theight; // Update the png info struct. png_read_update_info(png_ptr, info_ptr); // Row size in bytes. int rowbytes = png_get_rowbytes(png_ptr, info_ptr); // Allocate the image_data as a big block, to be given to opengl png_byte *image_data = new png_byte[rowbytes * height]; if (!image_data) { //clean up memory and close stuff png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); LOGE("Unable to allocate image_data while loading %s ", filename); zip_fclose(file); return TEXTURE_LOAD_ERROR; } //row_pointers is for pointing to image_data for reading the png with libpng png_bytep *row_pointers = new png_bytep[height]; if (!row_pointers) { //clean up memory and close stuff png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); delete[] image_data; LOGE("Unable to allocate row_pointer while loading %s ", filename); zip_fclose(file); return TEXTURE_LOAD_ERROR; } // set the individual row_pointers to point at the correct offsets of image_data for (int i = 0; i < height; ++i) row_pointers[height - 1 - i] = image_data + i * rowbytes; //read the png into image_data through row_pointers png_read_image(png_ptr, row_pointers); //Now generate the OpenGL texture object GLuint texture; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) image_data); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); //clean up memory and close stuff png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); delete[] image_data; delete[] row_pointers; zip_fclose(file); return texture; }
static void read_png(const char* filename, int& width, int& height, png_bytep*& rowPtrs, png_structp& pngPtr, png_infop& infoPtr) { char header[8]; FILE* input = fopen(filename, "rb"); if (!input) error("[read_png] File %s could not be opened for reading", filename); AutoFileCloser _(input); fread(header, 1, 8, input); if (png_sig_cmp((png_byte *)header, 0, 8 )) error("[read_png] File %s is not recognized as a PNG file", filename); pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!pngPtr) error("[read_png] png_create_read_struct failed"); infoPtr = png_create_info_struct(pngPtr); if (!infoPtr) error("[read_png] png_create_info_struct failed"); // TODO: I don't know which version of libpng introduced this feature: #if PNG_LIBPNG_VER > 10005 if (setjmp(png_jmpbuf(pngPtr))) error("[read_png] Error during init_io"); #endif png_init_io(pngPtr, input); png_set_sig_bytes(pngPtr, 8); // make sure we automatically get RGB data with 8 bits per channel // also make sure the alpha channel is stripped, in the end, we // expect 24 bits BGR data png_set_expand(pngPtr); png_set_expand_gray_1_2_4_to_8(pngPtr); png_set_palette_to_rgb(pngPtr); png_set_gray_to_rgb(pngPtr); png_set_strip_alpha(pngPtr); png_set_bgr(pngPtr); png_read_info(pngPtr, infoPtr); width = infoPtr->width; height = infoPtr->height; if (infoPtr->bit_depth != 8) error("[read_png] File %s has wrong bit depth\n", filename); if ((int)infoPtr->rowbytes < width * 3) { error("[read_png] File %s has wrong color type (RGB required)\n", filename); } png_set_interlace_handling(pngPtr); png_read_update_info(pngPtr, infoPtr); #if PNG_LIBPNG_VER > 10005 if (setjmp(png_jmpbuf(pngPtr))) error("[read_png] Error during read_image"); #endif rowPtrs = (png_bytep*)malloc(sizeof(png_bytep) * height); for (int y = 0; y < height; y++) rowPtrs[y] = (png_byte*)malloc(infoPtr->rowbytes); png_read_image(pngPtr, rowPtrs); }
PingPNG (const std::string& aPath) : File(0), PngPtr(0), InfoPtr(0), RowPointers(0), Width(0), Height(0), Valid(false) { File = fopen(aPath.c_str(), "rb"); if(File) { fread(Header, 1, 8, File); if(!png_sig_cmp(Header, 0, 8)) { PngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(PngPtr) { InfoPtr = png_create_info_struct(PngPtr); if(InfoPtr) { if(setjmp(png_jmpbuf(PngPtr))) { es_log->AppendLine("PNG Reader: Error during init_io. [File: %s]", aPath.c_str()); return; } png_init_io(PngPtr, File); png_set_sig_bytes(PngPtr, 8); if(setjmp(png_jmpbuf(PngPtr))) { es_log->AppendLine("PNG Reader: Error during read_png. [File: %s]", aPath.c_str()); return; } png_read_png(PngPtr, InfoPtr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_SWAP_ALPHA, 0); RowPointers = png_get_rows(PngPtr, InfoPtr); if(!RowPointers) { es_log->AppendLine("PNG Reader: Failed to get pixels. [File: %s]", aPath.c_str()); return; } Width = png_get_image_width(PngPtr, InfoPtr); Height = png_get_image_height(PngPtr, InfoPtr); Valid = true; return; } else { es_log->AppendLine("PNG Reader: png_create_info_struct failed. [File: %s]", aPath.c_str()); return; } } else { es_log->AppendLine("PNG Reader: png_create_read_struct failed. [File: %s]", aPath.c_str()); return; } } else { es_log->AppendLine("PNG Reader: File not recognized as a PNG file. [File: %s]", aPath.c_str()); return; } } else { es_log->AppendLine("PNG Reader: File could not be opened for reading. [File: %s]", aPath.c_str()); return; } }
int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight) { uch sig[8]; /* first do a quick check that the file really is a PNG image; could * have used slightly more general png_sig_cmp() function instead */ fread(sig, 1, 8, infile); if (png_sig_cmp(sig, 0, 8)) return 1; /* bad signature */ /* could pass pointers to user-defined error handlers instead of NULLs: */ png_ptr = png_create_read_struct(png_get_libpng_ver(NULL), NULL, NULL, NULL); if (!png_ptr) return 4; /* out of memory */ info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); return 4; /* out of memory */ } /* we could create a second info struct here (end_info), but it's only * useful if we want to keep pre- and post-IDAT chunk info separated * (mainly for PNG-aware image editors and converters) */ /* setjmp() must be called in every function that calls a PNG-reading * libpng function */ if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return 2; } png_init_io(png_ptr, infile); png_set_sig_bytes(png_ptr, 8); /* we already read the 8 signature bytes */ png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */ /* alternatively, could make separate calls to png_get_image_width(), * etc., but want bit_depth and color_type for later [don't care about * compression_type and filter_type => NULLs] */ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); *pWidth = width; *pHeight = height; /* OK, that's all we need for now; return happy */ return 0; }
void png_loader::read_image( const char* filename ) { ld_.reset(new LibpngData); if ( filename == NULL ) { throw image_load_error("png_loader: invalid filename, it is NULL"); } FILE *fp = fopen( filename, "rb" ); if ( !fp ) { throw image_load_error(std::string("png_loader: unable to open file ") + filename); } png_byte sig[8]; if (fread( sig, 1, 8, fp ) != 8) { fclose( fp ); throw image_load_error(std::string("png_loader: error reading file ") + filename); } if ( png_sig_cmp( sig, 0, 8 ) != 0 ) { fclose( fp ); throw image_load_error(std::string("png_loader: format error in file ") + filename); } ld_->png_ptr_ = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, &png_loader_user_error_fn_silent, &png_loader_user_warning_fn_silent ); if ( ld_->png_ptr_ == NULL ) { fclose( fp ); throw image_load_error(std::string("png_loader: parse error in file ") + filename); } ld_->info_ptr_ = png_create_info_struct( ld_->png_ptr_ ); if ( ld_->info_ptr_ == NULL ) { fclose( fp ); png_destroy_read_struct( &( ld_->png_ptr_ ), ( png_infopp )NULL, ( png_infopp )NULL ); throw image_load_error(std::string("png_loader: parse error in file ") + filename); } ld_->end_info_ = png_create_info_struct( ld_->png_ptr_ ); if ( ld_->end_info_ == NULL ) { fclose( fp ); png_destroy_read_struct( &( ld_->png_ptr_ ), &( ld_->info_ptr_ ), ( png_infopp )NULL ); throw image_load_error(std::string("png_loader: parse error in file ") + filename); } if (setjmp(png_jmpbuf(ld_->png_ptr_))) { // If we get here, we had a problem writing the file fclose(fp); png_destroy_read_struct( &( ld_->png_ptr_ ), &( ld_->info_ptr_ ), &( ld_->end_info_ ) ); throw image_load_error(std::string("png_loader: parse error in file ") + filename); } png_set_palette_to_rgb(ld_->png_ptr_); png_init_io( ld_->png_ptr_, fp ); png_set_sig_bytes( ld_->png_ptr_, 8 ); // flags force one byte per channel output byte_orderer bo; int png_transforms = PNG_TRANSFORM_PACKING; if (bo.host_is_little_endian()) png_transforms |= PNG_TRANSFORM_SWAP_ENDIAN; png_read_png( ld_->png_ptr_, ld_->info_ptr_, png_transforms, NULL ); height_ = png_get_image_height( ld_->png_ptr_, ld_->info_ptr_ ); width_ = png_get_image_width( ld_->png_ptr_, ld_->info_ptr_ ); bit_depth_ = png_get_bit_depth( ld_->png_ptr_, ld_->info_ptr_ ); color_type_ = png_get_color_type( ld_->png_ptr_, ld_-> info_ptr_ ); if (color_type_ != PNG_COLOR_TYPE_GRAY && color_type_ != PNG_COLOR_TYPE_RGB && color_type_ != PNG_COLOR_TYPE_RGB_ALPHA && color_type_ != PNG_COLOR_TYPE_GRAY_ALPHA) { fclose( fp ); png_destroy_read_struct( &( ld_->png_ptr_ ), &( ld_->info_ptr_ ), &( ld_->end_info_ ) ); throw image_load_error(std::string("png_loader: unsupported color type in file ") + filename); } if (bit_depth_ != 8 && bit_depth_ != 16) { fclose( fp ); png_destroy_read_struct( &( ld_->png_ptr_ ), &( ld_->info_ptr_ ), &( ld_->end_info_ ) ); throw image_load_error("png_loader: unsupported bit depth of " + cast_to_string(bit_depth_) + " in file " + std::string(filename)); } ld_->row_pointers_ = png_get_rows( ld_->png_ptr_, ld_->info_ptr_ ); fclose( fp ); if ( ld_->row_pointers_ == NULL ) { png_destroy_read_struct( &( ld_->png_ptr_ ), &( ld_->info_ptr_ ), &( ld_->end_info_ ) ); throw image_load_error(std::string("png_loader: parse error in file ") + filename); } }
/** 从本地磁盘中加载图像 @Param 图像文件的路径 */ F3DImage* F3DPNGCodec::Load( const char* filename ) { F3DImage* image; // 打开指定的文件 FVFile file; if( !file.Open(filename,FVFile::VFILE_OPENEXIST) ) { FLOG_WARNINGF( "F3DPNGCodec::Load, Open the image file (%s) failed!",filename ); return NULL; } FBYTE** row_pointers; png_byte buffer[8]; // 判断是否为一个正确的PNG文件 if( file.Read(buffer,8) != 8 || !png_sig_cmp(buffer,0,8) ) { FLOG_WARNINGF( "F3DPNGCodec::Load, Invalid PNG format! (%s)",filename ); return NULL; } // 创建一个PNG读取对象 png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING,NULL,NULL,NULL ); // 创建一个PNG信息结构体 png_infop info_ptr = png_create_info_struct( png_ptr ); if( setjmp(png_jmpbuf(png_ptr)) ) { png_destroy_read_struct( &png_ptr,&info_ptr,NULL ); if( row_pointers ) delete[] row_pointers; FLOG_ERROR("F3DPNGCodec::Load, An error occurs when reading..."); return NULL; } // 设置读取数据的回调函数 png_set_read_fn( png_ptr,&file,PNGReadFunc ); // 告诉PNG我们已经读取过文件标识 png_set_sig_bytes( png_ptr,8 ); // 读取PNG文件的信息 png_read_info( png_ptr,info_ptr ); png_uint_32 width,height; int bitDepth,colorType; png_get_IHDR( png_ptr,info_ptr,&width,&height,&bitDepth,&colorType,NULL,NULL,NULL ); // 如果是调色板图像则将其转换为真彩色 if( colorType == PNG_COLOR_TYPE_PALETTE ) png_set_palette_to_rgb( png_ptr ); if( bitDepth < 8 ) { if ( colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA ) png_set_gray_1_2_4_to_8( png_ptr ); else png_set_packing( png_ptr ); } if( png_get_valid(png_ptr,info_ptr,PNG_INFO_tRNS) ) png_set_tRNS_to_alpha( png_ptr ); if( bitDepth == 16 ) png_set_strip_16( png_ptr ); // 将灰色转换为真彩色 if( colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA ) png_set_gray_to_rgb( png_ptr ); // 更新信息的改变 png_read_update_info( png_ptr,info_ptr ); // 将RGBA格式转换为BGRA if( colorType == PNG_COLOR_TYPE_RGB_ALPHA ) png_set_bgr( png_ptr ); png_get_IHDR( png_ptr,info_ptr,&width,&height,&bitDepth,&colorType,NULL,NULL,NULL ); // 创建图像对象 if( colorType == PNG_COLOR_TYPE_RGB_ALPHA ) image = new F3DImage( width,height,PFT_A8R8G8B8 ); else image = new F3DImage( width,height,PFT_R8G8B8 ); row_pointers = new png_bytep[height]; FBYTE* imageData = image->GetImageData(); for( size_t i=0;i<height;i++ ) { row_pointers[i] = imageData; imageData += F3D_PixelSize(image->GetPixelFormat()) * image->GetWidth(); } if( setjmp(png_jmpbuf(png_ptr)) ) { png_destroy_read_struct( &png_ptr,&info_ptr,NULL ); delete image; delete[] row_pointers; FLOG_ERROR("F3DPNGCodec::Load, An error occurs when reading..."); return NULL; } // 读取像素数据 png_read_image( png_ptr,row_pointers ); png_read_end( png_ptr,NULL ); png_destroy_read_struct( &png_ptr,&info_ptr,NULL ); delete[] row_pointers; file.Close(); return image; }
static FIBITMAP * DLL_CALLCONV Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_uint_32 width, height; int color_type; int bit_depth; int pixel_depth = 0; // pixel_depth = bit_depth * channels FIBITMAP *dib = NULL; png_bytepp row_pointers = NULL; fi_ioStructure fio; fio.s_handle = handle; fio.s_io = io; if (handle) { BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; try { // check to see if the file is in fact a PNG file BYTE png_check[PNG_BYTES_TO_CHECK]; io->read_proc(png_check, PNG_BYTES_TO_CHECK, 1, handle); if (png_sig_cmp(png_check, (png_size_t)0, PNG_BYTES_TO_CHECK) != 0) { return NULL; // Bad signature } // create the chunk manage structure png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, error_handler, warning_handler); if (!png_ptr) { return NULL; } // create the info structure info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); return NULL; } // init the IO png_set_read_fn(png_ptr, &fio, _ReadProc); if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } // because we have already read the signature... png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); // read the IHDR chunk png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); // configure the decoder FREE_IMAGE_TYPE image_type = FIT_BITMAP; if(!ConfigureDecoder(png_ptr, info_ptr, flags, &image_type)) { throw FI_MSG_ERROR_UNSUPPORTED_FORMAT; } // update image info color_type = png_get_color_type(png_ptr, info_ptr); bit_depth = png_get_bit_depth(png_ptr, info_ptr); pixel_depth = bit_depth * png_get_channels(png_ptr, info_ptr); // create a dib and write the bitmap header // set up the dib palette, if needed switch (color_type) { case PNG_COLOR_TYPE_RGB: case PNG_COLOR_TYPE_RGB_ALPHA: dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); break; case PNG_COLOR_TYPE_PALETTE: dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); if(dib) { png_colorp png_palette = NULL; int palette_entries = 0; png_get_PLTE(png_ptr,info_ptr, &png_palette, &palette_entries); palette_entries = MIN((unsigned)palette_entries, FreeImage_GetColorsUsed(dib)); // store the palette RGBQUAD *palette = FreeImage_GetPalette(dib); for(int i = 0; i < palette_entries; i++) { palette[i].rgbRed = png_palette[i].red; palette[i].rgbGreen = png_palette[i].green; palette[i].rgbBlue = png_palette[i].blue; } } break; case PNG_COLOR_TYPE_GRAY: dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); if(dib && (pixel_depth <= 8)) { RGBQUAD *palette = FreeImage_GetPalette(dib); const int palette_entries = 1 << pixel_depth; for(int i = 0; i < palette_entries; i++) { palette[i].rgbRed = palette[i].rgbGreen = palette[i].rgbBlue = (BYTE)((i * 255) / (palette_entries - 1)); } } break; default: throw FI_MSG_ERROR_UNSUPPORTED_FORMAT; } if(!dib) { throw FI_MSG_ERROR_DIB_MEMORY; } // store the transparency table if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { // array of alpha (transparency) entries for palette png_bytep trans_alpha = NULL; // number of transparent entries int num_trans = 0; // graylevel or color sample values of the single transparent color for non-paletted images png_color_16p trans_color = NULL; png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color); if((color_type == PNG_COLOR_TYPE_GRAY) && trans_color) { // single transparent color if (trans_color->gray < 256) { BYTE table[256]; memset(table, 0xFF, 256); table[trans_color->gray] = 0; FreeImage_SetTransparencyTable(dib, table, 256); } // check for a full transparency table, too else if ((trans_alpha) && (pixel_depth <= 8)) { FreeImage_SetTransparencyTable(dib, (BYTE *)trans_alpha, num_trans); } } else if((color_type == PNG_COLOR_TYPE_PALETTE) && trans_alpha) { // transparency table FreeImage_SetTransparencyTable(dib, (BYTE *)trans_alpha, num_trans); } } // store the background color (only supported for FIT_BITMAP types) if ((image_type == FIT_BITMAP) && png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD)) { // Get the background color to draw transparent and alpha images over. // Note that even if the PNG file supplies a background, you are not required to // use it - you should use the (solid) application background if it has one. png_color_16p image_background = NULL; RGBQUAD rgbBkColor; if (png_get_bKGD(png_ptr, info_ptr, &image_background)) { rgbBkColor.rgbRed = (BYTE)image_background->red; rgbBkColor.rgbGreen = (BYTE)image_background->green; rgbBkColor.rgbBlue = (BYTE)image_background->blue; rgbBkColor.rgbReserved = 0; FreeImage_SetBackgroundColor(dib, &rgbBkColor); } } // get physical resolution if (png_get_valid(png_ptr, info_ptr, PNG_INFO_pHYs)) { png_uint_32 res_x, res_y; // we'll overload this var and use 0 to mean no phys data, // since if it's not in meters we can't use it anyway int res_unit_type = PNG_RESOLUTION_UNKNOWN; png_get_pHYs(png_ptr,info_ptr, &res_x, &res_y, &res_unit_type); if (res_unit_type == PNG_RESOLUTION_METER) { FreeImage_SetDotsPerMeterX(dib, res_x); FreeImage_SetDotsPerMeterY(dib, res_y); } } // get possible ICC profile if (png_get_valid(png_ptr, info_ptr, PNG_INFO_iCCP)) { png_charp profile_name = NULL; png_bytep profile_data = NULL; png_uint_32 profile_length = 0; int compression_type; png_get_iCCP(png_ptr, info_ptr, &profile_name, &compression_type, &profile_data, &profile_length); // copy ICC profile data (must be done after FreeImage_AllocateHeader) FreeImage_CreateICCProfile(dib, profile_data, profile_length); } // --- header only mode => clean-up and return if (header_only) { // get possible metadata (it can be located both before and after the image data) ReadMetadata(png_ptr, info_ptr, dib); if (png_ptr) { // clean up after the read, and free any memory allocated - REQUIRED png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); } return dib; } // set the individual row_pointers to point at the correct offsets row_pointers = (png_bytepp)malloc(height * sizeof(png_bytep)); if (!row_pointers) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); FreeImage_Unload(dib); return NULL; } // read in the bitmap bits via the pointer table // allow loading of PNG with minor errors (such as images with several IDAT chunks) for (png_uint_32 k = 0; k < height; k++) { row_pointers[height - 1 - k] = FreeImage_GetScanLine(dib, k); } png_set_benign_errors(png_ptr, 1); png_read_image(png_ptr, row_pointers); // check if the bitmap contains transparency, if so enable it in the header if (FreeImage_GetBPP(dib) == 32) { if (FreeImage_GetColorType(dib) == FIC_RGBALPHA) { FreeImage_SetTransparent(dib, TRUE); } else { FreeImage_SetTransparent(dib, FALSE); } } // cleanup if (row_pointers) { free(row_pointers); row_pointers = NULL; } // read the rest of the file, getting any additional chunks in info_ptr png_read_end(png_ptr, info_ptr); // get possible metadata (it can be located both before and after the image data) ReadMetadata(png_ptr, info_ptr, dib); if (png_ptr) { // clean up after the read, and free any memory allocated - REQUIRED png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); } return dib; } catch (const char *text) { if (png_ptr) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); } if (row_pointers) { free(row_pointers); } if (dib) { FreeImage_Unload(dib); } FreeImage_OutputMessageProc(s_format_id, text); return NULL; } } return NULL; }
int loadPNG(ePtr<gPixmap> &result, const char *filename, int accel) { __u8 header[8]; FILE *fp=fopen(filename, "rb"); if (!fp) { // eDebug("couldn't open %s", filename ); return 0; } if (!fread(header, 8, 1, fp)) { eDebug("couldn't read"); fclose(fp); return 0; } if (png_sig_cmp(header, 0, 8)) { fclose(fp); return 0; } png_structp png_ptr=png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if (!png_ptr) { eDebug("no pngptr"); fclose(fp); return 0; } png_infop info_ptr=png_create_info_struct(png_ptr); if (!info_ptr) { eDebug("no info ptr"); png_destroy_read_struct(&png_ptr, (png_infopp)0, (png_infopp)0); fclose(fp); return 0; } png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { eDebug("no end"); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(fp); return 0; } if (setjmp(png_jmpbuf(png_ptr))) { eDebug("das war wohl nix"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fp); result = 0; return 0; } png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, 8); png_set_invert_alpha(png_ptr); png_read_info(png_ptr, info_ptr); png_uint_32 width, height; int bit_depth; int color_type; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0); if (color_type == PNG_COLOR_TYPE_GRAY || color_type & PNG_COLOR_MASK_PALETTE) { if (bit_depth < 8) { png_set_packing(png_ptr); bit_depth = 8; } result=new gPixmap(eSize(width, height), bit_depth, accel); gSurface *surface = result->surface; png_bytep *rowptr=new png_bytep[height]; for (unsigned int i=0; i<height; i++) rowptr[i]=((png_byte*)(surface->data))+i*surface->stride; png_read_rows(png_ptr, rowptr, 0, height); delete [] rowptr; if (png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)) { png_color *palette; int num_palette; png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette); if (num_palette) surface->clut.data=new gRGB[num_palette]; else surface->clut.data=0; surface->clut.colors=num_palette; for (int i=0; i<num_palette; i++) { surface->clut.data[i].a=0; surface->clut.data[i].r=palette[i].red; surface->clut.data[i].g=palette[i].green; surface->clut.data[i].b=palette[i].blue; } if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_byte *trans; png_get_tRNS(png_ptr, info_ptr, &trans, &num_palette, 0); for (int i=0; i<num_palette; i++) surface->clut.data[i].a=255-trans[i]; } } else { surface->clut.data=0; surface->clut.colors=0; } surface->clut.start=0; png_read_end(png_ptr, end_info); } else { result=0; eDebug("%s: %dx%dx%d png, %d", filename, (int)width, (int)height, (int)bit_depth, color_type); } png_destroy_read_struct(&png_ptr, &info_ptr,&end_info); fclose(fp); return 0; }
img_t* load_png(char* filename) { FILE* fp = fopen(filename, "rb"); if (!fp) { fprintf(stderr, "ERROR: Could not open input file %s\n", filename); exit(-1); } png_byte pngsig[8]; fread(pngsig, 1, 8, fp); int is_png = !png_sig_cmp(pngsig, 0, 8); if (!is_png) { fprintf(stderr, "ERROR: File %s is not a PNG!\n", filename); fclose(fp); exit(-1); } png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if (!png_ptr) { fprintf(stderr, "ERROR: Could not open input file %s\n", filename); fclose(fp); exit(-1); } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, 0, 0); fprintf(stderr, "ERROR: Could not open input file %s\n", filename); fclose(fp); exit(-1); } png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { png_destroy_read_struct(&png_ptr, &info_ptr, 0); fprintf(stderr, "ERROR: Could not open input file %s\n", filename); fclose(fp); exit(-1); } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fprintf(stderr, "ERROR: Could not open input file %s\n", filename); fclose(fp); exit(-1); } png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, 8); png_uint_32 width, height; int bit_depth, color_type; png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_expand (png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand (png_ptr); if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand (png_ptr); if (bit_depth == 16) png_set_strip_16 (png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb (png_ptr); png_read_update_info (png_ptr, info_ptr); png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); unsigned row_bytes = png_get_rowbytes (png_ptr, info_ptr); unsigned char* png_pixels = malloc (row_bytes * height * sizeof (png_byte)); unsigned char** ret = malloc(height * sizeof (png_bytep)); unsigned i; for (i = 0; i < (height); i++) ret[i] = png_pixels + i * row_bytes; png_read_image (png_ptr, ret); png_read_end (png_ptr, info_ptr); fclose(fp); img_t* image = malloc(sizeof(img_t)); image->pixels = ret; image->top = 0; image->left = 0; image->w = width; image->h = height; image->center_x = width / 2; image->center_y = height / 2; image->filename = filename; return image; }
bool Cc3dImage::_initWithPngData(void * pData, int nDatalen) { // length of bytes to check if it is a valid png file #define PNGSIGSIZE 8 bool bRet = false; png_byte header[PNGSIGSIZE] = {0}; png_structp png_ptr = 0; png_infop info_ptr = 0; do { // png header len is 8 bytes if(nDatalen < PNGSIGSIZE) break; // check the data is png or not memcpy(header, pData, PNGSIGSIZE); if(png_sig_cmp(header, 0, PNGSIGSIZE)) break; // init png_struct png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if(! png_ptr) break; // init png_info info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) break; // set the read call back function tImageSource imageSource; imageSource.data = (unsigned char*)pData; imageSource.size = nDatalen; imageSource.offset = 0; png_set_read_fn(png_ptr, &imageSource, pngReadCallback); // read png header info // read png file info png_read_info(png_ptr, info_ptr); m_nWidth = png_get_image_width(png_ptr, info_ptr); m_nHeight = png_get_image_height(png_ptr, info_ptr); m_nBitsPerComponent = png_get_bit_depth(png_ptr, info_ptr); png_uint_32 color_type = png_get_color_type(png_ptr, info_ptr); //CCLOG("color type %u", color_type); // force palette images to be expanded to 24-bit RGB // it may include alpha channel if (color_type == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png_ptr); } // low-bit-depth grayscale images are to be expanded to 8 bits if (color_type == PNG_COLOR_TYPE_GRAY && m_nBitsPerComponent < 8) { png_set_expand_gray_1_2_4_to_8(png_ptr); } // expand any tRNS chunk data into a full alpha channel if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); } // reduce images with 16-bit samples to 8 bits if (m_nBitsPerComponent == 16) { png_set_strip_16(png_ptr); } // expand grayscale images to RGB if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb(png_ptr); } // read png data // m_nBitsPerComponent will always be 8 m_nBitsPerComponent = 8; png_uint_32 rowbytes; png_bytep* row_pointers = (png_bytep*)malloc( sizeof(png_bytep) * m_nHeight ); png_read_update_info(png_ptr, info_ptr); rowbytes = png_get_rowbytes(png_ptr, info_ptr); m_pData = new unsigned char[rowbytes * m_nHeight]; if(!m_pData) break; for (unsigned short i = 0; i < m_nHeight; ++i) { row_pointers[i] = m_pData + i*rowbytes; } png_read_image(png_ptr, row_pointers); png_read_end(png_ptr, NULL); png_uint_32 channel = rowbytes/m_nWidth; if (channel == 4) { m_bHasAlpha = true; unsigned int *tmp = (unsigned int *)m_pData; for(unsigned short i = 0; i < m_nHeight; i++) { for(unsigned int j = 0; j < rowbytes; j += 4) { *tmp++ = CC_RGB_PREMULTIPLY_ALPHA( row_pointers[i][j], row_pointers[i][j + 1], row_pointers[i][j + 2], row_pointers[i][j + 3] ); } } m_bPreMulti = true; } do { if(row_pointers) { free(row_pointers); (row_pointers) = 0; } } while(0); bRet = true; } while (0); if (png_ptr) { png_destroy_read_struct(&png_ptr, (info_ptr) ? &info_ptr : 0, 0); } return bRet; }
int main(int argc, char **argv) { char* outfile = NULL; save_mode mode = RAW; unsigned split_w = 0; unsigned split_h = 0; int opt; while((opt=getopt(argc, argv, "brpns:o:h?")) != -1) { switch(opt) { case 'b': mode = BINARY; break; case 'n': mode = PALETTE_NO_OUTPUT; break; case 'p': mode = PALETTE; break; case 'r': mode = RGB; break; case 's': { unsigned pos; if(sscanf(optarg, "%ux%u%n", &split_w, &split_h, &pos)!=2 || pos != strlen(optarg)) { usage(); exit(1); } } break; case 'o': outfile = optarg; break; case 'h': case '?': usage(); exit(1); } } char** inputfiles = argv + optind; unsigned inputcount = argc - optind; if (!inputcount) { usage(); exit(1); } for (unsigned input_nr = 0; input_nr < inputcount; input_nr++) { FILE *f = fopen(inputfiles[input_nr], "rb"); if (!f) { fprintf(stderr, "Could not open file %s for reading\n", inputfiles[input_nr]); continue; } char *out = outfile; if (!out) { out = (char*)malloc(strlen(inputfiles[input_nr])+3); sprintf(out, "%s.h", inputfiles[input_nr]); } FILE *outstream = fopen(out, "w"); if (!outstream) { fprintf(stderr, "Could not open file %s for writing\n", out); continue; } char *file_basename = basename(inputfiles[input_nr]); for (unsigned i = 0; i < strlen(file_basename); i++) { if (file_basename[i] >= 'a' && file_basename[i] <= 'z') { file_basename[i] = file_basename[i] + 'A' - 'a'; } else if (file_basename[i] >= 'A' && file_basename[i] <= 'Z') { } else { file_basename[i] = '_'; } } char *data_array_name = (char*)malloc(strlen(file_basename)+6); sprintf(data_array_name, "%s_DATA", file_basename); char *plte_array_name = (char*)malloc(strlen(file_basename)+6); sprintf(plte_array_name, "%s_PLTE", file_basename); unsigned char header[8]; fread(header, 1, 8, f); if (png_sig_cmp(header, 0, 8)) { fprintf(stderr, "%s is not a png file", inputfiles[input_nr]); continue; } png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { fprintf(stderr, "png_create_read_struct failed"); continue; } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { fprintf(stderr, "png_create_info_struct failed"); png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); continue; } if (setjmp(png_jmpbuf(png_ptr))) { fprintf(stderr, "Error during init_io"); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); continue; } png_init_io(png_ptr, f); png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); unsigned width = png_get_image_width(png_ptr, info_ptr); unsigned height = png_get_image_height(png_ptr, info_ptr); png_byte color_type = png_get_color_type(png_ptr, info_ptr); png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr); if (mode == PALETTE || mode == PALETTE_NO_OUTPUT) { // does the user want palette output? if ((color_type & PNG_COLOR_MASK_PALETTE) == 0 && (color_type & PNG_COLOR_MASK_COLOR)) { //the image must have a palette or be grayscale fprintf(stderr, "%s is not a palette or grayscale image\n", inputfiles[input_nr]); continue; } } png_set_interlace_handling(png_ptr); // Reduce to 8 bits png_set_strip_16(png_ptr); png_set_strip_alpha(png_ptr); // Unpack 1, 2, 4 bits into 8 png_set_packing(png_ptr); if (mode == RGB) { png_set_palette_to_rgb(png_ptr); } // Done setting read flags png_read_update_info(png_ptr, info_ptr); png_bytep* row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * height); for (unsigned y = 0; y < height; y++) { row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png_ptr, info_ptr)); } png_read_image(png_ptr, row_pointers); png_read_end(png_ptr, info_ptr); if (mode == PALETTE) { if (color_type & PNG_COLOR_MASK_COLOR) { // image is actually paletted int plte_length; png_colorp plte_colors; png_get_PLTE(png_ptr, info_ptr, &plte_colors, &plte_length); fprintf(outstream, "uint32_t %s[%d] = {\n", plte_array_name, plte_length); for (int i = 0; i < plte_length; i++) { uint32_t color = plte_colors[i].red << 16 | plte_colors[i].green << 8 | plte_colors[i].blue; fprintf(outstream, "0x%06lX, ", (unsigned long)color); } fprintf(outstream, "\n};\n\n"); } else { // create a default grayscale palette int plte_length = 1 << bit_depth; fprintf(outstream, "uint32_t %s[%d] = {\n", plte_array_name, plte_length); for (int i = 0; i < plte_length; i++) { printf("%d\n", i); int current_bits = i; uint32_t color = 0; int target_bits = 3 * 8; for (int bit = 0; bit < target_bits; bit += bit_depth) { color |= current_bits; current_bits <<= bit_depth; } fprintf(outstream, "0x%06lX, ", (unsigned long)color); } fprintf(outstream, "};\n\n"); } } unsigned tile_h = split_h ? split_h : height; unsigned tile_w = split_w ? split_w : width; unsigned byte_per_pixel = png_get_rowbytes(png_ptr, info_ptr) / width; unsigned long pixel_count = width * height; fprintf(outstream, "uint%d_t %s[%lu] = {\n", mode == RGB ? 32 : 8, data_array_name, mode == BINARY ? pixel_count / 8 : pixel_count); for (unsigned tile_y = 0; tile_y + tile_h <= height; tile_y += tile_h) { for (unsigned tile_x = 0; tile_x + tile_w <= width; tile_x += tile_w) { fprintf(outstream, "// Tile (%d, %d)\n", tile_x / tile_w, tile_y / tile_h); switch(mode) { case BINARY: for (unsigned y = tile_y; y < tile_y + tile_h; y++) { png_byte* row = row_pointers[y]; for (unsigned x0 = tile_x; x0 < tile_x + tile_w; x0 += 8) { uint8_t current_bit = 1; uint8_t total = 0; for (unsigned x = x0; x < x0 + 8 && x < tile_x + tile_w; x++, current_bit <<= 1) { if (row[byte_per_pixel * x]) { total |= current_bit; } } fprintf(outstream, "0x%02X, ", total); } fprintf(outstream, "\n"); } break; case PALETTE: case PALETTE_NO_OUTPUT: for (unsigned y = tile_y; y < tile_y + tile_h; y++) { png_byte* row = row_pointers[y]; for (unsigned x = tile_x; x < tile_x + tile_w; x++) { fprintf(outstream, "%d, ", row[byte_per_pixel * x]); } fprintf(outstream, "\n"); } break; case RGB: case RAW: default: for (unsigned y = tile_y; y < tile_y + tile_h; y++) { png_byte* row = row_pointers[y]; for (unsigned x = tile_x; x < tile_x + tile_w; x++) { fprintf(outstream, "0x"); for (unsigned i = 0; i < byte_per_pixel; i++) { fprintf(outstream, "%02X", row[byte_per_pixel * x + i]); } fprintf(outstream, ", "); } fprintf(outstream, "\n"); } break; } } } fprintf(outstream, "};\n\n"); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(f); } }
/* (Obsolete) function to check signature bytes. It does not allow one * to check a partial signature. This function might be removed in the * future - use png_sig_cmp(). Returns true (nonzero) if the file is PNG. */ int PNGAPI png_check_sig(png_bytep sig, int num) { return ((int)!png_sig_cmp(sig, (png_size_t)0, (png_size_t)num)); }
bool isPNG(struct VFile* source) { png_byte header[PNG_HEADER_BYTES]; source->read(source, header, PNG_HEADER_BYTES); return !png_sig_cmp(header, 0, PNG_HEADER_BYTES); }