示例#1
0
int
SplashDecodePng(Splash * splash, png_rw_ptr read_func, void *io_ptr)
{
    int stride;
    ImageFormat srcFormat;
    png_uint_32 i, rowbytes;
    png_bytepp row_pointers = NULL;
    png_bytep image_data = NULL;
    int success = 0;
    double gamma;

    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL;

    png_uint_32 width, height;
    int bit_depth, color_type;

    ImageRect srcRect, dstRect;

    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr) {
        goto done;
    }

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        goto done;
    }

#ifdef __APPLE__
    /* use setjmp/longjmp versions that do not save/restore the signal mask */
    if (_setjmp(png_set_longjmp_fn(png_ptr, _longjmp, sizeof(jmp_buf)))) {
#else
    if (setjmp(png_jmpbuf(png_ptr))) {
#endif
        goto done;
    }

    png_set_read_fn(png_ptr, io_ptr, read_func);

    png_set_sig_bytes(png_ptr, SIG_BYTES);      /* we already read the 8 signature bytes */

    png_read_info(png_ptr, info_ptr);   /* read all PNG info up to image data */

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

    /* expand palette images to RGB, low-bit-depth grayscale images to 8 bits,
     * transparency chunks to full alpha channel; strip 16-bit-per-sample
     * images to 8 bits per sample; and convert grayscale to RGB[A]
     * this may be sub-optimal but this simplifies implementation */

    png_set_expand(png_ptr);
    png_set_tRNS_to_alpha(png_ptr);
    png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
    png_set_strip_16(png_ptr);
    png_set_gray_to_rgb(png_ptr);

    if (png_get_gAMA(png_ptr, info_ptr, &gamma))
        png_set_gamma(png_ptr, 2.2, gamma);

    png_set_interlace_handling(png_ptr);
    png_read_update_info(png_ptr, info_ptr);

    rowbytes = png_get_rowbytes(png_ptr, info_ptr);

    if (!SAFE_TO_ALLOC(rowbytes, height)) {
        goto done;
    }

    if ((image_data = (unsigned char *) malloc(rowbytes * height)) == NULL) {
        goto done;
    }

    if (!SAFE_TO_ALLOC(height, sizeof(png_bytep))) {
        goto done;
    }
    if ((row_pointers = (png_bytepp) malloc(height * sizeof(png_bytep)))
            == NULL) {
        goto done;
    }

    for (i = 0; i < height; ++i)
        row_pointers[i] = image_data + i * rowbytes;

    png_read_image(png_ptr, row_pointers);

    SplashCleanup(splash);

    splash->width = width;
    splash->height = height;

    if (!SAFE_TO_ALLOC(splash->width, splash->imageFormat.depthBytes)) {
        goto done;
    }
    stride = splash->width * splash->imageFormat.depthBytes;

    if (!SAFE_TO_ALLOC(splash->height, stride)) {
        goto done;
    }
    splash->frameCount = 1;
    splash->frames = (SplashImage *)
        malloc(sizeof(SplashImage) * splash->frameCount);

    if (splash->frames == NULL) {
        goto done;
    }

    splash->loopCount = 1;
    splash->frames[0].bitmapBits = malloc(stride * splash->height);
    if (splash->frames[0].bitmapBits == NULL) {
        free(splash->frames);
        goto done;
    }
    splash->frames[0].delay = 0;

    /* FIXME: sort out the real format */
    initFormat(&srcFormat, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
    srcFormat.byteOrder = BYTE_ORDER_MSBFIRST;

    initRect(&srcRect, 0, 0, width, height, 1, rowbytes,
        image_data, &srcFormat);
    initRect(&dstRect, 0, 0, width, height, 1, stride,
        splash->frames[0].bitmapBits, &splash->imageFormat);
    convertRect(&srcRect, &dstRect, CVT_COPY);

    SplashInitFrameShape(splash, 0);

    png_read_end(png_ptr, NULL);
    success = 1;

  done:
    free(row_pointers);
    free(image_data);
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    return success;
}

int
SplashDecodePngStream(Splash * splash, SplashStream * stream)
{
    unsigned char sig[SIG_BYTES];
    int success = 0;

    stream->read(stream, sig, SIG_BYTES);
    if (png_sig_cmp(sig, 0, SIG_BYTES)) {
        goto done;
    }
    success = SplashDecodePng(splash, my_png_read_stream, stream);

  done:
    return success;
}
示例#2
0
	int Read ( byte **data, int *width, int *height )
	{
		// Setup the pointers
		*data = NULL;
		*width = 0;
		*height = 0;

		// Make sure we're actually reading PNG data.
		const int SIGNATURE_LEN = 8;

		byte ident[SIGNATURE_LEN];
		memcpy (ident, buf, SIGNATURE_LEN);

		if ( !png_check_sig (ident, SIGNATURE_LEN) )
		{
			ri->Printf (PRINT_ERROR, "PNG signature not found in given image.");
			return 0;
		}

		png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, png_print_error, png_print_warning);
		if ( png_ptr == NULL )
		{
			ri->Printf (PRINT_ERROR, "Could not allocate enough memory to load the image.");
			return 0;
		}

		info_ptr = png_create_info_struct (png_ptr);
		if ( setjmp (png_jmpbuf (png_ptr)) )
		{
			return 0;
		}

		// We've read the signature
		offset += SIGNATURE_LEN;

		// Setup reading information, and read header
		png_set_read_fn (png_ptr, (png_voidp)this, &user_read_data);
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
		// This generic "ignore all, except required chunks" requires 1.6.0 or newer"
		png_set_keep_unknown_chunks (png_ptr, PNG_HANDLE_CHUNK_NEVER, NULL, -1);
#endif
		png_set_sig_bytes (png_ptr, SIGNATURE_LEN);
		png_read_info (png_ptr, info_ptr);

		png_uint_32 width_;
		png_uint_32 height_;
		int depth;
		int colortype;

		png_get_IHDR (png_ptr, info_ptr, &width_, &height_, &depth, &colortype, NULL, NULL, NULL);

		// While modern OpenGL can handle non-PoT textures, it's faster to handle only PoT
		// so that the graphics driver doesn't have to fiddle about with the texture when uploading.
		
		/*
		if ( !IsPowerOfTwo (width_) || !IsPowerOfTwo (height_) )
		{
			ri->Printf (PRINT_ERROR, "Width or height is not a power-of-two.\n");
			return 0;
		}
		*/

		// This function is equivalent to using what used to be LoadPNG32. LoadPNG8 also existed,
		// but this only seemed to be used by the RMG system which does not work in JKA. If this
		// does need to be re-implemented, then colortype should be PNG_COLOR_TYPE_PALETTE or
		// PNG_COLOR_TYPE_GRAY.
		if ( colortype != PNG_COLOR_TYPE_RGB && colortype != PNG_COLOR_TYPE_RGBA )
		{
			ri->Printf (PRINT_ERROR, "Image is not 24-bit or 32-bit.");
			return 0;
		}

		// Read the png data
		if ( colortype == PNG_COLOR_TYPE_RGB )
		{
			// Expand RGB -> RGBA
			png_set_add_alpha (png_ptr, 0xff, PNG_FILLER_AFTER);
		}

		png_read_update_info (png_ptr, info_ptr);

		// We always assume there are 4 channels. RGB channels are expanded to RGBA when read.
		byte *tempData = (byte *)ri->Z_Malloc (width_ * height_ * 4, TAG_TEMP_PNG, qfalse, 4);
		if ( !tempData )
		{
			ri->Printf (PRINT_ERROR, "Could not allocate enough memory to load the image.");
			return 0;
		}

		// Dynamic array of row pointers, with 'height' elements, initialized to NULL.
		byte **row_pointers = (byte **)ri->Hunk_AllocateTempMemory (sizeof (byte *) * height_);
		if ( !row_pointers )
		{
			ri->Printf (PRINT_ERROR, "Could not allocate enough memory to load the image.");

			ri->Z_Free (tempData);

			return 0;
		}

		// Re-set the jmp so that these new memory allocations can be reclaimed
		if ( setjmp (png_jmpbuf (png_ptr)) )
		{
			ri->Hunk_FreeTempMemory (row_pointers);
			ri->Z_Free (tempData);
			return 0;
		}

		for ( unsigned int i = 0, j = 0; i < height_; i++, j += 4 )
		{
			row_pointers[i] = tempData + j * width_;
		}

		png_read_image (png_ptr, row_pointers);

		// Finish reading
		png_read_end (png_ptr, NULL);

		ri->Hunk_FreeTempMemory (row_pointers);

		// Finally assign all the parameters
		*data = tempData;
		*width = width_;
		*height = height_;

		return 1;
	}
示例#3
0
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);
}
示例#4
0
/*
ReadPNG - Reads the contents of a PNG file and stores the contents into
    BMGImageStruct

Inputs:
    filename    - the name of the file to be opened

Outputs:
    img         - the BMGImageStruct containing the image data

Returns:
    BMGError - if the file could not be read or a resource error occurred
    BMG_OK   - if the file was read and the data was stored in img

Limitations:
    None.

Comments:
    2-bit images are converted to 4-bit images.
    16-bit images are converted to 8-bit images.
    gray scale images with alpha components are converted to 32-bit images
*/
BMGError ReadPNG( const char *filename,
        struct BMGImageStruct * volatile img )
{
    jmp_buf             err_jmp;
    int                 error;

    FILE * volatile     file = NULL;
    int                 BitDepth;
    int                 ColorType;
    int                 InterlaceType;
    unsigned char       signature[8];
    png_structp volatile png_ptr = NULL;
    png_infop   volatile info_ptr = NULL;
    png_infop   volatile end_info = NULL;
    png_color_16       *ImageBackground = NULL;
    png_bytep           trns = NULL;
    int                 NumTrans = 0;
    int                 i, k;
    png_color_16p       TransColors = NULL;
    png_uint_32         Width, Height;

    unsigned char      *bits;
    unsigned char** volatile rows = NULL;

    BMGError tmp;

    /* error handler */
    error = setjmp( err_jmp );
    if (error != 0)
    {
        if (end_info != NULL)
            png_destroy_read_struct((png_structp *) &png_ptr, (png_infop *) &info_ptr, (png_infop *) &end_info);
        else if (info_ptr != NULL)
            png_destroy_read_struct((png_structp *) &png_ptr, (png_infop *) &info_ptr, NULL);
        else if (png_ptr != NULL)
            png_destroy_read_struct((png_structp *) &png_ptr, NULL, NULL);
        if (rows)
        {
            if (rows[0])
                free(rows[0]);
            free(rows);
        }
        if (img)
            FreeBMGImage(img);
        if (file)
            fclose(file);
        SetLastBMGError((BMGError) error);
        return (BMGError) error;
    }

    if ( img == NULL )
        longjmp ( err_jmp, (int)errInvalidBMGImage );

    file = fopen( filename, "rb" );
    if ( !file || fread( signature, 1, 8, file ) != 8)
        longjmp ( err_jmp, (int)errFileOpen );

    /* check the signature */
    if ( png_sig_cmp( signature, 0, 8 ) != 0 )
        longjmp( err_jmp, (int)errUnsupportedFileFormat );

    /* create a pointer to the png read structure */
    png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
    if ( !png_ptr )
        longjmp( err_jmp, (int)errMemoryAllocation );

    /* create a pointer to the png info structure */
    info_ptr = png_create_info_struct( png_ptr );
    if ( !info_ptr )
        longjmp( err_jmp, (int)errMemoryAllocation );

    /* create a pointer to the png end-info structure */
    end_info = png_create_info_struct(png_ptr);
    if (!end_info)
        longjmp( err_jmp, (int)errMemoryAllocation );

    /* bamboozle the PNG longjmp buffer */
    /*generic PNG error handler*/
    /* error will always == 1 which == errLib */
//    error = png_setjmp(png_ptr);
    error = setjmp( png_jmpbuf( png_ptr ) );
    if ( error > 0 )
        longjmp( err_jmp, error );

    /* set function pointers in the PNG library, for read callbacks */
    png_set_read_fn(png_ptr, (png_voidp) file, user_read_data);

    /*let the read functions know that we have already read the 1st 8 bytes */
    png_set_sig_bytes( png_ptr, 8 );

    /* read all PNG data up to the image data */
    png_read_info( png_ptr, info_ptr );

    /* extract the data we need to form the HBITMAP from the PNG header */
    png_get_IHDR( png_ptr, info_ptr, &Width, &Height, &BitDepth, &ColorType,
        &InterlaceType, NULL, NULL);

    img->width = (unsigned int) Width;
    img->height = (unsigned int) Height;

    img->bits_per_pixel = (unsigned char)32;
    img->scan_width = Width * 4;

    /* convert 16-bit images to 8-bit images */
    if (BitDepth == 16)
        png_set_strip_16(png_ptr);

    /* These are not really required per Rice format spec,
     * but is done just in case someone uses them.
     */
    /* convert palette color to rgb color */
    if (ColorType == PNG_COLOR_TYPE_PALETTE) {
        png_set_palette_to_rgb(png_ptr);
        ColorType = PNG_COLOR_TYPE_RGB;
    }

    /* expand 1,2,4 bit gray scale to 8 bit gray scale */
    if (ColorType == PNG_COLOR_TYPE_GRAY && BitDepth < 8)
        png_set_expand_gray_1_2_4_to_8(png_ptr);

    /* convert gray scale or gray scale + alpha to rgb color */
    if (ColorType == PNG_COLOR_TYPE_GRAY ||
        ColorType == PNG_COLOR_TYPE_GRAY_ALPHA) {
        png_set_gray_to_rgb(png_ptr);
        ColorType = PNG_COLOR_TYPE_RGB;
    }

    /* add alpha channel if any */
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
        png_set_tRNS_to_alpha(png_ptr);
        ColorType = PNG_COLOR_TYPE_RGB_ALPHA;
    }

    /* convert rgb to rgba */
    if (ColorType == PNG_COLOR_TYPE_RGB) {
        png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
        ColorType = PNG_COLOR_TYPE_RGB_ALPHA;
    }

    png_set_bgr(png_ptr);

    /* set the background color if one is found */
    if ( png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD) )
        png_get_bKGD(png_ptr, info_ptr, &ImageBackground);

    /* get the transparent color if one is there */
    if ( png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS ) )
        png_get_tRNS( png_ptr, info_ptr, &trns, &NumTrans, &TransColors );

    img->palette_size = (unsigned short)0;
    img->bytes_per_palette_entry = 4U;

    tmp = AllocateBMGImage( img );
    if ( tmp != BMG_OK )
        longjmp( err_jmp, (int)tmp );

    png_read_update_info( png_ptr, info_ptr );

    /* create buffer to read data to */
    rows = (unsigned char **)malloc(Height*sizeof(unsigned char *));
    if ( !rows )
        longjmp( err_jmp, (int)errMemoryAllocation );

    k = png_get_rowbytes( png_ptr, info_ptr );
    rows[0] = (unsigned char *)malloc( Height*k*sizeof(char));
    if ( !rows[0] )
        longjmp( err_jmp, (int)errMemoryAllocation );

    for ( i = 1; i < (int)Height; i++ )
        rows[i] = rows[i-1] + k;

    /* read the entire image into rows */
    png_read_image( png_ptr, rows );

    bits = img->bits + (Height - 1) * img->scan_width;
    for ( i = 0; i < (int)Height; i++ )
    {
        memcpy(bits, rows[i], 4*Width);
        bits -= img->scan_width;
    }

    free( rows[0] );
    free( rows );
    png_read_end( png_ptr, info_ptr );
    png_destroy_read_struct((png_structp *) &png_ptr, (png_infop *) &info_ptr, (png_infop *) &end_info);
    fclose( file );

    return BMG_OK;
}
示例#5
0
文件: npng.c 项目: Crockadavin/naev
/**
 * @brief Opens an npng struct from an SDL_RWops. It does not close the RWops.
 *
 *    @param rw SDL_RWops to create npng from.
 *    @return npng created from rw.
 */
npng_t *npng_open( SDL_RWops *rw )
{
   png_byte header[8]; /* Maximum size to check. */
   npng_t *npng;

   /* Allocate memory. */
   npng = malloc( sizeof(npng_t) );
   if (npng == NULL) {
      WARN("Out of memory.");
      return NULL;
   }
   memset( npng, 0, sizeof(npng_t) );

   /* Set up struct. */
   npng->rw       = rw;
   npng->png_ptr  = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
   if (npng->png_ptr == NULL) {
      WARN("png_create_read_struct failed");
      goto ERR_FAIL;
   }
   npng->info_ptr = png_create_info_struct( npng->png_ptr );
   if (npng->info_ptr == NULL) {
      WARN("png_create_info_struct failed");
      goto ERR_FAIL;
   }

   /* Check header. */
   SDL_RWread( rw, header, 8, 1 );
   if (png_sig_cmp(header, 0, 8)) {
      WARN("RWops not recognized as a PNG file.");
      goto ERR_FAIL;
   }

   /* Set up for reading. */
   png_set_read_fn( npng->png_ptr, (png_voidp) rw, npng_read );

   /* Set up long jump for IO. */
   if (setjmp( png_jmpbuf( npng->png_ptr )) ) {
      WARN("Error during setjmp");
      goto ERR_FAIL;
   }

   /* We've already checked sig. */
   png_set_sig_bytes( npng->png_ptr, 8 );

   /* Get start. */
   npng->start = SDL_RWtell( npng->rw );

   /* Get info. */
   npng_info( npng );

   /* Load text. */
   png_get_text( npng->png_ptr, npng->info_ptr, &npng->text_ptr, &npng->num_text );

   return npng;

ERR_FAIL:
#if 0 /* Memory leaks are better than segfaults. */
   if (npng != NULL) {
      if (npng->png_ptr != NULL)
         png_destroy_read_struct( &npng->png_ptr, (npng->info_ptr != NULL) ? &npng->info_ptr : NULL, NULL );
      free(npng);
   }
#endif
   return NULL;
}
示例#6
0
// load in the image data
IImage* CImageLoaderPng::loadImage(irr::io::IReadFile* file)
{
#ifdef _IRR_COMPILE_WITH_LIBPNG_
    if (!file)
        return 0;

    Image = 0;
    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

    // Extract info
    png_get_IHDR(png_ptr, info_ptr,
                 (png_uint_32*)&Width, (png_uint_32*)&Height,
                 &BitDepth, &ColorType, NULL, NULL, NULL);

    // 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)
            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);

    // Convert high bit colors to 8 bit colors
    if (BitDepth == 16)
        png_set_strip_16(png_ptr);

    // Convert gray color to true color
    if (ColorType==PNG_COLOR_TYPE_GRAY || ColorType==PNG_COLOR_TYPE_GRAY_ALPHA)
        png_set_gray_to_rgb(png_ptr);

    // Update the changes
    png_read_update_info(png_ptr, info_ptr);
    png_get_IHDR(png_ptr, info_ptr,
                 (png_uint_32*)&Width, (png_uint_32*)&Height,
                 &BitDepth, &ColorType, NULL, NULL, NULL);

    // Convert RGBA to BGRA
    if (ColorType==PNG_COLOR_TYPE_RGB_ALPHA)
    {
#ifdef __BIG_ENDIAN__
        png_set_swap_alpha(png_ptr);
#else
        png_set_bgr(png_ptr);
#endif
    }

    // Update the changes
    png_get_IHDR(png_ptr, info_ptr,
                 (png_uint_32*)&Width, (png_uint_32*)&Height,
                 &BitDepth, &ColorType, NULL, NULL, NULL);

    // Create the image structure to be filled by png data
    if (ColorType==PNG_COLOR_TYPE_RGB_ALPHA)
        Image = new CImage(ECF_A8R8G8B8, core::dimension2d<s32>(Width, Height));
    else
        Image = new CImage(ECF_R8G8B8, core::dimension2d<s32>(Width, Height));
    if (!Image)
    {
        os::Printer::log("LOAD PNG: Internal PNG create image struct failure\n", file->getFileName(), ELL_ERROR);
        png_destroy_read_struct(&png_ptr, NULL, NULL);
        return 0;
    }

    // Create array of pointers to rows in image data
    RowPointers = new png_bytep[Height];
    if (!RowPointers)
    {
        os::Printer::log("LOAD PNG: Internal PNG create row pointers failure\n", file->getFileName(), ELL_ERROR);
        png_destroy_read_struct(&png_ptr, NULL, NULL);
        delete Image;
        return 0;
    }

    // Fill array of pointers to rows in image data
    unsigned char* data = (unsigned char*)Image->lock();
    for (u32 i=0; i<Height; ++i)
    {
        RowPointers[i]=data;
        data += Image->getPitch();
    }

    // for proper error handling
    if (setjmp(png_jmpbuf(png_ptr)))
    {
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        delete [] RowPointers;
        Image->unlock();
        delete [] Image;
        return 0;
    }

    // Read data using the library function that handles all transformations including interlacing
    png_read_image(png_ptr, RowPointers);

    png_read_end(png_ptr, NULL);
    delete [] RowPointers;
    Image->unlock();
    png_destroy_read_struct(&png_ptr,&info_ptr, 0); // Clean up memory

    return Image;
#else
    return 0;
#endif // _IRR_COMPILE_WITH_LIBPNG_
}
示例#7
0
int ImageFormatPNG::load(const char *name, int& width, int& height, int& format) {
 	printf("ImageFormatPNG::load\n");

    // Open File
 	FILE* file = fopen(name,"rb");
 	if (file == 0) {
        printf("ImageFormatPNG::load(): can't open file '%s'\n",name);
 		return 0;
 	}

    // init width / height / format value to 0
    width  = 0;
 	height = 0;
    format = 0;
    
 	//Allocate a buffer of 8 bytes, where we can put the file signature.
    png_byte sig[8];

    //Read the 8 bytes from the file into the sig buffer.
    fread((char*)sig, sizeof(png_byte), 8, file);
 	if(!png_check_sig(sig,8)) {
 		fclose(file);
 		return 0;
 	}

 	//Here we create the png read struct.
 	png_structp pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
 	if(pngPtr == 0) {
 		fclose(file);
 		return 0;
 	}

 	//Here we create the png info struct.
 	png_infop infoPtr = png_create_info_struct(pngPtr);
 	if(infoPtr == 0) {
 		png_destroy_read_struct(&pngPtr, (png_infopp)0, (png_infopp)0);
 		fclose(file);
 		return 0;
 	}

 	png_set_read_fn(pngPtr,file, file_read_function);

    //Set the amount signature bytes we've already read:
    png_set_sig_bytes(pngPtr, 8);

    //Now call png_read_info with our pngPtr as image handle, and infoPtr to receive the file info.
    png_read_info(pngPtr, infoPtr);

    png_uint_32 imgWidth =  png_get_image_width(pngPtr, infoPtr);
    png_uint_32 imgHeight = png_get_image_height(pngPtr, infoPtr);

    //bits per CHANNEL! note: not per pixel!
    png_uint_32 bitdepth   = png_get_bit_depth(pngPtr, infoPtr);
    //Number of channels
    png_uint_32 channels   = png_get_channels(pngPtr, infoPtr);
    //Color type. (RGB, RGBA, Luminance, luminance alpha... palette... etc)
    png_uint_32 color_type = png_get_color_type(pngPtr, infoPtr);

    switch (color_type) {
        case PNG_COLOR_TYPE_PALETTE:
            png_set_palette_to_rgb(pngPtr);
            //Don't forget to update the channel info (thanks Tom!)
            //It's used later to know how big a buffer we need for the image
            channels = 3;
            break;
        case PNG_COLOR_TYPE_GRAY:
            if (bitdepth < 8)
                png_set_expand_gray_1_2_4_to_8(pngPtr);
            //And the bitdepth info
            bitdepth = 8;
        break;
    }

    /*if the image has a transperancy set.. convert it to a full Alpha channel..*/
    if (png_get_valid(pngPtr, infoPtr, PNG_INFO_tRNS)) {
        png_set_tRNS_to_alpha(pngPtr);
        channels+=1;
    }

    //We don't support 16 bit precision.. so if the image Has 16 bits per channel
    //precision... round it down to 8.
    if (bitdepth == 16)
        png_set_strip_16(pngPtr);

    //Array of row pointers. One for every row.
    png_bytep*  rowPtrs = new png_bytep[imgHeight];

    width = imgWidth;
    height = imgHeight;
    format = bitdepth * channels / 8;
    
    int data_decoded_size = width * height * format;
    
    // raw data image container
    unsigned char * img_data_decoded = new unsigned char[data_decoded_size];
    memset(img_data_decoded,0x00,data_decoded_size + 1);
    
	int stride = width * format;
    
    for (size_t i = 0; i < imgHeight; i++) {
        //Set the pointer to the data pointer + i times the row stride.
        png_uint_32 q = (imgHeight- i - 1) * stride;
        rowPtrs[i] = (png_bytep)img_data_decoded + q;
    }

    //And here it is! The actuall reading of the image!
    png_read_image(pngPtr, rowPtrs);

    //Delete the row pointers array....
    delete[] (png_bytep)rowPtrs;
    //And don't forget to clean up the read and info structs !
    png_destroy_read_struct(&pngPtr, &infoPtr,(png_infopp)0);

    // create temporary file for glue code javascript
    ImageFormat::flip_y((unsigned char *)img_data_decoded,width,height,format);
    
    FILE* raw = fopen(kTempararyName,"wb");
    if (raw) {
        fwrite(img_data_decoded,width * height * format ,1 , raw);
        fclose(raw);
    }
     
    delete img_data_decoded;
    
    fclose(file);
    
	return 1;
}
示例#8
0
bool BitmapData::initWithPNGData(const unsigned char *data, ssize_t size) {
    
    static const int PNGSIGSIZE = 8;
    
    png_byte        header[PNGSIGSIZE] = {0};
    png_structp     png_ptr     = 0;
    png_infop       info_ptr    = 0;
    
    memcpy(header, data, PNGSIGSIZE);
    if (png_sig_cmp(header, 0, PNGSIGSIZE) != 0) {
        return false;
    }
    
    png_ptr  = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
    info_ptr = png_create_info_struct(png_ptr);
    setjmp(png_jmpbuf(png_ptr));
    
    
    PngSource pngSource;
    pngSource.data    = (unsigned char*)data;
    pngSource.size    = size;
    pngSource.offset  = 0;
    png_set_read_fn(png_ptr, &pngSource, pngReadCallback);
    
    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);
    png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr);
    png_uint_32 color_type = png_get_color_type(png_ptr, info_ptr);
    
    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;
    }
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
        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);
    }
    // update info
    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:
            _renderFormat = Texture2D::PixelFormat::I8;
            break;
        case PNG_COLOR_TYPE_GRAY_ALPHA:
            _renderFormat = Texture2D::PixelFormat::AI88;
            break;
        case PNG_COLOR_TYPE_RGB:
            _renderFormat = Texture2D::PixelFormat::RGB888;
            break;
        case PNG_COLOR_TYPE_RGB_ALPHA:
            _renderFormat = Texture2D::PixelFormat::RGBA8888;
            break;
        default:
            break;
    }
    
    // read png data
    png_size_t rowbytes;
    png_bytep* row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * _height);
    rowbytes = png_get_rowbytes(png_ptr, info_ptr);
    
    _dataSize = rowbytes * _height;
    _data = static_cast<unsigned char*>(malloc(_dataSize * sizeof(unsigned char)));
    
    if(!_data) {
        if (row_pointers != nullptr) {
            free(row_pointers);
        }
        return false;
    }
    
    for (unsigned short i = 0; i < _height; ++i) {
        row_pointers[i] = _data + i*rowbytes;
    }
    
    png_read_image(png_ptr, row_pointers);
    png_read_end(png_ptr, nullptr);
    
    if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
        _alpha = true;
    } else {
        _alpha = false;
    }
    
    if (row_pointers != nullptr) {
        free(row_pointers);
    }
    
    if (png_ptr) {
        png_destroy_read_struct(&png_ptr, (info_ptr) ? &info_ptr : 0, 0);
    }
    
    return true;
}
示例#9
0
	uint8_t* GraphicsTexture::loadImage()
	{
		Pegas_log_info("GraphicsTexture::loadImage");

		Resource::AutoDispose autoDispose(mResource);
		if (mResource.open() != STATUS_OK)
		{
			Pegas_log_error("mResource.open failed");
			return NULL;
		}

		png_byte header[8];
		if (mResource.read(header, sizeof(header)) != STATUS_OK)
		{
			Pegas_log_error("mResource.read failed");
			return NULL;
		}

		if (png_sig_cmp(header, 0, 8) != 0)
		{
			Pegas_log_error("png_sig_cmp failed, header param: %s", header);
			return NULL;
		}

		png_structp pngMain = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
		if (!pngMain) {
			Pegas_log_error("png_create_read_struct failed");
			return NULL;
		}
		png_infop pngInfo = png_create_info_struct(pngMain);
		if (!pngInfo) {
			Pegas_log_error("png_create_info_struct failed");
			return NULL;
		}
		png_set_read_fn(pngMain, &mResource, callback_read);
		if (setjmp(png_jmpbuf(pngMain))) {
			Pegas_log_error("setjmp failed");
			return NULL;
		}
		png_set_sig_bytes(pngMain, 8);
		png_read_info(pngMain, pngInfo);
		png_int_32 depth, colorType;
		png_uint_32 width, height;
		png_get_IHDR(pngMain, pngInfo, &width, &height, &depth, &colorType, NULL,
				NULL, NULL);
		mWidth = width;
		mHeight = height;
		bool transparency = false;
		// Creates a full alpha channel if transparency is encoded as
		// an array of palette entries or a single transparent color.
		if (png_get_valid(pngMain, pngInfo, PNG_INFO_tRNS)) {
			png_set_tRNS_to_alpha(pngMain);
			transparency = true;

			Pegas_log_error("png_get_valid failed");
			return NULL;
		}
		// Expands PNG with less than 8bits per channel to 8bits.
		if (depth < 0) {
			png_set_packing(pngMain);
			// Shrinks PNG with 16bits per color channel down to 8bits.
		} else if (depth == 16) {
			png_set_strip_16(pngMain);
		}

		// Indicates that image needs conversion to RGBA if	needed.
		switch (colorType) {
		case PNG_COLOR_TYPE_PALETTE:
			png_set_palette_to_rgb(pngMain);
			mFormat = transparency ? GL_RGBA : GL_RGB;
			break;
		case PNG_COLOR_TYPE_RGB:
			mFormat = transparency ? GL_RGBA : GL_RGB;
			break;
		case PNG_COLOR_TYPE_RGBA:
			mFormat = GL_RGBA;
			break;
		case PNG_COLOR_TYPE_GRAY:
			png_set_expand_gray_1_2_4_to_8(pngMain);
			mFormat = transparency ? GL_LUMINANCE_ALPHA : GL_LUMINANCE;
			break;
		case PNG_COLOR_TYPE_GA:
			png_set_expand_gray_1_2_4_to_8(pngMain);
			mFormat = GL_LUMINANCE_ALPHA;
			break;
		}
		png_read_update_info(pngMain, pngInfo);
		png_int_32 rowSize = png_get_rowbytes(pngMain, pngInfo);
		if (rowSize <= 0) {
			Pegas_log_error("invalid png row size: %d", rowSize);
			return NULL;
		}
		png_byte* imageBuffer = new png_byte[rowSize * height];
		if (!imageBuffer) {
			Pegas_log_error("can not allocate image buffer");
			return NULL;
		}
		png_bytep* rowPtrs = new png_bytep[height];
		if (!rowPtrs) {
			Pegas_log_error("can not allocate row pointers");
			//TODO: use smart pointer for this
			delete[] imageBuffer;

			return NULL;
		}
		for (int32_t i = 0; i < height; ++i) {
			rowPtrs[height - (i + 1)] = imageBuffer + (i * rowSize);
		}
		png_read_image(pngMain, rowPtrs);
		png_destroy_read_struct(&pngMain, &pngInfo, NULL);
		delete[] rowPtrs;

		return imageBuffer;
}
static HPDF_STATUS
LoadPngData  (HPDF_Dict     image,
              HPDF_Xref     xref,
              HPDF_Stream   png_data,
              HPDF_BOOL     delayed_loading)

{
	HPDF_STATUS ret = HPDF_OK;
	png_uint_32 width, height;
	int bit_depth, color_type;
	png_structp png_ptr = NULL;
	png_infop info_ptr = NULL;

	HPDF_PTRACE ((" HPDF_Image_LoadPngImage\n"));

	/* create read_struct. */
	png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,
			image->error, PngErrorFunc, NULL);

	if (png_ptr == NULL) {
		HPDF_SetError (image->error, HPDF_FAILD_TO_ALLOC_MEM, 0);
		return HPDF_FAILD_TO_ALLOC_MEM;
	}

	/* create info-struct */
	info_ptr = png_create_info_struct (png_ptr);

	if (info_ptr == NULL) {
		HPDF_SetError (image->error, HPDF_FAILD_TO_ALLOC_MEM, 0);
		goto Exit;
	}

	png_set_sig_bytes (png_ptr, HPDF_PNG_BYTES_TO_CHECK);
	png_set_read_fn (png_ptr, (void *)png_data, (png_rw_ptr)&PngReadFunc);

	/* reading info structure. */
	png_read_info(png_ptr, info_ptr);
	if (image->error->error_no != HPDF_OK) {
		goto Exit;
	}

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

	/* 16bit images are not supported. */
	if (bit_depth == 16) {
		png_set_strip_16(png_ptr);
	}

	png_read_update_info(png_ptr, info_ptr);
	if (image->error->error_no != HPDF_OK) {
		goto Exit;
	}

	/* check palette-based images for transparent areas and load them immediately if found */
	if (xref && PNG_COLOR_TYPE_PALETTE & color_type) {
		png_bytep trans;
		int num_trans;
		HPDF_Dict smask;
		png_bytep smask_data;

		if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) ||
			!png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL)) {
			goto no_transparent_color_in_palette;
		}

		smask = HPDF_DictStream_New (image->mmgr, xref);
		if (!smask) {
			ret = HPDF_FAILD_TO_ALLOC_MEM;
			goto Exit;
		}

		smask->header.obj_class |= HPDF_OSUBCLASS_XOBJECT;
		ret = HPDF_Dict_AddName (smask, "Type", "XObject");
		ret += HPDF_Dict_AddName (smask, "Subtype", "Image");
		ret += HPDF_Dict_AddNumber (smask, "Width", (HPDF_UINT)width);
		ret += HPDF_Dict_AddNumber (smask, "Height", (HPDF_UINT)height);
		ret += HPDF_Dict_AddName (smask, "ColorSpace", "DeviceGray");
		ret += HPDF_Dict_AddNumber (smask, "BitsPerComponent", (HPDF_UINT)bit_depth);

		if (ret != HPDF_OK) {
			HPDF_Dict_Free(smask);
			ret = HPDF_INVALID_PNG_IMAGE;
			goto Exit;
		}

		smask_data = HPDF_GetMem(image->mmgr, width * height);
		if (!smask_data) {
			HPDF_Dict_Free(smask);
			ret = HPDF_FAILD_TO_ALLOC_MEM;
			goto Exit;
		}

		if (ReadTransparentPaletteData(image, png_ptr, info_ptr, smask_data, trans, num_trans) != HPDF_OK) {
			HPDF_FreeMem(image->mmgr, smask_data);
			HPDF_Dict_Free(smask);
			ret = HPDF_INVALID_PNG_IMAGE;
			goto Exit;
		}

		if (HPDF_Stream_Write(smask->stream, smask_data, width * height) != HPDF_OK) {
			HPDF_FreeMem(image->mmgr, smask_data);
			HPDF_Dict_Free(smask);
			ret = HPDF_FILE_IO_ERROR;
			goto Exit;
		}
		HPDF_FreeMem(image->mmgr, smask_data);


		ret += CreatePallet(image, png_ptr, info_ptr);
		ret += HPDF_Dict_AddNumber (image, "Width", (HPDF_UINT)width);
		ret += HPDF_Dict_AddNumber (image, "Height", (HPDF_UINT)height);
		ret += HPDF_Dict_AddNumber (image, "BitsPerComponent",	(HPDF_UINT)bit_depth);
		ret += HPDF_Dict_Add (image, "SMask", smask);

		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		return HPDF_OK;
	}

no_transparent_color_in_palette:

	/* read images with alpha channel right away
	   we have to do this because image transparent mask must be added to the Xref */
	if (xref && PNG_COLOR_MASK_ALPHA & color_type) {
		HPDF_Dict smask;
		png_bytep smask_data;

		smask = HPDF_DictStream_New (image->mmgr, xref);
		if (!smask) {
			ret = HPDF_FAILD_TO_ALLOC_MEM;
			goto Exit;
		}

		smask->header.obj_class |= HPDF_OSUBCLASS_XOBJECT;
		ret = HPDF_Dict_AddName (smask, "Type", "XObject");
		ret += HPDF_Dict_AddName (smask, "Subtype", "Image");
		ret += HPDF_Dict_AddNumber (smask, "Width", (HPDF_UINT)width);
		ret += HPDF_Dict_AddNumber (smask, "Height", (HPDF_UINT)height);
		ret += HPDF_Dict_AddName (smask, "ColorSpace", "DeviceGray");
		ret += HPDF_Dict_AddNumber (smask, "BitsPerComponent", (HPDF_UINT)bit_depth);

		if (ret != HPDF_OK) {
			HPDF_Dict_Free(smask);
			ret = HPDF_INVALID_PNG_IMAGE;
			goto Exit;
		}

		smask_data = HPDF_GetMem(image->mmgr, width * height);
		if (!smask_data) {
			HPDF_Dict_Free(smask);
			ret = HPDF_FAILD_TO_ALLOC_MEM;
			goto Exit;
		}

		if (ReadTransparentPngData(image, png_ptr, info_ptr, smask_data) != HPDF_OK) {
			HPDF_FreeMem(image->mmgr, smask_data);
			HPDF_Dict_Free(smask);
			ret = HPDF_INVALID_PNG_IMAGE;
			goto Exit;
		}

		if (HPDF_Stream_Write(smask->stream, smask_data, width * height) != HPDF_OK) {
			HPDF_FreeMem(image->mmgr, smask_data);
			HPDF_Dict_Free(smask);
			ret = HPDF_FILE_IO_ERROR;
			goto Exit;
		}
		HPDF_FreeMem(image->mmgr, smask_data);

		if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
			ret += HPDF_Dict_AddName (image, "ColorSpace", "DeviceGray");
		} else {
			ret += HPDF_Dict_AddName (image, "ColorSpace", "DeviceRGB");
		}
		ret += HPDF_Dict_AddNumber (image, "Width", (HPDF_UINT)width);
		ret += HPDF_Dict_AddNumber (image, "Height", (HPDF_UINT)height);
		ret += HPDF_Dict_AddNumber (image, "BitsPerComponent",	(HPDF_UINT)bit_depth);
		ret += HPDF_Dict_Add (image, "SMask", smask);

		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		return HPDF_OK;
	}

	/* if the image has color palette, copy the pallet of the image to
	 * create color map.
	 */
	if (color_type == PNG_COLOR_TYPE_PALETTE)
		ret = CreatePallet(image, png_ptr, info_ptr);
	else if (color_type == PNG_COLOR_TYPE_GRAY)
		ret = HPDF_Dict_AddName (image, "ColorSpace", "DeviceGray");
	else
		ret = HPDF_Dict_AddName (image, "ColorSpace", "DeviceRGB");

	if (ret != HPDF_OK)
		goto Exit;

	/* read image-data
	 * if the image is interlaced, read whole image at once.
	 * if delayed_loading is HPDF_TRUE, the data does not load this phase.
	 */
	if (delayed_loading) {
		image->before_write_fn = PngBeforeWrite;
		image->after_write_fn = PngAfterWrite;
	} else {
		if (png_get_interlace_type(png_ptr, info_ptr) != PNG_INTERLACE_NONE)
			ret = ReadPngData_Interlaced(image, png_ptr, info_ptr);
		else
			ret = ReadPngData(image, png_ptr, info_ptr);

		if (ret != HPDF_OK)
			goto Exit;
	}

	/* setting the info of the image. */
	if (HPDF_Dict_AddNumber (image, "Width", (HPDF_UINT)width)
			!= HPDF_OK)
		goto Exit;

	if (HPDF_Dict_AddNumber (image, "Height", (HPDF_UINT)height)
			!= HPDF_OK)
		goto Exit;

	if (HPDF_Dict_AddNumber (image, "BitsPerComponent",
				(HPDF_UINT)bit_depth) != HPDF_OK)
		goto Exit;

	/* clean up */
	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

	return HPDF_OK;

Exit:
	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

	if (ret != HPDF_OK) {
		return ret;
	}
	return image->error->error_no;
}
示例#11
0
文件: rwpng.c 项目: cheoree/pngquant
pngquant_error rwpng_read_image24_libpng(FILE *infile, png24_image *mainprog_ptr)
{
    png_structp  png_ptr = NULL;
    png_infop    info_ptr = NULL;
    png_size_t   rowbytes;
    int          color_type, bit_depth;

    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, mainprog_ptr,
      rwpng_error_handler, NULL);
    if (!png_ptr) {
        return PNG_OUT_OF_MEMORY_ERROR;   /* out of memory */
    }

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        png_destroy_read_struct(&png_ptr, NULL, NULL);
        return PNG_OUT_OF_MEMORY_ERROR;   /* out of memory */
    }

    /* setjmp() must be called in every function that calls a non-trivial
     * libpng function */

    if (setjmp(mainprog_ptr->jmpbuf)) {
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        return LIBPNG_FATAL_ERROR;   /* fatal libpng error (via longjmp()) */
    }

    struct rwpng_read_data read_data = {infile, 0};
    png_set_read_fn(png_ptr, &read_data, user_read_data);

    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, &mainprog_ptr->width, &mainprog_ptr->height,
      &bit_depth, &color_type, NULL, NULL, NULL);


    /* expand palette images to RGB, low-bit-depth grayscale images to 8 bits,
     * transparency chunks to full alpha channel; strip 16-bit-per-sample
     * images to 8 bits per sample; and convert grayscale to RGB[A] */

    /* GRR TO DO:  preserve all safe-to-copy ancillary PNG chunks */

    if (!(color_type & PNG_COLOR_MASK_ALPHA)) {
#ifdef PNG_READ_FILLER_SUPPORTED
        png_set_expand(png_ptr);
        png_set_filler(png_ptr, 65535L, PNG_FILLER_AFTER);
#else
        fprintf(stderr, "pngquant readpng:  image is neither RGBA nor GA\n");
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        mainprog_ptr->retval = 26;
        return mainprog_ptr->retval;
#endif
    }
/*
    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);


    /* get and save the gamma info (if any) for writing */

    double gamma;
    mainprog_ptr->gamma = png_get_gAMA(png_ptr, info_ptr, &gamma) ? gamma : 0.45455;

    png_set_interlace_handling(png_ptr);

    /* all transformations have been registered; now update info_ptr data,
     * get rowbytes and channels, and allocate image memory */

    png_read_update_info(png_ptr, info_ptr);

    rowbytes = png_get_rowbytes(png_ptr, info_ptr);

    if ((mainprog_ptr->rgba_data = malloc(rowbytes*mainprog_ptr->height)) == NULL) {
        fprintf(stderr, "pngquant readpng:  unable to allocate image data\n");
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        return PNG_OUT_OF_MEMORY_ERROR;
    }

    png_bytepp row_pointers = rwpng_create_row_pointers(info_ptr, png_ptr, mainprog_ptr->rgba_data, mainprog_ptr->height, 0);

    /* now we can go ahead and just read the whole image */

    png_read_image(png_ptr, row_pointers);

    /* and we're done!  (png_read_end() can be omitted if no processing of
     * post-IDAT text/time/etc. is desired) */

    png_read_end(png_ptr, NULL);

#if USE_LCMS
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_iCCP)) {
        png_uint_32 ProfileLen;
        png_bytep ProfileData;
        int  Compression;
        png_charp ProfileName;

        png_get_iCCP(png_ptr, info_ptr, &ProfileName,
                                        &Compression,
                                        &ProfileData,
                                        &ProfileLen);

        cmsHPROFILE hInProfile = cmsOpenProfileFromMem(ProfileData, ProfileLen);
        cmsHPROFILE hOutProfile = cmsCreate_sRGBProfile();

        cmsHTRANSFORM hTransform = cmsCreateTransform(hInProfile, TYPE_RGBA_8,
                                                    hOutProfile, TYPE_RGBA_8,
                                                    INTENT_PERCEPTUAL, 0);

        // suprisingly, using the same input and output works
        cmsDoTransform(hTransform, mainprog_ptr->rgba_data,
                                   mainprog_ptr->rgba_data,
                                   mainprog_ptr->height * mainprog_ptr->width);

        cmsDeleteTransform(hTransform);
        cmsCloseProfile(hOutProfile);
        cmsCloseProfile(hInProfile);
    }
#endif

    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

    mainprog_ptr->file_size = read_data.bytes_read;
    mainprog_ptr->row_pointers = (unsigned char **)row_pointers;

    return SUCCESS;
}
//
// Reads the image
//
void PNGReader::read(ImageFile * image)
{
	volatile unsigned char ** volatile rowPointers = NULL;
	png_struct * pngPtr = NULL;
	png_info * infoPtr = NULL;
	byte * data = NULL;

	try
	{
		int colorType, bitDepth;
		bool hasAlpha = false;
		uint bytesPerElement;
		ImageFormat format;
		unsigned long w, h;
		unsigned rowbytes;

		// Initialize the PNG library
		pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, pngErrorFunc, pngWarningFunc);
		if (unlikely(!pngPtr))
			throw Exception(QString("%1: png_create_read_struct() failed").arg(m_File.fileName()));

		// Initialize the PNG info struct
		infoPtr = png_create_info_struct(pngPtr);
		if (unlikely(!infoPtr))
			throw Exception(QString("%1: png_create_info_struct() failed").arg(m_File.fileName()));

		// Setup error handler
		if (unlikely(setjmp(png_jmpbuf(pngPtr)) != 0))
			throw Exception(QString("%1: PNG decompression failed").arg(m_File.fileName()));

		// Setup file reading
		png_set_read_fn(pngPtr, &m_File, pngReadFunc);
		png_set_sig_bytes(pngPtr, 8);
		png_read_info(pngPtr, infoPtr);
		png_get_IHDR(pngPtr, infoPtr, &w, &h, &bitDepth, &colorType, NULL, NULL, NULL);

		// Setup 16 bit -> 8 bit conversion
		if (bitDepth > 8) 
			png_set_strip_16(pngPtr);

		// Translate transparency to alpha channel
  		if (png_get_valid(pngPtr, infoPtr, PNG_INFO_tRNS))
		{
			png_set_tRNS_to_alpha(pngPtr);
			hasAlpha = true;
		}

		// Setup gamma correction
		double gamma;
		if (png_get_gAMA(pngPtr, infoPtr, &gamma))
			png_set_gamma(pngPtr, 2.2, gamma);
		else
			png_set_gamma(pngPtr, 2.2, 0.45455);

		// We want at least 8-bit
		if (bitDepth < 8)
		{
			if ((colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA))
				png_set_gray_1_2_4_to_8(pngPtr);
			else
				png_set_packing(pngPtr);
		}

		// Convert paletted images to RGB
		if (colorType == PNG_COLOR_TYPE_PALETTE)
		{
			png_set_palette_to_rgb(pngPtr);
			colorType = hasAlpha ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB;
		}

		// Convert gray/alpha images to RGB
		if (colorType == PNG_COLOR_TYPE_GRAY_ALPHA ||
			(colorType == PNG_COLOR_TYPE_GRAY && hasAlpha))
		{
			png_set_gray_to_rgb(pngPtr);
			colorType = PNG_COLOR_TYPE_RGB_ALPHA;
		}

		// Add dummy alpha channel for RGB images
		if (colorType == PNG_COLOR_TYPE_RGB && !hasAlpha)
		{
			png_set_filler(pngPtr, 0xFF, PNG_FILLER_BEFORE);
			hasAlpha = true;
		}
		else if (colorType == PNG_COLOR_TYPE_RGB_ALPHA)
			hasAlpha = true;

		// Select pixel format
		switch (colorType)
		{
		case PNG_COLOR_TYPE_PALETTE:
		case PNG_COLOR_TYPE_GRAY_ALPHA:
			Q_ASSERT(false);	// Should be handled in the code above
			break;

		case PNG_COLOR_TYPE_GRAY:
			bytesPerElement = 1;
			format = R8_UNORM;
			break;

		default:
			Q_ASSERT(hasAlpha);	// Should be handled in the code above
			bytesPerElement = 4;
			format = RGBA8_UNORM;
			break;
		}

		// Re-configure PNG reading to include configured conversions
		png_read_update_info(pngPtr, infoPtr);
		rowbytes = png_get_rowbytes(pngPtr, infoPtr);

		// Set basic image info
		setImageSize(image, w, h);
		setImageDepth(image, 0);
		setImageMipLevels(image, 1);
		setImageFaces(image, 0);
		setImageFormat(image, format);
		setImageElementSize(image, bytesPerElement);

		// Allocate memory for image data
		data = new byte[w * h * bytesPerElement];
		if (unlikely(!data))
			throw Exception("Out of memory.");

		// Allocate array of row pointers
		rowPointers = new volatile unsigned char * [h];
		for (unsigned j = 0; j < h; j++)
			rowPointers[j] = data + j * rowbytes;

		// Read the image
		png_read_image(pngPtr, (png_byte **)rowPointers);

		// Store image information
		appendImageLevelData(image, data);
		data = NULL;

		// Free memory
		png_destroy_read_struct(&pngPtr, &infoPtr, NULL);
		pngPtr = NULL;
	}
	catch (...)
	{
		delete[] rowPointers;
		delete[] data;

		if (pngPtr)
		{
			if (infoPtr)
				png_destroy_read_struct(&pngPtr, &infoPtr, NULL);
			else
				png_destroy_read_struct(&pngPtr, NULL, NULL);
		}	

		throw;
	}

	delete[] rowPointers;
}
示例#13
0
PyObject*
_png_module::_read_png(const Py::Object& py_fileobj, const bool float_result)
{
    png_byte header[8];   // 8 is the maximum size that can be checked
    FILE* fp = NULL;
    bool close_file = false;

#if PY3K
    int fd = PyObject_AsFileDescriptor(py_fileobj.ptr());
    PyErr_Clear();
#endif

    if (py_fileobj.isString())
    {
        std::string fileName = Py::String(py_fileobj);
        const char *file_name = fileName.c_str();
        if ((fp = fopen(file_name, "rb")) == NULL)
        {
            throw Py::RuntimeError(
                Printf("Could not open file %s for reading", file_name).str());
        }
        close_file = true;
    }
#if PY3K
    else if (fd != -1) {
        fp = fdopen(fd, "r");
    }
#else
    else if (PyFile_CheckExact(py_fileobj.ptr()))
    {
        fp = PyFile_AsFile(py_fileobj.ptr());
    }
#endif
    else
    {
        PyObject* read_method = PyObject_GetAttrString(py_fileobj.ptr(), "read");
        if (!(read_method && PyCallable_Check(read_method)))
        {
            Py_XDECREF(read_method);
            throw Py::TypeError("Object does not appear to be a 8-bit string path or a Python file-like object");
        }
        Py_XDECREF(read_method);
    }

    if (fp)
    {
        if (fread(header, 1, 8, fp) != 8)
        {
            throw Py::RuntimeError(
                "_image_module::readpng: error reading PNG header");
        }
    }
    else
    {
        _read_png_data(py_fileobj.ptr(), header, 8);
    }
    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");
    }

    if (fp)
    {
        png_init_io(png_ptr, fp);
    }
    else
    {
        png_set_read_fn(png_ptr, (void*)py_fileobj.ptr(), &read_png_data);
    }
    png_set_sig_bytes(png_ptr, 8);
    png_read_info(png_ptr, info_ptr);

    png_uint_32 width = png_get_image_width(png_ptr, info_ptr);
    png_uint_32 height = png_get_image_height(png_ptr, info_ptr);

    int bit_depth = png_get_bit_depth(png_ptr, info_ptr);

    // Unpack 1, 2, and 4-bit images
    if (bit_depth < 8)
        png_set_packing(png_ptr);

    // If sig bits are set, shift data
    png_color_8p sig_bit;
    if ((png_get_color_type(png_ptr, info_ptr) != PNG_COLOR_TYPE_PALETTE) &&
        png_get_sBIT(png_ptr, info_ptr, &sig_bit))
    {
        png_set_shift(png_ptr, sig_bit);
    }

    // Convert big endian to little
    if (bit_depth == 16)
    {
        png_set_swap(png_ptr);
    }

    // Convert palletes to full RGB
    if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE)
    {
        png_set_palette_to_rgb(png_ptr);
    }

    // If there's an alpha channel convert gray to RGB
    if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_GRAY_ALPHA)
    {
        png_set_gray_to_rgb(png_ptr);
    }

    png_set_interlace_handling(png_ptr);
    png_read_update_info(png_ptr, info_ptr);

    /* read file */
    if (setjmp(png_jmpbuf(png_ptr)))
    {
        throw Py::RuntimeError(
            "_image_module::readpng: error during read_image");
    }

    png_bytep *row_pointers = new png_bytep[height];
    png_uint_32 row;

    for (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);

    npy_intp dimensions[3];
    dimensions[0] = height;  //numrows
    dimensions[1] = width;   //numcols
    if (png_get_color_type(png_ptr, info_ptr) & PNG_COLOR_MASK_ALPHA)
    {
        dimensions[2] = 4;     //RGBA images
    }
    else if (png_get_color_type(png_ptr, info_ptr) & PNG_COLOR_MASK_COLOR)
    {
        dimensions[2] = 3;     //RGB images
    }
    else
    {
        dimensions[2] = 1;     //Greyscale images
    }
    //For gray, return an x by y array, not an x by y by 1
    int num_dims  = (png_get_color_type(png_ptr, info_ptr)
                                & PNG_COLOR_MASK_COLOR) ? 3 : 2;

    PyArrayObject *A = NULL;
    if (float_result) {
        double max_value = (1 << bit_depth) - 1;
        PyArrayObject *A = (PyArrayObject *) PyArray_SimpleNew(
            num_dims, dimensions, PyArray_FLOAT);

        if (A == NULL)
        {
            throw Py::MemoryError("Could not allocate image array");
        }

        for (png_uint_32 y = 0; y < height; y++)
        {
            png_byte* row = row_pointers[y];
            for (png_uint_32 x = 0; x < width; x++)
            {
                size_t offset = y * A->strides[0] + x * A->strides[1];
                if (bit_depth == 16)
                {
                    png_uint_16* ptr = &reinterpret_cast<png_uint_16*>(row)[x * dimensions[2]];
                    for (png_uint_32 p = 0; p < (png_uint_32)dimensions[2]; p++)
                    {
                        *(float*)(A->data + offset + p*A->strides[2]) = (float)(ptr[p]) / max_value;
                    }
                }
                else
                {
                    png_byte* ptr = &(row[x * dimensions[2]]);
                    for (png_uint_32 p = 0; p < (png_uint_32)dimensions[2]; p++)
                    {
                        *(float*)(A->data + offset + p*A->strides[2]) = (float)(ptr[p]) / max_value;
                    }
                }
            }
        }
    } else {
        A = (PyArrayObject *) PyArray_SimpleNew(num_dims, dimensions, NPY_UBYTE);

        if (A == NULL)
        {
            throw Py::MemoryError("Could not allocate image array");
        }

        for (png_uint_32 y = 0; y < height; y++)
        {
            png_byte* row = row_pointers[y];
            for (png_uint_32 x = 0; x < width; x++)
            {
                size_t offset = y * A->strides[0] + x * A->strides[1];
                if (bit_depth == 16)
                {
                    png_uint_16* ptr = &reinterpret_cast<png_uint_16*>(row)[x * dimensions[2]];
                    for (png_uint_32 p = 0; p < (png_uint_32)dimensions[2]; p++)
                    {
                        *(png_byte*)(A->data + offset + p*A->strides[2]) = ptr[p] >> 8;
                    }
                }
                else
                {
                    png_byte* ptr = &(row[x * dimensions[2]]);
                    for (png_uint_32 p = 0; p < (png_uint_32)dimensions[2]; p++)
                    {
                        *(png_byte*)(A->data + offset + p*A->strides[2]) = ptr[p];
                    }
                }
            }
        }
示例#14
0
static GF_Err PNG_ProcessData(GF_MediaDecoder *ifcg, 
		char *inBuffer, u32 inBufferLength,
		u16 ES_ID,
		char *outBuffer, u32 *outBufferLength,
		u8 PaddingBits, u32 mmlevel)
{
	png_struct *png_ptr;
	png_info *info_ptr;
	png_byte **rows;
	u32 i, stride;

	PNGCTX();
	if ((inBufferLength<8) || png_sig_cmp(inBuffer, 0, 8) ) return GF_NON_COMPLIANT_BITSTREAM;

	ctx->in_data = inBuffer;
	ctx->in_length = inBufferLength;
	ctx->current_pos = 0;

	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp) ctx, NULL, NULL);
	if (!png_ptr) return GF_IO_ERR;
	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL) {
		png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
		return GF_IO_ERR;
	}
	if (setjmp(png_ptr->jmpbuf)) {
		png_destroy_info_struct(png_ptr,(png_infopp) & info_ptr);
		png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
		return GF_IO_ERR;
	}
    png_set_read_fn(png_ptr, ctx, (png_rw_ptr) user_read_data);
	png_set_error_fn(png_ptr, ctx, (png_error_ptr) user_error_fn, NULL);

	png_read_info(png_ptr, info_ptr);

	/*unpaletize*/
	if (info_ptr->color_type==PNG_COLOR_TYPE_PALETTE) {
		png_set_expand(png_ptr);
		png_read_update_info(png_ptr, info_ptr);
	}
	if (info_ptr->num_trans) {
		png_set_tRNS_to_alpha(png_ptr);
		png_read_update_info(png_ptr, info_ptr);
	}

	ctx->BPP = info_ptr->pixel_depth / 8;
	ctx->width = info_ptr->width;
	ctx->height = info_ptr->height;

	switch (ctx->BPP) {
	case 1:
		ctx->pixel_format = GF_PIXEL_GREYSCALE;
		break;
	case 2:
		ctx->pixel_format = GF_PIXEL_ALPHAGREY;
		break;
	case 3:
		ctx->pixel_format = GF_PIXEL_RGB_24;
		break;
	case 4:
		ctx->pixel_format = GF_PIXEL_RGBA;
		break;
	}

	/*new cfg, reset*/
	if (ctx->out_size != ctx->width * ctx->height * ctx->BPP) {
		ctx->out_size = ctx->width * ctx->height * ctx->BPP;
		*outBufferLength = ctx->out_size;
		png_destroy_info_struct(png_ptr,(png_infopp) & info_ptr);
		png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
		return GF_BUFFER_TOO_SMALL;
	}

	/*read*/
	stride = png_get_rowbytes(png_ptr, info_ptr);
	rows = (png_bytepp) malloc(sizeof(png_bytep) * ctx->height);
	for (i=0; i<ctx->height; i++) {
		rows[i] = outBuffer + i*stride;
	}
	png_read_image(png_ptr, rows);
	png_read_end(png_ptr, NULL);
	free(rows);

	png_destroy_info_struct(png_ptr,(png_infopp) & info_ptr);
	png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
	*outBufferLength = ctx->out_size;

	
	return GF_OK;
}
示例#15
0
/* Alternate create PNG structure for reading, and allocate any memory
 * needed.
 */
png_structp PNGAPI
png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
   png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
   png_malloc_ptr malloc_fn, png_free_ptr free_fn)
{
#endif /* PNG_USER_MEM_SUPPORTED */

#ifdef PNG_SETJMP_SUPPORTED
   volatile
#endif
   png_structp png_ptr;

#ifdef PNG_SETJMP_SUPPORTED
#ifdef USE_FAR_KEYWORD
   jmp_buf jmpbuf;
#endif
#endif

   int i;

   png_debug(1, "in png_create_read_struct");

#ifdef PNG_USER_MEM_SUPPORTED
   png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
      (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr);
#else
   png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
#endif
   if (png_ptr == NULL)
      return (NULL);

   /* Added at libpng-1.2.6 */
#ifdef PNG_USER_LIMITS_SUPPORTED
   png_ptr->user_width_max = PNG_USER_WIDTH_MAX;
   png_ptr->user_height_max = PNG_USER_HEIGHT_MAX;
#  ifdef PNG_USER_CHUNK_CACHE_MAX
   /* Added at libpng-1.2.43 and 1.4.0 */
   png_ptr->user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX;
#  endif
#  ifdef PNG_SET_USER_CHUNK_MALLOC_MAX
   /* Added at libpng-1.2.43 and 1.4.1 */
   png_ptr->user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX;
#  endif
#endif

#ifdef PNG_SETJMP_SUPPORTED
#ifdef USE_FAR_KEYWORD
   if (setjmp(jmpbuf))
#else
   if (setjmp(png_ptr->jmpbuf))
#endif
   {
      png_free(png_ptr, png_ptr->zbuf);
      png_ptr->zbuf = NULL;
#ifdef PNG_USER_MEM_SUPPORTED
      png_destroy_struct_2((png_voidp)png_ptr,
         (png_free_ptr)free_fn, (png_voidp)mem_ptr);
#else
      png_destroy_struct((png_voidp)png_ptr);
#endif
      return (NULL);
   }
#ifdef USE_FAR_KEYWORD
   png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf));
#endif
#endif /* PNG_SETJMP_SUPPORTED */

#ifdef PNG_USER_MEM_SUPPORTED
   png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
#endif

   png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);

   if (user_png_ver)
   {
      i = 0;
      do
      {
         if (user_png_ver[i] != png_libpng_ver[i])
            png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
      } while (png_libpng_ver[i++]);
    }
    else
         png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;


    if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH)
    {
       /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
       * we must recompile any applications that use any older library version.
       * For versions after libpng 1.0, we will be compatible, so we need
       * only check the first digit.
       */
      if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||
          (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) ||
          (user_png_ver[0] == '0' && user_png_ver[2] < '9'))
      {
#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
         char msg[80];
         if (user_png_ver)
         {
           png_snprintf(msg, 80,
              "Application was compiled with png.h from libpng-%.20s",
              user_png_ver);
           png_warning(png_ptr, msg);
         }
         png_snprintf(msg, 80,
             "Application  is  running with png.c from libpng-%.20s",
             png_libpng_ver);
         png_warning(png_ptr, msg);
#endif
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
         png_ptr->flags = 0;
#endif
         png_error(png_ptr,
            "Incompatible libpng version in application and library");
      }
   }

   /* Initialize zbuf - compression buffer */
   png_ptr->zbuf_size = PNG_ZBUF_SIZE;
   png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
     (png_uint_32)png_ptr->zbuf_size);
   png_ptr->zstream.zalloc = png_zalloc;
   png_ptr->zstream.zfree = png_zfree;
   png_ptr->zstream.opaque = (voidpf)png_ptr;

      switch (inflateInit(&png_ptr->zstream))
      {
         case Z_OK: /* Do nothing */ break;
         case Z_MEM_ERROR:
         case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error");
            break;
         case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error");
            break;
         default: png_error(png_ptr, "Unknown zlib error");
      }


   png_ptr->zstream.next_out = png_ptr->zbuf;
   png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;

   png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL);

#ifdef PNG_SETJMP_SUPPORTED
/* Applications that neglect to set up their own setjmp() and then
   encounter a png_error() will longjmp here.  Since the jmpbuf is
   then meaningless we abort instead of returning. */
#ifdef USE_FAR_KEYWORD
   if (setjmp(jmpbuf))
       PNG_ABORT();
   png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf));
#else
   if (setjmp(png_ptr->jmpbuf))
       PNG_ABORT();
#endif
#endif /* PNG_SETJMP_SUPPORTED */

   return (png_ptr);
}
示例#16
0
void LoadImage (const char *filename, unsigned char **pic, int *width, int *height)
{
    png_byte** row_pointers;
    unsigned char *fbuffer = NULL;
    png_bytep p_fbuffer;

    int nLen = g_FileSystemTable.m_pfnLoadFile( (char *)filename, (void **)&fbuffer, 0 );
    if (nLen == -1)
        return;

    p_fbuffer = fbuffer;

    // the reading glue
    // http://www.libpng.org/pub/png/libpng-manual.html

    png_structp png_ptr = png_create_read_struct
                          (PNG_LIBPNG_VER_STRING, png_voidp_NULL,
                           user_error_fn, user_warning_fn);
    if (!png_ptr)
    {
        g_FuncTable.m_pfnSysPrintf ("libpng error: png_create_read_struct\n");
        return;
    }

    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);
        g_FuncTable.m_pfnSysPrintf ("libpng error: png_create_info_struct (info_ptr)\n");
        return;
    }

    png_infop end_info = png_create_info_struct(png_ptr);
    if (!end_info) {
        png_destroy_read_struct(&png_ptr, &info_ptr,
                                png_infopp_NULL);
        g_FuncTable.m_pfnSysPrintf ("libpng error: png_create_info_struct (end_info)\n");
        return;
    }

    // configure the read function
    png_set_read_fn(png_ptr, (voidp)&p_fbuffer, (png_rw_ptr)&user_read_data);

    if (setjmp(png_ptr->jmpbuf)) {
        png_destroy_read_struct(&png_ptr, &info_ptr,
                                &end_info);
        if (*pic)
        {
            g_free(*pic);
            free(row_pointers);
        }
        return;
    }

    png_read_info(png_ptr, info_ptr);

    int bit_depth = png_get_bit_depth(png_ptr, info_ptr);
    int color_type = png_get_color_type(png_ptr, info_ptr);

    // we want to treat all images the same way
    //   The following code transforms grayscale images of less than 8 to 8 bits,
    //   changes paletted images to RGB, and adds a full alpha channel if there is
    //   transparency information in a tRNS chunk.
    if (color_type == PNG_COLOR_TYPE_PALETTE)
        png_set_palette_to_rgb(png_ptr);

    if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
        png_set_gray_1_2_4_to_8(png_ptr);

    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
        png_set_tRNS_to_alpha(png_ptr);

    if ( ! ( color_type & PNG_COLOR_MASK_ALPHA ) ) {
        // Set the background color to draw transparent and alpha images over.
        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);

        // Add alpha byte after each RGB triplet
        png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
    }

    // read the sucker in one chunk
    png_read_update_info(png_ptr, info_ptr);

    color_type = png_get_color_type(png_ptr, info_ptr);
    bit_depth = png_get_bit_depth(png_ptr, info_ptr);

    *width = png_get_image_width(png_ptr, info_ptr);
    *height = png_get_image_height(png_ptr, info_ptr);

    // allocate the pixel buffer, and the row pointers
    int size = (*width)*(*height)*4;
    // still have to use that g_malloc heresy
    *pic = (unsigned char *)g_malloc(size);
    row_pointers = (png_byte**) malloc((*height) * sizeof(png_byte*));

    int i;
    for(i = 0; i < (*height); i++)
        row_pointers[i] = (png_byte*)(*pic) + i * 4 * (*width);

    // actual read
    png_read_image(png_ptr, row_pointers);

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

    /* free up the memory structure */
    png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);

    free(row_pointers);
    g_FileSystemTable.m_pfnFreeFile (fbuffer);
}
示例#17
0
void ossimPngReader::restart()
{
   if ( m_str )
   {
      // Destroy the existing memory associated with png structs.
      if (m_pngReadPtr && m_pngReadInfoPtr)
      {
         png_destroy_read_struct(&m_pngReadPtr, &m_pngReadInfoPtr, NULL);
      }

      m_pngReadPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
                                            NULL,
                                            NULL,
                                            NULL);
      m_pngReadInfoPtr = png_create_info_struct(m_pngReadPtr);

      if ( setjmp( png_jmpbuf(m_pngReadPtr) ) )
      {
         ossimNotify(ossimNotifyLevel_WARN)
            << "Error while reading.  File corrupted?  "
            << theImageFile
            << std::endl;
      
         return;
      }

      // Reset the file pointer.
      m_str->seekg( m_restartPosition, std::ios_base::beg );
   
      //---
      // Pass the static read method to libpng to allow us to use our
      // c++ stream instead of doing "png_init_io (pp, ...);" with
      // c stream.
      //---
      png_set_read_fn( m_pngReadPtr,
                       (png_voidp)m_str,
                       (png_rw_ptr)&ossimPngReader::pngReadData );

      //---
      // Note we won't do png_set_sig_bytes(png_ptr, 8) here because we are not
      // rechecking for png signature.
      //---
      png_read_info(m_pngReadPtr, m_pngReadInfoPtr);

      //---
      // If png_set_expand used:
      // Expand data to 24-bit RGB, or 8-bit grayscale,
      // with alpha if available.
      //---
      bool expandFlag = false;

      if ( m_pngColorType == PNG_COLOR_TYPE_PALETTE )
      {
         expandFlag = true;
      }
      if ( (m_pngColorType == PNG_COLOR_TYPE_GRAY) && (m_bitDepth < 8) )
      {
         expandFlag = true;
      }
      if ( png_get_valid(m_pngReadPtr, m_pngReadInfoPtr, PNG_INFO_tRNS) )
      {
         expandFlag = true;
      }

      //---
      // If png_set_packing used:
      // Use 1 byte per pixel in 1, 2, or 4-bit depth files. */
      //---
      bool packingFlag = false;

      if ( (m_bitDepth < 8) && (m_pngColorType == PNG_COLOR_TYPE_GRAY) )
      {
         packingFlag = true;
      }

      if (expandFlag)
      {
         png_set_expand(m_pngReadPtr);
      }
      if (packingFlag)
      {
         png_set_packing(m_pngReadPtr);
      }

      // Gamma correction.
      //    ossim_float64 gamma;
      //    if (png_get_gAMA(m_pngReadPtr, m_pngReadInfoPtr, &gamma))
      //    {
      //       png_set_gamma(m_pngReadPtr, display_exponent, gamma);
      //    }

      //---
      // Turn on interlace handling... libpng returns just 1 (ie single pass)
      //  if the image is not interlaced
      //---
      png_set_interlace_handling (m_pngReadPtr);

      //---
      // Update the info structures after the transformations take effect
      //---
      png_read_update_info (m_pngReadPtr, m_pngReadInfoPtr);
   
      // We're back on row 0 or first line.
      m_currentRow = 0;
   }
}
示例#18
0
bool CCImage::_initWithPngData(void * pData, int nDatalen)
{
    bool bRet = false;
    png_byte        header[8]   = {0}; 
    png_structp     png_ptr     =   0;
    png_infop       info_ptr    = 0;
    unsigned char * pImateData  = 0;

    do 
    {
        // png header len is 8 bytes
    	CC_BREAK_IF(nDatalen < 8);

        // check the data is png or not
        memcpy(header, pData, 8);
        CC_BREAK_IF(png_sig_cmp(header, 0, 8));

        // init png_struct
        png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
        CC_BREAK_IF(! png_ptr);

        // init png_info
        info_ptr = png_create_info_struct(png_ptr);
        CC_BREAK_IF(!info_ptr || setjmp(png_jmpbuf(png_ptr)));

        // 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
        // PNG_TRANSFORM_EXPAND: perform set_expand()
        // PNG_TRANSFORM_PACKING: expand 1, 2 and 4-bit samples to bytes
        // PNG_TRANSFORM_STRIP_16: strip 16-bit samples to 8 bits
        // PNG_TRANSFORM_GRAY_TO_RGB: expand grayscale samples to RGB (or GA to RGBA)
        png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_PACKING 
            | PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_GRAY_TO_RGB, 0);

        int         color_type  = 0;
        png_uint_32 nWidth = 0;
        png_uint_32 nHeight = 0;
        int         nBitsPerComponent = 0;
        png_get_IHDR(png_ptr, info_ptr, &nWidth, &nHeight, &nBitsPerComponent, &color_type, 0, 0, 0);

        // init image info
        m_bPreMulti = true;
        m_bHasAlpha = ( info_ptr->color_type & PNG_COLOR_MASK_ALPHA ) ? true : false;

        // allocate memory and read data
        int bytesPerComponent = 3;
        if (m_bHasAlpha)
        {
            bytesPerComponent = 4;
        }
        pImateData = new unsigned char[nHeight * nWidth * bytesPerComponent];
        CC_BREAK_IF(! pImateData);

        png_bytep * rowPointers = png_get_rows(png_ptr, info_ptr);

        // copy data to image info
        int bytesPerRow = nWidth * bytesPerComponent;
        if(m_bHasAlpha)
        {
            unsigned int *tmp = (unsigned int *)pImateData;
            for(unsigned int i = 0; i < nHeight; i++)
            {
                for(int j = 0; j < bytesPerRow; j += 4)
                {
                    *tmp++ = CC_RGB_PREMULTIPLY_APLHA( rowPointers[i][j], rowPointers[i][j + 1], 
                        rowPointers[i][j + 2], rowPointers[i][j + 3] );
                }
            }
        }
        else
        {
            for (unsigned int j = 0; j < nHeight; ++j)
            {
                memcpy(pImateData + j * bytesPerRow, rowPointers[j], bytesPerRow);
            }
        }

        m_nBitsPerComponent = nBitsPerComponent;
        m_nHeight   = (short)nHeight;
        m_nWidth    = (short)nWidth;
        m_pData     = pImateData;
        pImateData  = 0;
        bRet        = true;
    } while (0);

    CC_SAFE_DELETE_ARRAY(pImateData);

    if (png_ptr)
    {
        png_destroy_read_struct(&png_ptr, (info_ptr) ? &info_ptr : 0, 0);
    }
    return bRet;
}
示例#19
0
int PngDecoder::validate()
{
    if (png_sig_cmp((png_bytep)buf->data(), 0, PNG_HEADER_SIZE)) {
        std::cout << "[PngDecoder] error: %s is not a PNG." << std::endl;
        return -1;
    }
    buf->drain(PNG_HEADER_SIZE);

    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr) {
        std::cout << "[PngDecoder] error: png_create_read_struct returned 0." << std::endl;
        return -1;
    }

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        std::cout << "[PngDecoder] error: png_create_info_struct returned 0." << std::endl;
        png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
        return -1;
    }

    end_info = png_create_info_struct(png_ptr);
    if (!end_info) {
        std::cout << "[PngDecoder] error: png_create_info_struct returned 0." << std::endl;
        png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
        return -1;
    }

    if (setjmp(png_jmpbuf(png_ptr))) {
        std::cout << "[PngDecoder] error from libpng" << std::endl;
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        return -1;
    }

    png_set_read_fn(png_ptr, buf, pngDecoderReadFunction);

    png_set_sig_bytes(png_ptr, PNG_HEADER_SIZE);

    png_read_info(png_ptr, info_ptr);

    png_set_expand(png_ptr);
    png_set_strip_16(png_ptr);
    png_set_gray_to_rgb(png_ptr);
    png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER);
    png_set_interlace_handling(png_ptr);

    png_read_update_info(png_ptr, info_ptr);

    imgInfo.width    = png_get_image_width(png_ptr, info_ptr);
    imgInfo.height   = png_get_image_height(png_ptr, info_ptr);

    imgInfo.color_type = png_get_color_type(png_ptr, info_ptr);
    imgInfo.channels = png_get_channels(png_ptr, info_ptr);
    imgInfo.bit_depth = png_get_bit_depth(png_ptr, info_ptr);
    imgInfo.interlance_type = png_get_interlace_type(png_ptr, info_ptr);
    imgInfo.rowbytes = png_get_rowbytes(png_ptr, info_ptr);

#ifdef _PNGDECODER_DEBUG
    std::cout << "[PngDecoder] Extracted w=" << imgInfo.width
              << " h="  << imgInfo.height
              << " color_type=" << imgInfo.color_type
              << " bit_depth="<< imgInfo.bit_depth
              << " rowbytes="<< imgInfo.rowbytes
              << " channels="<< imgInfo.channels
              << " interlance_type="<< imgInfo.interlance_type
              << std::endl;
#endif

    if (imgInfo.bit_depth != 8) {
        std::cout << "[PngDecoder] error: Unsupported bit depth=" << imgInfo.bit_depth <<". Must be 8." << std::endl;
        return -1;
    }

    switch(imgInfo.color_type) {
    case PNG_COLOR_TYPE_RGB:
        imgInfo.format = GL_RGB;
        break;
    case PNG_COLOR_TYPE_RGB_ALPHA:
        imgInfo.format = GL_RGBA;
        break;
    case PNG_COLOR_TYPE_PALETTE:
        if (imgInfo.color_type & PNG_COLOR_MASK_ALPHA) {
            imgInfo.format = GL_RGBA;
        } else if (imgInfo.color_type & PNG_COLOR_MASK_COLOR) {
            imgInfo.format = GL_RGB;
        }
        break;
    default:
        std::cout << "[PngDecoder] error: unknown libpng color type=" << imgInfo.color_type << " rgb=" << PNG_COLOR_TYPE_RGB << " rgba=" << PNG_COLOR_TYPE_RGBA << " palette=" << PNG_COLOR_TYPE_PALETTE << std::endl;
        return -1;
    }

    return 0;
}
示例#20
0
bool
wxPNGHandler::LoadFile(wxImage *image,
                       wxInputStream& stream,
                       bool verbose,
                       int WXUNUSED(index))
{
    // VZ: as this function uses setjmp() the only fool-proof error handling
    //     method is to use goto (setjmp is not really C++ dtors friendly...)

    unsigned char **lines = NULL;
    png_infop info_ptr = (png_infop) NULL;
    wxPNGInfoStruct wxinfo;

    png_uint_32 i, width, height = 0;
    int bit_depth, color_type, interlace_type;

    wxinfo.verbose = verbose;
    wxinfo.stream.in = &stream;

    image->Destroy();

    png_structp png_ptr = png_create_read_struct
                          (
                            PNG_LIBPNG_VER_STRING,
                            NULL,
                            wx_PNG_error,
                            wx_PNG_warning
                          );
    if (!png_ptr)
        goto error;

    // NB: please see the comment near wxPNGInfoStruct declaration for
    //     explanation why this line is mandatory
    png_set_read_fn( png_ptr, &wxinfo, wx_PNG_stream_reader);

    info_ptr = png_create_info_struct( png_ptr );
    if (!info_ptr)
        goto error;

    if (setjmp(wxinfo.jmpbuf))
        goto error;

    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_expand( png_ptr );

    // Fix for Bug [ 439207 ] Monochrome PNG images come up black
    if (bit_depth < 8)
        png_set_expand( png_ptr );

    png_set_strip_16( png_ptr );
    png_set_packing( png_ptr );
    if (png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS))
        png_set_expand( png_ptr );
    png_set_filler( png_ptr, 0xff, PNG_FILLER_AFTER );

    image->Create((int)width, (int)height, (bool) false /* no need to init pixels */);

    if (!image->IsOk())
        goto error;

    // initialize all line pointers to NULL to ensure that they can be safely
    // free()d if an error occurs before all of them could be allocated
    lines = (unsigned char **)calloc(height, sizeof(unsigned char *));
    if ( !lines )
        goto error;

    for (i = 0; i < height; i++)
    {
        if ((lines[i] = (unsigned char *)malloc( (size_t)(width * 4))) == NULL)
            goto error;
    }

    png_read_image( png_ptr, lines );
    png_read_end( png_ptr, info_ptr );

#if wxUSE_PALETTE
    if (color_type == PNG_COLOR_TYPE_PALETTE)
    {
        png_colorp palette = NULL;
        int numPalette = 0;

        (void) png_get_PLTE(png_ptr, info_ptr, &palette, &numPalette);

        unsigned char* r = new unsigned char[numPalette];
        unsigned char* g = new unsigned char[numPalette];
        unsigned char* b = new unsigned char[numPalette];

        for (int j = 0; j < numPalette; j++)
        {
            r[j] = palette[j].red;
            g[j] = palette[j].green;
            b[j] = palette[j].blue;
        }

        image->SetPalette(wxPalette(numPalette, r, g, b));
        delete[] r;
        delete[] g;
        delete[] b;
    }
#endif // wxUSE_PALETTE


    // set the image resolution if it's available
    png_uint_32 resX, resY;
    int unitType;
    if (png_get_pHYs(png_ptr, info_ptr, &resX, &resY, &unitType)
        == PNG_INFO_pHYs)
    {
        wxImageResolution res = wxIMAGE_RESOLUTION_CM;

        switch (unitType)
        {
            default:
                wxLogWarning(_("Unknown PNG resolution unit %d"), unitType);
                wxFALLTHROUGH;

            case PNG_RESOLUTION_UNKNOWN:
                image->SetOption(wxIMAGE_OPTION_RESOLUTIONX, resX);
                image->SetOption(wxIMAGE_OPTION_RESOLUTIONY, resY);

                res = wxIMAGE_RESOLUTION_NONE;
                break;

            case PNG_RESOLUTION_METER:
                /*
                Convert meters to centimeters.
                Use a string to not lose precision (converting to cm and then
                to inch would result in integer rounding error).
                If an app wants an int, GetOptionInt will convert and round
                down for them.
                */
                image->SetOption(wxIMAGE_OPTION_RESOLUTIONX,
                    wxString::FromCDouble((double) resX / 100.0, 2));
                image->SetOption(wxIMAGE_OPTION_RESOLUTIONY,
                    wxString::FromCDouble((double) resY / 100.0, 2));
                break;
        }

        image->SetOption(wxIMAGE_OPTION_RESOLUTIONUNIT, res);
    }


    png_destroy_read_struct( &png_ptr, &info_ptr, (png_infopp) NULL );

    // loaded successfully, now init wxImage with this data
    CopyDataFromPNG(image, lines, width, height, color_type);

    for ( i = 0; i < height; i++ )
        free( lines[i] );
    free( lines );

    return true;

error:
    if (verbose)
    {
       wxLogError(_("Couldn't load a PNG image - file is corrupted or not enough memory."));
    }

    if ( image->IsOk() )
    {
        image->Destroy();
    }

    if ( lines )
    {
        for ( unsigned int n = 0; n < height; n++ )
            free( lines[n] );

        free( lines );
    }

    if ( png_ptr )
    {
        if ( info_ptr )
        {
            png_destroy_read_struct( &png_ptr, &info_ptr, (png_infopp) NULL );
            free(info_ptr);
        }
        else
            png_destroy_read_struct( &png_ptr, (png_infopp) NULL, (png_infopp) NULL );
    }
    return false;
}
示例#21
0
BMGError ReadPNGInfo( const char *filename,
        struct BMGImageStruct * volatile img )
{
    jmp_buf             err_jmp;
    int                 error;

    FILE * volatile     file = NULL;
    int                 BitDepth;
    int                 ColorType;
    int                 InterlaceType;
    unsigned char       signature[8];
    png_structp volatile png_ptr = NULL;
    png_infop   volatile info_ptr = NULL;
    png_infop   volatile end_info = NULL;
    png_uint_32         Width, Height;

    /* error handler */
    error = setjmp( err_jmp );
    if (error != 0)
    {
        if (end_info != NULL)
            png_destroy_read_struct((png_structp *) &png_ptr, (png_infop *) &info_ptr, (png_infop *) &end_info);
        else if (info_ptr != NULL)
            png_destroy_read_struct((png_structp *) &png_ptr, (png_infop *) &info_ptr, NULL);
        else if (png_ptr != NULL)
            png_destroy_read_struct((png_structp *) &png_ptr, NULL, NULL);
        if (img)
            FreeBMGImage(img);
        if (file)
            fclose(file);
        SetLastBMGError((BMGError) error);
        return (BMGError) error;
    }

    if ( img == NULL )
        longjmp ( err_jmp, (int)errInvalidBMGImage );

    file = fopen( filename, "rb" );
    if ( !file || fread( signature, 1, 8, file ) != 8)
        longjmp ( err_jmp, (int)errFileOpen );

    /* check the signature */
    if ( png_sig_cmp( signature, 0, 8 ) != 0 )
        longjmp( err_jmp, (int)errUnsupportedFileFormat );

    /* create a pointer to the png read structure */
    png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
    if ( !png_ptr )
        longjmp( err_jmp, (int)errMemoryAllocation );

    /* create a pointer to the png info structure */
    info_ptr = png_create_info_struct( png_ptr );
    if ( !info_ptr )
        longjmp( err_jmp, (int)errMemoryAllocation );

    /* create a pointer to the png end-info structure */
    end_info = png_create_info_struct(png_ptr);
    if (!end_info)
        longjmp( err_jmp, (int)errMemoryAllocation );

    /* bamboozle the PNG longjmp buffer */
    /*generic PNG error handler*/
    /* error will always == 1 which == errLib */
//    error = png_setjmp(png_ptr);
    error = setjmp( png_jmpbuf( png_ptr ) );
    if ( error > 0 )
        longjmp( err_jmp, error );

    /* set function pointers in the PNG library, for read callbacks */
    png_set_read_fn(png_ptr, (png_voidp) file, user_read_data);

    /*let the read functions know that we have already read the 1st 8 bytes */
    png_set_sig_bytes( png_ptr, 8 );

    /* read all PNG data up to the image data */
    png_read_info( png_ptr, info_ptr );

    /* extract the data we need to form the HBITMAP from the PNG header */
    png_get_IHDR( png_ptr, info_ptr, &Width, &Height, &BitDepth, &ColorType,
        &InterlaceType, NULL, NULL);

    img->width = (unsigned int) Width;
    img->height = (unsigned int) Height;

    img->bits_per_pixel = (unsigned char)32;
    img->scan_width = Width * 4;

    img->palette_size = (unsigned short)0;
    img->bytes_per_palette_entry = 4U;
    img->bits = NULL;

    png_destroy_read_struct((png_structp *) &png_ptr, (png_infop *) &info_ptr, (png_infop *) &end_info);
    fclose( file );

    return BMG_OK;
}
示例#22
0
bool R9_ImgReadPNG( F9FILE file, r9Img* img )
{
	if(file==NULL || img==NULL) return false;
	R9_ImgDestroy(img);
	
	// check png sig
	const int headersize = 8;
	byte header[headersize];
	if(file->Read( header, headersize) != headersize) return false;

	BOOL ispng = png_check_sig(header, headersize) != 0;
	if(!ispng) { elog::rnd() << "png sig failed" << std::endl; return false; }

	// create png structures
	png_structp png_ptr = png_create_read_struct_2( PNG_LIBPNG_VER_STRING,
												NULL,
												R9_ImgPNG_FatalError,
												R9_ImgPNG_Warning,
												NULL,
												R9_ImgPNG_Malloc,
												R9_ImgPNG_Free );

	if(png_ptr==NULL) return false;

	png_infop info_ptr = png_create_info_struct(png_ptr);
	if(info_ptr == NULL) 
	{
		png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
		return false;
	}

	png_infop end_info = png_create_info_struct(png_ptr);
	if(end_info == NULL) 
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
		return false;
	}

	// set global file
	r9_imgpng_file = file;
	png_set_read_fn(png_ptr, NULL, R9_ImgPNG_ReadData);

	// read off the info on the image
	png_set_sig_bytes(png_ptr, headersize);
	png_read_info(png_ptr, info_ptr);

	png_uint_32 pngwidth;
	png_uint_32 pngheight;	
	int32 pngbits;
	int32 pngpf;

	png_get_IHDR(png_ptr, info_ptr,
				&pngwidth, &pngheight,
				&pngbits, &pngpf,
				NULL,                        // interlace
				NULL,                        // compression_type
				NULL);                       // filter_type

	BOOL alpha = FALSE;
	img->m_width = pngwidth;
	img->m_height = pngheight;
	img->m_pf = R9_PF_RGB;
	assert(img->m_width!=0 && img->m_height!=0);

	// Strip off any 16 bit info
	if(pngbits==16) png_set_strip_16(png_ptr);

	// Expand a transparency channel into a full alpha channel...
	if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) 
	{
		png_set_expand(png_ptr);
		alpha = TRUE;
	}

	if( pngpf == PNG_COLOR_TYPE_RGB) 
	{
		png_set_expand(png_ptr);
		img->m_pf = alpha ? R9_PF_ARGB : R9_PF_RGB;
	} 
	else 
	if( pngpf == PNG_COLOR_TYPE_RGB_ALPHA) 
	{
		png_set_expand(png_ptr);
		img->m_pf = R9_PF_ARGB;
	}
	else
	{
		elog::rnd() << "png wrong color format" << std::endl;
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		return false;
	}

	// Update the info pointer with the result of the transformations above...
	png_read_update_info(png_ptr, info_ptr);

	png_uint_32 rowbytes = png_get_rowbytes(png_ptr, info_ptr);
	if(img->m_pf==R9_PF_RGB) assert(rowbytes==img->m_width*3);
	else
	if(img->m_pf==R9_PF_RGB) assert(rowbytes==img->m_width*4);

	// create image
	R9_ImgCreate(img);

	// set up the row pointers...
	png_bytep* rowpointers = new png_bytep[img->m_height];
	for(int i=0; i<img->m_height; i++)
	  rowpointers[i] = img->m_data + (i*rowbytes);

	// read image
	png_read_image(png_ptr, rowpointers);

	// release
	png_read_end(png_ptr, NULL);
	png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
	delete [] rowpointers;
	r9_imgpng_file = NULL;

	R9_ImgFlipRGB(img); // it was BGR, we want it RGB !
	return true;
}
示例#23
0
unsigned char* LoadPNGJPGFromMemory(const unsigned char* buffer, int len, int* width, int* height)
{
	const int number=8;
	// проверяем сигнатуру файла (первые number байт)
	if ( !png_check_sig((png_bytep)buffer, number) )
	{
		// неизвестный формат
		return LoadJPGWithAlphaFromMemory(buffer, len, width, height);
	}

	// создаем внутреннюю структуру png для работы с файлом
	// последние параметры - структура, для функции обработки ошибок и варнинга (последн. 2 параметра)
	png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
	// создаем структуру с информацией о файле
	png_infop info_ptr = png_create_info_struct(png_ptr);

	PNGBuffer pngBuffer;
	pngBuffer.data = (png_bytep)buffer;
	pngBuffer.position = 8;

	png_set_read_fn(png_ptr, (void*)&pngBuffer, PNGRead);

	// говорим библиотеке, что мы уже прочли number байт, когда проверяли сигнатуру
	png_set_sig_bytes(png_ptr, number);
	// читаем всю информацию о файле
	png_read_info(png_ptr, info_ptr);
	// Эта функция возвращает инфу из info_ptr
	png_uint_32 w = 0, h = 0;  // размер картинки в пикселях
	int bit_depth = 0;      // глубина цвета (одного из каналов, может быть 1, 2, 4, 8, 16)
	int color_type = 0;      // описывает какие каналы присутствуют:
	// PNG_COLOR_TYPE_GRAY, PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE,
	// PNG_COLOR_TYPE_RGB, PNG_COLOR_TYPE_RGB_ALPHA...
	// последние 3 параметра могут быть нулями и обозначают: тип фильтра, тип компрессии и тип смещения
	png_get_IHDR(png_ptr, info_ptr, &w, &h, &bit_depth, &color_type, 0, 0, 0);

	// png формат может содержать 16 бит на канал, но нам нужно только 8, поэтому сужаем канал
	if (bit_depth == 16) png_set_strip_16(png_ptr);
	// преобразуем файл если он содержит палитру в нормальный RGB
	if (color_type == PNG_COLOR_TYPE_PALETTE && bit_depth <= 8) png_set_palette_to_rgb(png_ptr);
	// если в грэйскейле меньше бит на канал чем 8, то конвертим к нормальному 8-битному
	//if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_gray_1_2_4_to_8(png_ptr);
	// и добавляем полный альфа-канал
	if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr);

	if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
		png_set_gray_to_rgb(png_ptr);
    

	double gamma = 0.0f;
	// если есть информация о гамме в файле, то устанавливаем на 2.2
	if ( png_get_gAMA(png_ptr, info_ptr, &gamma) ) png_set_gamma(png_ptr, 2.2, gamma);
	// иначе ставим дефолтную гамму для файла в 0.45455 (good guess for GIF images on PCs)
	else png_set_gamma(png_ptr, 2.2, 0.45455);

	// после всех трансформаций, апдейтим информацию в библиотеке
	png_read_update_info(png_ptr, info_ptr);
	// опять получаем все размеры и параметры обновленной картинки
	png_get_IHDR(png_ptr, info_ptr, &w, &h, &bit_depth, &color_type, 0, 0, 0);

	// определяем кол-во байт нужных для того чтобы вместить строку
	png_uint_32 row_bytes = png_get_rowbytes(png_ptr, info_ptr);
	// теперь, мы можем выделить память чтобы вместить картинку
	png_byte* data = new png_byte[row_bytes * h];
	// выделяем память, для указателей на каждую строку
	png_byte **row_pointers = new png_byte * [h];
	// сопоставляем массив указателей на строчки, с выделенными в памяти (res)
	// т.к. изображение перевернутое, то указатели идут снизу вверх
	for (unsigned int i = 0; i < h; i++)
		row_pointers[i] = data + i * row_bytes; 
	// все, читаем картинку
	png_read_image(png_ptr, row_pointers);

	// освобождаем память от указателей на строки
	delete []row_pointers;
	// освобождаем память выделенную для библиотеки libpng
	png_destroy_read_struct(&png_ptr, &info_ptr, 0);

	*width=w;
	*height=h;

	return data;
}
示例#24
0
bool R9_ImgReadHeaderPNG( F9FILE file, r9Img* img )
{
	if(file==NULL || img==NULL) return false;
	R9_ImgDestroy(img);
	
	// check png sig
	const int headersize = 8;
	byte header[headersize];
	if(file->Read( header, headersize)!=headersize) return false;

	BOOL ispng = png_check_sig(header, headersize) != 0;
	if(!ispng) { elog::rnd() << "png sig failed" << std::endl; return false; }

	// create png structures
	png_structp png_ptr = png_create_read_struct_2( PNG_LIBPNG_VER_STRING,
												NULL,
												R9_ImgPNG_FatalError,
												R9_ImgPNG_Warning,
												NULL,
												R9_ImgPNG_Malloc,
												R9_ImgPNG_Free );

	if(png_ptr==NULL) return false;

	png_infop info_ptr = png_create_info_struct(png_ptr);
	if(info_ptr == NULL) 
	{
		png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
		return false;
	}

	png_infop end_info = png_create_info_struct(png_ptr);
	if(end_info == NULL) 
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
		return false;
	}

	// set global file
	r9_imgpng_file = file;
	png_set_read_fn(png_ptr, NULL, R9_ImgPNG_ReadData);

	// read off the info on the image
	png_set_sig_bytes(png_ptr, headersize);
	png_read_info(png_ptr, info_ptr);

	png_uint_32 pngwidth;
	png_uint_32 pngheight;	
	int32 pngbits;
	int32 pngpf;

	png_get_IHDR(png_ptr, info_ptr,
				&pngwidth, &pngheight,
				&pngbits, &pngpf,
				NULL,                        // interlace
				NULL,                        // compression_type
				NULL);                       // filter_type

	BOOL alpha = FALSE;
	img->m_width = pngwidth;
	img->m_height = pngheight;
	img->m_pf = R9_PF_RGB;

	// release
	png_read_end(png_ptr, NULL);
	png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
	r9_imgpng_file = NULL;

	return true;
}
示例#25
0
/* 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, NULL, 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, 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
    * quantizing, 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, 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, NULL, 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.
    * Use accurate scaling if it's available, otherwise just chop off the
    * low byte.
    */
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
    png_set_scale_16(png_ptr);
#else
   png_set_strip_16(png_ptr);
#endif

   /* 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) != 0)
      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) != 0)
      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)
示例#26
0
void LoadPNG( const char *name, byte **pic, int *width, int *height,
	      int *numLayers, int *numMips, int *bits, byte alphaByte )
{
	int          bit_depth;
	int          color_type;
	png_uint_32  w;
	png_uint_32  h;
	unsigned int row;
	png_infop    info;
	png_structp  png;
	png_bytep    *row_pointers;
	byte         *data;
	byte         *out;

	// load png
	ri.FS_ReadFile( name, ( void ** ) &data );

	if ( !data )
	{
		return;
	}

	png = png_create_read_struct( PNG_LIBPNG_VER_STRING, ( png_voidp ) nullptr, png_user_error_fn, png_user_warning_fn );

	if ( !png )
	{
		ri.Printf( PRINT_WARNING, "LoadPNG: png_create_write_struct() failed for (%s)\n", name );
		ri.FS_FreeFile( data );
		return;
	}

	// allocate/initialize the memory for image information.  REQUIRED
	info = png_create_info_struct( png );

	if ( !info )
	{
		ri.Printf( PRINT_WARNING, "LoadPNG: png_create_info_struct() failed for (%s)\n", name );
		ri.FS_FreeFile( data );
		png_destroy_read_struct( &png, ( png_infopp ) nullptr, ( png_infopp ) nullptr );
		return;
	}

	/*
	 * Set error handling if you are using the setjmp/longjmp method (this is
	 * the common 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 ) ) )
	{
		// if we get here, we had a problem reading the file
		ri.Printf( PRINT_WARNING, "LoadPNG: first exception handler called for (%s)\n", name );
		ri.FS_FreeFile( data );
		png_destroy_read_struct( &png, ( png_infopp ) & info, ( png_infopp ) nullptr );
		return;
	}

	png_set_read_fn( png, data, png_read_data );

	png_set_sig_bytes( png, 0 );

	// 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, info );

	// get picture info
	png_get_IHDR( png, info, ( png_uint_32 * ) &w, ( png_uint_32 * ) &h, &bit_depth, &color_type, nullptr, nullptr, nullptr );

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

	// expand paletted images to RGB triplets
	if ( color_type & PNG_COLOR_MASK_PALETTE )
	{
		png_set_expand( png );
	}

	// expand gray-scaled images to RGB triplets
	if ( !( color_type & PNG_COLOR_MASK_COLOR ) )
	{
		png_set_gray_to_rgb( png );
	}

	// expand grayscale images to the 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 ( png_get_valid( png, info, PNG_INFO_tRNS ) )
	{
		png_set_tRNS_to_alpha( png );
	}

	// if there is no alpha information, fill with alphaByte
	if ( !( color_type & PNG_COLOR_MASK_ALPHA ) )
	{
		png_set_filler( png, alphaByte, PNG_FILLER_AFTER );
	}

	// expand pictures with less than 8bpp to 8bpp
	if ( bit_depth < 8 )
	{
		png_set_packing( png );
	}

	png_set_interlace_handling( png );

	// update structure with the above settings
	png_read_update_info( png, info );

	// allocate the memory to hold the image
	*width = w;
	*height = h;
	*pic = out = ( byte * ) ri.Z_Malloc( w * h * 4 );

	row_pointers = ( png_bytep * ) ri.Hunk_AllocateTempMemory( sizeof( png_bytep ) * h );

	// set a new exception handler
	if ( setjmp( png_jmpbuf( png ) ) )
	{
		ri.Printf( PRINT_WARNING, "LoadPNG: second exception handler called for (%s)\n", name );
		ri.Hunk_FreeTempMemory( row_pointers );
		ri.FS_FreeFile( data );
		png_destroy_read_struct( &png, ( png_infopp ) & info, ( png_infopp ) nullptr );
		return;
	}

	for ( row = 0; row < h; row++ )
	{
		row_pointers[ row ] = ( png_bytep )( out + ( row * 4 * w ) );
	}

	// read image data
	png_read_image( png, row_pointers );

	// read rest of file, and get additional chunks in info
	png_read_end( png, info );

	// clean up after the read, and free any memory allocated
	png_destroy_read_struct( &png, &info, ( png_infopp ) nullptr );

	ri.Hunk_FreeTempMemory( row_pointers );
	ri.FS_FreeFile( data );
}
示例#27
0
void png_reader::read(unsigned x0, unsigned y0,image_data_32& image)
{
    FILE *fp=fopen(fileName_.c_str(),"rb");
    if (!fp) throw image_reader_exception("cannot open image file "+fileName_);

    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_read_info(png_ptr, info_ptr);

    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);

    // quick hack -- only work in >=libpng 1.2.7
    png_set_add_alpha(png_ptr,0xff,PNG_FILLER_AFTER); //rgba

    double gamma;
    if (png_get_gAMA(png_ptr, info_ptr, &gamma))
        png_set_gamma(png_ptr, 2.2, gamma);

    if (x0 == 0 && y0 == 0 && image.width() >= width_ && image.height() >= height_)
    {

        if (png_get_interlace_type(png_ptr,info_ptr) == PNG_INTERLACE_ADAM7)
        {
            png_set_interlace_handling(png_ptr); // FIXME: libpng bug?
            // according to docs png_read_image
            // "..automatically handles interlacing,
            // so you don't need to call png_set_interlace_handling()"
        }
        png_read_update_info(png_ptr, info_ptr);
        // we can read whole image at once
        // alloc row pointers
        boost::scoped_array<png_byte*> rows(new png_bytep[height_]);
        for (unsigned i=0; i<height_; ++i)
            rows[i] = (png_bytep)image.getRow(i);
        png_read_image(png_ptr, rows.get());
    }
    else
    {
        png_read_update_info(png_ptr, info_ptr);
        unsigned w=std::min(unsigned(image.width()),width_);
        unsigned h=std::min(unsigned(image.height()),height_);
        unsigned rowbytes=png_get_rowbytes(png_ptr, info_ptr);
        boost::scoped_array<png_byte> row(new png_byte[rowbytes]);
        //START read image rows
        for (unsigned i=0;i<height_;++i)
        {
            png_read_row(png_ptr,row.get(),0);
            if (i>=y0 && i<h)
            {
                image.setRow(i-y0,reinterpret_cast<unsigned*>(&row[x0]),w);
            }
        }
        //END
    }

    png_read_end(png_ptr,0);
    png_destroy_read_struct(&png_ptr, &info_ptr,0);
    fclose(fp);
}
示例#28
0
void PNGAPI
png_read_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver,
   png_size_t png_struct_size)
{
#ifdef PNG_SETJMP_SUPPORTED
   jmp_buf tmp_jmp;  /* to save current jump buffer */
#endif

   int i = 0;

   png_structp png_ptr=*ptr_ptr;

   if (png_ptr == NULL)
      return;

   do
   {
      if (user_png_ver[i] != png_libpng_ver[i])
      {
#ifdef PNG_LEGACY_SUPPORTED
        png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
#else
        png_ptr->warning_fn = NULL;
        png_warning(png_ptr,
         "Application uses deprecated png_read_init() and should be"
         " recompiled.");
        break;
#endif
      }
   } while (png_libpng_ver[i++]);

   png_debug(1, "in png_read_init_3");

#ifdef PNG_SETJMP_SUPPORTED
   /* Save jump buffer and error functions */
   png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf));
#endif

   if (png_sizeof(png_struct) > png_struct_size)
   {
      png_destroy_struct(png_ptr);
      *ptr_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
      png_ptr = *ptr_ptr;
   }

   /* Reset all variables to 0 */
   png_memset(png_ptr, 0, png_sizeof(png_struct));

#ifdef PNG_SETJMP_SUPPORTED
   /* Restore jump buffer */
   png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf));
#endif

   /* Added at libpng-1.2.6 */
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
   png_ptr->user_width_max = PNG_USER_WIDTH_MAX;
   png_ptr->user_height_max = PNG_USER_HEIGHT_MAX;
#endif

   /* Initialize zbuf - compression buffer */
   png_ptr->zbuf_size = PNG_ZBUF_SIZE;
   png_ptr->zstream.zalloc = png_zalloc;
   png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
     (png_uint_32)png_ptr->zbuf_size);
   png_ptr->zstream.zalloc = png_zalloc;
   png_ptr->zstream.zfree = png_zfree;
   png_ptr->zstream.opaque = (voidpf)png_ptr;

   switch (inflateInit(&png_ptr->zstream))
   {
      case Z_OK: /* Do nothing */ break;
      case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error"); break;
      case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error");
          break;
      default: png_error(png_ptr, "Unknown zlib error");
   }

   png_ptr->zstream.next_out = png_ptr->zbuf;
   png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;

   png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL);
}
示例#29
0
ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
	struct ImBuf *ibuf = NULL;
	png_structp png_ptr;
	png_infop info_ptr;
	unsigned char *pixels = NULL;
	unsigned short *pixels16 = NULL;
	png_bytepp row_pointers = NULL;
	png_uint_32 width, height;
	int bit_depth, color_type;
	PNGReadStruct ps;

	unsigned char *from, *to;
	unsigned short *from16;
	float *to_float;
	int i, bytesperpixel;

	if (imb_is_a_png(mem) == 0) return(NULL);

	/* both 8 and 16 bit PNGs are default to standard byte colorspace */
	colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);

	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
	                                 NULL, NULL, NULL);
	if (png_ptr == NULL) {
		printf("Cannot png_create_read_struct\n");
		return NULL;
	}

	png_set_error_fn(png_ptr, NULL, imb_png_error, imb_png_warning);

	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL) {
		png_destroy_read_struct(&png_ptr, (png_infopp)NULL, 
		                        (png_infopp)NULL);
		printf("Cannot png_create_info_struct\n");
		return NULL;
	}

	ps.size = size; /* XXX, 4gig limit! */
	ps.data = mem;
	ps.seek = 0;

	png_set_read_fn(png_ptr, (void *) &ps, ReadData);

	if (setjmp(png_jmpbuf(png_ptr))) {
		png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
		if (pixels) MEM_freeN(pixels);
		if (pixels16) MEM_freeN(pixels16);
		if (row_pointers) MEM_freeN(row_pointers);
		if (ibuf) IMB_freeImBuf(ibuf);
		return NULL;
	}

	// png_set_sig_bytes(png_ptr, 8);

	png_read_info(png_ptr, info_ptr);
	png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, 
	             &color_type, NULL, NULL, NULL);

	bytesperpixel = png_get_channels(png_ptr, info_ptr);

	switch (color_type) {
		case PNG_COLOR_TYPE_RGB:
		case PNG_COLOR_TYPE_RGB_ALPHA:
			break;
		case PNG_COLOR_TYPE_PALETTE:
			png_set_palette_to_rgb(png_ptr);
			if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
				bytesperpixel = 4;
			}
			else {
				bytesperpixel = 3;
			}
			break;
		case PNG_COLOR_TYPE_GRAY:
		case PNG_COLOR_TYPE_GRAY_ALPHA:
			if (bit_depth < 8) {
				png_set_expand(png_ptr);
				bit_depth = 8;
			}
			break;
		default:
			printf("PNG format not supported\n");
			longjmp(png_jmpbuf(png_ptr), 1);
			break;
	}
	
	ibuf = IMB_allocImBuf(width, height, 8 * bytesperpixel, 0);

	if (ibuf) {
		ibuf->ftype = PNG;
		if (bit_depth == 16)
			ibuf->ftype |= PNG_16BIT;

		if (png_get_valid(png_ptr, info_ptr, PNG_INFO_pHYs)) {
			int unit_type;
			png_uint_32 xres, yres;

			if (png_get_pHYs(png_ptr, info_ptr, &xres, &yres, &unit_type))
				if (unit_type == PNG_RESOLUTION_METER) {
					ibuf->ppm[0] = xres;
					ibuf->ppm[1] = yres;
				}
		}
	}
	else {
		printf("Couldn't allocate memory for PNG image\n");
	}

	if (ibuf && ((flags & IB_test) == 0)) {
		if (bit_depth == 16) {
			imb_addrectfloatImBuf(ibuf);
			png_set_swap(png_ptr);

			pixels16 = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(png_uint_16), "pixels");
			if (pixels16 == NULL) {
				printf("Cannot allocate pixels array\n");
				longjmp(png_jmpbuf(png_ptr), 1);
			}

			/* allocate memory for an array of row-pointers */
			row_pointers = (png_bytepp) MEM_mallocN(ibuf->y * sizeof(png_uint_16p), "row_pointers");
			if (row_pointers == NULL) {
				printf("Cannot allocate row-pointers array\n");
				longjmp(png_jmpbuf(png_ptr), 1);
			}

			/* set the individual row-pointers to point at the correct offsets */
			for (i = 0; i < ibuf->y; i++) {
				row_pointers[ibuf->y - 1 - i] = (png_bytep)
				                                ((png_uint_16 *)pixels16 + (i * ibuf->x) * bytesperpixel);
			}

			png_read_image(png_ptr, row_pointers);

			/* copy image data */

			to_float = ibuf->rect_float;
			from16 = pixels16;

			switch (bytesperpixel) {
				case 4:
					for (i = ibuf->x * ibuf->y; i > 0; i--) {
						to_float[0] = from16[0] / 65535.0;
						to_float[1] = from16[1] / 65535.0;
						to_float[2] = from16[2] / 65535.0;
						to_float[3] = from16[3] / 65535.0;
						to_float += 4; from16 += 4;
					}
					break;
				case 3:
					for (i = ibuf->x * ibuf->y; i > 0; i--) {
						to_float[0] = from16[0] / 65535.0;
						to_float[1] = from16[1] / 65535.0;
						to_float[2] = from16[2] / 65535.0;
						to_float[3] = 1.0;
						to_float += 4; from16 += 3;
					}
					break;
				case 2:
					for (i = ibuf->x * ibuf->y; i > 0; i--) {
						to_float[0] = to_float[1] = to_float[2] = from16[0] / 65535.0;
						to_float[3] = from16[1] / 65535.0;
						to_float += 4; from16 += 2;
					}
					break;
				case 1:
					for (i = ibuf->x * ibuf->y; i > 0; i--) {
						to_float[0] = to_float[1] = to_float[2] = from16[0] / 65535.0;
						to_float[3] = 1.0;
						to_float += 4; from16++;
					}
					break;
			}
		}
		else {
			imb_addrectImBuf(ibuf);

			pixels = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned char), "pixels");
			if (pixels == NULL) {
				printf("Cannot allocate pixels array\n");
				longjmp(png_jmpbuf(png_ptr), 1);
			}

			/* allocate memory for an array of row-pointers */
			row_pointers = (png_bytepp) MEM_mallocN(ibuf->y * sizeof(png_bytep), "row_pointers");
			if (row_pointers == NULL) {
				printf("Cannot allocate row-pointers array\n");
				longjmp(png_jmpbuf(png_ptr), 1);
			}

			/* set the individual row-pointers to point at the correct offsets */
			for (i = 0; i < ibuf->y; i++) {
				row_pointers[ibuf->y - 1 - i] = (png_bytep)
				                                ((unsigned char *)pixels + (i * ibuf->x) * bytesperpixel * sizeof(unsigned char));
			}

			png_read_image(png_ptr, row_pointers);

			/* copy image data */

			to = (unsigned char *) ibuf->rect;
			from = pixels;

			switch (bytesperpixel) {
				case 4:
					for (i = ibuf->x * ibuf->y; i > 0; i--) {
						to[0] = from[0];
						to[1] = from[1];
						to[2] = from[2];
						to[3] = from[3];
						to += 4; from += 4;
					}
					break;
				case 3:
					for (i = ibuf->x * ibuf->y; i > 0; i--) {
						to[0] = from[0];
						to[1] = from[1];
						to[2] = from[2];
						to[3] = 0xff;
						to += 4; from += 3;
					}
					break;
				case 2:
					for (i = ibuf->x * ibuf->y; i > 0; i--) {
						to[0] = to[1] = to[2] = from[0];
						to[3] = from[1];
						to += 4; from += 2;
					}
					break;
				case 1:
					for (i = ibuf->x * ibuf->y; i > 0; i--) {
						to[0] = to[1] = to[2] = from[0];
						to[3] = 0xff;
						to += 4; from++;
					}
					break;
			}
		}

		if (flags & IB_metadata) {
			png_text *text_chunks;
			int count = png_get_text(png_ptr, info_ptr, &text_chunks, NULL);
			for (i = 0; i < count; i++) {
				IMB_metadata_add_field(ibuf, text_chunks[i].key, text_chunks[i].text);
				ibuf->flags |= IB_metadata;
			}
		}

		png_read_end(png_ptr, info_ptr);
	}

	/* clean up */
	if (pixels)
		MEM_freeN(pixels);
	if (pixels16)
		MEM_freeN(pixels16);
	if (row_pointers)
		MEM_freeN(row_pointers);
	png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);

	return(ibuf);
}
示例#30
0
static void
gst_pngdec_task (GstPad * pad)
{
  GstPngDec *pngdec;
  GstBuffer *buffer = NULL;
  size_t buffer_size = 0;
  gint i = 0;
  png_bytep *rows, inp;
  png_uint_32 rowbytes;
  GstFlowReturn ret = GST_FLOW_OK;

  pngdec = GST_PNGDEC (GST_OBJECT_PARENT (pad));

  GST_LOG_OBJECT (pngdec, "read frame");

  /* Let libpng come back here on error */
  if (setjmp (png_jmpbuf (pngdec->png))) {
    ret = GST_FLOW_ERROR;
    goto pause;
  }

  /* Set reading callback */
  png_set_read_fn (pngdec->png, pngdec, user_read_data);

  /* Read info */
  png_read_info (pngdec->png, pngdec->info);

  /* Generate the caps and configure */
  ret = gst_pngdec_caps_create_and_set (pngdec);
  if (ret != GST_FLOW_OK) {
    goto pause;
  }

  /* Allocate output buffer */
  rowbytes = png_get_rowbytes (pngdec->png, pngdec->info);
  buffer_size = pngdec->height * GST_ROUND_UP_4 (rowbytes);
  ret =
      gst_pad_alloc_buffer_and_set_caps (pngdec->srcpad, GST_BUFFER_OFFSET_NONE,
      buffer_size, GST_PAD_CAPS (pngdec->srcpad), &buffer);
  if (ret != GST_FLOW_OK) {
    goto pause;
  }

  rows = (png_bytep *) g_malloc (sizeof (png_bytep) * pngdec->height);

  inp = GST_BUFFER_DATA (buffer);

  for (i = 0; i < pngdec->height; i++) {
    rows[i] = inp;
    inp += GST_ROUND_UP_4 (rowbytes);
  }

  /* Read the actual picture */
  png_read_image (pngdec->png, rows);
  free (rows);

  /* Push the raw RGB frame */
  ret = gst_pad_push (pngdec->srcpad, buffer);
  if (ret != GST_FLOW_OK) {
    goto pause;
  }

  /* And we are done */
  gst_pad_pause_task (pngdec->sinkpad);
  gst_pad_push_event (pngdec->srcpad, gst_event_new_eos ());
  return;

pause:
  GST_INFO_OBJECT (pngdec, "pausing task, reason %s", gst_flow_get_name (ret));
  gst_pad_pause_task (pngdec->sinkpad);
  if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
    GST_ELEMENT_ERROR (pngdec, STREAM, FAILED,
        (_("Internal data stream error.")),
        ("stream stopped, reason %s", gst_flow_get_name (ret)));
    gst_pad_push_event (pngdec->srcpad, gst_event_new_eos ());
  }
}