示例#1
0
static void
read_png(struct display *dp, struct buffer *bp, const char *operation,
   int transforms)
{
   png_structp pp;
   png_infop   ip;

   /* This cleans out any previous read and sets operation and transforms to
    * empty.
    */
   display_clean_read(dp);

   if (operation != NULL) /* else this is a verify and do not overwrite info */
   {
      dp->operation = operation;
      dp->transforms = transforms;
   }

   dp->read_pp = pp = png_create_read_struct(PNG_LIBPNG_VER_STRING, dp,
      display_error, display_warning);
   if (pp == NULL)
      display_log(dp, LIBPNG_ERROR, "failed to create read struct");

   /* The png_read_png API requires us to make the info struct, but it does the
    * call to png_read_info.
    */
   dp->read_ip = ip = png_create_info_struct(pp);
   if (ip == NULL)
      display_log(dp, LIBPNG_ERROR, "failed to create info struct");

#  ifdef PNG_SET_USER_LIMITS_SUPPORTED
      /* Remove the user limits, if any */
      png_set_user_limits(pp, 0x7fffffff, 0x7fffffff);
#  endif

   /* Set the IO handling */
   buffer_start_read(bp);
   png_set_read_fn(pp, bp, read_function);

   png_read_png(pp, ip, transforms, NULL/*params*/);

#if 0 /* crazy debugging */
   {
      png_bytep pr = png_get_rows(pp, ip)[0];
      size_t rb = png_get_rowbytes(pp, ip);
      size_t cb;
      char c = ' ';

      fprintf(stderr, "%.4x %2d (%3lu bytes):", transforms, png_get_bit_depth(pp,ip), (unsigned long)rb);

      for (cb=0; cb<rb; ++cb)
         fputc(c, stderr), fprintf(stderr, "%.2x", pr[cb]), c='.';

      fputc('\n', stderr);
   }
#endif
}
示例#2
0
int savePNG(const char * fileName,uint32_t width,uint32_t height,void * ptr,uint8_t*pal,unsigned pn){
	//saves a 24bit png with rgb byte order
	png_byte * dat=(png_byte*)ptr;//convert to uint8_t
	FILE * fp=fopen(fileName,"wb");
	if (!fp)
		return 1;
	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)0,0,0);
	if (!png_ptr){
		fclose(fp);
		return 1;
	}
	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr){
		png_destroy_write_struct(&png_ptr,(png_infopp)NULL);
		return 1;
	}
	if (setjmp(png_jmpbuf(png_ptr))){
		png_destroy_write_struct(&png_ptr, &info_ptr);
		fclose(fp);
		return 1;
	}
	png_init_io(png_ptr, fp);
	png_set_IHDR(png_ptr, info_ptr, width, height,8,pal?PNG_COLOR_TYPE_PALETTE:PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);//must be called before other png_set_*() functions
	png_color_struct*palTmp=0;
	if(pal){
		palTmp=(png_color_struct*)malloc(pn*sizeof(png_color_struct));
		for(unsigned i=0;i<pn;++i){
			palTmp[i].red=pal[i*3];
			palTmp[i].green=pal[i*3+1];
			palTmp[i].blue=pal[i*3+2];
		}
		png_set_PLTE(png_ptr,info_ptr,palTmp,pn);
	}
	png_set_compression_level(png_ptr,Z_BEST_COMPRESSION);
	uint32_t y;
	png_set_user_limits(png_ptr, width, height);
	png_write_info(png_ptr, info_ptr);
	for (y=0;y<height;++y)
		png_write_row(png_ptr, &dat[(y*width*(pal?1:3))]);
	png_write_end(png_ptr, info_ptr);
	png_destroy_write_struct(&png_ptr, &info_ptr);
	fclose(fp);//done with file
	free(palTmp);
	return 0;//will return 0 on success non-zero in error
}
示例#3
0
/*
=================
image_png_load
=================
*/
GNUC_NONNULL static erbool image_png_load (const char *name, image_t *im)
{
    fs_file_t   f;
    int         size, r, width, height, inc;
    png_byte   *image = NULL, *p = NULL;
    png_structp pngst;
    png_infop   info = NULL;
    png_byte    depth, color_type;

    if (NULL == (f = fs_open(name, FS_RDONLY, &size, false)))
        return false;

    if (NULL == (pngst = png_create_read_struct(PNG_LIBPNG_VER_STRING,
                                                NULL,
                                                &epng_error,
                                                &epng_warn)))
    {
        sys_printf("failed to create png read struct\n");
        fs_close(f);
        return false;
    }

    if (NULL == (info = png_create_info_struct(pngst)))
    {
        sys_printf("failed to create png info struct\n");
        goto error;
    }

    if (setjmp(png_jmpbuf(pngst)))
        goto error;

    png_set_user_limits(pngst, IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT);
    png_set_read_fn(pngst, f, &epng_read);
    png_read_info(pngst, info);

    width  = png_get_image_width(pngst, info);
    height = png_get_image_height(pngst, info);
    depth  = png_get_bit_depth(pngst, info);

    if (16 == depth)
    {
        /* 16 -> 8 */
        png_set_strip_16(pngst);
        depth = 8;
    }

    color_type = png_get_color_type(pngst, info);

    /* 1/2/4 gray -> 8 gray */
    if (PNG_COLOR_TYPE_GRAY == color_type && depth < 8)
        png_set_expand_gray_1_2_4_to_8(pngst);

    /* gray/palette -> rgb */
    if (PNG_COLOR_TYPE_GRAY == color_type || PNG_COLOR_TYPE_GRAY_ALPHA == color_type)
        png_set_gray_to_rgb(pngst);
    else if (PNG_COLOR_TYPE_PALETTE)
        png_set_palette_to_rgb(pngst);

    /* transparency -> alpha */
    if (png_get_valid(pngst, info, PNG_INFO_tRNS))
    {
        png_set_tRNS_to_alpha(pngst);
    }
    else
    {
        /* to rgba */
        if (PNG_COLOR_TYPE_RGB_ALPHA != color_type &&
            PNG_COLOR_TYPE_GRAY_ALPHA != color_type)
            png_set_add_alpha(pngst, 0xff, PNG_FILLER_AFTER);
    }

    /* deinterlace */
    png_set_interlace_handling(pngst);

    /* read */
    inc = width * 4;

    p = image = mem_alloc(image_mempool, height * inc);

    for (r = 0; r < height ;r++, p += inc)
        png_read_row(pngst, p, NULL);

    png_read_end(pngst, NULL);
    png_destroy_read_struct(&pngst, &info, NULL);

    fs_close(f);

    im->width  = width;
    im->height = height;
    im->data   = image;

    return true;

error:
    if (NULL != f)
        fs_close(f);

    png_destroy_read_struct(&pngst, NULL != info ? &info : NULL, NULL);

    if (NULL != image)
        mem_free(image);

    return false;
}
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);
}
示例#5
0
int filter_png(struct media_info const *info, int out_fd, int in_fd)
{
	FILE			*fp = fdopen(out_fd, "wb");
	struct png_struct_def	*png_ptr = NULL;
	struct png_info_def	*png_info = NULL;
	volatile int		rc = EX_SOFTWARE;
	png_bytep		row_pointers[info->height];
	void * volatile		raw_data = NULL;
	void * volatile		rgb_data = NULL;
	size_t			rgb_stride =
		info->width * ((info->bpp + 7) / 8) * 3;

	if (!fp) {
		perror("fdopen()");
		return EX_OSERR;
	}

	png_ptr =  png_create_write_struct(PNG_LIBPNG_VER_STRING,
					   NULL, NULL, NULL);
	if (!png_ptr)
		goto out;

	if (setjmp(png_jmpbuf(png_ptr)))
		goto out;

	/* allocate memory for raw (YCbCr) image data */
	raw_data = png_malloc(png_ptr, info->stride * info->height);
	if (!raw_data)
		goto out;

	rgb_data = png_malloc(png_ptr, rgb_stride * info->height);
	if (!rgb_data)
		goto out;

	for (size_t y = 0; y < info->height; ++y)
		row_pointers[y] = rgb_data + y * rgb_stride;

	png_info = png_create_info_struct(png_ptr);
	if (!png_info)
		goto out;

	png_init_io(png_ptr, fp);
	png_set_user_limits(png_ptr, info->width, info->height);
	png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);

	/* atm, only 8bpp support is implemented */
	assert(info->bpp == 8);

	for (;;) {
		bool	eof = false;

		if (read_all(in_fd, raw_data, info->stride * info->height, &eof))
			;		/* noop */
		else if (!eof)
			goto out;
		else
			break;

		convert_yuv422_rgb888(rgb_data, raw_data, info->bpp,
				      info->width, info->height);

		png_set_rows(png_ptr, png_info, row_pointers);

		png_set_IHDR(png_ptr, png_info, info->width, info->height,
			     info->bpp, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
			     PNG_COMPRESSION_TYPE_DEFAULT,
			     PNG_FILTER_TYPE_DEFAULT);
		png_write_png(png_ptr, png_info, PNG_TRANSFORM_IDENTITY, NULL);
		fflush(fp);
		break;
	}

	rc = 0;

out:
	png_free(png_ptr, rgb_data);
	png_free(png_ptr, raw_data);
	png_destroy_write_struct(&png_ptr, &png_info);
	fclose(fp);

	return rc;
}
示例#6
0
HBITMAP PngByteToBmpHandle(VBuf *vbuf)
{
	png_struct	*png  = NULL;
	png_info	*info = NULL;
	HBITMAP		hBmp  = NULL;
	BITMAPINFO	*bmi  = NULL;
	png_byte	**row = NULL;
	BYTE		*data = NULL;
	HWND		hWnd = ::GetDesktopWindow();
	HDC			hDc   = NULL;
	int			line_size, aligned_line_size, header_size;
	VBuf		bmpVbuf;

	if (vbuf->Size() < PNG_SIG_SIZE || !png_check_sig(vbuf->Buf(), PNG_SIG_SIZE)) return NULL;

	if (!(png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0))) return NULL;
	if (!(info = png_create_info_struct(png))) goto END;

	if (setjmp(png_jmpbuf(png))) goto END;

	png_set_user_limits(png, 15000, 10000); // 15,000 * 10,000 pix
	png_set_read_fn(png, (void *)vbuf, (png_rw_ptr)png_vbuf_rfunc);
	png_read_png(png, info, PNG_TRANSFORM_BGR, NULL);

	if (info->bit_depth > 8) goto END; // not support

	line_size = info->width * info->channels * ALIGN_SIZE(info->bit_depth, 8) / 8;
	aligned_line_size = ALIGN_SIZE(line_size, 4);
	header_size = sizeof(BITMAPV5HEADER) + sizeof(RGBQUAD) * info->num_palette;

	if (!bmpVbuf.AllocBuf(header_size + aligned_line_size * info->height)) goto END;
	bmi = (BITMAPINFO *)bmpVbuf.Buf();

	bmi->bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);
	bmi->bmiHeader.biSizeImage   = aligned_line_size * info->height;
	bmi->bmiHeader.biWidth       = info->width;
	bmi->bmiHeader.biHeight      = -(int)info->height;
	bmi->bmiHeader.biPlanes      = 1;
	bmi->bmiHeader.biCompression = BI_RGB;

	if (info->color_type == PNG_COLOR_TYPE_PALETTE) {
		bmi->bmiHeader.biBitCount = info->bit_depth;
		bmi->bmiHeader.biClrUsed = info->num_palette;
		for (int i=0; i < info->num_palette; i++) {
			bmi->bmiColors[i].rgbRed	= info->palette[i].red;
			bmi->bmiColors[i].rgbGreen	= info->palette[i].green;
			bmi->bmiColors[i].rgbBlue	= info->palette[i].blue;
		}
	}
	else  {
		bmi->bmiHeader.biBitCount = info->bit_depth * info->channels;
		if (info->channels == 4) {
			bmi->bmiHeader.biSize	= sizeof(BITMAPV5HEADER);
			BITMAPV5HEADER *bm5		= (BITMAPV5HEADER*)bmi;
			bm5->bV5Compression		= BI_BITFIELDS;
			bm5->bV5RedMask			= 0x00FF0000;
			bm5->bV5GreenMask		= 0x0000FF00;
			bm5->bV5BlueMask		= 0x000000FF;
			bm5->bV5AlphaMask		= 0xFF000000;
		}
	}

	if (!(row = png_get_rows(png, info))) goto END;

	data = bmpVbuf.Buf() + header_size;
	u_int i;
	for (i=0; i < info->height; i++) {
		memcpy(data + aligned_line_size * i, row[i], line_size);
	}

	if (!(hDc = ::GetDC(hWnd))) goto END;
	hBmp = ::CreateDIBitmap(hDc, (BITMAPINFOHEADER *)bmi, CBM_INIT, data, bmi, DIB_RGB_COLORS);
	if (hDc) ::ReleaseDC(hWnd, hDc);

END:
	png_destroy_read_struct(&png, &info, 0);
	return	hBmp;
}
示例#7
0
static GrTextureFormat_t PNG_Load(const char *filename, int *w, int *h, GLPatch_t *grpatch)
{
	png_structp png_ptr;
	png_infop png_info_ptr;
	png_uint_32 width, height;
	int bit_depth, color_type;
#ifdef PNG_SETJMP_SUPPORTED
#ifdef USE_FAR_KEYWORD
	jmp_buf jmpbuf;
#endif
#endif
	png_FILE_p png_FILE;
	char *pngfilename = va("md2/%s", filename);

	FIL_ForceExtension(pngfilename, ".png");
	png_FILE = fopen(pngfilename, "rb");
	if (!png_FILE)
	{
		//CONS_Debug(DBG_RENDER, "M_SavePNG: Error on opening %s for loading\n", filename);
		return 0;
	}

	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
		PNG_error, PNG_warn);
	if (!png_ptr)
	{
		CONS_Debug(DBG_RENDER, "PNG_Load: Error on initialize libpng\n");
		fclose(png_FILE);
		return 0;
	}

	png_info_ptr = png_create_info_struct(png_ptr);
	if (!png_info_ptr)
	{
		CONS_Debug(DBG_RENDER, "PNG_Load: Error on allocate for libpng\n");
		png_destroy_read_struct(&png_ptr, NULL, NULL);
		fclose(png_FILE);
		return 0;
	}

#ifdef USE_FAR_KEYWORD
	if (setjmp(jmpbuf))
#else
	if (setjmp(png_jmpbuf(png_ptr)))
#endif
	{
		//CONS_Debug(DBG_RENDER, "libpng load error on %s\n", filename);
		png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL);
		fclose(png_FILE);
		Z_Free(grpatch->mipmap.grInfo.data);
		return 0;
	}
#ifdef USE_FAR_KEYWORD
	png_memcpy(png_jmpbuf(png_ptr), jmpbuf, sizeof jmp_buf);
#endif

	png_init_io(png_ptr, png_FILE);

#ifdef PNG_SET_USER_LIMITS_SUPPORTED
	png_set_user_limits(png_ptr, 2048, 2048);
#endif

	png_read_info(png_ptr, png_info_ptr);

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

	if (bit_depth == 16)
		png_set_strip_16(png_ptr);

	if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
		png_set_gray_to_rgb(png_ptr);
	else if (color_type == PNG_COLOR_TYPE_PALETTE)
		png_set_palette_to_rgb(png_ptr);

	if (png_get_valid(png_ptr, png_info_ptr, PNG_INFO_tRNS))
		png_set_tRNS_to_alpha(png_ptr);
	else if (color_type != PNG_COLOR_TYPE_RGB_ALPHA && color_type != PNG_COLOR_TYPE_GRAY_ALPHA)
	{
#if PNG_LIBPNG_VER < 10207
		png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER);
#else
		png_set_add_alpha(png_ptr, 0xFF, PNG_FILLER_AFTER);
#endif
	}

	png_read_update_info(png_ptr, png_info_ptr);

	{
		png_uint_32 i, pitch = png_get_rowbytes(png_ptr, png_info_ptr);
		png_bytep PNG_image = Z_Malloc(pitch*height, PU_HWRCACHE, &grpatch->mipmap.grInfo.data);
		png_bytepp row_pointers = png_malloc(png_ptr, height * sizeof (png_bytep));
		for (i = 0; i < height; i++)
			row_pointers[i] = PNG_image + i*pitch;
		png_read_image(png_ptr, row_pointers);
		png_free(png_ptr, (png_voidp)row_pointers);
	}

	png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL);

	fclose(png_FILE);
	*w = (int)width;
	*h = (int)height;
	return GR_RGBA;
}