コード例 #1
0
ファイル: example.c プロジェクト: landswellsong/Stratagus
/* Read a PNG file.  You may want to return an error code if the read
 * fails (depending upon the failure).  There are two "prototypes" given
 * here - one where we are given the filename, and we need to open the
 * file, and the other where we are given an open file (possibly with
 * some or all of the magic bytes read - see comments above).
 */
#ifdef open_file /* prototype 1 */
void read_png(char *file_name)  /* We need to open the file */
{
   png_structp png_ptr;
   png_infop info_ptr;
   unsigned int sig_read = 0;
   png_uint_32 width, height;
   int bit_depth, color_type, interlace_type;
   FILE *fp;

   if ((fp = fopen(file_name, "rb")) == NULL)
      return (ERROR);

#else no_open_file /* prototype 2 */
void read_png(FILE *fp, unsigned int sig_read)  /* File is already open */
{
   png_structp png_ptr;
   png_infop info_ptr;
   png_uint_32 width, height;
   int bit_depth, color_type, interlace_type;
#endif no_open_file /* Only use one prototype! */

   /* 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 supply the
    * the compiler header file version, so that we know if the application
    * was compiled with a compatible version of the library.  REQUIRED
    */
   png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
      png_voidp user_error_ptr, user_error_fn, user_warning_fn);

   if (png_ptr == NULL)
   {
      fclose(fp);
      return (ERROR);
   }

   /* Allocate/initialize the memory for image information.  REQUIRED. */
   info_ptr = png_create_info_struct(png_ptr);
   if (info_ptr == NULL)
   {
      fclose(fp);
      png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
      return (ERROR);
   }

   /* Set error handling if you are using the setjmp/longjmp method (this is
    * the normal method of doing things with libpng).  REQUIRED unless you
    * set up your own error handlers in the png_create_read_struct() earlier.
    */

   if (setjmp(png_jmpbuf(png_ptr)))
   {
      /* Free all of the memory associated with the png_ptr and info_ptr */
      png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
      fclose(fp);
      /* If we get here, we had a problem reading the file */
      return (ERROR);
   }

   /* One of the following I/O initialization methods is REQUIRED */
#ifdef streams /* PNG file I/O method 1 */
   /* Set up the input control if you are using standard C streams */
   png_init_io(png_ptr, fp);

#else no_streams /* PNG file I/O method 2 */
   /* If you are using replacement read functions, instead of calling
    * png_init_io() here you would call:
    */
   png_set_read_fn(png_ptr, (void *)user_io_ptr, user_read_fn);
   /* where user_io_ptr is a structure you want available to the callbacks */
#endif no_streams /* Use only one I/O method! */

   /* If we have already read some of the signature */
   png_set_sig_bytes(png_ptr, sig_read);

#ifdef hilevel
   /*
    * If you have enough memory to read in the entire image at once,
    * and you need to specify only transforms that can be controlled
    * with one of the PNG_TRANSFORM_* bits (this presently excludes
    * dithering, filling, setting background, and doing gamma
    * adjustment), then you can read the entire image (including
    * pixels) into the info structure with this call:
    */
   png_read_png(png_ptr, info_ptr, png_transforms, png_voidp_NULL);

#else
   /* OK, you're doing it the hard way, with the lower-level functions */

   /* The call to png_read_info() gives us all of the information from the
    * PNG file before the first IDAT (image data chunk).  REQUIRED
    */
   png_read_info(png_ptr, info_ptr);

   png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
       &interlace_type, int_p_NULL, int_p_NULL);

   /* Set up the data transformations you want.  Note that these are all
    * optional.  Only call them if you want/need them.  Many of the
    * transformations only work on specific types of images, and many
    * are mutually exclusive.
    */

   /* Tell libpng to strip 16 bit/color files down to 8 bits/color */
   png_set_strip_16(png_ptr);

   /* Strip alpha bytes from the input data without combining with the
    * background (not recommended).
    */
   png_set_strip_alpha(png_ptr);

   /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single
    * byte into separate bytes (useful for paletted and grayscale images).
    */
   png_set_packing(png_ptr);

   /* Change the order of packed pixels to least significant bit first
    * (not useful if you are using png_set_packing). */
   png_set_packswap(png_ptr);

   /* Expand paletted colors into true RGB triplets */
   if (color_type == PNG_COLOR_TYPE_PALETTE)
      png_set_palette_to_rgb(png_ptr);

   /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
   if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
      png_set_expand_gray_1_2_4_to_8(png_ptr);

   /* Expand paletted or RGB images with transparency to full alpha channels
    * so the data will be available as RGBA quartets.
    */
   if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
      png_set_tRNS_to_alpha(png_ptr);

   /* Set the background color to draw transparent and alpha images over.
    * It is possible to set the red, green, and blue components directly
    * for paletted images instead of supplying a palette index.  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_16 my_background, *image_background;

   if (png_get_bKGD(png_ptr, info_ptr, &image_background))
      png_set_background(png_ptr, image_background,
                         PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
   else
      png_set_background(png_ptr, &my_background,
                         PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);

   /* Some suggestions as to how to get a screen gamma value
    *
    * Note that screen gamma is the display_exponent, which includes
    * the CRT_exponent and any correction for viewing conditions
    */
   if (/* We have a user-defined screen gamma value */)
   {
      screen_gamma = user-defined screen_gamma;
   }
   /* This is one way that applications share the same screen gamma value */
   else if ((gamma_str = getenv("SCREEN_GAMMA")) != NULL)
コード例 #2
0
void PNGAPI
png_read_png(png_structp png_ptr, png_infop info_ptr,
                           int transforms,
                           voidp params)
{
   int row;

   if (png_ptr == NULL)
      return;

   /* png_read_info() gives us all of the information from the
    * PNG file before the first IDAT (image data chunk).
    */
   png_read_info(png_ptr, info_ptr);
   if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep))
      png_error(png_ptr, "Image is too high to process with png_read_png()");

   /* -------------- image transformations start here ------------------- */

#ifdef PNG_READ_16_TO_8_SUPPORTED
   /* Tell libpng to strip 16 bit/color files down to 8 bits per color.
    */
   if (transforms & PNG_TRANSFORM_STRIP_16)
      png_set_strip_16(png_ptr);
#endif

#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
   /* Strip alpha bytes from the input data without combining with
    * the background (not recommended).
    */
   if (transforms & PNG_TRANSFORM_STRIP_ALPHA)
      png_set_strip_alpha(png_ptr);
#endif

#if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED)
   /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single
    * byte into separate bytes (useful for paletted and grayscale images).
    */
   if (transforms & PNG_TRANSFORM_PACKING)
      png_set_packing(png_ptr);
#endif

#ifdef PNG_READ_PACKSWAP_SUPPORTED
   /* Change the order of packed pixels to least significant bit first
    * (not useful if you are using png_set_packing).
    */
   if (transforms & PNG_TRANSFORM_PACKSWAP)
      png_set_packswap(png_ptr);
#endif

#ifdef PNG_READ_EXPAND_SUPPORTED
   /* Expand paletted colors into true RGB triplets
    * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel
    * Expand paletted or RGB images with transparency to full alpha
    * channels so the data will be available as RGBA quartets.
    */
   if (transforms & PNG_TRANSFORM_EXPAND)
      if ((png_ptr->bit_depth < 8) ||
          (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ||
          (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))
         png_set_expand(png_ptr);
#endif

   /* We don't handle background color or gamma transformation or quantizing.
    */

#ifdef PNG_READ_INVERT_SUPPORTED
   /* Invert monochrome files to have 0 as white and 1 as black
    */
   if (transforms & PNG_TRANSFORM_INVERT_MONO)
      png_set_invert_mono(png_ptr);
#endif

#ifdef PNG_READ_SHIFT_SUPPORTED
   /* If you want to shift the pixel values from the range [0,255] or
    * [0,65535] to the original [0,7] or [0,31], or whatever range the
    * colors were originally in:
    */
   if ((transforms & PNG_TRANSFORM_SHIFT)
       && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT))
   {
      png_color_8p sig_bit;

      png_get_sBIT(png_ptr, info_ptr, &sig_bit);
      png_set_shift(png_ptr, sig_bit);
   }
#endif

#ifdef PNG_READ_BGR_SUPPORTED
   /* Flip the RGB pixels to BGR (or RGBA to BGRA)
    */
   if (transforms & PNG_TRANSFORM_BGR)
      png_set_bgr(png_ptr);
#endif

#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
   /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR)
    */
   if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
       png_set_swap_alpha(png_ptr);
#endif

#ifdef PNG_READ_SWAP_SUPPORTED
   /* Swap bytes of 16 bit files to least significant byte first
    */
   if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
      png_set_swap(png_ptr);
#endif

/* Added at libpng-1.2.41 */
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
   /* Invert the alpha channel from opacity to transparency
    */
   if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
       png_set_invert_alpha(png_ptr);
#endif

/* Added at libpng-1.2.41 */
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
   /* Expand grayscale image to RGB
    */
   if (transforms & PNG_TRANSFORM_GRAY_TO_RGB)
       png_set_gray_to_rgb(png_ptr);
#endif

   /* We don't handle adding filler bytes */

   /* Optional call to gamma correct and add the background to the palette
    * and update info structure.  REQUIRED if you are expecting libpng to
    * update the palette for you (i.e., you selected such a transform above).
    */
   png_read_update_info(png_ptr, info_ptr);

   /* -------------- image transformations end here ------------------- */

   png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
   if (info_ptr->row_pointers == NULL)
   {
    png_uint_32 iptr;

      info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr,
         info_ptr->height * png_sizeof(png_bytep));
      for (iptr=0; iptr<info_ptr->height; iptr++)
         info_ptr->row_pointers[iptr] = NULL;

      info_ptr->free_me |= PNG_FREE_ROWS;

      for (row = 0; row < (int)info_ptr->height; row++)
         info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr,
            png_get_rowbytes(png_ptr, info_ptr));
   }

   png_read_image(png_ptr, info_ptr->row_pointers);
   info_ptr->valid |= PNG_INFO_IDAT;

   /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */
   png_read_end(png_ptr, info_ptr);

   transforms = transforms; /* Quiet compiler warnings */
   params = params;

}
コード例 #3
0
bool PNGImageFileType::write(const Image        *OSG_PNG_ARG(pImage  ), 
                                   std::ostream &OSG_PNG_ARG(os      ),
                             const std::string  &OSG_PNG_ARG(mimetype))
{
#ifdef OSG_WITH_PNG

    png_structp png_ptr;
    png_infop info_ptr;

    if(pImage->getDimension() < 1 || pImage->getDimension() > 2)
    {
        FWARNING(("PNGImageFileType::write: invalid dimension %d!\n",
                  pImage->getDimension()));

        return false;
    }
    
    /* 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, &errorOutput, &warningOutput);

    if(png_ptr == NULL)
        return false;

    /* Allocate/initialize the image information data.  REQUIRED */
    info_ptr = png_create_info_struct(png_ptr);

    if(info_ptr == NULL)
    {
        png_destroy_write_struct(&png_ptr,  NULL);
        return false;
    }
    
    /* set up the output handlers */
    png_set_write_fn(png_ptr, &os, &osWriteFunc, &osFlushFunc);

    /* This is the hard way */

    /* 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
    */

    Int32 ctype;
    switch(pImage->getPixelFormat())
    {
        case Image::OSG_L_PF:       
            ctype = PNG_COLOR_TYPE_GRAY;        
            break;
            
        case Image::OSG_LA_PF:      
            ctype = PNG_COLOR_TYPE_GRAY_ALPHA;          
            break;
            
#if defined(GL_BGR) || defined(GL_BGR_EXT)
        case Image::OSG_BGR_PF:
#endif
        case Image::OSG_RGB_PF:     
            ctype = PNG_COLOR_TYPE_RGB;                 
            break;
            
#if defined(GL_BGRA) || defined(GL_BGRA_EXT)
        case Image::OSG_BGRA_PF:
#endif
        case Image::OSG_RGBA_PF:    
            ctype = PNG_COLOR_TYPE_RGB_ALPHA;           
            break;
            
        default:
            FWARNING(("PNGImageFileType::write: unknown pixel format %d!\n",
                      pImage->getPixelFormat()));
            png_destroy_write_struct(&png_ptr,  NULL);
            return false;
            
    }
    
    Int32 bit_depth;
    switch(pImage->getDataType()) 
    {
        case Image::OSG_UINT8_IMAGEDATA:
            bit_depth = 8;
            break;
        case Image::OSG_UINT16_IMAGEDATA:
            bit_depth = 16;
            break;
        default:
            FWARNING (("Invalid pixeldepth, cannot store data\n"));
            return false;
    };

    png_set_IHDR(png_ptr, info_ptr, pImage->getWidth(), pImage->getHeight(),
                 bit_depth,ctype,      
                 PNG_INTERLACE_NONE, 
                 PNG_COMPRESSION_TYPE_BASE, 
                 PNG_FILTER_TYPE_BASE);

    // set resolution png supports only meter per pixel,
    // so we do a conversion from dpi with some rounding.
    png_uint_32 res_x = png_uint_32(pImage->getResX());
    png_uint_32 res_y = png_uint_32(pImage->getResY());
    if(pImage->getResUnit() == Image::OSG_RESUNIT_INCH)
    {
        res_x = png_uint_32((pImage->getResX() * 39.37007874f) < 0.0f ?
                            (pImage->getResX() * 39.37007874f) - 0.5f :
                            (pImage->getResX() * 39.37007874f) + 0.5f);
        res_y = png_uint_32((pImage->getResY() * 39.37007874f) < 0.0f ?
                            (pImage->getResY() * 39.37007874f) - 0.5f :
                            (pImage->getResY() * 39.37007874f) + 0.5f);
    }

    png_set_pHYs(png_ptr, info_ptr, res_x, res_y,
                 PNG_RESOLUTION_METER);

#if 0
    /* optional significant bit chunk */
    /* if we are dealing with a grayscale image then */
    sig_bit.gray = true_bit_depth;
    /* otherwise, if we are dealing with a color image then */
    sig_bit.red = true_red_bit_depth;
    sig_bit.green = true_green_bit_depth;
    sig_bit.blue = true_blue_bit_depth;
    /* if the image has an alpha channel then */
    sig_bit.alpha = true_alpha_bit_depth;
    png_set_sBIT(png_ptr, info_ptr, sig_bit);


    /* 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;
#ifdef PNG_iTXt_SUPPORTED
    text_ptr[0].lang = NULL;
    text_ptr[1].lang = NULL;
    text_ptr[2].lang = NULL;
#endif
    png_set_text(png_ptr, info_ptr, text_ptr, 3);
#endif
    /* other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs, */
    /* note that if sRGB is present the gAMA and cHRM chunks must be ignored
    * on read and must be written in accordance with the sRGB profile */

    /* Write the file header information.  REQUIRED */
    png_write_info(png_ptr, info_ptr);

#if BYTE_ORDER == LITTLE_ENDIAN
    if (bit_depth == 16) 
      png_set_swap(png_ptr);
#endif

#if 0
    /* invert monochrome pixels */
    png_set_invert_mono(png_ptr);

    /* Shift the pixels up to a legal bit depth and fill in
    * as appropriate to correctly scale the image.
    */
    png_set_shift(png_ptr, &sig_bit);

    /* pack pixels into bytes */
    png_set_packing(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.
    */
    png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);

    /* 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);
#endif

    if(pImage->getPixelFormat() == Image::OSG_BGR_PF ||
       pImage->getPixelFormat() == Image::OSG_BGRA_PF )
    {
        /* flip BGR pixels to RGB */
        png_set_bgr(png_ptr);
        
        /* swap location of alpha bytes from ARGB to RGBA */
        png_set_swap_alpha(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.
     */
    png_bytep *row_pointers = new png_bytep [pImage->getHeight()];
    
    for(Int32 k = 0; k < pImage->getHeight(); k++)
    {
        row_pointers[k] = 
            (const_cast<UInt8 *>(pImage->getData())) + 
            (pImage->getHeight() - 1 - k) * 
            pImage->getWidth() * pImage->getBpp();
    }
    
    /* write out the entire image data in one call */
    png_write_image(png_ptr, row_pointers);

    /* It is REQUIRED to call this to finish writing the rest of the file */
    png_write_end(png_ptr, info_ptr);
    
    /* clean up after the write, and free any memory allocated */
    png_destroy_write_struct(&png_ptr, &info_ptr);

    delete [] row_pointers;

    /* that's it */
    return true;

#else
    SWARNING << getMimeType() 
             << " write is not compiled into the current binary " 
             << endLog;

    return false;
#endif
}
コード例 #4
0
ファイル: Png.c プロジェクト: alexey-lysiuk/doom64ex-osx
cache Png_Create(int width, int height, int numpal, dPalette_t* pal,
				 int bits, cache data, int lump, int* size)
{
	int i = 0;
	int x = 0;
	int j = 0;
	cache image;
	cache out;
	cache* row_pointers;
	png_structp png_ptr;
	png_infop info_ptr;
	png_colorp palette;

	// setup png pointer
	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
	if(png_ptr == NULL)
	{
		WGen_Complain("Png_Create: Failed getting png_ptr");
		return NULL;
	}

	// setup info pointer
	info_ptr = png_create_info_struct(png_ptr);
	if(info_ptr == NULL)
	{
		png_destroy_write_struct(&png_ptr, NULL);
		WGen_Complain("Png_Create: Failed getting info_ptr");
		return NULL;
	}

	// what does this do again?
	if(setjmp(png_jmpbuf(png_ptr)))
	{
		png_destroy_write_struct(&png_ptr, &info_ptr);
		WGen_Complain("Png_Create: Failed on setjmp");
		return NULL;
	}

	// setup custom data writing procedure
	png_set_write_fn(png_ptr, NULL, Png_WriteData, NULL);

	// setup image
	png_set_IHDR(
		png_ptr,
		info_ptr,
		width,
		height,
		bits,
		PNG_COLOR_TYPE_PALETTE,
		PNG_INTERLACE_NONE,
		PNG_COMPRESSION_TYPE_BASE,
		PNG_FILTER_TYPE_DEFAULT);

	// setup palette
	palette = (png_colorp)Mem_Alloc((16 * numpal) * png_sizeof(png_color));

	// copy dPalette_t data over to png_colorp
	for(x = 0, j = 0; x < numpal; x++)
	{
		for(i = 0; i < 16; i++)
		{
			palette[j].red = pal[j].r;
			palette[j].green = pal[j].g;
			palette[j].blue = pal[j].b;
			j++;
		}
	}

    i = 0;

	// add palette to png
	png_set_PLTE(png_ptr, info_ptr, palette, (16 * numpal));

    // set transparent index
    if(palette[0].red == 0 && palette[0].green == 0 && palette[0].blue == 0)
    {
        char tmp[9];

        strncpy(tmp, romWadFile.lump[lump].name, 8);
        tmp[0] -= (char)0x80;
        tmp[8] = 0;

        // Exempt these lumps
        if(strcmp(tmp, "FIRE") && /*strcmp(tmp, "USLEGAL") &&
            strcmp(tmp, "TITLE") &&*/ strcmp(tmp, "EVIL") &&
            /*strcmp(tmp, "IDCRED1") && strcmp(tmp, "WMSCRED1") &&*/
            strcmp(tmp, "SPACE") && strcmp(tmp, "CLOUD") &&
            strcmp(tmp, "FINAL"))
            png_set_tRNS(png_ptr, info_ptr, (png_bytep)&i, 1, NULL);
    }

	// add png info to data
	png_write_info(png_ptr, info_ptr);

	// add offset chunk if png is a sprite
	if(INSPRITELIST(lump))
	{
		for(i = 0; i < spriteExCount; i++)
		{
			if(exSpriteLump[i].lumpRef == lump)
			{
				int offs[2];

				offs[0] = WGen_Swap32(exSpriteLump[i].sprite.offsetx);
				offs[1] = WGen_Swap32(exSpriteLump[i].sprite.offsety);

				png_write_chunk(png_ptr, "grAb", (byte*)offs, 8);
				break;
			}
		}
	}

	// setup packing if needed
	png_set_packing(png_ptr);
	png_set_packswap(png_ptr);

	// copy data over
	image = data;
	row_pointers = (cache*)Mem_Alloc(sizeof(byte*) * height);

	for(i = 0; i < height; i++)
	{
		row_pointers[i] = (cache)Mem_Alloc(width);
		if(bits == 4)
		{
			for(j = 0; j < width; j += 2)
			{
				row_pointers[i][j] = *image & 0xf;
				row_pointers[i][j+1] = *image >> 4;
				image++;
			}
		}
		else
		{
			for(j = 0; j < width; j++)
			{
				row_pointers[i][j] = *image;
				image++;
			}
		}

		png_write_rows(png_ptr, &row_pointers[i], 1);
	}
コード例 #5
0
ファイル: qpnghandler.cpp プロジェクト: 2gis/2gisqt5android
bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image, volatile int quality_in, const QString &description,
                                 int off_x_in, int off_y_in)
{
    QPoint offset = image.offset();
    int off_x = off_x_in + offset.x();
    int off_y = off_y_in + offset.y();

    png_structp png_ptr;
    png_infop info_ptr;

    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,0,0,0);
    if (!png_ptr) {
        return false;
    }

    png_set_error_fn(png_ptr, 0, 0, qt_png_warning);

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        png_destroy_write_struct(&png_ptr, 0);
        return false;
    }

    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_write_struct(&png_ptr, &info_ptr);
        return false;
    }

    int quality = quality_in;
    if (quality >= 0) {
        if (quality > 9) {
            qWarning("PNG: Quality %d out of range", quality);
            quality = 9;
        }
        png_set_compression_level(png_ptr, quality);
    }

    png_set_write_fn(png_ptr, (void*)this, qpiw_write_fn, qpiw_flush_fn);


    int color_type = 0;
    if (image.colorCount()) {
        if (image.isGrayscale())
            color_type = PNG_COLOR_TYPE_GRAY;
        else
            color_type = PNG_COLOR_TYPE_PALETTE;
    }
    else if (image.format() == QImage::Format_Grayscale8)
        color_type = PNG_COLOR_TYPE_GRAY;
    else if (image.hasAlphaChannel())
        color_type = PNG_COLOR_TYPE_RGB_ALPHA;
    else
        color_type = PNG_COLOR_TYPE_RGB;

    png_set_IHDR(png_ptr, info_ptr, image.width(), image.height(),
                 image.depth() == 1 ? 1 : 8, // per channel
                 color_type, 0, 0, 0);       // sets #channels

    if (gamma != 0.0) {
        png_set_gAMA(png_ptr, info_ptr, 1.0/gamma);
    }

    if (image.format() == QImage::Format_MonoLSB)
       png_set_packswap(png_ptr);

    if (color_type == PNG_COLOR_TYPE_PALETTE) {
        // Paletted
        int num_palette = qMin(256, image.colorCount());
        png_color palette[256];
        png_byte trans[256];
        int num_trans = 0;
        for (int i=0; i<num_palette; i++) {
            QRgb rgba=image.color(i);
            palette[i].red = qRed(rgba);
            palette[i].green = qGreen(rgba);
            palette[i].blue = qBlue(rgba);
            trans[i] = qAlpha(rgba);
            if (trans[i] < 255) {
                num_trans = i+1;
            }
        }
        png_set_PLTE(png_ptr, info_ptr, palette, num_palette);

        if (num_trans) {
            png_set_tRNS(png_ptr, info_ptr, trans, num_trans, 0);
        }
    }

    // Swap ARGB to RGBA (normal PNG format) before saving on
    // BigEndian machines
    if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
        png_set_swap_alpha(png_ptr);
    }

    // Qt==ARGB==Big(ARGB)==Little(BGRA). But RGB888 is RGB regardless
    if (QSysInfo::ByteOrder == QSysInfo::LittleEndian
        && image.format() != QImage::Format_RGB888) {
        png_set_bgr(png_ptr);
    }

    if (off_x || off_y) {
        png_set_oFFs(png_ptr, info_ptr, off_x, off_y, PNG_OFFSET_PIXEL);
    }

    if (frames_written > 0)
        png_set_sig_bytes(png_ptr, 8);

    if (image.dotsPerMeterX() > 0 || image.dotsPerMeterY() > 0) {
        png_set_pHYs(png_ptr, info_ptr,
                image.dotsPerMeterX(), image.dotsPerMeterY(),
                PNG_RESOLUTION_METER);
    }

    set_text(image, png_ptr, info_ptr, description);

    png_write_info(png_ptr, info_ptr);

    if (image.depth() != 1)
        png_set_packing(png_ptr);

    if (color_type == PNG_COLOR_TYPE_RGB && image.format() != QImage::Format_RGB888)
        png_set_filler(png_ptr, 0,
            QSysInfo::ByteOrder == QSysInfo::BigEndian ?
                PNG_FILLER_BEFORE : PNG_FILLER_AFTER);

    if (looping >= 0 && frames_written == 0) {
        uchar data[13] = "NETSCAPE2.0";
        //                0123456789aBC
        data[0xB] = looping%0x100;
        data[0xC] = looping/0x100;
        png_write_chunk(png_ptr, const_cast<png_bytep>((const png_byte *)"gIFx"), data, 13);
    }
    if (ms_delay >= 0 || disposal!=Unspecified) {
        uchar data[4];
        data[0] = disposal;
        data[1] = 0;
        data[2] = (ms_delay/10)/0x100; // hundredths
        data[3] = (ms_delay/10)%0x100;
        png_write_chunk(png_ptr, const_cast<png_bytep>((const png_byte *)"gIFg"), data, 4);
    }

    int height = image.height();
    int width = image.width();
    switch (image.format()) {
    case QImage::Format_Mono:
    case QImage::Format_MonoLSB:
    case QImage::Format_Indexed8:
    case QImage::Format_Grayscale8:
    case QImage::Format_RGB32:
    case QImage::Format_ARGB32:
    case QImage::Format_RGB888:
        {
            png_bytep* row_pointers = new png_bytep[height];
            for (int y=0; y<height; y++)
                row_pointers[y] = const_cast<png_bytep>(image.constScanLine(y));
            png_write_image(png_ptr, row_pointers);
            delete [] row_pointers;
        }
        break;
    default:
        {
            QImage::Format fmt = image.hasAlphaChannel() ? QImage::Format_ARGB32 : QImage::Format_RGB32;
            QImage row;
            png_bytep row_pointers[1];
            for (int y=0; y<height; y++) {
                row = image.copy(0, y, width, 1).convertToFormat(fmt);
                row_pointers[0] = const_cast<png_bytep>(row.constScanLine(0));
                png_write_rows(png_ptr, row_pointers, 1);
            }
        }
        break;
    }

    png_write_end(png_ptr, info_ptr);
    frames_written++;

    png_destroy_write_struct(&png_ptr, &info_ptr);

    return true;
}
コード例 #6
0
ファイル: fbutils.c プロジェクト: noisegate/fbpy
int read_PNG(char *file_name)
{
    /*
     * Took this code from doc/fblib
     * and adjusted it to the likings
     * of this program.
     * ?i
     * It is really awesome that a NOOB
     * like me, Noisegate can actually
     * make useable software on an open
     * system like this Linux...
     *
     * openSOFtWARE rocKS
     */

    png_structp png_ptr;
    png_infop info_ptr;
    unsigned int sig_read = 0;
    png_uint_32 _width, _height, row;
    int bit_depth, color_type, interlace_type;
    FILE *fp;

    float screen_gamma;

    if ((fp = fopen(file_name, "rb")) == NULL)
          return -1;

    /* 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 supply the
     * the compiler header file version, so that we know if the application
     * was compiled with a compatible version of the library.  REQUIRED
     */
    //png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, png_voidp user_error_ptr, user_error_fn, user_warning_fn);
    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 
            (png_voidp)NULL, 
            (png_error_ptr)NULL, 
            (png_error_ptr)NULL);

    if (png_ptr == NULL){
        fclose(fp);
        return -1;
    }

    /* Allocate/initialize the memory for image information.  REQUIRED. */
    info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL) {
        fclose(fp);
        png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
        return -1;
    }

    /* Set error handling if you are using the setjmp/longjmp method (this is
    * the normal method of doing things with libpng).  REQUIRED unless you
    * set up your own error handlers in the png_create_read_struct() earlier.
    */

    if (setjmp(png_jmpbuf(png_ptr))) {
        /* Free all of the memory associated with the png_ptr and info_ptr */
        png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
        fclose(fp);
        /* If we get here, we had a problem reading the file */
        fprintf(stderr, "Error: Couldn't read the file.");
        return -1;
    }

    /* One of the following I/O initialization methods is REQUIRED */
    /* Set up the input control if you are using standard C streams */
    png_init_io(png_ptr, fp);

    /* If we have already read some of the signature */
    png_set_sig_bytes(png_ptr, sig_read);

   /* OK, you're doing it the hard way, with the lower-level functions */

   /* The call to png_read_info() gives us all of the information from the
    * PNG file before the first IDAT (image data chunk).  REQUIRED
    */
   png_read_info(png_ptr, info_ptr);

   png_get_IHDR(png_ptr, info_ptr, &_width, &_height, &bit_depth, &color_type,
       &interlace_type, int_p_NULL, int_p_NULL);

   /* Set up the data transformations you want.  Note that these are all
    * optional.  Only call them if you want/need them.  Many of the
    * transformations only work on specific types of images, and many
    * are mutually exclusive.
    */

   /* Tell libpng to strip 16 bit/color files down to 8 bits/color */
   png_set_strip_16(png_ptr);

   /* Strip alpha bytes from the input data without combining with the
    * background (not recommended).
    */
   //png_set_strip_alpha(png_ptr);

   /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single
    * byte into separate bytes (useful for paletted and grayscale images).
    */
   png_set_packing(png_ptr);

   /* Change the order of packed pixels to least significant bit first
    * (not useful if you are using png_set_packing). */
   png_set_packswap(png_ptr);

   /* Expand paletted colors into true RGB triplets */
   if (color_type == PNG_COLOR_TYPE_PALETTE)
      png_set_palette_to_rgb(png_ptr);

   /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
   if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
      png_set_expand_gray_1_2_4_to_8(png_ptr);

   /* Expand paletted or RGB images with transparency to full alpha channels
    * so the data will be available as RGBA quartets.
    */
   if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
      png_set_tRNS_to_alpha(png_ptr);

   /* Set the background color to draw transparent and alpha images over.
    * It is possible to set the red, green, and blue components directly
    * for paletted images instead of supplying a palette index.  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_16 my_background, *image_background;

   if (png_get_bKGD(png_ptr, info_ptr, &image_background))
      png_set_background(png_ptr, image_background,
                         PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
   else
      png_set_background(png_ptr, &my_background,
                         PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);


   screen_gamma = 1.0;

   int intent;

   if (png_get_sRGB(png_ptr, info_ptr, &intent))
      png_set_gamma(png_ptr, screen_gamma, 0.45455);
   else
   {
      double image_gamma;
      if (png_get_gAMA(png_ptr, info_ptr, &image_gamma))
         png_set_gamma(png_ptr, screen_gamma, image_gamma);
      else
         png_set_gamma(png_ptr, screen_gamma, 0.45455);
   }

   /* Invert monochrome files to have 0 as white and 1 as black */
   png_set_invert_mono(png_ptr);

   /* If you want to shift the pixel values from the range [0,255] or
    * [0,65535] to the original [0,7] or [0,31], or whatever range the
    * colors were originally in:
    */
   if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT))
   {
      png_color_8p sig_bit_p;

      png_get_sBIT(png_ptr, info_ptr, &sig_bit_p);
      png_set_shift(png_ptr, sig_bit_p);
   }

   /* Flip the RGB pixels to BGR (or RGBA to BGRA) */
   if (color_type & PNG_COLOR_MASK_COLOR)
      png_set_bgr(png_ptr);

   /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */
   png_set_swap_alpha(png_ptr);

   /* Swap bytes of 16 bit files to least significant byte first */
   png_set_swap(png_ptr);

   /* Add filler (or alpha) byte (before/after each RGB triplet) */
   png_set_filler(png_ptr, 0x00, PNG_FILLER_AFTER);

   /* Turn on interlace handling.  REQUIRED if you are not using
    * png_read_image().  To see how to handle interlacing passes,
    * see the png_read_row() method below:
    */
   //number_passes = png_set_interlace_handling(png_ptr);

   /* Optional call to gamma correct and add the background to the palette
    * and update info structure.  REQUIRED if you are expecting libpng to
    * update the palette for you (ie you selected such a transform above).
    */
   png_read_update_info(png_ptr, info_ptr);

   /* Allocate the memory to hold the image using the fields of info_ptr. */

   /* The easiest way to read the image: */
   png_bytep row_pointers[_height];

   /* Clear the pointer array */
   for (row = 0; row < _height; row++)
      row_pointers[row] = NULL;

   for (row = 0; row < _height; row++)
      row_pointers[row] = png_malloc(png_ptr, png_get_rowbytes(png_ptr,
         info_ptr));

   /* Now it's time to read the image.  One of these methods is REQUIRED */
   png_read_image(png_ptr, row_pointers);


   /* Now mess this rowpointer thing into the tmp_buf
    * U dont know if width>_width and height>_height
    * so we trunc the guy
    */
    
   int maxY = _height>height?height:_height;
   int maxX = _width>width?finfo.line_length:_width;
   int pix_offset=0;

   for (row=0; row<maxY;row++){
       pix_offset = Ox*BPP + ((Oy+row)*finfo.line_length);
       memcpy(tmp_buf+pix_offset, row_pointers[row], maxX*BPP);
   }

   /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */
   png_read_end(png_ptr, info_ptr);

   /* At this point you have read the entire image */

   /* Clean up after the read, and free any memory allocated - REQUIRED */
   png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);

   /* Close the file */
   fclose(fp);


   //printf("png W x H = %i x %i\n", _width, _height);
   /* That's it */
    return 0;
}
コード例 #7
0
ファイル: loader-png.cpp プロジェクト: mettalla/dali
bool LoadBitmapFromPng( const ResourceLoadingClient& client, const ImageLoader::Input& input, Integration::Bitmap& bitmap )
{
  png_structp png = NULL;
  png_infop info = NULL;
  auto_png autoPng(png, info);

  /// @todo: consider parameters
  unsigned int y;
  unsigned int width, height;
  unsigned char *pixels;
  png_bytep *rows;
  unsigned int bpp = 0; // bytes per pixel
  bool valid = false;

  // Load info from the header
  if( !LoadPngHeader( input.file, width, height, png, info ) )
  {
    return false;
  }

  Pixel::Format pixelFormat = Pixel::RGBA8888;

  // decide pixel format
  unsigned int colordepth = png_get_bit_depth(png, info);

  // Ask PNGLib to convert high precision images into something we can use:
  if (colordepth == 16)
  {
    png_set_strip_16(png);
    colordepth = 8;
  }

  png_byte colortype = png_get_color_type(png, info);

  if(colortype == PNG_COLOR_TYPE_GRAY)
  {
    switch( colordepth )
    {
      case 8:
      {
        pixelFormat = Pixel::L8;
        valid = true;
        break;
      }
      default:
      {
        break;
      }
    }
  }
  else if(colortype == PNG_COLOR_TYPE_GRAY_ALPHA)
  {
    switch(colordepth)
    {
      case 8:
      {
        pixelFormat = Pixel::LA88;
        valid = true;
        break;
      }
      default:
      {
        break;
      }
    }
  }
  else if(colortype == PNG_COLOR_TYPE_RGB )
  {
    switch(colordepth)
    {
      case 8:
      {
        pixelFormat = Pixel::RGB888;
        valid = true;
        break;
      }
      case 5:      /// @todo is this correct for RGB16 5-6-5 ?
      {
        pixelFormat = Pixel::RGB565;
        valid = true;
        break;
      }
      default:
      {
        break;
      }
    }
  }
  else if(colortype == PNG_COLOR_TYPE_RGBA)
  {
    switch(colordepth)
    {
      case 8:
      {
        pixelFormat = Pixel::RGBA8888;
        valid = true;
        break;
      }
      default:
      {
        break;
      }
    }
  }
  else if(colortype == PNG_COLOR_TYPE_PALETTE)
  {
    switch(colordepth)
    {
      case 2:
      case 4:
      case 8:
      {
        /* Expand paletted or RGB images with transparency to full alpha channels
         * so the data will be available as RGBA quartets. PNG_INFO_tRNS = 0x10
         */
        if(png_get_valid(png, info, PNG_INFO_tRNS) == 0x10)
        {
          pixelFormat = Pixel::RGBA8888;
          valid = true;
        }
        else
        {
          pixelFormat = Pixel::RGB888;
          png_set_packing(png);
          png_set_packswap(png);
          png_set_palette_to_rgb(png);
          valid = true;
        }
        break;
      }
      default:
      {
        break;
      }
    }
  }

  if( !valid )
  {
    DALI_LOG_WARNING( "Unsupported png format\n" );
    return false;
  }

  // bytes per pixel
  bpp = Pixel::GetBytesPerPixel(pixelFormat);

  png_read_update_info(png, info);

  if(setjmp(png_jmpbuf(png)))
  {
    DALI_LOG_WARNING("error during png_read_image\n");
    return false;
  }

  unsigned int rowBytes = png_get_rowbytes(png, info);

  unsigned int bufferWidth   = GetTextureDimension(width);
  unsigned int bufferHeight  = GetTextureDimension(height);
  unsigned int stride        = bufferWidth*bpp;

  // not sure if this ever happens
  if( rowBytes > stride )
  {
    stride = GetTextureDimension(rowBytes);
    bufferWidth = stride / bpp;
  }

  // decode the whole image into bitmap buffer
  pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(pixelFormat, width, height, bufferWidth, bufferHeight);

  DALI_ASSERT_DEBUG(pixels);
  rows = (png_bytep*) malloc(sizeof(png_bytep) * height);
  for(y=0; y<height; y++)
  {
    rows[y] = (png_byte*) (pixels + y * stride);
  }

  // decode image
  png_read_image(png, rows);

  free(rows);

  return true;
}
コード例 #8
0
ファイル: io_base.hpp プロジェクト: Jesse-V/Folding-Atomata
 void set_packswap() const
 {
     TRACE_IO_TRANSFORM("png_set_packswap\n");
     png_set_packswap(m_png);
 }
コード例 #9
0
ファイル: pngread.c プロジェクト: qtekfun/htcDesire820Kernel
void PNGAPI
png_read_png(png_structp png_ptr, png_infop info_ptr,
             int transforms,
             voidp params)
{
    int row;

    if(png_ptr == NULL) return;
#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
    if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
        png_set_invert_alpha(png_ptr);
#endif

    png_read_info(png_ptr, info_ptr);
    if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep))
        png_error(png_ptr,"Image is too high to process with png_read_png()");



#if defined(PNG_READ_16_TO_8_SUPPORTED)
    if (transforms & PNG_TRANSFORM_STRIP_16)
        png_set_strip_16(png_ptr);
#endif

#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
    if (transforms & PNG_TRANSFORM_STRIP_ALPHA)
        png_set_strip_alpha(png_ptr);
#endif

#if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED)
    if (transforms & PNG_TRANSFORM_PACKING)
        png_set_packing(png_ptr);
#endif

#if defined(PNG_READ_PACKSWAP_SUPPORTED)
    if (transforms & PNG_TRANSFORM_PACKSWAP)
        png_set_packswap(png_ptr);
#endif

#if defined(PNG_READ_EXPAND_SUPPORTED)
    if (transforms & PNG_TRANSFORM_EXPAND)
        if ((png_ptr->bit_depth < 8) ||
                (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ||
                (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))
            png_set_expand(png_ptr);
#endif


#if defined(PNG_READ_INVERT_SUPPORTED)
    if (transforms & PNG_TRANSFORM_INVERT_MONO)
        png_set_invert_mono(png_ptr);
#endif

#if defined(PNG_READ_SHIFT_SUPPORTED)
    if ((transforms & PNG_TRANSFORM_SHIFT)
            && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT))
    {
        png_color_8p sig_bit;

        png_get_sBIT(png_ptr, info_ptr, &sig_bit);
        png_set_shift(png_ptr, sig_bit);
    }
#endif

#if defined(PNG_READ_BGR_SUPPORTED)
    if (transforms & PNG_TRANSFORM_BGR)
        png_set_bgr(png_ptr);
#endif

#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
    if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
        png_set_swap_alpha(png_ptr);
#endif

#if defined(PNG_READ_SWAP_SUPPORTED)
    if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
        png_set_swap(png_ptr);
#endif



    png_read_update_info(png_ptr, info_ptr);



#ifdef PNG_FREE_ME_SUPPORTED
    png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
#endif
    if(info_ptr->row_pointers == NULL)
    {
        info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr,
                                 info_ptr->height * png_sizeof(png_bytep));
#ifdef PNG_FREE_ME_SUPPORTED
        info_ptr->free_me |= PNG_FREE_ROWS;
#endif
        for (row = 0; row < (int)info_ptr->height; row++)
        {
            info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr,
                                          png_get_rowbytes(png_ptr, info_ptr));
        }
    }

    png_read_image(png_ptr, info_ptr->row_pointers);
    info_ptr->valid |= PNG_INFO_IDAT;


    png_read_end(png_ptr, info_ptr);

    transforms = transforms;
    params = params;

}
コード例 #10
0
    void initialize()
    {
        // Now it's time for some transformations.

        if( little_endian() )
        {
            if( this->_info._bit_depth == 16 )
            {
                // Swap bytes of 16 bit files to least significant byte first.
                png_set_swap( this->get()->_struct );
            }

            if( this->_info._bit_depth < 8 )
            {
                // swap bits of 1, 2, 4 bit packed pixel formats
                png_set_packswap( this->get()->_struct );
            }
        }

        if( this->_info._color_type == PNG_COLOR_TYPE_PALETTE )
        {
            png_set_palette_to_rgb( this->get()->_struct );
        }

        if( this->_info._num_trans > 0 )
        {
            png_set_tRNS_to_alpha( this->get()->_struct );
        }

        // Tell libpng to handle the gamma conversion for you.  The final call
        // is a good guess for PC generated images, but it should be configurable
        // by the user at run time by the user.  It is strongly suggested that
        // your application support gamma correction.
        if( this->_settings._apply_screen_gamma )
        {
            // png_set_gamma will change the image data!

#ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
        png_set_gamma( this->get()->_struct
                     , this->_settings._screen_gamma
                     , this->_info._file_gamma
                     );
#else
        png_set_gamma( this->get()->_struct
                     , this->_settings._screen_gamma
                     , this->_info._file_gamma
                     );
#endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
        }

        // Interlaced images are not supported.
        this->_number_passes = png_set_interlace_handling( this->get()->_struct );
        io_error_if( this->_number_passes != 1
                   , "scanline_read_iterator cannot read interlaced png images."
                   );


        // The above transformation might have changed the bit_depth and color type.
        png_read_update_info( this->get()->_struct
                            , this->get()->_info
                            );

        this->_info._bit_depth = png_get_bit_depth( this->get()->_struct
                                                  , this->get()->_info
                                                  );

        this->_info._num_channels = png_get_channels( this->get()->_struct
                                                    , this->get()->_info
                                                    );

        this->_info._color_type = png_get_color_type( this->get()->_struct
                                                    , this->get()->_info
                                                    );

        this->_scanline_length = png_get_rowbytes( this->get()->_struct
                                                 , this->get()->_info
                                                 );
    }
コード例 #11
0
/* pngReadImage: Reads an image from a memory buffer.
   Returns: non-zero if successful.
*/
int pngReadImage(int w, int h, int d, char* bits, char *data, int nBytes) {
  png_bytep *row_pointers = NULL;
  pngReadState rs;
  png_structp png_ptr;
  png_infop info_ptr;
  png_uint_32 width, height;
  int bit_depth, color_type, interlace_type;

  DBG("pngReadImage: png_sig_cmp");
  /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature. */
  if(png_sig_cmp(data, (png_size_t)0, PNG_BYTES_TO_CHECK)) return 0;

  DBG("pngReadImage: png_create_read_struct");
  /* Create the png_struct */
  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (png_ptr == NULL) return 0;

  DBG("pngReadImage: png_create_info_struct");
  /* Allocate/initialize the image information data.  REQUIRED */
  info_ptr = png_create_info_struct(png_ptr);
  if (info_ptr == NULL) {
    png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
    return 0;
  }

  /* Set error handling.  REQUIRED if you aren't supplying your own
   * error handling functions in the png_create_read_struct() call.
   */
  if (setjmp(png_jmpbuf(png_ptr))) {
    DBG("pngReadImage: triggered png_error");
    /* If we get here, we had a problem reading the file */
    png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
    if(row_pointers) free(row_pointers);
    return 0;
  }
  rs.data = data;
  rs.position = 0;
  rs.length = nBytes;
  png_set_read_fn(png_ptr, (void *)&rs, readBytes);


  DBG("pngReadImage: png_read_info");
  /* The call to png_read_info() gives us all of the information from the
   * PNG file before the first IDAT (image data chunk).  REQUIRED
   */
  png_read_info(png_ptr, info_ptr);
  png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
	       &interlace_type, int_p_NULL, int_p_NULL);

  /* Set up the data transformations you want.  Note that these are all
   * optional.  Only call them if you want/need them.  Many of the
   * transformations only work on specific types of images, and many
   * are mutually exclusive.
   */

  /* tell libpng to strip 16 bit/color files down to 8 bits/color */
  png_set_strip_16(png_ptr);

   /* flip the RGB pixels to BGR (or RGBA to BGRA) */
  if (color_type & PNG_COLOR_MASK_COLOR) {
    DBG("pngReadImage: png_set_bgr");
    png_set_bgr(png_ptr);
  }

  if(d == 32 && color_type == PNG_COLOR_TYPE_RGB) {
    /* Add filler (or alpha) byte (before/after each RGB triplet) */
    DBG("pngReadImage: png_set_filler");
    png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
  }

  if(0) {
    /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single
     * byte into separate bytes (useful for paletted and grayscale images).
     */
    png_set_packing(png_ptr);
    
    /* Change the order of packed pixels to least significant bit first
     * (not useful if you are using png_set_packing). */
    png_set_packswap(png_ptr);

    /* Expand paletted colors into true RGB triplets */
    if (color_type == PNG_COLOR_TYPE_PALETTE)
      png_set_palette_to_rgb(png_ptr);
  }
  
  /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
  if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
    png_set_gray_1_2_4_to_8(png_ptr);

  /* Expand paletted or RGB images with transparency to full alpha channels
   * so the data will be available as RGBA quartets.
   */
  if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
    png_set_tRNS_to_alpha(png_ptr);


  if(0) {
    /* Set the background color to draw transparent and alpha images over.
     * It is possible to set the red, green, and blue components directly
     * for paletted images instead of supplying a palette index.  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_16 my_background, *image_background;
  
    if (png_get_bKGD(png_ptr, info_ptr, &image_background))
      png_set_background(png_ptr, image_background,
			 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
    else
      png_set_background(png_ptr, &my_background,
			 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
  }

  if(0) {
   /* Tell libpng to handle the gamma conversion for you.  The final call
    * is a good guess for PC generated images, but it should be configurable
    * by the user at run time by the user.  It is strongly suggested that
    * your application support gamma correction.
    */

    int intent;
    double screen_gamma = 1.2;

    if (png_get_sRGB(png_ptr, info_ptr, &intent))
      png_set_gamma(png_ptr, screen_gamma, 0.45455);
    else {
      double image_gamma;
      if (png_get_gAMA(png_ptr, info_ptr, &image_gamma))
	png_set_gamma(png_ptr, screen_gamma, image_gamma);
      else
	png_set_gamma(png_ptr, screen_gamma, 0.45455);
    }
  }

  if(0) {
    /* If you want to shift the pixel values from the range [0,255] or
     * [0,65535] to the original [0,7] or [0,31], or whatever range the
     * colors were originally in:
     */
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) {
      png_color_8p sig_bit;
      png_get_sBIT(png_ptr, info_ptr, &sig_bit);
      png_set_shift(png_ptr, sig_bit);
    }
  }

  if(0) {
    /* flip the RGB pixels to BGR (or RGBA to BGRA) */
    if (color_type & PNG_COLOR_MASK_COLOR)
      png_set_bgr(png_ptr);
    
    /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */
    png_set_swap_alpha(png_ptr);
    
    /* swap bytes of 16 bit files to least significant byte first */
    png_set_swap(png_ptr);
  }

  { /* initialize the png row pointers */
    int row, ppw = 32 / d;
    int pitch = ((w + ppw - 1) / ppw) * 4;
    int rowbytes = png_get_rowbytes(png_ptr, info_ptr);

    if(0) {
      char info[100];
      sprintf(info, "Form pitch: %d\nPNG rowbytes: %d",pitch, rowbytes);
      DBG(info);
    }

    /* XXXX: It seems that this test is pretty pointless; PNG appears
       to return the raw rowbytes value, not the padded one.
       A better test is probably to compare the w/h/d values
       of png with the form values to ensure correctness. */
    if(pitch < rowbytes) {
      png_error(png_ptr, "Row bytes mismatch");
    }
    row_pointers = (png_bytep*) calloc(h, sizeof(void*));
    for (row = 0; row < h; row++) {
      row_pointers[row] = bits + (row*pitch);
    }
  }

  DBG("pngReadImage: png_read_image");
  /* Read the entire image in one go */
  png_read_image(png_ptr, row_pointers);

  DBG("pngReadImage: Cleaning up");
  /* clean up after the read, and free any memory allocated - REQUIRED */
  png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);

  if(row_pointers) free(row_pointers);

  return 1;
}