📄 pngr.cpp
字号:
/** PNGR.CPP -- QImageIO read/write handlers for* the PNG graphic format using libpng.** Copyright (c) October 1998, Sirtaj Singh Kang. Distributed under* the LGPL.** $Id: pngr.cpp,v 1.1 2003/09/08 19:42:14 jasonk Exp $*/#ifdef HAVE_CONFIG_H#include"config.h"#endif#ifdef HAVE_LIBPNG#include<stdio.h>#include<stdlib.h>#include<qimage.h>#include<qfile.h>extern "C" {#include<png.h>}void kimgio_png_read( QImageIO *io ){ // open png file QImage image; FILE *fp = fopen ( io->fileName(), "r" ); int passes = 0; if( fp == 0 ) { debug( "Couldn't open %s for reading.", io->fileName() ); return; } // init png structures png_structp png_ptr = png_create_read_struct( // image ptr PNG_LIBPNG_VER_STRING, 0, 0, 0 ); if( png_ptr == 0 ) { fclose( fp ); return; } png_infop png_info = png_create_info_struct( png_ptr ); // info ptr if( png_info == 0 ) { png_destroy_read_struct( &png_ptr, 0, 0 ); fclose( fp ); return; } png_infop png_end = png_create_info_struct( png_ptr ); if( !png_end ) { png_destroy_read_struct( &png_ptr, &png_info, 0 ); fclose( fp ); return; } // error jump point if( setjmp( png_ptr->jmpbuf ) ) { png_destroy_read_struct( &png_ptr, &png_info, &png_end ); fclose( fp ); return; } // read header png_init_io( png_ptr, fp ); png_read_info( png_ptr, png_info ); // transformations png_set_packing( png_ptr ); png_set_strip_16( png_ptr ); if( !(png_ptr->color_type & PNG_COLOR_MASK_COLOR) ) { png_set_gray_to_rgb( png_ptr ); } else { png_set_expand( png_ptr ); } if( ! (png_info->color_type & PNG_COLOR_MASK_ALPHA) ) { debug( "using filler" ); png_set_filler( png_ptr, 0, PNG_FILLER_BEFORE ); } passes = png_set_interlace_handling ( png_ptr ); png_read_update_info( png_ptr, png_info ); if ( png_info->color_type != PNG_COLOR_TYPE_RGB_ALPHA ) { debug( "Colortype %d is not rgb/alpha", png_info->color_type ); } if( png_info->bit_depth != 8 ) { debug( "Depth %d is not 8", png_info->bit_depth ); } // create image if ( !image.create( png_info->width, png_info->height, 32 ) ) { // out of memory warning( "Out of memory creating QImage." ); png_destroy_read_struct( &png_ptr, &png_info, &png_end ); fclose( fp ); return; } // read image for( ; passes; passes-- ) { for( unsigned row = 0; row < png_info->height; row++ ) { png_read_row( png_ptr, image.scanLine( row ), NULL ); } } if ( png_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ) { debug( "Colortype %d is rgb/alpha", png_info->color_type ); image.setAlphaBuffer(true); } else { unsigned *pixels = (unsigned *) image.bits(); for( unsigned row = 0; row < png_info->height; row++ ) { for( int i = 0; i < image.width(); i++ ) { *pixels = *pixels >> 8; pixels++; } } } png_read_end( png_ptr, png_info ); io->setImage( image ); io->setStatus( 0 ); // clean up png_destroy_read_struct( &png_ptr, &png_info, &png_end ); fclose( fp ); return;}#if (defined PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 100)void kimgio_png_write( QImageIO *iio ){ QIODevice *f = ( iio->ioDevice() ); FILE *fp = 0; png_structp png_ptr; png_infop info_ptr; int colortype = 0; const QImage& image = iio->image(); int w = image.width(), h = image.height(); int numcolors = image.numColors(); int depth = image.depth() == 1 ? 1 : 8; //debug("Size:\t%d X %d\n\tColors:\t%d\n\tDepth:\t%d", // w, h, numcolors, image.depth()); if(numcolors > 0) { //debug("PALETTE"); colortype = PNG_COLOR_TYPE_PALETTE; } else if(image.hasAlphaBuffer()) { //debug("RGB_ALPHA"); colortype = PNG_COLOR_TYPE_RGB_ALPHA; } else { //debug("RGB"); colortype = PNG_COLOR_TYPE_RGB; } // open the file fp = fdopen(((QFile*)f)->handle(), "wb"); if (fp == 0) { iio->setStatus( -1 ); return; } /* Create and initialize the png_struct with the desired error handler * functions. If you want to use the default stderr and longjump method, * you can supply NULL for the last three parameters. We also check that * the library version is compatible with the one used at compile time, * in case we are using dynamically linked libraries. REQUIRED. */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if (png_ptr == 0) { fclose(fp); iio->setStatus( -2 ); return; } /* Allocate/initialize the image information data. REQUIRED */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == 0) { fclose(fp); png_destroy_write_struct(&png_ptr, (png_infopp)NULL); iio->setStatus( -3 ); return; } /* set up the output control if you are using standard C streams */ png_init_io(png_ptr, fp); /* Set the image information here. Width and height are up to 2^31, * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED */ png_set_IHDR(png_ptr, info_ptr, w, h, depth, colortype, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); /* set the palette if there is one. REQUIRED for indexed-color images */ if(numcolors > 0) { info_ptr->palette = (png_colorp)png_malloc(png_ptr, numcolors * sizeof (png_color)); for(int i = 0; i < numcolors; i++) { info_ptr->palette[i].red = qRed(image.color(i)); info_ptr->palette[i].blue = qBlue(image.color(i)); info_ptr->palette[i].green = qGreen(image.color(i)); } png_set_PLTE(png_ptr, info_ptr, info_ptr->palette, numcolors); } //optional significant bit chunk if(image.isGrayscale()) { info_ptr->sig_bit.gray = 8; } else { info_ptr->sig_bit.red = 8; info_ptr->sig_bit.green = 8; info_ptr->sig_bit.blue = 8; } if(image.hasAlphaBuffer()) info_ptr->sig_bit.alpha = 8; // Optional gamma chunk is strongly suggested if you have any guess // as to the correct gamma of the image. //png_set_gAMA(png_ptr, info_ptr, gamma); // Optionally write comments into the image //text_ptr[0].key = "Title"; //text_ptr[0].text = "Mona Lisa"; //text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE; //text_ptr[1].key = "Author"; //text_ptr[1].text = "Leonardo DaVinci"; //text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE; //text_ptr[2].key = "Description"; //text_ptr[2].text = "<long text>"; //text_ptr[2].compression = PNG_TEXT_COMPRESSION_zTXt; //png_set_text(png_ptr, info_ptr, text_ptr, 2); // Write the file header information. REQUIRED png_write_info(png_ptr, info_ptr); // Once we write out the header, the compression type on the text // chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or // PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again // at the end. // pack pixels into bytes png_set_packing( png_ptr ); png_set_strip_16( png_ptr ); // swap location of alpha bytes from ARGB to RGBA //png_set_swap_alpha(png_ptr); // Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into // RGB (4 channels -> 3 channels). The second parameter is not used. if ( depth == 8 && !image.hasAlphaBuffer() ) png_set_filler(png_ptr, 0, QImage::systemByteOrder() == QImage::BigEndian ? PNG_FILLER_BEFORE : PNG_FILLER_AFTER); // flip BGR pixels to RGB //png_set_bgr(png_ptr); // swap bytes of 16-bit files to most significant byte first //png_set_swap(png_ptr); // swap bits of 1, 2, 4 bit packed pixel formats //png_set_packswap(png_ptr); // The easiest way to write the image (you may have a different memory // layout, however, so choose what fits your needs best). You need to // use the first method if you aren't handling interlacing yourself.#define entire // One of the following output methods is REQUIRED #ifdef entire // write out the entire image data in one call png_byte **row_pointers = image.jumpTable(); png_write_image(png_ptr, row_pointers);#else // (no_entire) write out the image data by one or more scanlines // If you are only writing one row at a time, this works for (int y = 0; y < h; y++) { png_bytep row_pointer = image.scanLine(y); png_write_rows(png_ptr, row_pointer, 1); }#endif // (no_entire) use only one output method // You can write optional chunks like tEXt, zTXt, and tIME at the end as well. // It is REQUIRED to call this to finish writing the rest of the file png_write_end(png_ptr, info_ptr); // if you malloced the palette, free it here if(numcolors > 0) free(info_ptr->palette); // if you allocated any text comments, free them here // clean up after the write, and free any memory allocated png_destroy_write_struct(&png_ptr, (png_infopp)NULL); // close the file fclose(fp); iio->setStatus( 0 ); return;}#else // png library is too oldvoid kimgio_png_write( QImageIO *iio ){ // TODO: implement this warning("kimgio_png_write: not yet implemented for old PNG libraries");}#endif#endif /* HAVE_LIBPNG */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -