修改
我现在正在使用Brett的代码来加载png,并且在渲染到opengl中的纹理(作为软件光标)时工作正常但是每次我作为GLFWcursor加载时我都会得到一个扭曲的图像(不同的并且有一个问题,GLFWcursor只会使用最后加载的GLFWimage。我输入的像素不是我得到的像素。
修改
GLFWimage CursorManager::LoadImageFromFile(string filename)
{
FILE* file = fopen(filename.c_str(), "rb");
if (!file) {
//return NULL;
}
unsigned int width = 0;
unsigned int height = 0;
unsigned char* buffer = NULL;
int error = png_rgba_load(file
,&width
,&height
,&buffer);
if(error == 0)
{
GLFWimage image;
int w = 32; //32
int h = 32; //32
unsigned char pixels[w * h * 4];
memcpy(pixels, buffer, sizeof(pixels));
//for(int i=0;i<sizeof(pixels);i++)
// cout << pixels[i];
cout << "unsigned char pixels:" << endl;
for(int i=0;i<sizeof(pixels);i++)
cout << hex((int)pixels[i]);
cout << endl << "image.pixels:" << endl;
image.width = w;
image.height = h;
image.pixels = pixels;
for(int i=0;i<sizeof(image.pixels);i++)
cout << hex((int)image.pixels[i]);
return image;
}
else
{
cout << "ERROR @ png_rgba_load" << endl;
//return NULL;
}
fclose(file);
//if (fclose(file) != 0) /* filesystem I/O error (?) */
// goto fail;
}
-
cout << "Loading GLimage " << m_sFileName_Arrow << endl;
m_oArrow = LoadImageFromFile(m_sFileName_Arrow);
cout << "Loading GLimage " << m_sFileName_Text << endl;
m_oText = LoadImageFromFile(m_sFileName_Text);
cout << "Loading GLimage " << m_sFileName_Crosshair << endl;
m_oCrosshair = LoadImageFromFile(m_sFileName_Crosshair);
cout << "Loading GLimage " << m_sFileName_Hand << endl;
m_oHand = LoadImageFromFile(m_sFileName_Hand);
cout << "Loading GLimage " << m_sFileName_Hresize << endl;
m_oHresize = LoadImageFromFile(m_sFileName_Hresize);
cout << "Loading GLimage " << m_sFileName_Vresize << endl;
m_oVresize = LoadImageFromFile(m_sFileName_Vresize);
-
cout << "Set cursor to Crosshair" << endl;
cur = glfwCreateCursor(&m_oCrosshair,0,0);
游标从从libpng加载的GLFWimage加载,但是(1)它每次都有不同的随机像素。 (2)此外,无论我设置为新光标的是什么图像,它始终显示最后加载的图像,在打印图像时为m_oVresize(3)。设置为像素后像素为十六进制与像素不匹配
unsigned char像素: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FFD97400FF272D70FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FFD97400FFD97400FFD97400FF272D70FF0000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FFD97400FFD97400FFD97400FFD97400FFD97400FF272D70FF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF272D70FF272D70FF272D70FF272D70FF272D70FF272D70FF272D70FF272D70FF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF00000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF00000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF00000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF272D70FF272D70FF 272D70FF272D70FF272D70FF272D70FF272D70FF272D70FF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FFD97400FFD97400FFD97400FFD97400FFD97400FF272D70FF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FFD97400FFD97400FFD97400FF272D70FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FFD97400FF272D70FF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000272D70FF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 image.pixels:0000000000000000
答案 0 :(得分:3)
这可能接近S.O.的过多代码转储,但它可能对其他人充满了有用的提示。尝试阅读PNG API和各种示例等是一种折磨。最后,这是我提供的(相对)简单的界面:
(至于'版权' - 只要你不管我,就做你想做的任何事情,等等。)
/*******************************************************************************
*
* png_rgba.h : PNG file I/O in (8) bits per channel RGBA format:
*
* Copyright (c) Brett Hale 2008, 2012. Public Domain.
*
*******************************************************************************/
#ifndef _PNG_RGBA_H
#define _PNG_RGBA_H
#if defined (__cplusplus) /* ISO C declaration scope: */
#define _PNG_RGBA_INIT_DECL extern "C" {
#define _PNG_RGBA_FINI_DECL }
#else
#define _PNG_RGBA_INIT_DECL
#define _PNG_RGBA_FINI_DECL
#endif /* defined (__cplusplus) */
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h> /* ISO C : standard I/O library. */
_PNG_RGBA_INIT_DECL
/******************************************************************************/
/* load a PNG image using an opened file stream. return the image data
* as a (malloc) allocated RGBA image buffer, with the width: (w), and
* height: (h). return (0) on success: */
/* if the operation fails, then the dimensions are set to (0), and the
* buffer is set to (NULL). */
/* the operation fails if the image has zero area, or if the number of
* pixels exceeds PNG_RGBA_PIXEL_LIMIT. */
/* asserts that 'unsigned int' has a width of at least 32 bits. */
#define PNG_RGBA_PIXEL_LIMIT (0x1000000)
int png_rgba_load (FILE *, unsigned *w, unsigned *h, unsigned char **);
/******************************************************************************/
/* save an RGBA image buffer, with the width: (w), and height: (h), as
* a PNG image, using an opened file stream. return (0) on success: */
/* the operation fails if the image has zero area, or if the number of
* pixels exceeds PNG_RGBA_PIXEL_LIMIT. */
/* asserts that 'unsigned int' has a width of at least 32 bits. */
int png_rgba_save (FILE *, unsigned w, unsigned h, const unsigned char *);
/******************************************************************************/
_PNG_RGBA_FINI_DECL
#endif /* _PNG_RGBA_H */
实施:
/*******************************************************************************
*
* png_rgba.c : PNG file I/O in (8) bits per channel RGBA format:
*
* Copyright (c) Brett Hale 2008, 2012. Public Domain.
*
*******************************************************************************/
#include "png_rgba.h"
#include <png.h> /* PNG library. */
#define PNG_SIG_BYTES (8) /* bytes in the PNG file signature. */
/******************************************************************************/
static int
png_rgba_pixel_limit (png_uint_32 w, png_uint_32 h)
{
double da;
/* assert(w != 0 && h != 0); */
if (w > PNG_RGBA_PIXEL_LIMIT || h > PNG_RGBA_PIXEL_LIMIT)
return (1); /* since both (w) and (h) are non-zero. */
/* since an IEEE-754 double has a 53 bit mantissa, it can
* represent the maximum area: (w * h == 2^48) exactly. */
da = ((double) w) * ((double) h);
if (da > ((double) PNG_RGBA_PIXEL_LIMIT))
return (1);
return (0); /* the PNG image is within the pixel limit. */
}
/******************************************************************************/
int png_rgba_load
(
FILE *fp, unsigned *w, unsigned *h, unsigned char **buf)
{
png_byte magic[PNG_SIG_BYTES]; /* (signature byte buffer) */
png_structp png_ctx;
png_infop info_ctx;
png_uint_32 img_width, img_height, row;
png_byte img_depth, img_color_type;
/* 'volatile' qualifier forces reload in setjmp cleanup: */
png_byte *volatile img_data = NULL;
png_bytep *volatile row_data = NULL;
*w = 0, *h = 0, *buf = NULL;
/* it is assumed that 'longjmp' can be invoked within this
* code to efficiently unwind resources for *all* errors. */
/* PNG structures and resource unwinding: */
if ((png_ctx = png_create_read_struct(
PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL)
return (1); /* ENOMEM (?) */
if ((info_ctx = png_create_info_struct(png_ctx)) == NULL)
{
png_destroy_read_struct(& png_ctx, NULL, NULL);
return (1); /* ENOMEM (?) */
}
if (setjmp(png_jmpbuf(png_ctx)) != 0)
{
png_destroy_read_struct(& png_ctx, & info_ctx, NULL);
free(img_data); free(row_data);
return (1); /* libpng feedback (?) */
}
/* check PNG file signature: */
if (fread(magic, (1), PNG_SIG_BYTES, fp) != PNG_SIG_BYTES)
png_error(png_ctx, "invalid PNG file");
if (png_sig_cmp(magic, 0, PNG_SIG_BYTES))
png_error(png_ctx, "invalid PNG file");
/* set the input file stream and get the PNG image info: */
png_init_io(png_ctx, fp);
png_set_sig_bytes(png_ctx, PNG_SIG_BYTES);
png_read_info(png_ctx, info_ctx);
img_width = png_get_image_width(png_ctx, info_ctx);
img_height = png_get_image_height(png_ctx, info_ctx);
#if (1) /* PNG doesn't support zero area image? */
if (img_width == 0 || img_height == 0)
png_error(png_ctx, "zero area PNG image");
#endif
if (png_rgba_pixel_limit(img_width, img_height))
png_error(png_ctx, "PNG image exceeds pixel limits");
img_depth = png_get_bit_depth(png_ctx, info_ctx);
img_color_type = png_get_color_type(png_ctx, info_ctx);
/* ignored image interlacing, compression and filtering. */
/* force 8-bit color channels: */
if (img_depth == 16)
png_set_strip_16(png_ctx);
else if (img_depth < 8)
png_set_packing(png_ctx);
/* force formats to RGB: */
if (img_color_type != PNG_COLOR_TYPE_RGBA)
png_set_expand(png_ctx);
if (img_color_type == PNG_COLOR_TYPE_PALETTE)
png_set_palette_to_rgb(png_ctx);
if (img_color_type == PNG_COLOR_TYPE_GRAY)
png_set_gray_to_rgb(png_ctx);
if (img_color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
png_set_gray_to_rgb(png_ctx);
/* add full opacity alpha channel if required: */
if (img_color_type != PNG_COLOR_TYPE_RGBA)
png_set_filler(png_ctx, 0xff, PNG_FILLER_AFTER);
/* apply the output transforms before reading image data: */
png_read_update_info(png_ctx, info_ctx);
/* allocate RGBA image data: */
img_data = (png_byte *)
malloc((size_t) (img_width * img_height * (4)));
if (img_data == NULL)
png_error(png_ctx, "error allocating image buffer");
/* allocate row pointers: */
row_data = (png_bytep *)
malloc((size_t) (img_height * sizeof(png_bytep)));
if (row_data == NULL)
png_error(png_ctx, "error allocating row pointers");
/* set the row pointers and read the RGBA image data: */
for (row = 0; row < img_height; row++)
row_data[row] = img_data +
(img_height - (row + 1)) * (img_width * (4));
png_read_image(png_ctx, row_data);
/* libpng and dynamic resource unwinding: */
png_read_end(png_ctx, NULL);
png_destroy_read_struct(& png_ctx, & info_ctx, NULL);
free(row_data);
*w = (unsigned) img_width, *h = (unsigned) img_height;
*buf = img_data; /* (asserts png_byte is an unsigned char) */
return (0);
}
/******************************************************************************/
int png_rgba_save
(
FILE *fp, unsigned w, unsigned h, const unsigned char *data)
{
png_structp png_ctx;
png_infop info_ctx;
png_uint_32 img_width, img_height, row;
img_width = (png_uint_32) w, img_height = (png_uint_32) h;
/* it is assumed that 'longjmp' can be invoked within this
* code to efficiently unwind resources for *all* errors. */
/* PNG structures and resource unwinding: */
if ((png_ctx = png_create_write_struct(
PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL)
return (1); /* ENOMEM (?) */
if ((info_ctx = png_create_info_struct(png_ctx)) == NULL)
{
png_destroy_write_struct(& png_ctx, NULL);
return (1); /* ENOMEM (?) */
}
if (setjmp(png_jmpbuf(png_ctx)) != 0)
{
png_destroy_write_struct(& png_ctx, & info_ctx);
return (1); /* libpng feedback (?) */
}
/* set the output file stream and set the PNG image HDR: */
png_init_io(png_ctx, fp);
if (png_rgba_pixel_limit(img_width, img_height))
png_error(png_ctx, "PNG image exceeds pixel limits");
png_set_IHDR(
png_ctx, info_ctx, img_width, img_height, (8),
PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
/* write the RGBA image data from the bottom to top row: */
png_write_info(png_ctx, info_ctx);
for (row = img_height; row != 0; row--)
{
png_bytep row_data = (png_bytep)
(data + (row - 1) * (img_width * (4)));
png_write_row(png_ctx, row_data); /* non-interlaced. */
}
/* libpng and dynamic resource unwinding: */
png_write_end(png_ctx, NULL);
png_destroy_write_struct(& png_ctx, & info_ctx);
return (0); /* (much easier when the data format is known) */
}
/******************************************************************************/
#if (0)
int main (int argc, char **argv)
{
/* test the ability to read any PNG file and save as RGBA: */
FILE *ifile = NULL, *ofile = NULL;
int load_error, save_error;
unsigned int img_width, img_height;
unsigned char *img_data = NULL;
if (argc < 3)
{
fprintf(stderr, "png_rgba <infile> <outfile>\n");
return (1);
}
if ((ifile = fopen(argv[1], "rb")) == NULL)
goto fail;
load_error = png_rgba_load(
ifile, & img_width, & img_height, & img_data);
if (fclose(ifile) != 0) /* filesystem I/O error (?) */
goto fail;
if (load_error)
{
fprintf(stderr, "could not load '%s'\n", argv[1]);
return (1);
}
if ((ofile = fopen(argv[2], "wb")) == NULL)
goto fail;
save_error = png_rgba_save(
ofile, img_width, img_height, img_data);
if (fclose(ofile) != 0) /* filesystem I/O error (?) */
goto fail;
if (save_error)
{
fprintf(stderr, "could not save '%s'\n", argv[2]);
return (1);
}
fprintf(stdout, "%u x %u image\n", img_width, img_height);
return (0);
fail:
perror("png_rgba"); /* prepend to the system error message. */
return (1);
}
#endif
/******************************************************************************/
malloc的大多数实现将至少产生8字节对齐 - 通常在x86 [-64]等平台上进行16字节对齐。对于OpenGL,因此可以安全地假设行是4字节(RGBA)对齐,在实践中。这是glPixelStore
的默认值 - 如果有疑问,请使用:
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
来电之前 glTexImage2D
。
答案 1 :(得分:1)
您还可以使用Soil获取PNG的像素数据。
我用它来设置一个窗口图标,但是根据cursor specification,这个方法也适用于那里。
GLFWimage icons[1];
icons[0].pixels = SOIL_load_image("icon.png", &icons[0].width, &icons[0].height, 0, SOIL_LOAD_RGBA);
glfwSetWindowIcon(window.window, 1, icons);
SOIL_free_image_data(icons[0].pixels);
答案 2 :(得分:0)
尝试在png_read_image()之前放置它:
png_set_expand(png_ptr); // expand to RGB or RGBA
png_set_add_alpha(png_ptr, filler, PNG_FILLER_AFTER);
//"filler" contains the alpha value to assign to each pixel.
即使您的图像已经是RGB或RGBA,也可以安全地执行此操作。 如果要编写每个样本8位的图像,请使用filler = 255 你希望像素不透明。
答案 3 :(得分:0)
如果将png图像加载到纹理中是唯一需要做的事情,我建议可以放弃libpng并使用stb_image代替。这是一个非常简单的使用,仅限标头的库,可以为您提供来自PNG的原始RGB数据。