예제 #1
0
int main(int argc, char **argv)
{
	if (argc != 4)
	{
		fprintf(stderr, "usage: %s <input.png> <output_basename> <jpeg-quality>\n", *argv);
		return 1;
	}

	const char *infile = argv[1];
	const char *outfile = argv[2];
	int jpeg_quality = atoi(argv[3]);

	FILE *fpin = fopen(infile, "rb");
	if (!fpin)
	{
		perror(infile);
		return 1;
	}

	unsigned char header[8];
	fread(header, 1, 8, fpin);
	if (png_sig_cmp(header, 0, 8))
	{
		fprintf(stderr, "this is not a PNG file\n");
		fclose(fpin);
		return 1;
	}
	png_structp png_ptr = png_create_read_struct
		(PNG_LIBPNG_VER_STRING, 0, 0, 0);
	assert(png_ptr);

	png_infop info_ptr = png_create_info_struct(png_ptr);
	assert(info_ptr);

	png_infop end_info = png_create_info_struct(png_ptr);
	assert (end_info);

	if (setjmp(png_jmpbuf(png_ptr)))
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		fclose(fpin);
		fprintf(stderr, "failed.\n");
		return 1;
	}

	png_init_io(png_ptr, fpin);
	png_set_sig_bytes(png_ptr, 8);
	png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, 0);
	png_bytep * row_pointers = png_get_rows(png_ptr, info_ptr);

	png_uint_32 width, height;
	int bit_depth, color_type;
	png_get_IHDR(png_ptr, info_ptr, &width, &height, 
		&bit_depth, &color_type, 0, 0, 0);

	if (color_type != PNG_COLOR_TYPE_RGB_ALPHA)
	{
		fprintf(stderr, "input PNG must be RGB+Alpha\n");
		fclose(fpin);
		return 1;
	}
	if (bit_depth != 8)
	{
		fprintf(stderr, "input bit depth must be 8bit!\n");
		fclose(fpin);
		return 1;
	}
	printf("png is %ldx%ld\n", width, height);
	int channels = png_get_channels(png_ptr, info_ptr);
	if (channels != 4)
	{
		fprintf(stderr, "channels must be 4.\n");
		fclose(fpin);
		return 1;
	}

	fclose(fpin);

	/* now write jpeg */
	struct jpeg_compress_struct cinfo;
	struct jpeg_error_mgr jerr;
	JSAMPROW jrow_pointer[1];
	FILE *outfp;

	char filename[strlen(outfile) + 10];
	strcpy(filename, outfile);
	strcat(filename, ".rgb.jpg");

	outfp = fopen(filename, "wb");
	if (!outfp)
	{
		perror(filename);
		return 1;
	}

	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_compress(&cinfo);
	jpeg_stdio_dest(&cinfo, outfp);

	cinfo.image_width = width;
	cinfo.image_height = height;
	cinfo.input_components = 3;
	cinfo.in_color_space = JCS_RGB;
	jpeg_set_defaults(&cinfo);
	jpeg_set_quality(&cinfo, jpeg_quality, 1);
	jpeg_start_compress(&cinfo, 1);

	unsigned char *row = malloc(width * 3);
	while (cinfo.next_scanline < cinfo.image_height)
	{
		int x;
		jrow_pointer[0] = row;
		unsigned char *source = row_pointers[cinfo.next_scanline];
		for (x = 0; x < width; ++x)
		{
			row[x * 3 + 0] = source[0];
			row[x * 3 + 1] = source[1];
			row[x * 3 + 2] = source[2];
			source += 4;
		}
		jpeg_write_scanlines(&cinfo, jrow_pointer, 1);
	}

	jpeg_finish_compress(&cinfo);
	fclose(outfp);
	jpeg_destroy_compress(&cinfo);

	/* and write png */
	strcpy(filename, outfile);
	strcat(filename, ".a.png");

	outfp = fopen(filename, "wb");
	if (!outfp)
	{
		perror(filename);
		return 1;
	}

	png_structp png_ptr_w = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
	png_infop info_ptr_w = png_create_info_struct(png_ptr_w);
	if (setjmp(png_jmpbuf(png_ptr_w)))
	{
		png_destroy_write_struct(&png_ptr_w, &info_ptr_w);
		fclose(outfp);
		return 1;
	}
	png_init_io(png_ptr_w, outfp);
	png_set_IHDR(png_ptr_w, info_ptr_w, width, height, 8, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

		/* turn RGBA into A, in-place */
	int x, y;
	for (y=0; y < height; ++y)
	{
		unsigned char *source = row_pointers[y];
		unsigned char *dst = source;
		for (x=0; x < width; ++x)
		{
			*dst++ = source[3];
			source += 4;
		}
	}
	png_set_rows(png_ptr_w, info_ptr_w, row_pointers);
	png_write_png(png_ptr_w, info_ptr_w, PNG_TRANSFORM_IDENTITY, 0);
	png_write_end(png_ptr_w, info_ptr_w);
	png_destroy_write_struct(&png_ptr_w, &info_ptr_w);
	fclose(outfp);
	return 0;
}
예제 #2
0
파일: CGLCG.cpp 프로젝트: Nebuleon/snes9x
bool CGLCG::loadPngImage(const TCHAR *name, int &outWidth, int &outHeight, bool &outHasAlpha, GLubyte **outData) {
    png_structp png_ptr;
    png_infop info_ptr;
    unsigned int sig_read = 0;
    int color_type, interlace_type;
    FILE *fp;

	if ((fp = _tfopen(name, TEXT("rb"))) == NULL)
        return false;

    /* Create and initialize the png_struct
     * with the desired error handler
     * functions.  If you want to use the
     * default stderr and longjump method,
     * you can supply NULL for the last
     * three parameters.  We also 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,
            NULL, NULL, NULL);

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

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

    /* Set error handling if you are
     * using the setjmp/longjmp method
     * (this is the normal method of
     * doing things with libpng).
     * REQUIRED unless you  set up
     * your own error handlers in
     * the png_create_read_struct()
     * earlier.
     */
    if (setjmp(png_jmpbuf(png_ptr))) {
        /* Free all of the memory associated
         * with the png_ptr and info_ptr */
        png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
        fclose(fp);
        /* If we get here, we had a
         * problem reading the file */
        return false;
    }

    /* Set up the output control if
     * you are using standard C streams */
    png_init_io(png_ptr, fp);

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

    /*
     * If you have enough memory to read
     * in the entire image at once, and
     * you need to specify only
     * transforms that can be controlled
     * with one of the PNG_TRANSFORM_*
     * bits (this presently excludes
     * dithering, filling, setting
     * background, and doing gamma
     * adjustment), then you can read the
     * entire image (including pixels)
     * into the info structure with this
     * call
     *
     * PNG_TRANSFORM_STRIP_16 |
     * PNG_TRANSFORM_PACKING  forces 8 bit
     * PNG_TRANSFORM_EXPAND forces to
     *  expand a palette into RGB
     */
    png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, (png_voidp)NULL);

    outWidth = png_get_image_width(png_ptr, info_ptr);
    outHeight = png_get_image_height(png_ptr, info_ptr);
    switch (png_get_color_type(png_ptr, info_ptr)) {
        case PNG_COLOR_TYPE_RGBA:
            outHasAlpha = true;
            break;
        case PNG_COLOR_TYPE_RGB:
            outHasAlpha = false;
            break;
        default:
            png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
            fclose(fp);
            return false;
    }
    unsigned int row_bytes = png_get_rowbytes(png_ptr, info_ptr);
    *outData = (unsigned char*) malloc(row_bytes * outHeight);

    png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr);

    for (int i = 0; i < outHeight; i++) {
        memcpy(*outData+(row_bytes * i), row_pointers[i], row_bytes);
    }

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

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

    /* That's it */
    return true;
}
예제 #3
0
void PngLoader::PngLoad(){
  int i,j;
  FILE *fp = fopen(filename,"rb");
  png_structp png_sp;
  png_infop png_ip;
  if(!fp){
    std::cout<<"Cannot open file:"<<filename<<std::endl;
    return;
  }

  png_sp = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
  png_ip = png_create_info_struct(png_sp);
  
  if(setjmp(png_jmpbuf(png_sp))){
    png_destroy_read_struct(&png_sp,&png_ip,NULL);
    return;
  }
  
  png_init_io(png_sp,fp);
  png_read_png(png_sp,png_ip,PNG_TRANSFORM_EXPAND,NULL);
 
  png_byte** raw_pointers = png_get_rows (png_sp,png_ip);
  width = 640;
  height = 480;
  bpp = 4;

  raw_data = new unsigned char[width*height*bpp];
  
  for(j = 0; j < height; j++){
    for(i = 0; i < width; i++){
      //テクスチャにAlpha値を入れる場合
      raw_data[j*width*4+(i*4)+0] = raw_pointers[height-j-1][i*3];
      raw_data[j*width*4+(i*4)+1] = raw_pointers[height-j-1][i*3+1];
      raw_data[j*width*4+(i*4)+2] = raw_pointers[height-j-1][i*3+2];
      raw_data[j*width*4+(i*4)+3] = 255;
      if(raw_data[j*width*4+(i*4)+0] == 255 && raw_data[j*width*4+(i*4)+1] == 255 && raw_data[j*width*4+(i*4)+2] == 255){
	raw_data[j*width*4+(i*4)+3] = 0;
      }
      /*
      if(raw_data[j*width*4+(i*4)+0] == 0 && raw_data[j*width*4+(i*4)+1] == 0 && raw_data[j*width*4+(i*4)+2] == 0){
	raw_data[j*width*4+(i*4)+3] = 0;
      }
      */
      /*
      if(i%4 == 0)
	raw_data[j*width*4+i] = 0;
      else if(i%4 == 1)
	raw_data[j*width*4+i] = 255;
      else if(i%4  == 2)
	raw_data[j*width*4+i] = 0;
      else
	raw_data[j*width*4+i] = 128.0; //これより低い値では表示しない
      */
    }
  }

  /*
    Alpha値がない場合はこれでいい
  for(j = 0; j < height; j++){
    for(i = 0; i < width*3; i++){
      raw_data[j*width*3+i] = raw_pointers[height-j-1][i];
    }
  }

  for(i = 0; i < height; i++){
    memcpy(raw_data+(i*width*bpp),raw_pointers[height-i-1],width*bpp);
  }
  */

  fclose(fp);
  png_destroy_read_struct(&png_sp,&png_ip,NULL);
}
예제 #4
0
파일: image.cpp 프로젝트: dvhart/libstk
    void image::load_png(const std::string filename)
    {
#ifdef HAVE_LIBPNG
        FILE *fp = fopen(filename.c_str(), "rb");
        if (!fp)
            throw image_file_exception("image::load_png - could not open file: " + filename);
        char header[8];
        fread(header,1,8,fp);
        bool is_png= !png_sig_cmp((png_byte*)header,0,8);
        if (!is_png)
            throw image_read_exception("image::load_png - File is not in PNG format: " + filename);

        png_structp png_ptr = png_create_read_struct ( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL);
        if(!png_ptr)
            throw image_read_exception("image::load_png - Couldnt create PNG read structure");
        
        png_infop info_ptr = png_create_info_struct(png_ptr);
        if(!info_ptr)
            throw image_read_exception("image::load_png - Couldnt create PNG info struct 1");

        png_infop end_info = png_create_info_struct(png_ptr);
        if(!end_info)
            throw image_read_exception("image::load_png - Couldnt create PNG info struct 2");

        if(setjmp(png_jmpbuf(png_ptr)))
        {
            png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
            fclose(fp);
            throw image_read_exception("image::load_png - PNG error");
        }

        png_init_io(png_ptr,fp);
        png_set_sig_bytes(png_ptr,8);
        
        png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND,NULL);

        unsigned long width,height,bit_depth;

        width=png_get_image_width(png_ptr,info_ptr);
        height=png_get_image_height(png_ptr,info_ptr);
        bit_depth=png_get_bit_depth(png_ptr,info_ptr);
        
        INFO("Read PNG: width " << width << "  height " << height << "  depth " << bit_depth );

        int bytes_per_pixel = png_get_channels(png_ptr,info_ptr);
        
        INFO("PNG file has " << bytes_per_pixel << " Bytes per Pixel");

        png_bytep* row_pointers = png_get_rows(png_ptr, info_ptr);

        offscreen_surface = onscreen_surface->create_surface(rectangle(0, 0, width, height));

        graphics_context::ptr gc=graphics_context::create();
        offscreen_surface->gc(gc);
        gc->alpha_blend(false); // We want the image data with its alpha channel to be in
                                // the offscreen surface verbatim, not blended 
        
        offscreen_surface->clip_rect(rectangle(0, 0, width, height));
        for (unsigned int y = 0; y < height; y++)
        {
            for (unsigned int x = 0; x < width; x++)
            {
                char r = row_pointers[y][(x*bytes_per_pixel)+0];
                char g = row_pointers[y][(x*bytes_per_pixel)+1];
                char b = row_pointers[y][(x*bytes_per_pixel)+2];
                char a = 255; // FIXME we need acces to stk::opaque here
                if (bytes_per_pixel > 3) a = row_pointers[y][(x*bytes_per_pixel)+3];
                color pixel_color = offscreen_surface->gen_color(r, g, b, a);
                offscreen_surface->draw_pixel(x, y, pixel_color);
            }
        }
        gc->alpha_blend(true);  // If the user draws the image, he should get alpha blending by default
        
//        png_read_end(png_ptr, end_info);

        INFO("Destroying png read struct");
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
#else
        throw image_read_exception("image::load_png() No support for loading PNG files compiled in!");
#endif
    }
예제 #5
0
// Load PNG for texture
int LoadPNG (char *filename)			// Loads A PNG File Into Memory
{
	char		header[8];
	GLuint		bytesPerPixel;								// Holds Number Of Bytes Per Pixel Used In The TGA File
	GLuint		imageSize;									// Used To Store The Image Size When Setting Aside Ram
	GLuint		temp;										// Temporary Variable
	GLuint		type = GL_RGBA;								// Set The Default GL Mode To RBGA (32 BPP)
	GLuint		i;
	GLuint		pos = 0;
	unsigned char value[4];

	FILE *file = fopen(filename, "rb");						// Open The TGA File

	if ( file==NULL )
		return 0;

	// Check if this is indeed a PNG file
	fread(header, 1, 8, file);
	if (png_sig_cmp(header, 0, 8))
		{
		fclose(file);
		return 0;
		}

	// Initialise PNG structures
	png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (!png_ptr)
		{
		fclose(file);
		return 0;
		}

	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr)
		{
		fclose(file);
		png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
		return 0;
		}

	png_infop end_info = png_create_info_struct(png_ptr);
	if (!end_info)
		{
		fclose(file);
		png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
		return 0;
		}

	// Init PNG file i/o
	png_init_io(png_ptr, file);

	// We've already read the header (8 bytes)
	png_set_sig_bytes(png_ptr, 8);

	// Read the image into memory
	png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
	

	g_overlay.width  = png_ptr->width;			// Determine The PNG Width
	g_overlay.height = png_ptr->height;			// Determine The PNG Height
    
 	if(	g_overlay.width	<=0	||								// Is The Width Less Than Or Equal To Zero
		g_overlay.height <=0)								// Is The Height Less Than Or Equal To Zero
	{
		fclose(file);										// If Anything Failed, Close The File
		return 0;										// Return False
	}

	g_overlay.bpp	= png_ptr->bit_depth * png_ptr->channels;	// Bits per pixel (24 or 32)
	bytesPerPixel	= g_overlay.bpp/8;						// Divide By 8 To Get The Bytes Per Pixel
	imageSize		= g_overlay.width*g_overlay.height*bytesPerPixel;	// Calculate The Memory Required For The TGA Data
	//g_overlay.upsideDown = (header[17] & 0x20) ? 0 : 1;		// If TGA origin is bottom-left

	g_overlay.imageData = (GLubyte *)png_ptr->row_buf[0];		// Reserve Memory To Hold The TGA Data



	//if ( 2 == tgaType )
	//{
	//	// uncompressed RGB (24 or 32-bit)
	//	g_overlay.imageData=(GLubyte *)malloc(imageSize);		// Reserve Memory To Hold The TGA Data

	//	if(	g_overlay.imageData==NULL ||							// Does The Storage Memory Exist?
	//		fread(g_overlay.imageData, 1, imageSize, file)!=imageSize)	// Does The Image Size Match The Memory Reserved?
	//	{
	//		if(g_overlay.imageData!=NULL)						// Was Image Data Loaded
	//			free(g_overlay.imageData);						// If So, Release The Image Data

	//		fclose(file);										// Close The File
	//		return 0;											// Return False
	//	}

	//	for (i=0; i < imageSize; i += bytesPerPixel)
	//	{
	//		temp = g_overlay.imageData[i];						// Temporarily Store The Value At Image Data 'i'
	//		g_overlay.imageData[i] = g_overlay.imageData[i + 2];	// Set The 1st Byte To The Value Of The 3rd Byte
	//		g_overlay.imageData[i + 2] = temp;					// Set The 3rd Byte To The Value In 'temp' (1st Byte Value)
	//	}
	//}
	//else if (10 == tgaType)
	//{
	//	// RLE compressed RGB (24 or 32-bit)
	//	g_overlay.imageData=(GLubyte *)malloc(imageSize);		// Reserve Memory To Hold The TGA Data
	//	pos = 0;
	//	while(1)
	//	{
	//		// read packet header
	//		unsigned char ph; // = fgetc(file);
	//		if (fread(&ph, 1, 1, file)!=1)
	//		{
	//			fclose(file);
	//			return 0;
	//		}
	//		// packet type
	//		if (ph & 0x80)
	//		{
	//			// run-length packet
	//			unsigned int len = (ph & 0x7F) + 1;
	//			fread(value, 1, bytesPerPixel, file);
	//			for (i=0; i<len; i++)
	//			{
	//				g_overlay.imageData[pos] = value[2];
	//				g_overlay.imageData[pos+1] = value[1];
	//				g_overlay.imageData[pos+2] = value[0];
	//				pos += bytesPerPixel;
	//			}
	//		}
	//		else
	//		{
	//			// "raw" packet
	//			unsigned int len = (ph & 0x7F) + 1;
	//			for (i=0; i<len; i++)
	//			{
	//				fread(value, 1, bytesPerPixel, file);
	//				g_overlay.imageData[pos] = value[2];
	//				g_overlay.imageData[pos+1] = value[1];
	//				g_overlay.imageData[pos+2] = value[0];
	//				pos += bytesPerPixel;
	//			}
	//		}
	//		if (pos >= imageSize)
	//			break;
	//	}

	//}

	fclose (file);											// Close The File

	// resize if neccessary
	if (g_overlay.width != 512 || g_overlay.height != 512)
	{
		GLubyte* newImageData = (GLubyte *)malloc(512*512*bytesPerPixel);		// Reserve Memory To Hold The RGB Data
		gluScaleImage(GL_RGB, g_overlay.width, g_overlay.height, GL_UNSIGNED_BYTE, g_overlay.imageData, 
						512, 512, GL_UNSIGNED_BYTE, newImageData);
		free(g_overlay.imageData);
		g_overlay.imageData = newImageData;
		g_overlay.width = 512;
		g_overlay.height = 512;
	}

	// Build A Texture From The Data
	glGenTextures(1, &g_overlay.texID);					// Generate OpenGL texture IDs

	glBindTexture(GL_TEXTURE_2D, g_overlay.texID);			// Bind Our Texture
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);	// Linear Filtered
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);	// Linear Filtered
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

	if (g_overlay.bpp==24)									// Was The TGA 24 Bits
	{
		type=GL_RGB;										// If So Set The 'type' To GL_RGB
	}

	glTexImage2D(GL_TEXTURE_2D, 0, type, g_overlay.width, g_overlay.height, 0, type, GL_UNSIGNED_BYTE, g_overlay.imageData);

	return 1;											// Texture Building Went Ok, Return True
}
예제 #6
0
파일: shapeme.c 프로젝트: abarax/shapeme
unsigned char *PngLoad(FILE *fp, int *widthptr, int *heightptr, int *alphaptr) {
    unsigned char buf[PNG_BYTES_TO_CHECK];
    png_structp png_ptr;
    png_infop info_ptr;
    png_uint_32 width, height, j;
    int color_type, row_bytes;
    unsigned char **imageData, *rgb;

    /* Check signature */
    if (fread(buf, 1, PNG_BYTES_TO_CHECK, fp) != PNG_BYTES_TO_CHECK)
        return NULL;
    if (png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK))
        return NULL; /* Not a PNG image */

    /* Initialize data structures */
    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
        NULL,NULL,NULL);
    if (png_ptr == NULL) {
        return NULL; /* Out of memory */
    }

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

    /* Error handling code */
    if (setjmp(png_jmpbuf(png_ptr)))
    {
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        return NULL;
    }

    /* Set the I/O method */
    png_init_io(png_ptr, fp);

    /* Undo the fact that we read some data to detect the PNG file */
    png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK);

    /* Read the PNG in memory at once */
    png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

    /* Get image info */
    width = png_get_image_width(png_ptr, info_ptr);
    height = png_get_image_height(png_ptr, info_ptr);
    color_type = png_get_color_type(png_ptr, info_ptr);
    if (color_type != PNG_COLOR_TYPE_RGB &&
        color_type != PNG_COLOR_TYPE_RGB_ALPHA) {
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        return NULL;
    }

    /* Get the image data */
    imageData = png_get_rows(png_ptr, info_ptr);
    row_bytes = png_get_rowbytes(png_ptr, info_ptr);
    rgb = malloc(row_bytes*height);
    if (!rgb) {
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        return NULL;
    }

    for (j = 0; j < height; j++) {
        unsigned char *dst = rgb+(j*width*3);
        unsigned char *src = imageData[j];
        unsigned int i;

        for (i = 0; i < width; i++) {
            dst[0] = src[0];
            dst[1] = src[1];
            dst[2] = src[2];
            dst += 3;
            src += (color_type == PNG_COLOR_TYPE_RGB_ALPHA) ? 4 : 3;
        }
    }

    /* Free the image and resources and return */
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    *widthptr = width;
    *heightptr = height;
    *alphaptr = (color_type == PNG_COLOR_TYPE_RGB_ALPHA);
    return rgb;
}
예제 #7
0
파일: example.c 프로젝트: trap/Trap
/* 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;
#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;
    }

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

    /* 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.
     */
#ifndef PNG_JMPBUF_SUPPORTED
    /* Old interface */
    if (setjmp(png_ptr->jmpbuf))
#else
    /* New interface */
    if (png_setjmp(png_ptr))
#endif
    {
        /* Free all of the memory associated with the png_ptr and info_ptr */
        png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
        fclose(fp);
        /* If we get here, we had a problem reading the file */
        return;
    }

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

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

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

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

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

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

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

    /* Expand paletted colors into true RGB triplets */
    if (color_type == PNG_COLOR_TYPE_PALETTE)
        png_set_expand(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(png_ptr);

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

    /* Set the background color to draw transparent and alpha images over.
     * It is possible to set the red, green, and blue components directly
     * for paletted images instead of supplying a palette index.  Note that
     * even if the PNG file supplies a background, you are not required to
     * use it - you should use the (solid) application background if it has one.
     */

    png_color_16 my_background, *image_background;

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

    /* Some suggestions as to how to get a screen gamma value */

    /* Note that screen gamma is the display_exponent, which includes
     * the CRT_exponent and any correction for viewing conditions */
    if (/* We have a user-defined screen gamma value */)
    {
        screen_gamma = user-defined screen_gamma;
    }
    /* This is one way that applications share the same screen gamma value */
    else if ((gamma_str = getenv("SCREEN_GAMMA")) != NULL)
예제 #8
0
/*!
 *  pixReadStreamPng()
 *
 *      Input:  stream
 *      Return: pix, or null on error
 *
 *  Notes:
 *      (1) If called from pixReadStream(), the stream is positioned
 *          at the beginning of the file.
 *      (2) To do sequential reads of png format images from a stream,
 *          use pixReadStreamPng()
 */
PIX *
pixReadStreamPng(FILE  *fp)
{
l_uint8      rval, gval, bval;
l_int32      i, j, k;
l_int32      wpl, d, spp, cindex;
l_uint32     png_transforms;
l_uint32    *data, *line, *ppixel;
int          num_palette, num_text;
png_byte     bit_depth, color_type, channels;
png_uint_32  w, h, rowbytes;
png_uint_32  xres, yres;
png_bytep    rowptr;
png_bytep   *row_pointers;
png_structp  png_ptr;
png_infop    info_ptr, end_info;
png_colorp   palette;
png_textp    text_ptr;  /* ptr to text_chunk */
PIX         *pix;
PIXCMAP     *cmap;

    PROCNAME("pixReadStreamPng");

    if (!fp)
        return (PIX *)ERROR_PTR("fp not defined", procName, NULL);
    pix = NULL;

        /* Allocate the 3 data structures */
    if ((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
                   (png_voidp)NULL, NULL, NULL)) == NULL)
        return (PIX *)ERROR_PTR("png_ptr not made", procName, NULL);

    if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) {
        png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
        return (PIX *)ERROR_PTR("info_ptr not made", procName, NULL);
    }

    if ((end_info = png_create_info_struct(png_ptr)) == NULL) {
        png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
        return (PIX *)ERROR_PTR("end_info not made", procName, NULL);
    }

        /* Set up png setjmp error handling */
    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        return (PIX *)ERROR_PTR("internal png error", procName, NULL);
    }

    png_init_io(png_ptr, fp);

        /* ---------------------------------------------------------- *
         *  Set the transforms flags.  Whatever happens here,
         *  NEVER invert 1 bpp using PNG_TRANSFORM_INVERT_MONO.
         * ---------------------------------------------------------- */
        /* To strip 16 --> 8 bit depth, use PNG_TRANSFORM_STRIP_16 */
    if (var_PNG_STRIP_16_TO_8 == 1)   /* our default */
        png_transforms = PNG_TRANSFORM_STRIP_16;
    else
        png_transforms = PNG_TRANSFORM_IDENTITY;
        /* To remove alpha channel, use PNG_TRANSFORM_STRIP_ALPHA */
    if (var_PNG_STRIP_ALPHA == 1)   /* our default */
        png_transforms |= PNG_TRANSFORM_STRIP_ALPHA;

        /* Read it */
    png_read_png(png_ptr, info_ptr, png_transforms, NULL);

    row_pointers = png_get_rows(png_ptr, info_ptr);
    w = png_get_image_width(png_ptr, info_ptr);
    h = png_get_image_height(png_ptr, info_ptr);
    bit_depth = png_get_bit_depth(png_ptr, info_ptr);
    rowbytes = png_get_rowbytes(png_ptr, info_ptr);
    color_type = png_get_color_type(png_ptr, info_ptr);
    channels = png_get_channels(png_ptr, info_ptr);
    spp = channels;

    if (spp == 1)
        d = bit_depth;
    else if (spp == 2) {
        d = 2 * bit_depth;
        L_WARNING("there shouldn't be 2 spp!", procName);
    }
    else  /* spp == 3 (rgb), spp == 4 (rgba) */
        d = 4 * bit_depth;

        /* Remove if/when this is implemented for all bit_depths */
    if (spp == 3 && bit_depth != 8) {
        fprintf(stderr, "Help: spp = 3 and depth = %d != 8\n!!", bit_depth);
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        return (PIX *)ERROR_PTR("not implemented for this depth",
            procName, NULL);
    }

    if (color_type == PNG_COLOR_TYPE_PALETTE ||
        color_type == PNG_COLOR_MASK_PALETTE) {   /* generate a colormap */
        png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
        cmap = pixcmapCreate(d);  /* spp == 1 */
        for (cindex = 0; cindex < num_palette; cindex++) {
            rval = palette[cindex].red;
            gval = palette[cindex].green;
            bval = palette[cindex].blue;
            pixcmapAddColor(cmap, rval, gval, bval);
        }
    }
    else
        cmap = NULL;

    if ((pix = pixCreate(w, h, d)) == NULL) {
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        return (PIX *)ERROR_PTR("pix not made", procName, NULL);
    }
    wpl = pixGetWpl(pix);
    data = pixGetData(pix);
    pixSetColormap(pix, cmap);

    if (spp == 1) {   /* copy straight from buffer to pix */
        for (i = 0; i < h; i++) {
            line = data + i * wpl;
            rowptr = row_pointers[i];
            for (j = 0; j < rowbytes; j++) {
                SET_DATA_BYTE(line, j, rowptr[j]);
            }
        }
    }
    else  {   /* spp == 3 or spp == 4 */
        for (i = 0; i < h; i++) {
            ppixel = data + i * wpl;
            rowptr = row_pointers[i];
            for (j = k = 0; j < w; j++) {
                SET_DATA_BYTE(ppixel, COLOR_RED, rowptr[k++]);
                SET_DATA_BYTE(ppixel, COLOR_GREEN, rowptr[k++]);
                SET_DATA_BYTE(ppixel, COLOR_BLUE, rowptr[k++]);
                if (spp == 4)
                    SET_DATA_BYTE(ppixel, L_ALPHA_CHANNEL, rowptr[k++]);
                ppixel++;
            }
        }
    }

#if  DEBUG
    if (cmap) {
        for (i = 0; i < 16; i++) {
            fprintf(stderr, "[%d] = %d\n", i,
                   ((l_uint8 *)(cmap->array))[i]);
        }
    }
#endif  /* DEBUG */

        /* If there is no colormap, PNG defines black = 0 and
         * white = 1 by default for binary monochrome.  Therefore,
         * since we use the opposite definition, we must invert
         * the image colors in either of these cases:
         *    (i) there is no colormap (default)
         *    (ii) there is a colormap which defines black to
         *         be 0 and white to be 1.
         * We cannot use the PNG_TRANSFORM_INVERT_MONO flag
         * because that flag (since version 1.0.9) inverts 8 bpp
         * grayscale as well, which we don't want to do.
         * (It also doesn't work if there is a colormap.)
         * If there is a colormap that defines black = 1 and
         * white = 0, we don't need to do anything.
         *
         * How do we check the polarity of the colormap?
         * The colormap determines the values of black and
         * white pixels in the following way:
         *     if black = 1 (255), white = 0
         *          255, 255, 255, 0, 0, 0, 0, 0, 0
         *     if black = 0, white = 1 (255)
         *          0, 0, 0, 0, 255, 255, 255, 0
         * So we test the first byte to see if it is 0;
         * if so, invert the colors.
         *
         * If there is a colormap, after inverting the pixels it is
         * necessary to destroy the colormap.  Otherwise, if someone were
         * to call pixRemoveColormap(), this would cause the pixel
         * values to be inverted again!
         */
    if (d == 1 && (!cmap || (cmap && ((l_uint8 *)(cmap->array))[0] == 0x0))) {
/*        fprintf(stderr, "Inverting binary data on png read\n"); */
        pixInvert(pix, pix);
        pixDestroyColormap(pix);
    }

    xres = png_get_x_pixels_per_meter(png_ptr, info_ptr);
    yres = png_get_y_pixels_per_meter(png_ptr, info_ptr);
    pixSetXRes(pix, (l_int32)((l_float32)xres / 39.37 + 0.5));  /* to ppi */
    pixSetYRes(pix, (l_int32)((l_float32)yres / 39.37 + 0.5));  /* to ppi */

        /* Get the text if there is any */
    png_get_text(png_ptr, info_ptr, &text_ptr, &num_text);
    if (num_text && text_ptr)
        pixSetText(pix, text_ptr->text);

    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    return pix;
}
예제 #9
0
/*Loads a png image*/
bool Engine::loadImage(char *name, int &outWidth, int &outHeight, bool &outHasAlpha, GLubyte **outData) {
    png_structp pngPtr;
    png_infop infoPtr;
    unsigned int sigRead = 0;
    int colorType, interlaceType;
    FILE *file;

    if ((file = fopen(name, "rb")) == NULL) return false;

    pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (pngPtr == NULL) {
        fclose(file);
        return false;
    }

    infoPtr = png_create_info_struct(pngPtr);
    if (infoPtr == NULL) {
        fclose(file);
        png_destroy_read_struct(&pngPtr, png_infopp_NULL, png_infopp_NULL);
        return false;
    }

    if (setjmp(png_jmpbuf(pngPtr))) {
        png_destroy_read_struct(&pngPtr, &infoPtr, png_infopp_NULL);
        fclose(file);
        return false;
    }

    png_init_io(pngPtr, file);
    png_set_sig_bytes(pngPtr, sigRead);

    png_read_png(pngPtr, infoPtr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, png_voidp_NULL);

    outWidth = infoPtr->width;
    outHeight = infoPtr->height;

    switch (infoPtr->color_type) {
        case PNG_COLOR_TYPE_RGBA:
            outHasAlpha = true;
            break;
        case PNG_COLOR_TYPE_RGB:
            outHasAlpha = false;
            break;
        default:
            cout << "Color type " << infoPtr->color_type << " not supported" << endl;
            png_destroy_read_struct(&pngPtr, &infoPtr, NULL);
            fclose(file);
            return false;
    }

    unsigned int rowBytes = png_get_rowbytes(pngPtr, infoPtr);
    *outData = (unsigned char*) malloc(rowBytes*outHeight);
    png_bytepp rowPointers = png_get_rows(pngPtr, infoPtr);

    for (int i = 0; i < outHeight; i++)
        memcpy(*outData+(rowBytes*(outHeight-1-i)), rowPointers[i], rowBytes);

    png_destroy_read_struct(&pngPtr, &infoPtr, png_infopp_NULL);
    fclose(file);

    return true;
}
예제 #10
0
static void read_png_file(const char* file_name, png_image_data_t *png_image_data, int max_width, int max_height)
{
    png_structp png_ptr;
    png_infop info_ptr;
    png_bytep *row_pointers;
	char header[8];	// 8 is the maximum size that can be checked
    int y;
    char* dest;

	/* open file and test for it being a png */
	FILE *fp = fopen(file_name, "rb");
	if (!fp)
		abort_("[read_png_file] File %s could not be opened for reading", file_name);
	fread(header, 1, 8, fp);
	if (png_sig_cmp(header, 0, 8))
		abort_("[read_png_file] File %s is not recognized as a PNG file", file_name);


	/* initialize stuff */
	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	
	if (!png_ptr)
		abort_("[read_png_file] png_create_read_struct failed");

    if (max_width > 0 && max_height > 0)
        png_set_user_limits(png_ptr, max_width, max_height);

	info_ptr = png_create_info_struct(png_ptr);

	if (setjmp(png_jmpbuf(png_ptr)))
		abort_("[read_png_file] Error during init_io");
	png_init_io(png_ptr, fp);

	if (setjmp(png_jmpbuf(png_ptr)))
		abort_("[read_png_file] Error during init_io");
   png_set_sig_bytes(png_ptr, sizeof(header));

	if (setjmp(png_jmpbuf(png_ptr)))
		abort_("[read_png_file] Error during init_io");
   png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_ALPHA, png_voidp_NULL);

	if (setjmp(png_jmpbuf(png_ptr)))
		abort_("[read_png_file] Error during init_io");

    row_pointers = png_get_rows(png_ptr, info_ptr);

    png_image_data->height = png_get_image_height(png_ptr, info_ptr);
    png_image_data->width = png_get_image_width(png_ptr, info_ptr);

    png_image_data->image4c = (void*)qemu_malloc(png_image_data->width * png_image_data->height * 4);

    dest = (char*)png_image_data->image4c;

    /* transform this from 3 channels to a (fake for now) 4 channels */
	for (y=0; y < png_image_data->height; y++) {
        char* src = row_pointers[y];
        int x;
        for (x = 0; x < png_image_data->width; x++) {
            *dest = *src; dest++, src++;
            *dest = *src; dest++, src++;
            *dest = *src; dest++, src++;
            *dest = 0; dest++; /* alpha channel ignored */ 
        }
    }

    png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);

    fclose(fp);
}
예제 #11
0
    PingPNG												(const std::string& aPath) :
        File(0),
        PngPtr(0),
        InfoPtr(0),
        RowPointers(0),
        Width(0),
        Height(0),
        Valid(false)
    {
        File = fopen(aPath.c_str(), "rb");

        if(File)
        {
            fread(Header, 1, 8, File);
            if(!png_sig_cmp(Header, 0, 8))
            {
                PngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
                if(PngPtr)
                {
                    InfoPtr = png_create_info_struct(PngPtr);
                    if(InfoPtr)
                    {
                        if(setjmp(png_jmpbuf(PngPtr)))
                        {
                            es_log->AppendLine("PNG Reader: Error during init_io. [File: %s]", aPath.c_str());
                            return;
                        }

                        png_init_io(PngPtr, File);
                        png_set_sig_bytes(PngPtr, 8);


                        if(setjmp(png_jmpbuf(PngPtr)))
                        {
                            es_log->AppendLine("PNG Reader: Error during read_png. [File: %s]", aPath.c_str());
                            return;
                        }
                        png_read_png(PngPtr, InfoPtr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_SWAP_ALPHA, 0);

                        RowPointers = png_get_rows(PngPtr, InfoPtr);
                        if(!RowPointers)
                        {
                            es_log->AppendLine("PNG Reader: Failed to get pixels. [File: %s]", aPath.c_str());
                            return;
                        }

                        Width = png_get_image_width(PngPtr, InfoPtr);
                        Height = png_get_image_height(PngPtr, InfoPtr);
                        Valid = true;
                        return;
                    }
                    else
                    {
                        es_log->AppendLine("PNG Reader: png_create_info_struct failed. [File: %s]", aPath.c_str());
                        return;
                    }
                }
                else
                {
                    es_log->AppendLine("PNG Reader: png_create_read_struct failed. [File: %s]", aPath.c_str());
                    return;
                }
            }
            else
            {
                es_log->AppendLine("PNG Reader: File not recognized as a PNG file. [File: %s]", aPath.c_str());
                return;
            }
        }
        else
        {
            es_log->AppendLine("PNG Reader: File could not be opened for reading. [File: %s]", aPath.c_str());
            return;
        }
    }
예제 #12
0
ImageReader::ImageHandle ImageReader::getImage(text::string_hash id)
{
	if (hasProduct(id))
		return getProduct(id);

	// Image is not in cache, load it.

	const std::string& url = text::get(id);

	INFO_OUT(TAG, "Loading image %s", url.c_str());

	FILE* fp = fopen(url.c_str(), "rb");

	if (fp == NULL)
		throw ResourceException("Cannot open file.");

	if ( !isPNGFile(fp) )
	{
		fclose(fp);
		throw ResourceException("File is not PNG.");
	}

	png_structp pngStruct = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
	if (!pngStruct)
	{
		fclose(fp);
		throw ResourceException("[LIBPNG] Error creating read struct.");
	}

	png_infop pngInfo = png_create_info_struct(pngStruct);
	if (!pngInfo)
	{
		png_destroy_read_struct(&pngStruct, nullptr, nullptr);
		fclose(fp);
		throw ResourceException("[LIBPNG] Error creating info struct.");
	}

	if ( setjmp(png_jmpbuf(pngStruct)) )
	{
		png_destroy_read_struct(&pngStruct, &pngInfo, nullptr);
		fclose(fp);
		throw ResourceException("Error while reading file.");
	}

	png_init_io(pngStruct, fp);

	png_set_sig_bytes(pngStruct, pngHeaderCheckSize);

	// FIXME Write directly to buffer, don't copy.

	png_read_png(pngStruct,
	             pngInfo,
	             PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND,
	             NULL);

	struct
	{
		png_uint_32 width;
		png_uint_32 height;
		png_byte bitsPerPixel;
		png_byte colorType;
		png_size_t rowSize;
	} imageData;

	imageData.width 		= png_get_image_width(pngStruct, pngInfo);
	imageData.height 		= png_get_image_height(pngStruct, pngInfo);
	imageData.bitsPerPixel 	= png_get_bit_depth(pngStruct, pngInfo);
	imageData.colorType 	= png_get_color_type(pngStruct, pngInfo);
	imageData.rowSize		= png_get_rowbytes(pngStruct, pngInfo);

	// FIXME Let PixelFormat decide what format is suitable.

	gr::PixelFormat fmt;
	if (imageData.colorType == PNG_COLOR_TYPE_RGBA)
		fmt = gr::PixelFormat::R8G8B8A8;
	else
		fmt = gr::PixelFormat::R8G8B8;

	unsigned char* pixels = new unsigned char[imageData.rowSize * imageData.height];
	png_bytepp rowPointers = png_get_rows(pngStruct, pngInfo);

	for (unsigned int i = 0; i < imageData.height; i++)
		memcpy(pixels + (imageData.rowSize * (imageData.height - 1 - i)),
		       rowPointers[i],
		       imageData.rowSize);

	png_destroy_read_struct(&pngStruct, &pngInfo, NULL);
	fclose(fp);

	return addProduct(id, gr::Image((unsigned int) imageData.width,
	                                (unsigned int) imageData.height,
	                                fmt,
	                                1u,
	                                pixels));
}
예제 #13
0
Texture PNGFile::Load(std::string _path)
{
	Texture tex;
	
	// png specifics
	png_structp png_ptr = NULL;
	png_infop info_ptr = NULL, end_info = NULL;
	png_bytep *row_pointers = NULL;
	png_byte sig[8];
	
	// the rest
	FILE *pngFile = NULL;
	GLubyte *pixels = NULL;
	GLuint glformat = 0;
	int components, rowsize;
	tex.path = _path;
	pngFile = fopen(_path.c_str(), "rb");
	
	if (!pngFile)
	{
		Log->Print("File \"%s\" not found.", tex.path.c_str());
		return Texture();
	}
	
	if (fread(&sig, sizeof(png_byte), 8, pngFile) < 8)
	{
		Log->Print("Header of the file \"%s\" couldn't be fully read!", tex.path.c_str());
		fclose(pngFile);
		return Texture();
	}
	
	if (png_sig_cmp(sig, 0, 8))
	{
		Log->Print("File \"%s\" is not a valid png file!", tex.path.c_str());
		fclose(pngFile);
		return Texture();
	}
	
	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,NULL,NULL);
	
	if (!png_ptr)
	{
		fclose(pngFile);
		return Texture();
	}
	
	info_ptr = png_create_info_struct(png_ptr);
	
	if (!info_ptr)
	{
		png_destroy_read_struct(&png_ptr, NULL, NULL);
		fclose(pngFile);
		return Texture();
	}
	
	end_info = png_create_info_struct(png_ptr);
	
	if (!end_info)
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		fclose(pngFile);
		return Texture();
	}
	
	// safety first. :)
	if (setjmp(png_jmpbuf(png_ptr)))
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		fclose(pngFile);
		return Texture();
	}
	
	// init io and tell libpng we've already read the sig.
	png_init_io(png_ptr, pngFile);
	png_set_sig_bytes(png_ptr, 8);
	
	// If we've got tRNS on an RGB image, it's a color key. Make this RGBA.
	if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
		png_set_tRNS_to_alpha(png_ptr);
		
	// filler for keys
	png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
	
	// read the file
	png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
	tex.width = png_get_image_width(png_ptr,info_ptr);
	tex.height = png_get_image_height(png_ptr,info_ptr);
	rowsize = png_get_rowbytes(png_ptr,info_ptr);
	components = png_get_channels(png_ptr,info_ptr);
	row_pointers = png_get_rows(png_ptr, info_ptr);
	pixels = new GLubyte[rowsize * tex.height];
	
	for (unsigned int i = 0; i < tex.height; i++)
		memcpy(&pixels[i*rowsize], row_pointers[i], rowsize);
		
	// prepare texture for uploading to GPU
	glGenTextures(1, &tex.ptr); // make it
	glBindTexture(GL_TEXTURE_2D, tex.ptr); // bind it
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	
	switch(components)
	{
	case 1:
		glformat = GL_LUMINANCE;
		break;
	case 2:
		glformat = GL_LUMINANCE_ALPHA;
		break;
		// case 3 would be converted to 4, above.
	case 4:
		glformat = GL_RGBA;
		break;
	default:
		glformat = 0; // this shouldn't happen.
		break;
	}
	
	// log some stats
	Log->Print("Uploading texture (res = %dx%d, channels = %d)", tex.width, tex.height, components);
	
	// finally upload the texture
	glTexImage2D(GL_TEXTURE_2D, 0, components, tex.width, tex.height, 0, glformat, GL_UNSIGNED_BYTE, pixels);

	// cleanup
	png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
	delete[] pixels;
	fclose(pngFile);
	return tex;
}
예제 #14
0
/**
 * @brief pngloader loads texture from png file
 * @param filename is name of file
 * @param alpha is amount of blending
 */
pngloader::pngloader(const char* filename, float alpha) {

  unsigned int sig_read = 0;
#ifdef ZIP_ARCHIVE
  file = zip_fopen(APKArchive, prefix(filename), 0);
#else
  fp = fopen(prefix(filename), "rb");
#endif

  png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  png_infop info_ptr = png_create_info_struct(png_ptr);
  setjmp(png_jmpbuf(png_ptr));

  png_set_read_fn(png_ptr, NULL, png_read);

  png_set_sig_bytes(png_ptr, sig_read);
  png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16, NULL);

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

  switch (color_type) {
      case PNG_COLOR_TYPE_RGBA:
          alpha = true;
          break;
      case PNG_COLOR_TYPE_RGB:
          alpha = false;
          break;
  }

  unsigned int row_bytes = png_get_rowbytes(png_ptr, info_ptr);
  GLubyte *outData = new GLubyte[row_bytes * height];
  png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr);

  for (unsigned int i = 0; i < height; i++) {
      memcpy(outData+(row_bytes * (height-1-i)), row_pointers[i], row_bytes);
  }

  /* Clean up after the read,
   * and free any memory allocated */
  png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
#ifdef ZIP_ARCHIVE
  zip_fclose(file);
#else
  fclose(fp);
#endif

  /// transform data
  transparent = alpha;

  glGenTextures(1, &textureID);
  glEnable(GL_TEXTURE_2D);
  glActiveTexture(GL_TEXTURE0);
  glBindTexture(GL_TEXTURE_2D, textureID);
  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR );

  if (alpha) {
      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, outData);
  } else {
      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, outData);
  }

  delete[] outData;
}
예제 #15
0
    void png_loader::read_image( const char* filename )
    {
        ld_.reset(new LibpngData);
        if ( filename == NULL )
        {
            throw image_load_error("png_loader: invalid filename, it is NULL");
        }
        FILE *fp = fopen( filename, "rb" );
        if ( !fp )
        {
            throw image_load_error(std::string("png_loader: unable to open file ") + filename);
        }
        png_byte sig[8];
        if (fread( sig, 1, 8, fp ) != 8)
        {
            fclose( fp );
            throw image_load_error(std::string("png_loader: error reading file ") + filename);
        }
        if ( png_sig_cmp( sig, 0, 8 ) != 0 )
        {
            fclose( fp );
            throw image_load_error(std::string("png_loader: format error in file ") + filename);
        }
        ld_->png_ptr_ = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, &png_loader_user_error_fn_silent, &png_loader_user_warning_fn_silent );
        if ( ld_->png_ptr_ == NULL )
        {
            fclose( fp );
            throw image_load_error(std::string("png_loader: parse error in file ") + filename);
        }
        ld_->info_ptr_ = png_create_info_struct( ld_->png_ptr_ );
        if ( ld_->info_ptr_ == NULL )
        {
            fclose( fp );
            png_destroy_read_struct( &( ld_->png_ptr_ ), ( png_infopp )NULL, ( png_infopp )NULL );
            throw image_load_error(std::string("png_loader: parse error in file ") + filename);
        }
        ld_->end_info_ = png_create_info_struct( ld_->png_ptr_ );
        if ( ld_->end_info_ == NULL )
        {
            fclose( fp );
            png_destroy_read_struct( &( ld_->png_ptr_ ), &( ld_->info_ptr_ ), ( png_infopp )NULL );
            throw image_load_error(std::string("png_loader: parse error in file ") + filename);
        }

        if (setjmp(png_jmpbuf(ld_->png_ptr_)))
        {
            // If we get here, we had a problem writing the file 
            fclose(fp);
            png_destroy_read_struct( &( ld_->png_ptr_ ), &( ld_->info_ptr_ ), &( ld_->end_info_ ) );
            throw image_load_error(std::string("png_loader: parse error in file ") + filename);
        }

        png_set_palette_to_rgb(ld_->png_ptr_);

        png_init_io( ld_->png_ptr_, fp );
        png_set_sig_bytes( ld_->png_ptr_, 8 );
        // flags force one byte per channel output
        byte_orderer bo;
        int png_transforms = PNG_TRANSFORM_PACKING;
        if (bo.host_is_little_endian())
            png_transforms |= PNG_TRANSFORM_SWAP_ENDIAN;
        png_read_png( ld_->png_ptr_, ld_->info_ptr_, png_transforms, NULL );
        height_ = png_get_image_height( ld_->png_ptr_, ld_->info_ptr_ );
        width_ = png_get_image_width( ld_->png_ptr_, ld_->info_ptr_ );
        bit_depth_ = png_get_bit_depth( ld_->png_ptr_, ld_->info_ptr_ );
        color_type_ = png_get_color_type( ld_->png_ptr_, ld_-> info_ptr_ );


        if (color_type_ != PNG_COLOR_TYPE_GRAY && 
            color_type_ != PNG_COLOR_TYPE_RGB && 
            color_type_ != PNG_COLOR_TYPE_RGB_ALPHA )
        {
            fclose( fp );
            png_destroy_read_struct( &( ld_->png_ptr_ ), &( ld_->info_ptr_ ), &( ld_->end_info_ ) );
            throw image_load_error(std::string("png_loader: unsupported color type in file ") + filename);
        }

        if (bit_depth_ != 8 && bit_depth_ != 16)
        {
            fclose( fp );
            png_destroy_read_struct( &( ld_->png_ptr_ ), &( ld_->info_ptr_ ), &( ld_->end_info_ ) );
            throw image_load_error("png_loader: unsupported bit depth of " + cast_to_string(bit_depth_) + " in file " + std::string(filename));
        }

        ld_->row_pointers_ = png_get_rows( ld_->png_ptr_, ld_->info_ptr_ );

        fclose( fp );
        if ( ld_->row_pointers_ == NULL )
        {
            png_destroy_read_struct( &( ld_->png_ptr_ ), &( ld_->info_ptr_ ), &( ld_->end_info_ ) );
            throw image_load_error(std::string("png_loader: parse error in file ") + filename);
        }
    }
예제 #16
0
파일: image_io.cpp 프로젝트: Aand1/Autoware
TypedImage LoadPng(const std::string& filename)
{
#ifdef HAVE_PNG
    FILE *in = fopen(filename.c_str(), "rb");
    
    if( in )  {
        //check the header
        const size_t nBytes = 8;
        png_byte header[nBytes];
        size_t nread = fread(header, 1, nBytes, in);
        int nIsPNG = png_sig_cmp(header, 0, nread);
        
        if ( nIsPNG != 0 )  {
            throw std::runtime_error( filename + " is not a PNG file" );
        }
        
        //set up initial png structs
        png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, &PngWarningsCallback);
        if (!png_ptr) {
            throw std::runtime_error( "PNG Init error 1" );
        }
        
        png_infop info_ptr = png_create_info_struct(png_ptr);
        if (!info_ptr)  {
            png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
            throw std::runtime_error( "PNG Init error 2" );
        }
        
        png_infop end_info = png_create_info_struct(png_ptr);
        if (!end_info) {
            png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
            throw std::runtime_error( "PNG Init error 3" );
        }
        
        png_init_io(png_ptr, in);
        png_set_sig_bytes(png_ptr, nBytes);
        
        //read the file
        png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
        
        if( png_get_bit_depth(png_ptr, info_ptr) == 1)  {
            //Unpack bools to bytes to ease loading.
            png_set_packing(png_ptr);
        } else if( png_get_bit_depth(png_ptr, info_ptr) < 8) {
            //Expand nonbool colour depths up to 8bpp
            png_set_expand_gray_1_2_4_to_8(png_ptr);
        }
        
        //Get rid of palette, by transforming it to RGB
        if(png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE) {
            png_set_palette_to_rgb(png_ptr);
        }
        
        if( png_get_interlace_type(png_ptr,info_ptr) != PNG_INTERLACE_NONE) {
            throw std::runtime_error( "Interlace not yet supported" );
        }
        
        const size_t w = png_get_image_width(png_ptr,info_ptr);
        const size_t h = png_get_image_height(png_ptr,info_ptr);
        const size_t pitch = png_get_rowbytes(png_ptr, info_ptr);
        
        TypedImage img;
        img.Alloc(w, h, PngFormat(png_ptr, info_ptr), pitch);
        
        png_bytepp rows = png_get_rows(png_ptr, info_ptr);
        for( unsigned int r = 0; r < h; r++) {
            memcpy( img.ptr + pitch*r, rows[r], pitch );
        }
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        
        fclose(in);
        return img;
    }
    
    throw std::runtime_error("Unable to load PNG file, '" + filename + "'");    
    
#else
    throw std::runtime_error("PNG Support not enabled. Please rebuild Pangolin.");
#endif
}
예제 #17
0
파일: PngImage.cpp 프로젝트: perjoh/stuff
	void read( Image& img, const char* file_name ) {

		// TODO: Use shared_ptr to execute fclose() etc. when exiting scope.

		// open file

		FILE *fp = fopen(file_name, "rb");
		if (!fp) {
			throw std::exception("Failed to open file.");
		}

		boost::shared_ptr<void> fp_cleanup( static_cast<void*>(0), boost::bind( fclose, fp ) );

		const int PNG_BYTES_TO_CHECK = 4;
		png_byte header[PNG_BYTES_TO_CHECK];

		fread(header, 1, PNG_BYTES_TO_CHECK, fp);
		const bool is_png = !png_sig_cmp(header, 0, PNG_BYTES_TO_CHECK);
		if (!is_png) {
			throw std::exception("File is not a valid PNG file.");
		}

		// setup PNG structs

		png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0);
		if (!png_ptr) {
			throw std::exception("png_create_read_struct failed.");
		}

		png_infop info_ptr = 0;
		png_infop end_info = 0;
		boost::shared_ptr<void> png_cleanup( static_cast<void*>(0), boost::bind( png_destroy_read_struct, &png_ptr, &info_ptr, &end_info ) );

		info_ptr = png_create_info_struct(png_ptr);
		if (!info_ptr) {
			throw std::exception("png_create_info_struct failed.");
		}

		end_info = png_create_info_struct(png_ptr);
		if (!end_info) {
			throw std::exception("png_create_info_struct failed.");
		}

		// TODO Remove setjmp
		if (setjmp(png_jmpbuf(png_ptr))) {
			throw std::exception("Failed to read PNG-image.");
		}

		png_init_io(png_ptr, fp);

		png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK);

		png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

		const png_bytep* row_pointers = png_get_rows(png_ptr, info_ptr);

		// Assert we are making correct assumptions about PNG lib.
		assert( info_ptr->rowbytes == info_ptr->channels * info_ptr->width );

		Image img_tmp( info_ptr->width, info_ptr->height, info_ptr->channels, row_pointers );
		img.swap( img_tmp );
	}
예제 #18
0
    bool PngRead(uint8 * * pixels, uint32 * width, uint32 * height, bool expand, const utf8 * path, sint32 * bitDepth)
    {
        png_structp png_ptr;
        png_infop info_ptr;

        // Setup PNG structures
        png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
        if (png_ptr == nullptr)
        {
            return false;
        }

        info_ptr = png_create_info_struct(png_ptr);
        if (info_ptr == nullptr)
        {
            png_destroy_read_struct(&png_ptr, nullptr, nullptr);
            return false;
        }

        // Open PNG file
        try
        {
            unsigned int sig_read = 0;
            auto fs = FileStream(path, FILE_MODE_OPEN);

            // Set error handling
            if (setjmp(png_jmpbuf(png_ptr)))
            {
                png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
                return false;
            }

            // Setup PNG reading
            png_set_read_fn(png_ptr, &fs, PngReadData);
            png_set_sig_bytes(png_ptr, sig_read);

            uint32 readFlags = PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING;
            if (expand)
            {
                // If we expand the resulting image always be full RGBA
                readFlags |= PNG_TRANSFORM_GRAY_TO_RGB | PNG_TRANSFORM_EXPAND;
            }
            png_read_png(png_ptr, info_ptr, readFlags, nullptr);

            // Read header
            png_uint_32 pngWidth, pngHeight;
            int colourType, interlaceType;
            png_get_IHDR(png_ptr, info_ptr, &pngWidth, &pngHeight, bitDepth, &colourType, &interlaceType, nullptr, nullptr);

            // Read pixels as 32bpp RGBA data
            png_size_t rowBytes = png_get_rowbytes(png_ptr, info_ptr);
            png_bytepp rowPointers = png_get_rows(png_ptr, info_ptr);
            uint8 * pngPixels = Memory::Allocate<uint8>(pngWidth * pngHeight * 4);
            uint8 * dst = pngPixels;
            if (colourType == PNG_COLOR_TYPE_RGB)
            {
                // 24-bit PNG (no alpha)
                Guard::Assert(rowBytes == pngWidth * 3, GUARD_LINE);
                for (png_uint_32 i = 0; i < pngHeight; i++)
                {
                    uint8 * src = rowPointers[i];
                    for (png_uint_32 x = 0; x < pngWidth; x++)
                    {
                        *dst++ = *src++;
                        *dst++ = *src++;
                        *dst++ = *src++;
                        *dst++ = 255;
                    }
                }
            }
            else if (*bitDepth == 8 && !expand)
            {
                // 8-bit paletted or grayscale
                Guard::Assert(rowBytes == pngWidth, GUARD_LINE);
                for (png_uint_32 i = 0; i < pngHeight; i++)
                {
                    std::copy_n(rowPointers[i], rowBytes, dst);
                    dst += rowBytes;
                }
            }
            else
            {
                // 32-bit PNG (with alpha)
                Guard::Assert(rowBytes == pngWidth * 4, GUARD_LINE);
                for (png_uint_32 i = 0; i < pngHeight; i++)
                {
                    std::copy_n(rowPointers[i], rowBytes, dst);
                    dst += rowBytes;
                }
            }

            // Close the PNG
            png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);

            // Return the output data
            *pixels = pngPixels;
            if (width != nullptr) *width = pngWidth;
            if (height != nullptr) *height = pngHeight;

            return true;
        }
        catch (const std::exception &)
        {
            *pixels = nullptr;
            if (width != nullptr) *width = 0;
            if (height != nullptr) *height = 0;
            return false;
        }
    }
예제 #19
0
int datpng_write (FILE * outfile, datpng_info * dat_info,
		  void *data, size_t data_size)
{
  png_colorp palette = NULL;
  int num_palette;

  int exit_stat = EXIT_SUCCESS;

  /* Check the bit depth. */
  if (dat_info->bit_depth != 8)
    return PNGDAT_INVALID_BIT_DEPTH;

  int pixel_width, color_type;
  switch (dat_info->color_type)
    {
    case PNGDAT_CT_AUTO:
      pixel_width = 3;
      color_type = PNG_COLOR_TYPE_RGB;
      break;

    case PNGDAT_CT_RGB:
      pixel_width = 3;
      color_type = PNG_COLOR_TYPE_RGB;
      break;

    case PNGDAT_CT_PALETTE:
      pixel_width = 1;
      color_type = PNG_COLOR_TYPE_PALETTE;
      break;

    default:
      return PNGDAT_INVALID_COLOR_TYPE;
      break;
    }

  int csum = dat_info->checksum;

  int x_pos = dat_info->x_pos;
  int y_pos = dat_info->y_pos;
  int data_width = dat_info->data_width;
  int data_height = dat_info->data_height;
  int img_width = dat_info->png_width;
  int img_height = dat_info->png_height;

  /* No constraints defined. */
  if (img_width == 0 && img_height == 0 &&
      data_width == 0 && data_height == 0)
    return PNGDAT_MISSING_CONSTRAINT;

  /* Propagate width value. */
  if (img_width == 0 && data_width > 0)
    img_width = data_width + x_pos;
  if (img_width > 0 && data_width == 0)
    data_width = img_width - x_pos;

  /* Propagate height value. */
  if (img_height == 0 && data_height > 0)
    img_height = data_height - y_pos;
  if (img_height > 0 && data_height == 0)
    data_height = img_height + y_pos;

  if (img_width == 0 && data_width == 0)
    {
      /* Calculate a width. */
      data_width = (int) ceil ((data_size + header_size)
			       / (data_height * pixel_width * 1.0));
      if (csum)
	data_width = (int) ceil ((data_size + header_size + data_height)
				 / (data_height * pixel_width * 1.0));
      img_width = data_width + x_pos;
    }
  if (img_height == 0 && data_height == 0)
    {
      /* Calculate a height. */
      data_height = (int) ceil ((data_size + header_size)
				/ (data_width * pixel_width * 1.0));
      if (csum)
	data_height = (int) ceil ((data_size + header_size + data_height)
				  / (data_width * pixel_width * 1.0));
      img_height = data_height + y_pos;
    }

  png_bytep *row_pointers;

  /* Set up the image data. */
  png_infop infoin_ptr;
  png_structp pngin_ptr;
  if (dat_info->insert)
    {
      pngin_ptr = png_create_read_struct
	(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
      infoin_ptr = png_create_info_struct (pngin_ptr);
      png_init_io (pngin_ptr, outfile);
      png_read_png (pngin_ptr, infoin_ptr, PNG_TRANSFORM_STRIP_ALPHA, NULL);

      row_pointers = png_get_rows (pngin_ptr, infoin_ptr);

      rewind (outfile);

      /* Check dimensions. */
      img_width = infoin_ptr->width;
      img_height = infoin_ptr->height;
      if (data_width + x_pos > img_width)
	data_width = img_width - x_pos;
      if (data_height + y_pos > img_height)
	data_height = img_height - y_pos;

      /* Check color type. */
      switch (infoin_ptr->color_type)
	{
	case PNG_COLOR_TYPE_PALETTE:
	  pixel_width = 1;
	  color_type = PNG_COLOR_TYPE_PALETTE;
	  break;

	case PNG_COLOR_TYPE_RGB:
	  pixel_width = 3;
	  color_type = PNG_COLOR_TYPE_RGB;
	  break;

	case PNG_COLOR_TYPE_RGB_ALPHA:
	  pixel_width = 3;
	  color_type = PNG_COLOR_TYPE_RGB;
	  break;

	default:
	  /* XXX free resources */
	  return PNGDAT_INVALID_COLOR_TYPE;
	  break;
	}

      /* Check the bit depth. */
      if (infoin_ptr->bit_depth != 8)
	{
	  /* XXX free resources */
	  return PNGDAT_INVALID_BIT_DEPTH;
	}
    }
  else
    {
      row_pointers = (png_bytep *) malloc (sizeof (png_bytep) * img_height);
    }

  int rowbytes = img_width * pixel_width;
  int datbytes = data_width * pixel_width - csum;

  if (datbytes * data_height < data_size)
    {
      data_size = datbytes * data_height - header_size;
      exit_stat = PNGDAT_TRUNCATED;
    }

  /* Initialize png structs. */
  png_structp png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL,
						 NULL, NULL);
  png_infop info_ptr = png_create_info_struct (png_ptr);
  png_init_io (png_ptr, outfile);

  /* Generate the header. */
  uint8_t header[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  header[1] = (uint8_t) dat_info->bit_depth;
  if (csum)
    header[0] = 128;
  header[0] += cur_ver;

  /* Length of data in network order. */
  uint32_t size = (int) data_size;
  size = htonl (size);
  memcpy (header + 2, &size, 4);

  /* Width of data in network order. */
  uint32_t hdr_width = data_width;
  hdr_width = htonl (hdr_width);
  memcpy (header + 6, &hdr_width, 4);

  /* Load data into row_pointers image data. */
  int data_len, offset;
  void *next_data = data;
  int i;
  for (i = 0; i < img_height; i++)
    {
      if (!dat_info->insert)
	row_pointers[i] = (png_bytep) calloc (1, rowbytes);

      /* Write the header. */
      if (i == y_pos)
	{
	  memcpy (row_pointers[y_pos] +
		  (x_pos * pixel_width), &header, header_size);
	  offset = header_size;
	}
      else
	offset = 0;

      /* 8-bit depth only: */

      data_len = (i - y_pos + 1) * datbytes - header_size;
      if (data_len > data_size)
	data_len = data_size - (data_len - datbytes);
      else

	data_len = datbytes - offset;

      if (data_len < 0)
	data_len = 0;

      int write_out;
      write_out = 0;
      if (i >= y_pos && data_len > 0)
	{
	  memcpy (row_pointers[i] + offset + (x_pos * pixel_width),
		  next_data, data_len);
	  next_data += data_len;
	  write_out = 1;
	}

      /* Calculate the checksum. */
      if (csum && write_out)
	{
	  int j;
	  uint8_t sum = 0;
	  for (j = (x_pos * pixel_width);
	       j < datbytes + (x_pos * pixel_width); j++)
	    sum += row_pointers[i][j];

	  row_pointers[i][(x_pos * pixel_width) + datbytes] = sum;
	}
    }

  /* Determine a palette. */
  if (color_type == PNG_COLOR_TYPE_PALETTE)
    {
      palette = gen_palette ();
      info_ptr->palette = palette;
      info_ptr->num_palette = num_palette;
      png_set_PLTE (png_ptr, info_ptr, palette, num_palette);
    }

  /* Set image meta data. */
  info_ptr->width = img_width;
  info_ptr->height = img_height;
  info_ptr->valid = 0;
  info_ptr->rowbytes = rowbytes;
  info_ptr->num_trans = 0;
  info_ptr->bit_depth = dat_info->bit_depth;
  info_ptr->color_type = color_type;
  info_ptr->compression_type = PNG_COMPRESSION_TYPE_DEFAULT;
  info_ptr->filter_type = PNG_FILTER_TYPE_DEFAULT;
  info_ptr->interlace_type = PNG_INTERLACE_NONE;

  png_write_info (png_ptr, info_ptr);

  if (setjmp (png_jmpbuf (png_ptr)))
    printf ("[write_png_file] Error during write\n");

  png_write_image (png_ptr, row_pointers);
  png_write_end (png_ptr, NULL);

  return exit_stat;
}
예제 #20
0
/* Ripped from the libpng manual */
png_bytepp readpng(const char *filename, int* width, int* height) {
   FILE *fp = fopen(filename, "rb");
   char header[8];
   png_structp png_ptr;
   png_infop info_ptr, end_info;

   if (!fp) {
      fprintf(stderr, "%s ", filename);
      perror("fopen");
      return NULL;
   }
   fread(header, 1, 8, fp);
   if(png_sig_cmp((png_byte*)header, 0, 8))
   {
      fprintf(stderr, "%s: Not a PNG image!\n", filename);
      return NULL;
   }

   png_ptr = png_create_read_struct(
      PNG_LIBPNG_VER_STRING,
      NULL, NULL, NULL);
   if(!png_ptr)
      return NULL;

   info_ptr = png_create_info_struct(png_ptr);
   if(!info_ptr) {
      png_destroy_read_struct(&png_ptr, NULL, NULL);
      return NULL;
   }

   end_info = png_create_info_struct(png_ptr);
   if(!end_info) {
      png_destroy_read_struct(&png_ptr, NULL, NULL);
      return NULL;
   }

   /* Set up jump target for libpng errors */
   if (setjmp(png_jmpbuf(png_ptr)))
   {
      png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
      fprintf(stderr, "libpng error!\n");
      fclose(fp);
      return NULL;
   }

   png_init_io(png_ptr, fp);
   png_set_sig_bytes(png_ptr, 8);
   png_read_png(png_ptr, info_ptr, 0, NULL);

   /* Make sure the image is in the format we want */
   *width = png_get_image_width(png_ptr, info_ptr);
   *height = png_get_image_height(png_ptr, info_ptr);
   if(png_get_bit_depth(png_ptr, info_ptr) != 8 ||
      png_get_color_type(png_ptr, info_ptr) != PNG_COLOR_TYPE_RGB)
      fprintf(stderr, "Need an 8 bit/color RGB image!!\n");

   fclose(fp);  // close the file so we don't have too many open

   /* Warning!  We leak these data structures!!! */
   return png_get_rows(png_ptr, info_ptr);
}
예제 #21
0
파일: dec_png.c 프로젝트: ahill818/pygrib
int dec_png(unsigned char *pngbuf,g2int *width,g2int *height,char *cout)
{
    int interlace,color,compres,filter,bit_depth;
    g2int j,k,n,bytes,clen;
    png_structp png_ptr;
    png_infop info_ptr,end_info;
    png_bytepp row_pointers;
    png_stream read_io_ptr;
    png_uint_32 h32, w32;

/*  check if stream is a valid PNG format   */

    if ( png_sig_cmp(pngbuf,0,8) != 0) 
       return (-3);

/* create and initialize png_structs  */

    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, 
                                      NULL, NULL);
    if (!png_ptr)
       return (-1);

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
    {
       png_destroy_read_struct(&png_ptr,(png_infopp)NULL,(png_infopp)NULL);
       return (-2);
    }

    end_info = png_create_info_struct(png_ptr);
    if (!end_info)
    {
       png_destroy_read_struct(&png_ptr,(png_infopp)info_ptr,(png_infopp)NULL);
       return (-2);
    }

/*     Set Error callback   */

    if (setjmp(png_jmpbuf(png_ptr)))
    {
       png_destroy_read_struct(&png_ptr, &info_ptr,&end_info);
       return (-3);
    }

/*    Initialize info for reading PNG stream from memory   */

    read_io_ptr.stream_ptr=(png_voidp)pngbuf;
    read_io_ptr.stream_len=0;

/*    Set new custom read function    */

    png_set_read_fn(png_ptr,(png_voidp)&read_io_ptr,(png_rw_ptr)user_read_data);
/*     png_init_io(png_ptr, fptr);   */

/*     Read and decode PNG stream   */

    png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

/*     Get pointer to each row of image data   */

    row_pointers = png_get_rows(png_ptr, info_ptr);

/*     Get image info, such as size, depth, colortype, etc...   */

    /*printf("SAGT:png %d %d %d\n",info_ptr->width,info_ptr->height,info_ptr->bit_depth);*/
    // (void)png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *)width, (png_uint_32 *)height,
    (void)png_get_IHDR(png_ptr, info_ptr, &w32, &h32,
               &bit_depth, &color, &interlace, &compres, &filter);

    *height = h32;
    *width = w32;

/*     Check if image was grayscale      */

/*
    if (color != PNG_COLOR_TYPE_GRAY ) {
       fprintf(stderr,"dec_png: Grayscale image was expected. \n");
    }
*/
    if ( color == PNG_COLOR_TYPE_RGB ) {
       bit_depth=24;
    }
    else if ( color == PNG_COLOR_TYPE_RGB_ALPHA ) {
       bit_depth=32;
    }
/*     Copy image data to output string   */

    n=0;
    bytes=bit_depth/8;
    clen=(*width)*bytes;
    for (j=0;j<*height;j++) {
      for (k=0;k<clen;k++) {
        cout[n]=*(row_pointers[j]+k);
        n++;
      }
    }

/*      Clean up   */

    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    return 0;

}
예제 #22
0
int read_png(png_structp *png_ptr2, png_infop *info_ptr2, struct archive* animarc)
{
	png_structp png_ptr;
	png_infop info_ptr;
	png_ptr = *png_ptr2;
	info_ptr = *info_ptr2;

	/* Get the first 8 bits of the first file. */
	void *pngheader;
	pngheader = malloc((size_t)8);

	if (pngheader == NULL) {
		printf("Failed to allocate.");
		return 1;
	}
	
	size_t hsize = 8;
	if (archive_read_data(animarc, pngheader, 8) < 1) {
		printf("Failed to read png header.\n");
		return 1;
	} else {
		/* printf("Read header from archive."); */
	}
	/* Check for PNG file. */
	if (png_sig_cmp(pngheader, 0, 8)) {
		printf("Not a PNG file.\n");
		return 1;
	} else {
		/* printf("Is a png file."); */
	}
	/* Get image data and print out the first row. */
	*png_ptr2 = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);	
	if (*png_ptr2 == NULL) {
		printf("Failed to create PNG read struct.");
		return 1;
	}
	*info_ptr2 = png_create_info_struct(*png_ptr2);
	if (*info_ptr2 == NULL) {
		printf("Failed to create PNG info struct.");
		png_destroy_read_struct(&(*png_ptr2), png_infopp_NULL, png_infopp_NULL);
		return 1;
	}

	if (setjmp(png_jmpbuf(*png_ptr2))) {
		printf("Error during init_io.\n");
		png_destroy_read_struct(&(*png_ptr2), &(*info_ptr2), png_infopp_NULL);
		return 1;
	}

	/* Set functions, get pointers, execute png_init_io */
	png_set_read_fn(*png_ptr2, (void *)animarc, tarpng_read_data);
	
	png_set_sig_bytes(*png_ptr2, 8);

	if (setjmp(png_jmpbuf(*png_ptr2))) {
		printf("Error during init_io.\n");
		png_destroy_read_struct(&(*png_ptr2), &(*info_ptr2), png_infopp_NULL);
		return 1;
	}
	/* Read image into info_ptr structure. */
	png_read_png(*png_ptr2, *info_ptr2, 0, png_voidp_NULL);

	return 0;
}
예제 #23
0
파일: png.c 프로젝트: bitbegin/LCUI
int Graph_LoadPNG( const char *filepath, LCUI_Graph *graph )
{
#ifdef USE_LIBPNG
	FILE *fp;
	uchar_t *pixel_ptr;
	png_structp png_ptr;
	png_infop info_ptr;
	png_bytep* row_pointers;
	char buf[PNG_BYTES_TO_CHECK];
	int w, h, x, y, ret = 0, temp, color_type;

	fp = fopen( filepath, "rb" );
	if( fp == NULL ) {
		return FILE_ERROR_OPEN_ERROR;
	}

	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 ) );
	/* 读取PNG_BYTES_TO_CHECK个字节的数据 */
	temp = fread( buf, 1, PNG_BYTES_TO_CHECK, fp );
	/* 若读到的数据并没有PNG_BYTES_TO_CHECK个字节 */
	if( temp < PNG_BYTES_TO_CHECK ) {
		fclose( fp );
		png_destroy_read_struct( &png_ptr, &info_ptr, 0 );
		return FILE_ERROR_UNKNOWN_FORMAT;
	}
	/* 检测数据是否为PNG的签名 */
	temp = png_sig_cmp( (png_bytep)buf, (png_size_t)0, PNG_BYTES_TO_CHECK );
	/* 如果不是PNG的签名,则说明该文件不是PNG文件 */
	if( temp != 0 ) {
		fclose( fp );
		png_destroy_read_struct( &png_ptr, &info_ptr, 0 );
		return FILE_ERROR_UNKNOWN_FORMAT;
	}
	/* 复位文件指针 */
	rewind( fp );
	/* 开始读文件 */
	png_init_io( png_ptr, fp );
	/* 读取PNG图片信息 */
	png_read_png( png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0 );
	/* 获取图像的色彩类型 */
	color_type = png_get_color_type( png_ptr, info_ptr );
	/* 获取图像的宽高 */
	w = png_get_image_width( png_ptr, info_ptr );
	h = png_get_image_height( png_ptr, info_ptr );
	/* 获取所有行像素数据,row_pointers里边就是rgba数据 */
	row_pointers = png_get_rows( png_ptr, info_ptr );
	/* 根据不同的色彩类型进行相应处理 */
	switch( color_type ) {
	case PNG_COLOR_TYPE_RGB_ALPHA:
		graph->color_type = COLOR_TYPE_ARGB;
		temp = Graph_Create( graph, w, h );
		if( temp != 0 ) {
			ret = FILE_ERROR_MALLOC_ERROR;
			break;
		}
		pixel_ptr = graph->bytes;
		for( y = 0; y < h; ++y ) {
			/*
			 * Graph的像素数据存储格式是BGRA,而PNG库
			 * 提供像素数据的是RGBA格式的,因此需要调整写入顺序
			 */
			for( x = 0; x < w * 4; x += 4 ) {
				*pixel_ptr++ = row_pointers[y][x + 2];
				*pixel_ptr++ = row_pointers[y][x + 1];
				*pixel_ptr++ = row_pointers[y][x];
				*pixel_ptr++ = row_pointers[y][x + 3];
			}
		}
		break;

	case PNG_COLOR_TYPE_RGB:
		graph->color_type = COLOR_TYPE_RGB;
		temp = Graph_Create( graph, w, h );
		if( temp != 0 ) {
			ret = FILE_ERROR_MALLOC_ERROR;
			break;
		}
		pixel_ptr = graph->bytes;
		for( y = 0; y < h; ++y ) {
			for( x = 0; x < w * 3; x += 3 ) {
				*pixel_ptr++ = row_pointers[y][x + 2];
				*pixel_ptr++ = row_pointers[y][x + 1];
				*pixel_ptr++ = row_pointers[y][x];
			}
		}
		break;
		/* 其它色彩类型的图像就读了 */
	default: ret = FILE_ERROR_UNKNOWN_FORMAT; break;
	}
	fclose( fp );
	png_destroy_read_struct( &png_ptr, &info_ptr, 0 );
#else
	_DEBUG_MSG( "warning: not PNG support!" );
#endif
	return ret;
}
예제 #24
0
/*
 * Loads a PNG image
 *
 * @param [in]  real_filename  name of the png file to load
 * @param [out] image_data     allocated storage for the bitmap
 * @param [in]  bpp
 * @param [in]  dest_size
 * @param [in]  cf_type
 *
 * @retval true if succesful, false otherwise
 */
int png_read_bitmap(const char *real_filename, ubyte *image_data, int *bpp, int dest_size, int cf_type)
{
	char filename[MAX_FILENAME_LEN];
	png_infop info_ptr;
	png_structp png_ptr;
	png_bytepp row_pointers;
	unsigned int i;

	png_read_status status;
	status.reading_header = false;
	status.filename = real_filename;

	strcpy_s( filename, real_filename );
	char *p = strchr( filename, '.' );
	if ( p ) *p = 0;
	strcat_s( filename, ".png" );

	status.cfp = cfopen(filename, "rb", CFILE_NORMAL, cf_type);

	if (status.cfp == NULL)
		return PNG_ERROR_READING;

	/* 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_2(PNG_LIBPNG_VER_STRING, &status, png_error_fn, png_warning_fn, NULL, NULL, NULL);

	if (png_ptr == NULL)
	{
		mprintf(("png_read_bitmap: png_ptr went wrong\n"));
		cfclose(status.cfp);
		return PNG_ERROR_READING;
	}

	/* Allocate/initialize the memory for image information.  REQUIRED. */
	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL)
	{
		mprintf(("png_read_bitmap: info_ptr went wrong\n"));
		cfclose(status.cfp);
		png_destroy_read_struct(&png_ptr, NULL, NULL);
		return PNG_ERROR_READING;
	}

	if (setjmp(png_jmpbuf(png_ptr)))
	{
		mprintf(("png_read_bitmap: something went wrong\n"));
		/* Free all of the memory associated with the png_ptr and info_ptr */
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		cfclose(status.cfp);
		/* If we get here, we had a problem reading the file */
		return PNG_ERROR_READING;
	}

	png_set_read_fn(png_ptr, &status, png_scp_read_data);

	png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_BGR | PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_STRIP_16, NULL);
	auto len = png_get_rowbytes(png_ptr, info_ptr);

	row_pointers = png_get_rows(png_ptr, info_ptr);

	if(bpp)
		*bpp = (ubyte)(len / png_get_image_width(png_ptr, info_ptr)) << 3;

	//copy row data to image
	unsigned int height = png_get_image_height(png_ptr, info_ptr);
	for (i = 0; i < height; i++) {
		memcpy(&image_data[i * len], row_pointers[i], len);
	}

	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
	cfclose(status.cfp);

	return PNG_ERROR_NONE;
}
예제 #25
0
short load_inp_png_file(ImageData& img, const std::string& fname_inp, ProgramOptions& opts)
{
    FILE* pngfile = fopen(fname_inp.c_str(),"rb");
    if (pngfile == NULL) {
        perror(fname_inp.c_str());
        return ERR_CANT_OPEN;
    }
    png_byte header[8];
    if (fread(header,8,1,pngfile) != 1) {
        perror(fname_inp.c_str());
        fclose(pngfile);
        return ERR_FILE_READ;
    }
    if (png_sig_cmp(header,0,8)) {
        LogErr("%s: Not a PNG file",fname_inp.c_str());
        fclose(pngfile);
        return ERR_BAD_FILE;
    }

    img.png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!img.png_ptr)
    {
        LogErr("%s: png_create_read_struct error",fname_inp.c_str());
        fclose(pngfile);
        return ERR_BAD_FILE;
    }

    img.info_ptr=png_create_info_struct(img.png_ptr);
    if (!img.info_ptr)
    {
        png_destroy_read_struct(&img.png_ptr, (png_infopp)NULL, (png_infopp)NULL);
        LogErr("%s: png_create_info_struct error",fname_inp.c_str());
        fclose(pngfile);
        return ERR_BAD_FILE;
    }

    img.end_info=png_create_info_struct(img.png_ptr);
    if (!img.end_info)
    {
        png_destroy_read_struct(&img.png_ptr, &img.info_ptr, (png_infopp)NULL);
        LogErr("%s: png_create_info_struct error",fname_inp.c_str());
        fclose(pngfile);
        return ERR_BAD_FILE;
    }

    if (setjmp(png_jmpbuf(img.png_ptr)))
    {
        png_destroy_read_struct(&img.png_ptr, &img.info_ptr, &img.end_info);
        LogErr("%s: PNG error",fname_inp.c_str());
        fclose(pngfile);
        exit(1);
    }

    png_init_io(img.png_ptr, pngfile);
    png_set_sig_bytes(img.png_ptr,8);
    int trafo=PNG_TRANSFORM_PACKING|PNG_TRANSFORM_STRIP_16|PNG_TRANSFORM_EXPAND;
    png_read_png(img.png_ptr, img.info_ptr, trafo , NULL);

    int bit_depth, interlace_type, compression_type, filter_method;
    png_get_IHDR(img.png_ptr, img.info_ptr, &img.width, &img.height, &bit_depth, &img.color_type,
        &interlace_type, &compression_type, &filter_method);

    if ((img.color_type & PNG_COLOR_MASK_COLOR)==0)
    {
        LogErr("%s: Grayscale image not supported",fname_inp.c_str());
        fclose(pngfile);
        return ERR_BAD_FILE;
    }

    fclose(pngfile);

    if (img.color_type==PNG_COLOR_TYPE_PALETTE)
    {
        LogErr("Invalid format. This shouldn't happen. PNG_TRANSFORM_EXPAND transforms image to RGB.");
        return ERR_BAD_FILE;
    }

    if (img.color_type & PNG_COLOR_MASK_ALPHA) {
        img.col_bits = 32;
    } else {
        img.col_bits = 24;
    }

    return ERR_OK;
}
예제 #26
0
bool read_png(char *name, int row_align, int *outStride, int *outWidth, int *outHeight, uint32_t **outData) 
{
    png_structp png_ptr;
    png_infop info_ptr;
    unsigned int sig_read = 0;
    int color_type, interlace_type;
    FILE *fp;
    
    if ((fp = fopen(name, "rb")) == NULL)
        return false;
    
    /* Create and initialize the png_struct
     * with the desired error handler
     * functions.  If you want to use the
     * default stderr and longjump method,
     * you can supply NULL for the last
     * three parameters.  We also 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,
                                     NULL, NULL, NULL);
    
    if (png_ptr == NULL) {
        fclose(fp);
        return false;
    }
    
    /* 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 false;
    }
    
    /* 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 false;
    }
    
    /* Set up the output control if
     * you are using standard C streams */
    png_init_io(png_ptr, fp);
    
    /* If we have already
     * read some of the signature */
    png_set_sig_bytes(png_ptr, sig_read);
    
    /*
     * If you have enough memory to read
     * in the entire image at once, and
     * you need to specify only
     * transforms that can be controlled
     * with one of the PNG_TRANSFORM_*
     * bits (this presently excludes
     * dithering, filling, setting
     * background, and doing gamma
     * adjustment), then you can read the
     * entire image (including pixels)
     * into the info structure with this
     * call
     *
     * PNG_TRANSFORM_STRIP_16 |
     * PNG_TRANSFORM_PACKING  forces 8 bit
     * PNG_TRANSFORM_EXPAND forces to
     *  expand a palette into RGB
     */
    png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, NULL);
    
    png_uint_32 width, height, stride;
    int bit_depth;
    png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
                 &interlace_type, NULL, NULL);
    
    unsigned int channels = png_get_channels(png_ptr, info_ptr);
    uint32_t *data = NULL;
    
    png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr);

    stride = (width * 4 + row_align - 1) & ~(row_align-1);
    data = malloc(stride * height);
  
    switch(channels)
    {
    case 3: /* Convert bytewise RGB to A8R8G8B8 */
        for (int i = 0; i < height; i++) 
        {
            for(int j = 0; j < width; j++) 
            {
                data[(stride/4) * i + j] = 
                    0xff000000 |
                    (row_pointers[i][j*3 + 0] << 16) |
                    (row_pointers[i][j*3 + 1] << 8) |
                    (row_pointers[i][j*3 + 2]);
            }
        }
        break;
    case 4: /* Convert bytewise RGBA to A8R8G8B8 */
        for (int i = 0; i < height; i++) 
        {
            for(int j = 0; j < width; j++) 
            {
                data[(stride/4) * i + j] = 
                    (row_pointers[i][j*3 + 3] << 24) |
                    (row_pointers[i][j*3 + 0] << 16) |
                    (row_pointers[i][j*3 + 1] << 8) |
                    (row_pointers[i][j*3 + 2]);
            }
        }
        break;
    default: /* Invalid number of channels */
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        free(data);
        return false;
    }
    
    /* Clean up after the read,
     * and free any memory allocated */
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    
    /* Close the file */
    fclose(fp);
    
    /* That's it */
    *outWidth = width;
    *outHeight = height;
    *outStride = stride;
    *outData = data;
    return true;
}
예제 #27
0
bool LoadPng(const char *name, int &iWidth, int &iHeight, bool &hasAlpha, GLubyte **outData)
{
  FILE *fp = NULL;
  fp = fopen(name, "rb");
  if (fp == NULL)
  {
    return false;
  }

  png_structp png_ptr;
  png_infop info_ptr;
  unsigned int sig_read = 0;
  int color_type, interlace_type;
  
  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

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

  info_ptr = png_create_info_struct(png_ptr);
  if (info_ptr == NULL)
  {
    fclose(fp);
    png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
    return false;
  }

  if (setjmp(png_jmpbuf(png_ptr)))
  {
    png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
    fclose(fp);
    return false;
  }

  png_init_io(png_ptr, fp);

  png_set_sig_bytes(png_ptr, sig_read);

  png_read_png(png_ptr, info_ptr, /*PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING |*/ PNG_TRANSFORM_EXPAND, png_voidp_NULL);

  iWidth = info_ptr->width;
  iHeight = info_ptr->height;
  switch (info_ptr->color_type)
  {
  case PNG_COLOR_TYPE_RGBA:
    hasAlpha = true;
  	break;
  case PNG_COLOR_TYPE_RGB:
    hasAlpha = false;
    break;
  default:
    printf("color type %d is not supported \n ", info_ptr->color_type);
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    fclose(fp);
    return false;
  }

  unsigned int row_bytes = png_get_rowbytes(png_ptr, info_ptr);
  
  *outData = (unsigned char*)malloc(row_bytes * iHeight);

  png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr);

  for (int i = 0; i < iHeight; ++i)
  {
    memcpy(*outData + (row_bytes * (iHeight - 1- i)), row_pointers[i], row_bytes);
  }

  png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);

  fclose(fp);
  return true;
}
예제 #28
0
파일: pngio.cpp 프로젝트: samcrow/PPL
void PngIO::read(IMAGEDATA& image, GLuint& type, const std::string& path) {
    
    FILE* file = std::fopen(path.c_str(), "rb");
    
    if(file == 0) {
        throw std::runtime_error("Failed to open image file "+path);
    }
    
    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
                                                 NULL, NULL, NULL);
    
    if(png_ptr == 0) {
        fclose(file);
        throw std::runtime_error("Failed to create PNG data structure");
    }
    
    png_infop info_ptr = png_create_info_struct(png_ptr);
    
    if(info_ptr == 0) {
        fclose(file);
        png_destroy_read_struct(&png_ptr, NULL, NULL);
        throw std::runtime_error("Failed to create PNG info data structure");
    }
    
    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        fclose(file);
        /* If we get here, we had a
             * problem reading the file */
        throw std::runtime_error("Problem reading image file "+path);
    }
    
    png_init_io(png_ptr, file);
    
    unsigned int sig_read = 0;
    png_set_sig_bytes(png_ptr, sig_read);
    
    // Read
    png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, NULL);
    
    png_uint_32 width, height;
    int color_type, interlace_type;
    int bit_depth;
    png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
                 &interlace_type, NULL, NULL);
    
    // Set image parameters
    image.Width = width;
    image.Height = height;
    image.bpp = bit_depth;
    
    // Process color type
    switch(color_type) {
    
    case PNG_COLOR_TYPE_RGB:
        type = GL_RGB;
        break;
        
    case PNG_COLOR_TYPE_RGB_ALPHA:
        type = GL_RGBA;
        break;
        
    default:
        // Not supported
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        fclose(file);
        throw std::runtime_error("Unsupported PNG image format: Not RGB or RGB+alpha in file "+path);
    }
    
    
    unsigned int row_bytes = png_get_rowbytes(png_ptr, info_ptr);
    image.pData.reserve(row_bytes * image.Height);
    unsigned char* dataPtr1 = & image.pData[0];
    unsigned char** outData = & dataPtr1;
 
    png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr);
 
    for (int i = 0; i < image.Height; i++) {
        // note that png is ordered top to
        // bottom, but OpenGL expect it bottom to top
        // so the order or swapped
        memcpy(*outData+(row_bytes * (image.Height-1-i)), row_pointers[i], row_bytes);
    }
 
    /* Clean up after the read,
     * and free any memory allocated */
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
 
    /* Close the file */
    fclose(file);
 
    
}
예제 #29
0
RawImage* ImageFactory::loadPNG(const char *filename)
{		
	int outWidth, outHeight;
	bool outHasAlpha;
    png_structp png_ptr;
    png_infop info_ptr;
    unsigned int sig_read = 0;
    int color_type, interlace_type;
    FILE* fp = fopen(filename, "rb");
		
    if (fp == NULL)
        return NULL;

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

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

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

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

    /* Set up the output control if
     * you are using standard C streams */
    png_init_io(png_ptr, fp);

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

    /*
     * If you have enough memory to read
     * in the entire image at once, and
     * you need to specify only
     * transforms that can be controlled
     * with one of the PNG_TRANSFORM_*
     * bits (this presently excludes
     * dithering, filling, setting
     * background, and doing gamma
     * adjustment), then you can read the
     * entire image (including pixels)
     * into the info structure with this
     * call
     *
     * PNG_TRANSFORM_STRIP_16 |
     * PNG_TRANSFORM_PACKING  forces 8 bit
     * PNG_TRANSFORM_EXPAND forces to
     *  expand a palette into RGB
     */
    png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, NULL);
	png_uint_32 width, height;
	int bit_depth;
	png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL);

    outWidth = width;
    outHeight = height;
    switch (color_type) {
        case PNG_COLOR_TYPE_RGBA:
            outHasAlpha = true;
            break;
        case PNG_COLOR_TYPE_RGB:
            outHasAlpha = false;
            break;
        default:
            printf("Color type %d not supported.", color_type);
            png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
            fclose(fp);
            return NULL;
    }
    unsigned int row_bytes = png_get_rowbytes(png_ptr, info_ptr);
    //*outData = (unsigned char*) malloc(row_bytes * outHeight);
	GLubyte *outData = (unsigned char*) malloc(row_bytes * outHeight);

    png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr);

    for (int i = 0; i < outHeight; i++) {
        // note that png is ordered top to
        // bottom, but OpenGL expect it bottom to top
        // so the order or swapped
        memcpy(outData+(row_bytes * (outHeight-1-i)), row_pointers[i], row_bytes);
    }

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

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

	
    /* That's it */
    return new RawImage(outWidth, outHeight, outHasAlpha, outData);
}
예제 #30
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);
#if (CC_TARGET_PLATFORM != CC_PLATFORM_BADA)
        CC_BREAK_IF(setjmp(png_jmpbuf(png_ptr)));
#endif
        // 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;
}