//
// Load a texture from a png image
//
bool PngLoader::loadImageIntoBuffer() {
DEBUG_ENTER_FUNC();
if (!basicImageLoad()) {
png_destroy_read_struct(&_pngPtr, &_infoPtr, png_infopp_NULL);
return false;
}
png_set_strip_16(_pngPtr); // Strip off 16 bit channels in case they occur
if (_paletteSize) {
// Copy the palette
png_colorp srcPal = _infoPtr->palette;
for (int i = 0; i < _infoPtr->num_palette; i++) {
unsigned char alphaVal = (i < _infoPtr->num_trans) ? _infoPtr->trans[i] : 0xFF; // Load alpha if it's there
_palette->setSingleColorRGBA(i, srcPal->red, srcPal->green, srcPal->blue, alphaVal);
srcPal++;
}
} else { // Not a palettized image
if (_colorType == PNG_COLOR_TYPE_GRAY && _bitDepth < 8)
png_set_gray_1_2_4_to_8(_pngPtr); // Round up grayscale images
if (png_get_valid(_pngPtr, _infoPtr, PNG_INFO_tRNS))
png_set_tRNS_to_alpha(_pngPtr); // Convert trans channel to alpha for 32 bits
png_set_add_alpha(_pngPtr, 0xff, PNG_FILLER_AFTER); // Filler for alpha if none exists
}
uint32 rowBytes = png_get_rowbytes(_pngPtr, _infoPtr);
// there seems to be a bug in libpng where it doesn't increase the rowbytes or the
// channel even after we add the alpha channel
if (_channels == 3 && (rowBytes / _width) == 3) {
_channels = 4;
rowBytes = _width * _channels;
}
PSP_DEBUG_PRINT("rowBytes[%d], channels[%d]\n", rowBytes, _channels);
unsigned char *line = (unsigned char*) malloc(rowBytes);
if (!line) {
png_destroy_read_struct(&_pngPtr, png_infopp_NULL, png_infopp_NULL);
PSP_ERROR("Couldn't allocate line\n");
return false;
}
for (size_t y = 0; y < _height; y++) {
png_read_row(_pngPtr, line, png_bytep_NULL);
_buffer->copyFromRect(line, rowBytes, 0, y, _width, 1); // Copy into buffer
}
free(line);
png_read_end(_pngPtr, _infoPtr);
png_destroy_read_struct(&_pngPtr, &_infoPtr, png_infopp_NULL);
return true;
}
void PNGImage_load(PNGImage *self)
{
png_structp png_ptr;
png_infop info_ptr;
int bit_depth;
int color_type;
int interlace_type;
png_uint_32 w;
png_uint_32 h;
int palleteComponents = 3;
int number_passes, row;
FILE *fp = fopen(self->path, "rb");
PNGImage_error_(self, "");
if (!fp)
{
PNGImage_error_(self, "file not found");
return;
}
/* 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);
PNGImage_error_(self, "unable to read png from file");
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);
PNGImage_error_(self, "error allocating png struct");
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.
*/
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);
PNGImage_error_(self, self->path);
return;
}
/* Set up the input control if you are using standard C streams */
png_init_io(png_ptr, fp);
png_read_info(png_ptr, info_ptr);
png_get_IHDR(png_ptr, info_ptr, &w, &h, &(bit_depth),
&(color_type), &(interlace_type), int_p_NULL, int_p_NULL);
self->width = w;
self->height = h;
/* tell libpng to strip 16 bit/color files down to 8 bits/color */
png_set_strip_16(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);
/* Expand paletted colors into true RGB triplets */
/*
if (color_type == PNG_COLOR_TYPE_PALETTE)
png_set_palette_rgb(png_ptr);
*/
/* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
png_set_gray_1_2_4_to_8(png_ptr);
/* Expand paletted or RGB images with transparency to full alpha channels
* so the data will be available as RGBA quartets.
*/
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
{
png_set_tRNS_to_alpha(png_ptr);
palleteComponents = 4;
}
/* swap bytes of 16 bit files to least significant byte first */
//.........这里部分代码省略.........
开发者ID:cdcarter,项目名称:io,代码行数:101,代码来源:PNGImage.c
示例9: rep
// ######################################################################
PngParser::PngParser(const char* filename)
:
rep(new Rep(filename))
{
errno = 0;
rep->file = fopen(filename, "rb");
if (rep->file == 0) rep->onError("couldn't open file for png reading");
const size_t nheader = 8;
png_byte header[nheader];
if (fread(header, 1, nheader, rep->file) != nheader) rep->onError("short read on png file header");
int is_png = !png_sig_cmp(header, 0, nheader);
if (!is_png) rep->onError("file was not a png image file");
rep->pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
if (rep->pngPtr == 0) rep->onError("png_create_read_struct failed");
rep->infoPtr = png_create_info_struct(rep->pngPtr);
if (rep->infoPtr == 0) rep->onError("png_create_info_struct failed");
rep->endPtr = png_create_info_struct(rep->pngPtr);
if (rep->endPtr == 0) rep->onError("png_create_info_struct failed");
png_init_io(rep->pngPtr, rep->file);
png_set_sig_bytes(rep->pngPtr, nheader);
png_read_info(rep->pngPtr, rep->infoPtr);
rep->bitDepth = png_get_bit_depth(rep->pngPtr, rep->infoPtr);
rep->colorType = png_get_color_type(rep->pngPtr, rep->infoPtr);
if (rep->bitDepth == 16)
png_set_strip_16(rep->pngPtr);
else if (rep->bitDepth < 8 && (rep->colorType == PNG_COLOR_TYPE_GRAY))
png_set_gray_1_2_4_to_8(rep->pngPtr);
else if (rep->bitDepth != 8 && (rep->colorType != PNG_COLOR_TYPE_PALETTE))
rep->onError(sformat("invalid bit-depth(%d)/color-mode(%d) "
"combination", rep->bitDepth, rep->colorType));
// Strip out the alpha channel, if present
if (rep->colorType & PNG_COLOR_MASK_ALPHA)
png_set_strip_alpha(rep->pngPtr);
if (rep->colorType & PNG_COLOR_MASK_PALETTE)
png_set_palette_to_rgb(rep->pngPtr);
// This must come after any+all transformations are specified
png_read_update_info(rep->pngPtr, rep->infoPtr);
// These calls must come after png_read_update_info, so that we get
// values that reflect any transformations
rep->width = png_get_image_width(rep->pngPtr, rep->infoPtr);
rep->height = png_get_image_height(rep->pngPtr, rep->infoPtr);
rep->rowBytes = png_get_rowbytes(rep->pngPtr, rep->infoPtr);
rep->numChannels = png_get_channels(rep->pngPtr, rep->infoPtr);
ASSERT(rep->rowBytes = rep->width*rep->numChannels);
// run-time mmx PNG optimizations (nate)
#if defined(HAVE_PNG_ASM_FLAGS)
const png_uint_32 flags = png_get_asm_flags(rep->pngPtr);
const png_uint_32 mask =
png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE);
png_set_asm_flags(rep->pngPtr, flags | mask);
#endif
}
static GstFlowReturn
gst_pngdec_caps_create_and_set (GstPngDec * pngdec)
{
GstFlowReturn ret = GST_FLOW_OK;
GstCaps *caps = NULL, *res = NULL;
GstPadTemplate *templ = NULL;
gint bpc = 0, color_type;
png_uint_32 width, height;
g_return_val_if_fail (GST_IS_PNGDEC (pngdec), GST_FLOW_ERROR);
/* Get bits per channel */
bpc = png_get_bit_depth (pngdec->png, pngdec->info);
/* We don't handle 16 bits per color, strip down to 8 */
if (bpc == 16) {
GST_LOG_OBJECT (pngdec,
"this is a 16 bits per channel PNG image, strip down to 8 bits");
png_set_strip_16 (pngdec->png);
}
/* Get Color type */
color_type = png_get_color_type (pngdec->png, pngdec->info);
#if 0
/* We used to have this HACK to reverse the outgoing bytes, but the problem
* that originally required the hack seems to have been in ffmpegcolorspace's
* RGBA descriptions. It doesn't seem needed now that's fixed, but might
* still be needed on big-endian systems, I'm not sure. J.S. 6/7/2007 */
if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
png_set_bgr (pngdec->png);
#endif
/* Gray scale converted to RGB and upscaled to 8 bits */
if ((color_type == PNG_COLOR_TYPE_GRAY_ALPHA) ||
(color_type == PNG_COLOR_TYPE_GRAY)) {
GST_LOG_OBJECT (pngdec, "converting grayscale png to RGB");
png_set_gray_to_rgb (pngdec->png);
if (bpc < 8) { /* Convert to 8 bits */
GST_LOG_OBJECT (pngdec, "converting grayscale image to 8 bits");
png_set_gray_1_2_4_to_8 (pngdec->png);
}
}
/* Palette converted to RGB */
if (color_type == PNG_COLOR_TYPE_PALETTE) {
GST_LOG_OBJECT (pngdec, "converting palette png to RGB");
png_set_palette_to_rgb (pngdec->png);
}
/* Update the info structure */
png_read_update_info (pngdec->png, pngdec->info);
/* Get IHDR header again after transformation settings */
png_get_IHDR (pngdec->png, pngdec->info, &width, &height,
&bpc, &pngdec->color_type, NULL, NULL, NULL);
pngdec->width = width;
pngdec->height = height;
GST_LOG_OBJECT (pngdec, "this is a %dx%d PNG image", pngdec->width,
pngdec->height);
switch (pngdec->color_type) {
case PNG_COLOR_TYPE_RGB:
GST_LOG_OBJECT (pngdec, "we have no alpha channel, depth is 24 bits");
pngdec->bpp = 24;
break;
case PNG_COLOR_TYPE_RGB_ALPHA:
GST_LOG_OBJECT (pngdec, "we have an alpha channel, depth is 32 bits");
pngdec->bpp = 32;
break;
default:
GST_ELEMENT_ERROR (pngdec, STREAM, NOT_IMPLEMENTED, (NULL),
("pngdec does not support this color type"));
ret = GST_FLOW_NOT_SUPPORTED;
goto beach;
}
caps = gst_caps_new_simple ("video/x-raw-rgb",
"width", G_TYPE_INT, pngdec->width,
"height", G_TYPE_INT, pngdec->height,
"bpp", G_TYPE_INT, pngdec->bpp,
"framerate", GST_TYPE_FRACTION, pngdec->fps_n, pngdec->fps_d, NULL);
templ = gst_static_pad_template_get (&gst_pngdec_src_pad_template);
res = gst_caps_intersect (caps, gst_pad_template_get_caps (templ));
gst_caps_unref (caps);
gst_object_unref (templ);
if (!gst_pad_set_caps (pngdec->srcpad, res))
ret = GST_FLOW_NOT_NEGOTIATED;
GST_DEBUG_OBJECT (pngdec, "our caps %" GST_PTR_FORMAT, res);
gst_caps_unref (res);
//.........这里部分代码省略.........
请发表评论