Exemple #1
0
static
void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scaledSize, bool *doScaledRead, float screen_gamma=0.0)
{
    if (screen_gamma != 0.0 && png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA)) {
        double file_gamma;
        png_get_gAMA(png_ptr, info_ptr, &file_gamma);
        png_set_gamma(png_ptr, screen_gamma, file_gamma);
    }

    png_uint_32 width;
    png_uint_32 height;
    int bit_depth;
    int color_type;
    png_bytep trans_alpha = 0;
    png_color_16p trans_color_p = 0;
    int num_trans;
    png_colorp palette = 0;
    int num_palette;
    int interlace_method;
    png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_method, 0, 0);
    png_set_interlace_handling(png_ptr);

    if (color_type == PNG_COLOR_TYPE_GRAY) {
        // Black & White or 8-bit grayscale
        if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) {
            png_set_invert_mono(png_ptr);
            png_read_update_info(png_ptr, info_ptr);
            if (image.size() != QSize(width, height) || image.format() != QImage::Format_Mono) {
                image = QImage(width, height, QImage::Format_Mono);
                if (image.isNull())
                    return;
            }
            image.setColorCount(2);
            image.setColor(1, qRgb(0,0,0));
            image.setColor(0, qRgb(255,255,255));
        } else if (bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
            png_set_expand(png_ptr);
            png_set_strip_16(png_ptr);
            png_set_gray_to_rgb(png_ptr);
            if (image.size() != QSize(width, height) || image.format() != QImage::Format_ARGB32) {
                image = QImage(width, height, QImage::Format_ARGB32);
                if (image.isNull())
                    return;
            }
            if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
                png_set_swap_alpha(png_ptr);

            png_read_update_info(png_ptr, info_ptr);
        } else {
            if (bit_depth == 16)
                png_set_strip_16(png_ptr);
            else if (bit_depth < 8)
                png_set_packing(png_ptr);
            int ncols = bit_depth < 8 ? 1 << bit_depth : 256;
            png_read_update_info(png_ptr, info_ptr);
            if (image.size() != QSize(width, height) || image.format() != QImage::Format_Indexed8) {
                image = QImage(width, height, QImage::Format_Indexed8);
                if (image.isNull())
                    return;
            }
            image.setColorCount(ncols);
            for (int i=0; i<ncols; i++) {
                int c = i*255/(ncols-1);
                image.setColor(i, qRgba(c,c,c,0xff));
            }
            if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_color_p) {
                const int g = trans_color_p->gray;
                if (g < ncols) {
                    image.setColor(g, 0);
                }
            }
        }
    } else if (color_type == PNG_COLOR_TYPE_PALETTE
               && png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)
               && num_palette <= 256)
    {
        // 1-bit and 8-bit color
        if (bit_depth != 1)
            png_set_packing(png_ptr);
        png_read_update_info(png_ptr, info_ptr);
        png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
        QImage::Format format = bit_depth == 1 ? QImage::Format_Mono : QImage::Format_Indexed8;
        if (image.size() != QSize(width, height) || image.format() != format) {
            image = QImage(width, height, format);
            if (image.isNull())
                return;
        }
        png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
        image.setColorCount(num_palette);
        int i = 0;
        if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_alpha) {
            while (i < num_trans) {
                image.setColor(i, qRgba(
                    palette[i].red,
                    palette[i].green,
                    palette[i].blue,
                    trans_alpha[i]
                   )
               );
                i++;
            }
        }
        while (i < num_palette) {
            image.setColor(i, qRgba(
                palette[i].red,
                palette[i].green,
                palette[i].blue,
                0xff
               )
           );
            i++;
        }
    } else {
        // 32-bit
        if (bit_depth == 16)
            png_set_strip_16(png_ptr);

        png_set_expand(png_ptr);

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

        QImage::Format format = QImage::Format_ARGB32;
        // Only add filler if no alpha, or we can get 5 channel data.
        if (!(color_type & PNG_COLOR_MASK_ALPHA)
            && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
            png_set_filler(png_ptr, 0xff, QSysInfo::ByteOrder == QSysInfo::BigEndian ?
                           PNG_FILLER_BEFORE : PNG_FILLER_AFTER);
            // We want 4 bytes, but it isn't an alpha channel
            format = QImage::Format_RGB32;
        }
        QSize outSize(width,height);
        if (!scaledSize.isEmpty() && quint32(scaledSize.width()) <= width &&
            quint32(scaledSize.height()) <= height && interlace_method == PNG_INTERLACE_NONE) {
            // Do inline downscaling
            outSize = scaledSize;
            if (doScaledRead)
                *doScaledRead = true;
        }
        if (image.size() != outSize || image.format() != format) {
            image = QImage(outSize, format);
            if (image.isNull())
                return;
        }

        if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
            png_set_swap_alpha(png_ptr);

        png_read_update_info(png_ptr, info_ptr);
    }

    // Qt==ARGB==Big(ARGB)==Little(BGRA)
    if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
        png_set_bgr(png_ptr);
    }
}
Exemple #2
0
static HPDF_STATUS
LoadPngData  (HPDF_Dict     image,
              HPDF_Xref     xref,
              HPDF_Stream   png_data,
              HPDF_BOOL     delayed_loading)

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

	HPDF_PTRACE ((" HPDF_Image_LoadPngImage\n"));

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

no_transparent_color_in_palette:

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

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

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

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

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

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

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

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

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

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

	if (ret != HPDF_OK)
		goto Exit;

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

		if (ret != HPDF_OK)
			goto Exit;
	}

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

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

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

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

	return HPDF_OK;

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

	if (ret != HPDF_OK) {
		return ret;
	}
	return image->error->error_no;
}
Exemple #3
0
s32 pngDecSetParameter(PStream stream, PInParam in_param, POutParam out_param, PExtInParam extra_in_param = vm::null, PExtOutParam extra_out_param = vm::null)
{
	if (in_param->outputPackFlag == CELL_PNGDEC_1BYTE_PER_NPIXEL)
	{
		fmt::throw_exception("Packing not supported! (%d)" HERE, in_param->outputPackFlag);
	}

	// flag to keep unknown chunks
	png_set_keep_unknown_chunks(stream->png_ptr, PNG_HANDLE_CHUNK_IF_SAFE, 0, 0);

	// Scale 16 bit depth down to 8 bit depth.
	if (stream->info.bitDepth == 16 && in_param->outputBitDepth == 8)
	{
		// PS3 uses png_set_strip_16, since png_set_scale_16 wasn't available back then.
		png_set_strip_16(stream->png_ptr);
	}

	// This shouldnt ever happen, but not sure what to do if it does, just want it logged for now
	if (stream->info.bitDepth != 16 && in_param->outputBitDepth == 16)
		cellPngDec.error("Output depth of 16 with non input depth of 16 specified!");
	if (in_param->commandPtr != vm::null)
		cellPngDec.warning("Ignoring CommandPtr.");

	if (stream->info.colorSpace != in_param->outputColorSpace)
	{
		// check if we need to set alpha
		const bool inputHasAlpha = cellPngColorSpaceHasAlpha(stream->info.colorSpace);
		const bool outputWantsAlpha = cellPngColorSpaceHasAlpha(in_param->outputColorSpace);

		if (outputWantsAlpha && !inputHasAlpha)
		{
			if (in_param->outputAlphaSelect == CELL_PNGDEC_FIX_ALPHA)
				png_set_add_alpha(stream->png_ptr, in_param->outputColorAlpha, in_param->outputColorSpace == CELL_PNGDEC_ARGB ? PNG_FILLER_BEFORE : PNG_FILLER_AFTER);
			else
			{
				// Check if we can steal the alpha from a trns block
				if (png_get_valid(stream->png_ptr, stream->info_ptr, PNG_INFO_tRNS))
					png_set_tRNS_to_alpha(stream->png_ptr);
				// if not, just set default of 0xff
				else
					png_set_add_alpha(stream->png_ptr, 0xff, in_param->outputColorSpace == CELL_PNGDEC_ARGB ? PNG_FILLER_BEFORE : PNG_FILLER_AFTER);
			}
		}
		else if (inputHasAlpha && !outputWantsAlpha)
			png_set_strip_alpha(stream->png_ptr);
		else if (in_param->outputColorSpace == CELL_PNGDEC_ARGB && stream->info.colorSpace == CELL_PNGDEC_RGBA)
			png_set_swap_alpha(stream->png_ptr);

		// Handle gray<->rgb colorspace conversions
		// rgb output
		if (in_param->outputColorSpace == CELL_PNGDEC_ARGB
			|| in_param->outputColorSpace == CELL_PNGDEC_RGBA
			|| in_param->outputColorSpace == CELL_PNGDEC_RGB)
		{

			if (stream->info.colorSpace == CELL_PNGDEC_PALETTE)
				png_set_palette_to_rgb(stream->png_ptr);
			if ((stream->info.colorSpace == CELL_PNGDEC_GRAYSCALE || stream->info.colorSpace == CELL_PNGDEC_GRAYSCALE_ALPHA)
				&& stream->info.bitDepth < 8)
				png_set_expand_gray_1_2_4_to_8(stream->png_ptr);
		}
		// grayscale output
		else
		{
			if (stream->info.colorSpace == CELL_PNGDEC_ARGB
				|| stream->info.colorSpace == CELL_PNGDEC_RGBA
				|| stream->info.colorSpace == CELL_PNGDEC_RGB)
			{

				png_set_rgb_to_gray(stream->png_ptr, PNG_ERROR_ACTION_NONE, PNG_RGB_TO_GRAY_DEFAULT, PNG_RGB_TO_GRAY_DEFAULT);
			}
			else {
				// not sure what to do here
				cellPngDec.error("Grayscale / Palette to Grayscale / Palette conversion currently unsupported.");
			}
		}
	}

	stream->passes = png_set_interlace_handling(stream->png_ptr);

	// Update the info structure
	png_read_update_info(stream->png_ptr, stream->info_ptr);

	stream->out_param.outputWidth = stream->info.imageWidth;
	stream->out_param.outputHeight = stream->info.imageHeight;
	stream->out_param.outputBitDepth = in_param->outputBitDepth;
	stream->out_param.outputColorSpace = in_param->outputColorSpace;
	stream->out_param.outputMode = in_param->outputMode;

	stream->out_param.outputWidthByte = png_get_rowbytes(stream->png_ptr, stream->info_ptr);
	stream->out_param.outputComponents = png_get_channels(stream->png_ptr, stream->info_ptr);

	stream->packing = in_param->outputPackFlag;

	// Set the memory usage. We currently don't actually allocate memory for libpng through the callbacks, due to libpng needing a lot more memory compared to PS3 variant.
	stream->out_param.useMemorySpace = 0;

	if (extra_in_param)
	{
		if (extra_in_param->bufferMode != CELL_PNGDEC_LINE_MODE)
		{
			cellPngDec.error("Invalid Buffermode specified.");
			return CELL_PNGDEC_ERROR_ARG;
		}

		if (stream->passes > 1)
		{
			stream->outputCounts = 1;
		}
		else
			stream->outputCounts = extra_in_param->outputCounts;

		if (extra_out_param)
		{
			if (stream->outputCounts == 0)
				extra_out_param->outputHeight = stream->out_param.outputHeight;
			else
				extra_out_param->outputHeight = std::min(stream->outputCounts, stream->out_param.outputHeight.value());
			extra_out_param->outputWidthByte = stream->out_param.outputWidthByte;
		}
	}

	*out_param = stream->out_param;

	return CELL_OK;
}
Exemple #4
0
void loadNativePNG(texture_t* tmpTex)
{
	png_structp     png_ptr;
	png_infop       info_ptr;
	unsigned int    width;
	unsigned int    height;
	int             i;

	int             bit_depth;
	int             color_type ;
	png_size_t      rowbytes;
	png_bytep       *row_pointers;
	png_byte header[8];


/*
 * char realPath[1024];
  memset(realPath, 0, 1024);
  strcat(realPath, FS_Gamedir());
  if (tmpTex->path[0] != '/')
	strcat(realPath, "/");
  strcat(realPath, tmpTex->path);
*/
  tmpTex->format = TEXTURE_TYPE_UNKNOWN ;

  file = FS_OpenFile(tmpTex->path, "rb");

  //LOGI("[Android Main] Opening %s", realPath);

	if ( !file  )
		abort_textureLoading_("[read_png_file] Could not open file '%s'\n",tmpTex->path);

	FS_Read(header,1, 8,file);

	if (png_sig_cmp(header, 0, 8) != 0 )
		abort_textureLoading_("[read_png_file] File is not recognized as a PNG file.\n", tmpTex->path);

	// initialize
	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

	if (png_ptr == NULL)
		abort_textureLoading_("[read_png_file] png_create_read_struct failed","");

	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL)
		abort_textureLoading_("[read_png_file] png_create_info_struct failed","");

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

	png_set_read_fn(png_ptr, NULL, png_zip_read);
	png_set_sig_bytes(png_ptr, 8);

	png_read_info(png_ptr, info_ptr);

  //Retrieve metadata and transfer to structure bean tmpTex
	png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);

	tmpTex->width = width;
	tmpTex->height =  height;

	// Set up some transforms.
	/*if (color_type & PNG_COLOR_MASK_ALPHA) {
		png_set_strip_alpha(png_ptr);
	}*/
	if (bit_depth > 8) {
		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);
	}
	if (color_type == PNG_COLOR_TYPE_PALETTE) {
		png_set_palette_to_rgb(png_ptr);
	}

	// Update the png info struct.
	png_read_update_info(png_ptr, info_ptr);

	// Rowsize in bytes.
	rowbytes = png_get_rowbytes(png_ptr, info_ptr);

  	tmpTex->bpp = rowbytes / width;
	if (tmpTex->bpp == 4)
		tmpTex->format = TEXTURE_GL_RGBA;
	else
		tmpTex->format = TEXTURE_GL_RGB;

	Log_Printf("DEBUG: For %s, bpp: %i, color_type: %i, bit_depth: %i", tmpTex->path, tmpTex->bpp, color_type, bit_depth);
  //Since PNG can only store one image there is only one mipmap, allocated an array of one
  tmpTex->numMipmaps = 1;
  tmpTex->data = malloc(sizeof(uchar*));
	if ((tmpTex->data[0] = (uchar*)malloc(rowbytes * height))==NULL)
  {
	//Oops texture won't be able to hold the result :(, cleanup LIBPNG internal state and return;
	free(tmpTex->data);
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
	return;
	}

  //Next we need to send to libpng an array of pointer, let's point to tmpTex->data[0]
	if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL)
  {
	// Oops looks like we won't have enough RAM to allocate an array of pointer....
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		free(tmpTex->data );
		tmpTex->data  = NULL;
	return;
	}

  //FCS: Hm, it looks like we are flipping the image vertically.
  //     Since iOS did not do it, we may have to not to that. If result is
  //     messed up, just swap to:   row_pointers[             i] = ....
	for (i = 0;  i < height;  ++i)
		//row_pointers[height - 1 - i] = tmpTex->data[0]  + i * rowbytes;
	row_pointers[             i] = tmpTex->data[0]  + i*rowbytes;


  //Decompressing PNG to RAW where row_pointers are pointing (tmpTex->data[0])
	png_read_image(png_ptr, row_pointers);

  //Last but not least:


	// Free LIBPNG internal state.
	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

  //Free the decompression buffer
  free(row_pointers);

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

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

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

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

    image->Destroy();

    png_structp png_ptr = png_create_read_struct
                          (
                            PNG_LIBPNG_VER_STRING,
                            (voidp) NULL,
                            wx_png_error,
                            wx_png_warning
                          );
    if (!png_ptr)
        goto error;

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

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

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

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

    if (color_type == PNG_COLOR_TYPE_PALETTE)
        png_set_expand( png_ptr );

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

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

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

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

    lines = (unsigned char **)malloc( (size_t)(height * sizeof(unsigned char *)) );
    if ( !lines )
        goto error;

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

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

#if wxUSE_PALETTE
    if (color_type == PNG_COLOR_TYPE_PALETTE)
    {
        const size_t ncolors = info_ptr->num_palette;
        unsigned char* r = new unsigned char[ncolors];
        unsigned char* g = new unsigned char[ncolors];
        unsigned char* b = new unsigned char[ncolors];

        for (size_t j = 0; j < ncolors; j++)
        {
            r[j] = info_ptr->palette[j].red;
            g[j] = info_ptr->palette[j].green;
            b[j] = info_ptr->palette[j].blue;
        }

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

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

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

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

    return true;

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

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

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

        free( lines );
    }

    if ( png_ptr )
    {
        if ( info_ptr )
        {
            png_destroy_read_struct( &png_ptr, &info_ptr, (png_infopp) NULL );
            free(info_ptr);
        }
        else
            png_destroy_read_struct( &png_ptr, (png_infopp) NULL, (png_infopp) NULL );
    }
    return false;
}
Exemple #6
0
pictw_t *
spng_read(session_t *ps, const char *path) {
	assert(path);

	char sig[SPNG_SIGBYTES] = "";
	pictw_t *pictw = NULL;
	png_structp png_ptr = NULL;
	png_infop info_ptr = NULL;
	FILE *fp = fopen(path, "rb");
	bool need_premultiply = false;
	if (unlikely(!fp)) {
		printfef("(\"%s\"): Failed to open file.", path);
		goto spng_read_end;
	}
	if (unlikely(SPNG_SIGBYTES != fread(&sig, 1, SPNG_SIGBYTES, fp))) {
		printfef("(\"%s\"): Failed to read %d-byte signature.",
				path, SPNG_SIGBYTES);
		goto spng_read_end;
	}
	if (unlikely(png_sig_cmp((png_bytep) sig, 0, SPNG_SIGBYTES))) {
		printfef("(\"%s\"): PNG signature invalid.", path);
		goto spng_read_end;
	}
	png_ptr = allocchk(png_create_read_struct(PNG_LIBPNG_VER_STRING,
				NULL, NULL, NULL));
	info_ptr = allocchk(png_create_info_struct(png_ptr));
	if (setjmp(png_jmpbuf(png_ptr)))
		goto spng_read_end;
	png_init_io(png_ptr, fp);
	png_set_sig_bytes(png_ptr, SPNG_SIGBYTES);
	png_read_info(png_ptr, info_ptr);
	png_uint_32 width = 0, height = 0;

	// Set transformations
	int bit_depth = 0, color_type = 0;
	{
		int interlace_type = 0;
		png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth,
				&color_type, &interlace_type, NULL, NULL);

		// Scale or strip 16-bit colors
		if (bit_depth == 16) {
			printfdf("(\"%s\"): Scaling 16-bit colors.", path);
#if PNG_LIBPNG_VER >= 10504
			png_set_scale_16(png_ptr);
#else
			png_set_strip_16(png_ptr);
#endif
			bit_depth = 8;
		}

		/* if (bit_depth < 8)
			png_set_packing(png_ptr); */

		// No idea why this is needed...
		png_set_bgr(png_ptr);

		// Convert palette to RGB
		if (color_type == PNG_COLOR_TYPE_PALETTE) {
			printfdf("(\"%s\"): Converting palette PNG to RGB.", path);
			png_set_palette_to_rgb(png_ptr);
			color_type = PNG_COLOR_TYPE_RGB;
		}

		if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
			printfdf("(\"%s\"): Converting rDNS to full alpha.", path);
			png_set_tRNS_to_alpha(png_ptr);
		}

		if (color_type == PNG_COLOR_TYPE_GRAY
				|| PNG_COLOR_TYPE_GRAY_ALPHA == color_type) {
			printfdf("(\"%s\"): Converting gray (+ alpha) PNG to RGB.", path);
			png_set_gray_to_rgb(png_ptr);
			if (PNG_COLOR_TYPE_GRAY == color_type)
				color_type = PNG_COLOR_TYPE_RGB;
			else
				color_type = PNG_COLOR_TYPE_RGB_ALPHA;
		}

		/*
		if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
			printfdf("(\"%s\"): Converting 1/2/4 bit gray PNG to 8-bit.", path);
#if PNG_LIBPNG_VER >= 10209
			png_set_expand_gray_1_2_4_to_8(png_ptr);
#else
			png_set_gray_1_2_4_to_8(png_ptr);
#endif
			bit_depth = 8;
		}
		*/

		// Somehow XImage requires 24-bit visual to use 32 bits per pixel
		if (color_type == PNG_COLOR_TYPE_RGB) {
			printfdf("(\"%s\"): Appending filler alpha values.", path);
			png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
		}

		// Premultiply alpha
		if (PNG_COLOR_TYPE_RGB_ALPHA == color_type) {
#if PNG_LIBPNG_VER >= 10504
			png_set_alpha_mode(png_ptr, PNG_ALPHA_STANDARD, 1.0);
#else
			need_premultiply = true;
#endif
		}

		/*
		int number_passes = 1;
#ifdef PNG_READ_INTERLACING_SUPPORTED
		number_passes = png_set_interlace_handling(png_ptr);
#endif */

		if (PNG_INTERLACE_NONE != interlace_type)
			png_set_interlace_handling(png_ptr);
	}

	png_read_update_info(png_ptr, info_ptr);

	int depth = 0;
	png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth,
				&color_type, NULL, NULL, NULL);
	switch (color_type) {
		case PNG_COLOR_TYPE_GRAY:       depth = 1 * bit_depth; break;
		case PNG_COLOR_TYPE_RGB:        depth = 3 * bit_depth; break;
		case PNG_COLOR_TYPE_RGB_ALPHA:  depth = 4 * bit_depth; break;
		default:                        assert(0); break;
	}

	// Read data and fill to Picture
	{
		int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
		png_bytep row_pointers[height];
		memset(row_pointers, 0, sizeof(row_pointers));
		row_pointers[0] = png_malloc(png_ptr, rowbytes * height);
		for (int row = 1; row < height; row++)
			row_pointers[row] = row_pointers[row - 1] + rowbytes;
		png_read_image(png_ptr, row_pointers);
		if (need_premultiply)
			for (int row = 0; row < height; row++)
				simg_data32_premultiply(row_pointers[row], width);
		if (unlikely(!(pictw = simg_data_to_pictw(ps, width, height, depth,
							row_pointers[0], rowbytes)))) {
			printfef("(\"%s\"): Failed to create Picture.", path);
			goto spng_read_end;
		}
	}

spng_read_end:
	if (png_ptr)
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
	if (fp)
		fclose(fp);

	return pictw;
}
  Load_SBit_Png( FT_GlyphSlot     slot,
                 FT_Int           x_offset,
                 FT_Int           y_offset,
                 FT_Int           pix_bits,
                 TT_SBit_Metrics  metrics,
                 FT_Memory        memory,
                 FT_Byte*         data,
                 FT_UInt          png_len,
                 FT_Bool          populate_map_and_metrics,
                 FT_Bool          metrics_only )
  {
    FT_Bitmap    *map   = &slot->bitmap;
    FT_Error      error = FT_Err_Ok;
    FT_StreamRec  stream;

    png_structp  png;
    png_infop    info;
    png_uint_32  imgWidth, imgHeight;

    int         bitdepth, color_type, interlace;
    FT_Int      i;
    png_byte*  *rows = NULL; /* pacify compiler */


    if ( x_offset < 0 ||
         y_offset < 0 )
    {
      error = FT_THROW( Invalid_Argument );
      goto Exit;
    }

    if ( !populate_map_and_metrics                            &&
         ( x_offset + metrics->width  > map->width ||
           y_offset + metrics->height > map->rows  ||
           pix_bits != 32                          ||
           map->pixel_mode != FT_PIXEL_MODE_BGRA   ) )
    {
      error = FT_THROW( Invalid_Argument );
      goto Exit;
    }

    FT_Stream_OpenMemory( &stream, data, png_len );

    png = png_create_read_struct( PNG_LIBPNG_VER_STRING,
                                  &error,
                                  error_callback,
                                  warning_callback );
    if ( !png )
    {
      error = FT_THROW( Out_Of_Memory );
      goto Exit;
    }

    info = png_create_info_struct( png );
    if ( !info )
    {
      error = FT_THROW( Out_Of_Memory );
      png_destroy_read_struct( &png, NULL, NULL );
      goto Exit;
    }

    if ( ft_setjmp( png_jmpbuf( png ) ) )
    {
      error = FT_THROW( Invalid_File_Format );
      goto DestroyExit;
    }

    png_set_read_fn( png, &stream, read_data_from_FT_Stream );

    png_read_info( png, info );
    png_get_IHDR( png, info,
                  &imgWidth, &imgHeight,
                  &bitdepth, &color_type, &interlace,
                  NULL, NULL );

    if ( error                                        ||
         ( !populate_map_and_metrics                &&
           ( (FT_Int)imgWidth  != metrics->width  ||
             (FT_Int)imgHeight != metrics->height ) ) )
      goto DestroyExit;

    if ( populate_map_and_metrics )
    {
      metrics->width  = (FT_UShort)imgWidth;
      metrics->height = (FT_UShort)imgHeight;

      map->width      = metrics->width;
      map->rows       = metrics->height;
      map->pixel_mode = FT_PIXEL_MODE_BGRA;
      map->pitch      = (int)( map->width * 4 );
      map->num_grays  = 256;

      /* reject too large bitmaps similarly to the rasterizer */
      if ( map->rows > 0x4FFF || map->width > 0x4FFF )
      {
        error = FT_THROW( Array_Too_Large );
        goto DestroyExit;
      }
    }

    /* convert palette/gray image to rgb */
    if ( color_type == PNG_COLOR_TYPE_PALETTE )
      png_set_palette_to_rgb( png );

    /* expand gray bit depth if needed */
    if ( color_type == PNG_COLOR_TYPE_GRAY )
    {
#if PNG_LIBPNG_VER >= 10209
      png_set_expand_gray_1_2_4_to_8( png );
#else
      png_set_gray_1_2_4_to_8( png );
#endif
    }

    /* transform transparency to alpha */
    if ( png_get_valid(png, info, PNG_INFO_tRNS ) )
      png_set_tRNS_to_alpha( png );

    if ( bitdepth == 16 )
      png_set_strip_16( png );

    if ( bitdepth < 8 )
      png_set_packing( png );

    /* convert grayscale to RGB */
    if ( color_type == PNG_COLOR_TYPE_GRAY       ||
         color_type == PNG_COLOR_TYPE_GRAY_ALPHA )
      png_set_gray_to_rgb( png );

    if ( interlace != PNG_INTERLACE_NONE )
      png_set_interlace_handling( png );

    png_set_filler( png, 0xFF, PNG_FILLER_AFTER );

    /* recheck header after setting EXPAND options */
    png_read_update_info(png, info );
    png_get_IHDR( png, info,
                  &imgWidth, &imgHeight,
                  &bitdepth, &color_type, &interlace,
                  NULL, NULL );

    if ( bitdepth != 8                              ||
        !( color_type == PNG_COLOR_TYPE_RGB       ||
           color_type == PNG_COLOR_TYPE_RGB_ALPHA ) )
    {
      error = FT_THROW( Invalid_File_Format );
      goto DestroyExit;
    }

    if ( metrics_only )
      goto DestroyExit;

    switch ( color_type )
    {
    default:
      /* Shouldn't happen, but fall through. */

    case PNG_COLOR_TYPE_RGB_ALPHA:
      png_set_read_user_transform_fn( png, premultiply_data );
      break;

    case PNG_COLOR_TYPE_RGB:
      /* Humm, this smells.  Carry on though. */
      png_set_read_user_transform_fn( png, convert_bytes_to_data );
      break;
    }

    if ( populate_map_and_metrics )
    {
      /* this doesn't overflow: 0x4FFF * 0x4FFF * 4 < 2^31 */
      FT_ULong  size = map->rows * (FT_ULong)map->pitch;


      error = ft_glyphslot_alloc_bitmap( slot, size );
      if ( error )
        goto DestroyExit;
    }

    if ( FT_NEW_ARRAY( rows, imgHeight ) )
    {
      error = FT_THROW( Out_Of_Memory );
      goto DestroyExit;
    }

    for ( i = 0; i < (FT_Int)imgHeight; i++ )
      rows[i] = map->buffer + ( y_offset + i ) * map->pitch + x_offset * 4;

    png_read_image( png, rows );

    FT_FREE( rows );

    png_read_end( png, info );

  DestroyExit:
    png_destroy_read_struct( &png, &info, NULL );
    FT_Stream_Close( &stream );

  Exit:
    return error;
  }
void PngReader::read(unsigned x0, unsigned y0,ImageData32& image)
{
    FILE *fp=fopen(fileName_.c_str(),"r");
    if (!fp) throw ImageReaderException("cannot open image file "+fileName_);

    png_structp png_ptr = png_create_read_struct
                          (PNG_LIBPNG_VER_STRING,0,0,0);

    if (!png_ptr)
    {
        fclose(fp);
        throw ImageReaderException("failed to allocate png_ptr");
    }

    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
    {
        png_destroy_read_struct(&png_ptr,0,0);
        fclose(fp);
        throw ImageReaderException("failed to create info_ptr");
    }

    png_init_io(png_ptr, fp);
    png_read_info(png_ptr, info_ptr);

    if (color_type_ == PNG_COLOR_TYPE_PALETTE)
        png_set_expand(png_ptr);
    if (color_type_ == PNG_COLOR_TYPE_GRAY && bit_depth_ < 8)
        png_set_expand(png_ptr);
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
        png_set_expand(png_ptr);
    if (bit_depth_ == 16)
        png_set_strip_16(png_ptr);
    if (color_type_ == PNG_COLOR_TYPE_GRAY ||
            color_type_ == PNG_COLOR_TYPE_GRAY_ALPHA)
        png_set_gray_to_rgb(png_ptr);

    // quick hack -- only work in >=libpng 1.2.7
    png_set_add_alpha(png_ptr,1,1);

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

    png_read_update_info(png_ptr, info_ptr);

    //START read image rows
    unsigned w=std::min((unsigned)image.width(),width_);
    unsigned h=std::min((unsigned)image.height(),height_);

    unsigned rowbytes=png_get_rowbytes(png_ptr, info_ptr);
    unsigned char* row= new unsigned char[rowbytes];
    for (unsigned i=0; i<height_; ++i)
    {
        png_read_row(png_ptr,row,0);
        if (i>=y0 && i<h)
        {
            image.setRow(i-y0,(unsigned*) &row[x0],w);
        }
    }
    //END
    delete [] row;
    png_read_end(png_ptr,0);
    png_destroy_read_struct(&png_ptr, &info_ptr,0);
    fclose(fp);
}
Exemple #9
0
void png_reader::read(unsigned x0, unsigned y0,image_data_32& image)
{
    FILE *fp=fopen(fileName_.c_str(),"rb");
    if (!fp) throw image_reader_exception("cannot open image file "+fileName_);

    png_structp png_ptr = png_create_read_struct
        (PNG_LIBPNG_VER_STRING,0,0,0);

    if (!png_ptr)
    {
        fclose(fp);
        throw image_reader_exception("failed to allocate png_ptr");
    }

    // catch errors in a custom way to avoid the need for setjmp
    png_set_error_fn(png_ptr, png_get_error_ptr(png_ptr), user_error_fn, user_warning_fn);

    png_infop info_ptr;
    try
    {
        info_ptr = png_create_info_struct(png_ptr);
        if (!info_ptr)
        {
            png_destroy_read_struct(&png_ptr,0,0);
            fclose(fp);
            throw image_reader_exception("failed to create info_ptr");
        }
    }
    catch (std::exception const& ex)
    {
        png_destroy_read_struct(&png_ptr,0,0);
        fclose(fp);
        throw;
    }

    png_set_read_fn(png_ptr, (png_voidp)fp, png_read_data);
    png_read_info(png_ptr, info_ptr);

    if (color_type_ == PNG_COLOR_TYPE_PALETTE)
        png_set_expand(png_ptr);
    if (color_type_ == PNG_COLOR_TYPE_GRAY && bit_depth_ < 8)
        png_set_expand(png_ptr);
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
        png_set_expand(png_ptr);
    if (bit_depth_ == 16)
        png_set_strip_16(png_ptr);
    if (color_type_ == PNG_COLOR_TYPE_GRAY ||
        color_type_ == PNG_COLOR_TYPE_GRAY_ALPHA)
        png_set_gray_to_rgb(png_ptr);

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

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

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

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

    png_read_end(png_ptr,0);
    png_destroy_read_struct(&png_ptr, &info_ptr,0);
    fclose(fp);
}
Exemple #10
0
char* Model::load_png(std::string fileName, int *width, int *height) {
    fileName = "Resources/" + fileName;
    FILE *png_file = fopen(fileName.c_str(), "rb");
    //assert(png_file.open);

    uint8_t header[PNG_SIG_BYTES];

    fread(header, 1, PNG_SIG_BYTES, png_file);
    assert(!png_sig_cmp(header, 0, PNG_SIG_BYTES));

    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    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);

    assert(!setjmp(png_jmpbuf(png_ptr)));
    png_init_io(png_ptr, png_file);
    png_set_sig_bytes(png_ptr, PNG_SIG_BYTES);
    png_read_info(png_ptr, info_ptr);

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

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

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

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

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

    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
        png_set_tRNS_to_alpha(png_ptr);
    else
        png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);

    png_read_update_info(png_ptr, info_ptr);

    png_uint_32 rowbytes = png_get_rowbytes(png_ptr, info_ptr);
    png_uint_32 numbytes = rowbytes * (*height);
    png_byte* pixels = (png_byte*) malloc(numbytes);
    png_byte** row_ptrs = (png_byte**) malloc((*height) * sizeof (png_byte*));

    int i;
    for (i = 0; i < (*height); i++)
        row_ptrs[i] = pixels + ((*height) - 1 - i) * rowbytes;


    png_read_image(png_ptr, row_ptrs);

    free(row_ptrs);
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    fclose(png_file);

    return (char *) pixels;
}
Exemple #11
0
/* Read a PNG file.  You may want to return an error code if the read
 * fails (depending upon the failure).  There are two "prototypes" given
 * here - one where we are given the filename, and we need to open the
 * file, and the other where we are given an open file (possibly with
 * some or all of the magic bytes read - see comments above).
 */
#ifdef open_file /* prototype 1 */
void read_png(char *file_name)  /* We need to open the file */
{
   png_structp png_ptr;
   png_infop info_ptr;
   unsigned int sig_read = 0;
   png_uint_32 width, height;
   int bit_depth, color_type, interlace_type;
   FILE *fp;

   if ((fp = fopen(file_name, "rb")) == NULL)
      return (ERROR);

#else no_open_file /* prototype 2 */
void read_png(FILE *fp, unsigned int sig_read)  /* File is already open */
{
   png_structp png_ptr;
   png_infop info_ptr;
   png_uint_32 width, height;
   int bit_depth, color_type, interlace_type;
#endif no_open_file /* Only use one prototype! */

   /* Create and initialize the png_struct with the desired error handler
    * functions.  If you want to use the default stderr and longjump method,
    * you can supply NULL for the last three parameters.  We also supply the
    * the compiler header file version, so that we know if the application
    * was compiled with a compatible version of the library.  REQUIRED
    */
   png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
      png_voidp user_error_ptr, user_error_fn, user_warning_fn);

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

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

   /* Set error handling if you are using the setjmp/longjmp method (this is
    * the normal method of doing things with libpng).  REQUIRED unless you
    * set up your own error handlers in the png_create_read_struct() earlier.
    */

   if (setjmp(png_jmpbuf(png_ptr)))
   {
      /* Free all of the memory associated with the png_ptr and info_ptr */
      png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
      fclose(fp);
      /* If we get here, we had a problem reading the file */
      return (ERROR);
   }

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

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

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

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

#else
   /* OK, you're doing it the hard way, with the lower-level functions */

   /* The call to png_read_info() gives us all of the information from the
    * PNG file before the first IDAT (image data chunk).  REQUIRED
    */
   png_read_info(png_ptr, info_ptr);

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

   /* Set up the data transformations you want.  Note that these are all
    * optional.  Only call them if you want/need them.  Many of the
    * transformations only work on specific types of images, and many
    * are mutually exclusive.
    */

   /* Tell libpng to strip 16 bit/color files down to 8 bits/color.
    * Use accurate scaling if it's available, otherwise just chop off the
    * low byte.
    */
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
    png_set_scale_16(png_ptr);
#else
   png_set_strip_16(png_ptr);
#endif

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

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

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

   /* Expand paletted colors into true RGB triplets */
   if (color_type == PNG_COLOR_TYPE_PALETTE)
      png_set_palette_to_rgb(png_ptr);

   /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
   if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
      png_set_expand_gray_1_2_4_to_8(png_ptr);

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

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

   png_color_16 my_background, *image_background;

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

   /* Some suggestions as to how to get a screen gamma value
    *
    * Note that screen gamma is the display_exponent, which includes
    * the CRT_exponent and any correction for viewing conditions
    */
   if (/* We have a user-defined screen gamma value */)
   {
      screen_gamma = user-defined screen_gamma;
   }
   /* This is one way that applications share the same screen gamma value */
   else if ((gamma_str = getenv("SCREEN_GAMMA")) != NULL)
Exemple #12
0
uint8_t* ImageDecoder::decodePNGImpl(png_structp pngPtr, uint32_t* width, uint32_t* height, bool* hasAlpha)
{
	png_bytep* rowPtrs = NULL;
	uint8_t* outData = NULL;
	png_infop infoPtr = png_create_info_struct(pngPtr);
	if (!infoPtr)
	{
		LOG(LOG_ERROR,"Couldn't initialize png info struct");
		png_destroy_read_struct(&pngPtr, (png_infopp)0, (png_infopp)0);
		return NULL;
	}

	if (setjmp(png_jmpbuf(pngPtr)))
	{
		png_destroy_read_struct(&pngPtr, &infoPtr,(png_infopp)0);
		if (rowPtrs != NULL) delete [] rowPtrs;
		if (outData != NULL) delete [] outData;

		LOG(LOG_ERROR,"error during reading of the png file");

		return NULL;
	}

	png_read_info(pngPtr, infoPtr);

	*width =  png_get_image_width(pngPtr, infoPtr);
	*height = png_get_image_height(pngPtr, infoPtr);

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

	// Transform everything into 24 bit RGB
	switch (color_type)
	{
		case PNG_COLOR_TYPE_PALETTE:
			png_set_palette_to_rgb(pngPtr);
			break;
		case PNG_COLOR_TYPE_GRAY:
			if (bitdepth < 8)
				png_set_gray_to_rgb(pngPtr);
			break;
	}

	if (bitdepth == 16)
	{
		png_set_strip_16(pngPtr);
	}

	*hasAlpha = (channels > 3);

	// Update the infoPtr to reflect the transformations set
	// above. Read new values by calling png_get_* again.
	png_read_update_info(pngPtr, infoPtr);

	//bitdepth = png_get_bit_depth(pngPtr, infoPtr);
	//color_type = png_get_color_type(pngPtr, infoPtr);

	const unsigned int stride = png_get_rowbytes(pngPtr, infoPtr);

	outData = new uint8_t[(*height) * stride];
	rowPtrs = new png_bytep[(*height)];
	for (size_t i = 0; i < (*height); i++)
	{
		rowPtrs[i] = (png_bytep)outData + i* stride;
	}

	png_read_image(pngPtr, rowPtrs);
	png_read_end(pngPtr, NULL);
	png_destroy_read_struct(&pngPtr, &infoPtr,(png_infopp)0);
	delete[] (png_bytep)rowPtrs;

	return outData;
}
unsigned char* LoadPNGJPGFromMemory(const unsigned char* buffer, int len, int* width, int* height)
{
	const int number=8;
	// проверяем сигнатуру файла (первые number байт)
	if ( !png_check_sig((png_bytep)buffer, number) )
	{
		// неизвестный формат
		return LoadJPGWithAlphaFromMemory(buffer, len, width, height);
	}

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

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

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

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

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

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

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

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

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

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

	*width=w;
	*height=h;

	return data;
}
Exemple #14
0
/*
ReadPNG - Reads the contents of a PNG file and stores the contents into
    BMGImageStruct

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

Outputs:
    img         - the BMGImageStruct containing the image data

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

Limitations:
    None.

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

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

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

    BMGError tmp;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    png_set_bgr(png_ptr);

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

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

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

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

    png_read_update_info( png_ptr, info_ptr );

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

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

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

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

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

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

    return BMG_OK;
}
Exemple #15
0
bool Texture::load2DPNG(const char *name, bool genMIPs)
{
	ASSERT(name);

	png_structp png_ptr;
	png_infop   info_ptr;
	png_uint_32 width, height;
	int32_t     bit_depth, color_type, stride;
	uint8_t     *buffer, *data;
	png_bytep   *row_pointers;
	uint32_t    size;
	GLint       internalFormat;
	GLenum      format;

	if (!VFS::load(name, VFS_BINARY, &buffer, &size))
		return false;

	if (size <= 8)
	{
		LOG_ERROR("Too small PNG file '%s'\n", name);
		delete[] buffer;
		return false;
	}

	if (png_sig_cmp((png_byte *)buffer, 0, 8))
	{
		LOG_ERROR("Wrong PNG format '%s'\n", name);
		delete[] buffer;
		return false;
	}

	if ((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
		NULL, PNGError, NULL)) == NULL)
	{
		LOG_ERROR("Failed to create PNG read struct\n");
		delete[] buffer;
		return false;
	}

	if ((info_ptr = png_create_info_struct(png_ptr)) == NULL)
	{
		LOG_ERROR("Failed to create PNG info struct\n");
		png_destroy_read_struct(&png_ptr, NULL, NULL);
		delete[] buffer;
		return false;
	}

	if (setjmp(png_jmpbuf(png_ptr)))
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		delete[] buffer;
		return false;
	}

	png_set_read_fn(png_ptr, (void *)(buffer + 8), PNGRead);
	png_set_sig_bytes(png_ptr, 8);
	png_read_info(png_ptr, info_ptr);

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

	png_set_strip_16(png_ptr);
	png_set_packing(png_ptr);

	if (color_type == PNG_COLOR_TYPE_PALETTE)
		png_set_palette_to_rgb(png_ptr);

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

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

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

	png_read_update_info(png_ptr, info_ptr);

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

	switch (color_type)
	{
		case PNG_COLOR_TYPE_GRAY:
		case PNG_COLOR_TYPE_GRAY_ALPHA:
			internalFormat = GL_R8;
			format         = GL_RED;
		break;
		case PNG_COLOR_TYPE_RGB:
			internalFormat = GL_RGB8;
			format         = GL_RGB;
		break;
		case PNG_COLOR_TYPE_RGBA:
			internalFormat = GL_RGBA8;
			format         = GL_RGBA;
		break;
		default:
			LOG_ERROR("Unknown PNG color type %d in '%s'\n", color_type, name);
			png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
			delete[] buffer;
			return false;
	}

	stride = png_get_rowbytes(png_ptr, info_ptr);

	row_pointers = new png_bytep[height];
	ASSERT(row_pointers);

	data = new uint8_t[height * stride];
	ASSERT(data);

	for (uint32_t i = 0; i < height; ++i)
		row_pointers[i] = (png_bytep)data + i * stride;

	png_read_image(png_ptr, row_pointers);
	png_read_end(png_ptr, info_ptr);
	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

	delete[] row_pointers;
	delete[] buffer;

	image2D(GL_PVOID(data), width, height, internalFormat, format,
		GL_UNSIGNED_BYTE, genMIPs);

	delete[] data;

	return true;
}
/** 
Reads one PNG file. 
@param process Process the image data (0 for initial parameter determination)
@returns -1 on failure, 1 on sucess
*/
int decode_png(const char *pngname, int process, parameters_t *param)
{
  int num_pass = 1;
  int bit_depth, color_type;
  FILE *pngfile;
  //png_byte hdptr[8];

  /* Now open this PNG file, and examine its header to retrieve the 
     YUV4MPEG info that shall be written */
  pngfile = fopen(pngname, "rb");
  if (!pngfile)
    {
      perror("PNG file open failed:");
      return -1;
    }

  //fread(hdptr, 1, 8, pngfile);

#if 0 
  bool is_png = !png_sig_cmp(hdptr, 0, 8);
  if (!is_png)
    {
      mjpeg_error("%s is _no_ PNG file !\n");
      return -1;
    }
#endif
  
  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (!png_ptr)
    mjpeg_error_exit1("%s: Could not allocate PNG read struct !", pngname);
  
  png_init_io(png_ptr, pngfile);
  //png_set_sig_bytes(png_ptr, 8);
  
  info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr)
    {
      png_destroy_read_struct(&png_ptr,
			      (png_infopp)NULL, (png_infopp)NULL);
      mjpeg_error_exit1("%s: Could not allocate PNG info struct !", pngname);
    }
  
  end_info = png_create_info_struct(png_ptr);
  if (!end_info)
    {
      png_destroy_read_struct(&png_ptr, &info_ptr,
			      (png_infopp)NULL);
      mjpeg_error_exit1("%s: Could not allocate PNG end info struct !", pngname);
    }
  
  if (setjmp(png_jmpbuf(png_ptr)))
    {
      png_destroy_read_struct(&png_ptr, &info_ptr,
			      &end_info);
      mjpeg_error("%s: Corrupted PNG file !", pngname);
      return -1;
    }
  
  if (process)
    png_set_read_user_transform_fn(png_ptr, png_separation);
  png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_STRIP_ALPHA, NULL);
  
  if (png_get_IHDR(png_ptr, info_ptr, &param->width, &param->height, &bit_depth,
		       //   &color_type, &interlace_type, &compression_type, &filter_type))
		   &color_type, NULL, NULL, NULL))	
    num_pass = png_set_interlace_handling(png_ptr);
  else
    mjpeg_error_exit1("PNG header reading failed !!\n");
#if 0 
  mjpeg_info("Reading info struct...\n");
  png_read_info(png_ptr, info_ptr);
  mjpeg_info("Done...\n");
  
  if (png_get_IHDR(png_ptr, info_ptr, &param->width, &param->height, &bit_depth,
		       //   &color_type, &interlace_type, &compression_type, &filter_type))
		   &color_type, NULL, NULL, NULL))	
    num_pass = png_set_interlace_handling(png_ptr);
  else
    mjpeg_error_exit1("PNG header reading failed !!\n");
  
  if (process)
    {
      printf("%d passes needed\n\n", num_pass);
      
      if (bit_depth != 8 && bit_depth != 16)
	{
	  mjpeg_error_exit1("Invalid bit_depth %d, only 8 and 16 bit allowed !!\n", bit_depth);
	}
      
      png_set_strip_16(png_ptr); // always has to strip the 16bit input, MPEG can't handle it	  
      png_set_strip_alpha(png_ptr); // Alpha can't be processed until Z/Alpha is integrated
      
      printf("\nAllocating row buffer...");
      png_set_read_user_transform_fn(png_ptr, png_separation);
      png_bytep row_buf = (png_bytep)png_malloc(png_ptr,
						png_get_rowbytes(png_ptr, info_ptr));
      
      for (int n=0; n < num_pass; n++)
	for (int y=0; y < sh_param->height; y++)
	  {
	    printf("Writing row data for pass %d\n", n);
	    png_read_rows(png_ptr, (png_bytepp)&row_buf, NULL, 1);
	  }
      
      png_free(png_ptr, row_buf);	      
    }
  png_read_end(png_ptr, info_ptr);
#endif  
  if (setjmp(png_ptr->jmpbuf)) {
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    return 2;
    }

  fclose(pngfile);

  return 1;
}
Exemple #17
0
png_bytep readpng_get_image(png_structp* png_ptr, png_infop* info_ptr, png_infop* end_ptr)
{
        //test for
        if(setjmp(png_jmpbuf(*png_ptr)))
        {
                png_destroy_read_struct(png_ptr, info_ptr, NULL);
                std::cerr << "error during setjmp" << std::endl;
                return NULL;
        }

        png_uint_32 width, height;
        int bit_depth, color_type;
        png_uint_32 numrowbytes;
        png_bytep dataBlock;

        // gamma correction start (optional)
        double display_exponent = 2.2; //standard in most systems + standard in imageprocessing
        int envGamma = 0;
        if(envGamma)
                display_exponent = (double)envGamma;


        double gamma;

        if(png_get_gAMA(*png_ptr, *info_ptr, &gamma))
                png_set_gamma(*png_ptr, display_exponent, gamma);

        // gamma correction end
       
       
        png_get_IHDR(*png_ptr, *info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);


        //transform the png to a standard format
        if(color_type == PNG_COLOR_TYPE_PALETTE)
                png_set_expand(*png_ptr);
        if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
                png_set_expand(*png_ptr);
        if(png_get_valid(*png_ptr, *info_ptr, PNG_INFO_tRNS))
                png_set_expand(*png_ptr);
        if(bit_depth == 16)
                png_set_strip_16(*png_ptr);
        if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
                png_set_gray_to_rgb(*png_ptr);

        png_read_update_info(*png_ptr, *info_ptr);
        //end

        //proccessing for the dataBlock (pixeldata)
        numrowbytes = png_get_rowbytes(*png_ptr, *info_ptr);
        png_bytep row_pointers[height];

        dataBlock = (png_bytep)malloc(sizeof(png_byte)*numrowbytes*height);
        for(png_uint_32 i = 0; i<height; i++)
                row_pointers[i] = dataBlock + i*numrowbytes;


        png_read_image(*png_ptr, row_pointers);
        //end

        //optional reading of end in end_ptr and test for consistence
        png_read_end(*png_ptr, NULL);
        
        return dataBlock;
}
Exemple #18
0
unsigned char *sdlgl_load_png_file(const char *filename,
    int *image_w, int *image_h)
{
  /* -AJA- all these volatiles here may seem strange.  They are needed
   * because the ANSI C standard (which GCC adheres to) says that when
   * setjmp/longjmp is being used, only volatile local variables are
   * guaranteed to keep their state if longjmp() gets called.
   */
  FILE * volatile fp = NULL;
  unsigned char * volatile image_dat = NULL;
  png_bytep * volatile row_pointers = NULL;

  /* we take the address of these two, so we shouldn't need the
   * volatile.  (GCC complains about discarding qualifiers if the
   * volatile is there).
   */
  png_structp /*volatile*/ png_ptr = NULL;
  png_infop   /*volatile*/ info_ptr = NULL;

  char sig_buf[CHECK_PNG_BYTES];
  png_uint_32 width, height;
  int bit_depth, color_type, interlace_type;
  int row, stride;

  /* open the prospective PNG file */
#ifdef FILE_AREAS
  fp = fopen_datafile_area(FILE_AREA_SHARE, filename, RDBMODE, FALSE);
#else
  fp = fopen_datafile(filename, RDBMODE, FALSE);
#endif
  if (!fp)
  {
    sdlgl_warning("Failed to open file: %s\n", filename);
    return NULL;
  }

  /* read in some of the signature bytes */
  if (fread(sig_buf, 1, CHECK_PNG_BYTES, fp) != CHECK_PNG_BYTES)
  {
    sdlgl_warning("Failed to read from file: %s\n", filename);
    goto failed;
  }

  /* compare the first CHECK_PNG_BYTES bytes of the signature */
  if (png_sig_cmp(sig_buf, (png_size_t)0, CHECK_PNG_BYTES) != 0)
  {
    sdlgl_warning("File is not a PNG file: %s\n", filename);
    goto failed;
  }

  /* pass NULLs for the error functions -- thus use the setjump stuff
   */
  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

  if (png_ptr == NULL)
  {
    sdlgl_warning("Problem within LibPNG (no memory ?)\n");
    goto failed;
  }

  /* allocate/initialize the memory for image information */
  info_ptr = png_create_info_struct(png_ptr);
  if (info_ptr == NULL)
  {
    sdlgl_warning("Out of memory with LibPNG\n");
    goto failed;
  }

  /* set error handling since we are using the setjmp/longjmp method
   * (this is the normal method of doing things with libpng).
   */
  if (setjmp(png_ptr->jmpbuf))
  {
    sdlgl_warning("Problem within LibPNG (unknown)\n");
    goto failed;
  }

  /* set up the input control since we're using standard C streams */
  png_init_io(png_ptr, fp);
  png_set_sig_bytes(png_ptr, CHECK_PNG_BYTES);

  /* the call to png_read_info() gives us all of the information from the
   * PNG file before the first IDAT (image data chunk)
   */
  png_read_info(png_ptr, info_ptr);

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

  *image_w = (int)width;
  *image_h = (int)height;

  /* tell libpng to strip 16 bit/color down to 8 bits/color */
  png_set_strip_16(png_ptr);

  /* expand paletted colors into true RGB triplets */
  if (color_type == PNG_COLOR_TYPE_PALETTE ||
      color_type == PNG_COLOR_TYPE_GRAY ||
      png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
  {
     png_set_expand(png_ptr);
  }

  /* set alpha position and filler value */
  png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER);
 
  /* let all the above calls take effect */
  png_read_update_info(png_ptr, info_ptr);
  
  /* allocate the memory for the image */
  stride = png_get_rowbytes(png_ptr, info_ptr);

  image_dat = (unsigned char *) alloc(height * stride);
  row_pointers = (png_bytep *) alloc(height * sizeof(png_bytep));
   
  for (row=0; row < height; row++)
  {
     row_pointers[row] = image_dat + row * stride;
  }

  /* now read in the image.  Yeah baby ! */
  png_read_image(png_ptr, row_pointers);
  png_read_end(png_ptr, info_ptr);

  /* free stuff & close the file */
  png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
  free(row_pointers);
  fclose(fp);

  return image_dat;

  /* -AJA- Normally I don't like gotos.  In this situation where there
   * are lots of points of possible failure and a growing set of
   * things to be undone, it makes for nicer code.
   */
failed:

  if (image_dat)
    free(image_dat);
  
  if (png_ptr)
  {
    /* assume NULLs not allowed (png docs don't say, bad bad) */
    if (info_ptr)
      png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
    else
      png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
  }

  if (row_pointers)
    free(row_pointers);

  if (fp)
    fclose(fp);
  
  return NULL;
}
unsigned char* PPGame_LoadPNG(const char* fileName,unsigned long* imageWidth,unsigned long* imageHeight,unsigned long* bytesPerRow)
{

	FILE *PNG_file = fopen(fileName, "rb");

    fprintf(stderr, "open PNG file %s\n", fileName);

    if (PNG_file == NULL)
    {
        fprintf(stderr, "Can't open PNG file %s\n", fileName);
		return NULL;
    }
    
    unsigned char PNG_header[PNG_HEADER_SIZE];
    
    fread(PNG_header, 1, PNG_HEADER_SIZE, PNG_file);
    if (png_sig_cmp(PNG_header, 0, PNG_HEADER_SIZE) != 0)
    {
        fprintf(stderr, "%s is not a PNG file\n", fileName);
        fclose(PNG_file);
		return NULL;
    }
/*	
	{
		for (int i=0;i<8;i++) {
			printf("%02X,",PNG_header[i]);
		}
		printf("\n");
	}
*/
    png_structp PNG_reader
        = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (PNG_reader == NULL)
    {
        fprintf(stderr, "Can't start reading PNG file %s\n", fileName);
        fclose(PNG_file);
		return NULL;
    }

    png_infop PNG_info = png_create_info_struct(PNG_reader);
    if (PNG_info == NULL)
    {
        fprintf(stderr, "Can't get info for PNG file %s\n", fileName);
        png_destroy_read_struct(&PNG_reader, NULL, NULL);
        fclose(PNG_file);
		return NULL;
    }

    png_infop PNG_end_info = png_create_info_struct(PNG_reader);
    if (PNG_end_info == NULL)
    {
        fprintf(stderr, "Can't get end info for PNG file %s\n", fileName);
        png_destroy_read_struct(&PNG_reader, &PNG_info, NULL);
        fclose(PNG_file);
		return NULL;
    }
    
    if (setjmp(png_jmpbuf(PNG_reader)))
    {
        fprintf(stderr, "Can't load PNG file %s\n", fileName);
        png_destroy_read_struct(&PNG_reader, &PNG_info, &PNG_end_info);
        fclose(PNG_file);
		return NULL;
    }
    
    png_init_io(PNG_reader, PNG_file);
    png_set_sig_bytes(PNG_reader, PNG_HEADER_SIZE);
    
    png_read_info(PNG_reader, PNG_info);

	if (PNG_reader == NULL) {
        fclose(PNG_file);
		return NULL;
    }
    
    png_uint_32 width, height;
    width = png_get_image_width(PNG_reader, PNG_info);
    height = png_get_image_height(PNG_reader, PNG_info);

//printf("width %d\n",width);
//printf("height %d\n",height);
    
    png_uint_32 bit_depth, color_type;
    bit_depth = png_get_bit_depth(PNG_reader, PNG_info);
    color_type = png_get_color_type(PNG_reader, PNG_info);

//printf("bit_depth %d\n",bit_depth);
//printf("rowbytes %d\n",png_get_rowbytes(PNG_reader, PNG_info));
    
    if (color_type == PNG_COLOR_TYPE_PALETTE)
    {
    //png_set_palette_to_rgb(PNG_reader);
    png_set_palette_to_rgb(PNG_reader);
    }
/*
    if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) 
    {
    png_set_gray_1_2_4_to_8(PNG_reader);
    }
*/
    if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
    {
    png_set_gray_to_rgb(PNG_reader);
    }
    if (png_get_valid(PNG_reader, PNG_info, PNG_INFO_tRNS))
    {
    png_set_tRNS_to_alpha(PNG_reader);
    }
    else
    {
    png_set_filler(PNG_reader, 0xff, PNG_FILLER_AFTER);
    }
    if (bit_depth == 16)
    {
        png_set_strip_16(PNG_reader);
    }
    
    png_read_update_info(PNG_reader, PNG_info);
    
    png_byte* PNG_image_buffer = (png_byte*)malloc(4 * width * height);
    png_byte** PNG_rows = (png_byte**)malloc(height * sizeof(png_byte*));
    
    unsigned int row;
    for (row = 0; row < height; ++row)
    {
        //PNG_rows[height - 1 - row] = PNG_image_buffer + (row * 4 * width);
        PNG_rows[row] = PNG_image_buffer + (row * 4 * width);
    }
    
    png_read_image(PNG_reader, PNG_rows);
    
    free(PNG_rows);
    
    png_destroy_read_struct(&PNG_reader, &PNG_info, &PNG_end_info);
    fclose(PNG_file);

    *imageWidth = width;
    *imageHeight = height;
	*bytesPerRow = width*4;

printf("width %d,height %d\n",width,height);

	{
		unsigned long width,height;
		unsigned char* image;
		width = *imageWidth;
		height = *imageHeight;
		image = PNG_image_buffer;
		if (image) {
			unsigned char* pixel = (unsigned char*)malloc(height*width*4);
			if (pixel) {
				int i,j;
				for (i = 0; i < height; i++) {
					for (j = 0; j < width; j++) {
#if 0
						pixel[j*4+0+i*width*4] = 0xff;
						pixel[j*4+1+i*width*4] = 0xff;
						pixel[j*4+2+i*width*4] = 0xff;
						pixel[j*4+3+i*width*4] = 0xff;
#else
						unsigned char r,g,b,a;
						r = image[j*4+0+i*width*4];
						g = image[j*4+1+i*width*4];
						b = image[j*4+2+i*width*4];
						a = image[j*4+3+i*width*4];

						if (a == 0) {
							pixel[j*4+0+i*width*4] = 0;
							pixel[j*4+1+i*width*4] = 0;
							pixel[j*4+2+i*width*4] = 0;
							pixel[j*4+3+i*width*4] = 0;
						} else {
							pixel[j*4+0+i*width*4] = r;
							pixel[j*4+1+i*width*4] = g;
							pixel[j*4+2+i*width*4] = b;
							pixel[j*4+3+i*width*4] = a;
						}
#endif
					}
				}
				free(image);
				PNG_image_buffer = pixel;
			}
		}
	}

	return PNG_image_buffer;
}
int fh_png_load(const char *name,unsigned char **buffer,int* /*xp*/,int* /*yp*/)
{
	static const png_color_16 my_background = {0, 0, 0, 0, 0};

	png_structp png_ptr;
	png_infop info_ptr;
	png_uint_32 width, height;
	unsigned int i;
	int bit_depth, color_type, interlace_type;
	int number_passes,pass;
	png_byte * fbptr;
	FILE     * fh;

	if(!(fh=fopen(name,"rb")))	return(FH_ERROR_FILE);

	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
	if(png_ptr == NULL) {
		fclose(fh);
		return(FH_ERROR_FORMAT);
	}
	info_ptr = png_create_info_struct(png_ptr);
	if(info_ptr == NULL)
	{
		png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
		fclose(fh);
		return(FH_ERROR_FORMAT);
	}

	if(setjmp(png_ptr->jmpbuf))
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
		fclose(fh);
		return(FH_ERROR_FORMAT);
	}

	png_init_io(png_ptr,fh);

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

	if (color_type == PNG_COLOR_TYPE_PALETTE)
	{
		png_set_palette_to_rgb(png_ptr);
		png_set_background(png_ptr, (png_color_16*)&my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
		/* other possibility for png_set_background: use png_get_bKGD */
	}

	if (color_type == PNG_COLOR_TYPE_GRAY        ||
			color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
	{
		png_set_gray_to_rgb(png_ptr);
		png_set_background(png_ptr, (png_color_16*)&my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
	}

	/* this test does not trigger for 8bit-paletted PNGs with newer libpng (1.2.36 at least),
	   but the data delivered is with alpha channel anyway, so always strip alpha for now
	 */
#if PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR <= 2 && PNG_LIBPNG_VER_RELEASE < 36
	if (color_type & PNG_COLOR_MASK_ALPHA)
#endif
		png_set_strip_alpha(png_ptr);

	if (bit_depth < 8)
		png_set_packing(png_ptr);

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

	/* on Intel PC ?:
	   if (bit_depth == 16)
	   png_set_swap(png_ptr);
	   */

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

	if (width * 3 != png_get_rowbytes(png_ptr, info_ptr))
	{
		printf("[png.cpp]: Error processing %s - please report (including image).\n", name);
		printf("           width: %lu rowbytes: %lu\n", width, png_get_rowbytes(png_ptr, info_ptr));
		fclose(fh);
		return(FH_ERROR_FORMAT);
	}

	for(pass = 0; pass < number_passes; pass++)
	{
		fbptr = (png_byte *)(*buffer);
		for (i = 0; i < height; i++, fbptr += width * 3)
		{
			png_read_row(png_ptr, fbptr, NULL);
		}
	}
	png_read_end(png_ptr, info_ptr);
	png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
	fclose(fh);
	return(FH_ERROR_OK);
}
static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
	png_structp png_ptr = NULL;
	png_infop info_ptr;
	png_uint_32 width, height;
	png_colorp png_palette = NULL;
	int color_type, palette_entries = 0;
	int bit_depth, pixel_depth;		// pixel_depth = bit_depth * channels

	FIBITMAP *dib = NULL;
	RGBQUAD *palette = NULL;		// pointer to dib palette
	png_bytepp  row_pointers = NULL;
	int i;

    fi_ioStructure fio;
    fio.s_handle = handle;
	fio.s_io = io;
    
	if (handle) {
		try {		
			// check to see if the file is in fact a PNG file

			BYTE png_check[PNG_BYTES_TO_CHECK];

			io->read_proc(png_check, PNG_BYTES_TO_CHECK, 1, handle);

			if (png_sig_cmp(png_check, (png_size_t)0, PNG_BYTES_TO_CHECK) != 0)
				return NULL;	// Bad signature
			
			// create the chunk manage structure

			png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, error_handler, warning_handler);

			if (!png_ptr)
				return NULL;			

			// create the info structure

		    info_ptr = png_create_info_struct(png_ptr);

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

			// init the IO

			png_set_read_fn(png_ptr, &fio, _ReadProc);

            if (setjmp(png_jmpbuf(png_ptr))) {
				png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
				return NULL;
			}

			// because we have already read the signature...

			png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK);

			// read the IHDR chunk

			png_read_info(png_ptr, info_ptr);
			png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);
			pixel_depth = info_ptr->pixel_depth;

			// get image data type (assume standard image type)

			FREE_IMAGE_TYPE image_type = FIT_BITMAP;
			if (bit_depth == 16) {
				if ((pixel_depth == 16) && (color_type == PNG_COLOR_TYPE_GRAY)) {
					image_type = FIT_UINT16;
				} 
				else if ((pixel_depth == 48) && (color_type == PNG_COLOR_TYPE_RGB)) {
					image_type = FIT_RGB16;
				} 
				else if ((pixel_depth == 64) && (color_type == PNG_COLOR_TYPE_RGB_ALPHA)) {
					image_type = FIT_RGBA16;
				} else {
					// tell libpng to strip 16 bit/color files down to 8 bits/color
					png_set_strip_16(png_ptr);
					bit_depth = 8;
				}
			}

#ifndef FREEIMAGE_BIGENDIAN
			if((image_type == FIT_UINT16) || (image_type == FIT_RGB16) || (image_type == FIT_RGBA16)) {
				// turn on 16 bit byte swapping
				png_set_swap(png_ptr);
			}
#endif						

			// set some additional flags

			switch(color_type) {
				case PNG_COLOR_TYPE_RGB:
				case PNG_COLOR_TYPE_RGB_ALPHA:
#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
					// flip the RGB pixels to BGR (or RGBA to BGRA)

					if(image_type == FIT_BITMAP)
						png_set_bgr(png_ptr);
#endif
					break;

				case PNG_COLOR_TYPE_PALETTE:
					// expand palette images to the full 8 bits from 2 bits/pixel

					if (pixel_depth == 2) {
						png_set_packing(png_ptr);
						pixel_depth = 8;
					}					

					break;

				case PNG_COLOR_TYPE_GRAY:
					// expand grayscale images to the full 8 bits from 2 bits/pixel

					if (pixel_depth == 2) {
						png_set_expand(png_ptr);
						pixel_depth = 8;
					}

					break;

				case PNG_COLOR_TYPE_GRAY_ALPHA:
					// expand 8-bit greyscale + 8-bit alpha to 32-bit

					png_set_gray_to_rgb(png_ptr);
#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
					// flip the RGBA pixels to BGRA

					png_set_bgr(png_ptr);
#endif
					pixel_depth = 32;

					break;

				default:
					throw "PNG format not supported";
			}

			// Get the background color to draw transparent and alpha images over.
			// 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_16p image_background = NULL;
			RGBQUAD rgbBkColor;

			if (png_get_bKGD(png_ptr, info_ptr, &image_background)) {
				rgbBkColor.rgbRed      = (BYTE)image_background->red;
				rgbBkColor.rgbGreen    = (BYTE)image_background->green;
				rgbBkColor.rgbBlue     = (BYTE)image_background->blue;
				rgbBkColor.rgbReserved = 0;
			}

			// unlike the example in the libpng documentation, we have *no* idea where
			// this file may have come from--so if it doesn't have a file gamma, don't
			// do any correction ("do no harm")

			double gamma = 0;
			double screen_gamma = 2.2;

			if (png_get_gAMA(png_ptr, info_ptr, &gamma) && ( flags & PNG_IGNOREGAMMA ) != PNG_IGNOREGAMMA)
				png_set_gamma(png_ptr, screen_gamma, gamma);

			// all transformations have been registered; now update info_ptr data

			png_read_update_info(png_ptr, info_ptr);

			// color type may have changed, due to our transformations

			color_type = png_get_color_type(png_ptr,info_ptr);

			// create a DIB and write the bitmap header
			// set up the DIB palette, if needed

			switch (color_type) {
				case PNG_COLOR_TYPE_RGB:
					png_set_invert_alpha(png_ptr);

					if(image_type == FIT_BITMAP) {
						dib = FreeImage_Allocate(width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
					} else {
						dib = FreeImage_AllocateT(image_type, width, height, pixel_depth);
					}
					break;

				case PNG_COLOR_TYPE_RGB_ALPHA:
					if(image_type == FIT_BITMAP) {
						dib = FreeImage_Allocate(width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
					} else {
						dib = FreeImage_AllocateT(image_type, width, height, pixel_depth);
					}
					break;

				case PNG_COLOR_TYPE_PALETTE:
					dib = FreeImage_Allocate(width, height, pixel_depth);

					png_get_PLTE(png_ptr,info_ptr, &png_palette,&palette_entries);

					palette = FreeImage_GetPalette(dib);

					// store the palette

					for (i = 0; i < palette_entries; i++) {
						palette[i].rgbRed   = png_palette[i].red;
						palette[i].rgbGreen = png_palette[i].green;
						palette[i].rgbBlue  = png_palette[i].blue;
					}

					// store the transparency table

					if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
						int num_trans = 0; 
						png_bytep trans = NULL; 
						png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL); 
						FreeImage_SetTransparencyTable(dib, (BYTE *)trans, num_trans);
					}

					break;

				case PNG_COLOR_TYPE_GRAY:
					dib = FreeImage_AllocateT(image_type, width, height, pixel_depth);

					if(pixel_depth <= 8) {
						palette = FreeImage_GetPalette(dib);
						palette_entries = 1 << pixel_depth;

						for (i = 0; i < palette_entries; i++) {
							palette[i].rgbRed   =
							palette[i].rgbGreen =
							palette[i].rgbBlue  = (BYTE)((i * 255) / (palette_entries - 1));
						}
					}

					// store the transparency table

					if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
						png_color_16p trans_values = NULL; 
						png_get_tRNS(png_ptr, info_ptr, NULL, NULL, &trans_values); 
						if(trans_values) {
							if (trans_values->gray < palette_entries) { 
								BYTE table[256]; 
								memset(table, 0xFF, palette_entries); 
								table[trans_values->gray] = 0; 
								FreeImage_SetTransparencyTable(dib, table, palette_entries); 
							}
						}
					}

					break;

				default:
					throw "PNG format not supported";
			}

			// store the background color 
			if(image_background) {
				FreeImage_SetBackgroundColor(dib, &rgbBkColor);
			}

			// get physical resolution

			if (png_get_valid(png_ptr, info_ptr, PNG_INFO_pHYs)) {
				png_uint_32 res_x, res_y;
				
				// we'll overload this var and use 0 to mean no phys data,
				// since if it's not in meters we can't use it anyway

				int res_unit_type = 0;

				png_get_pHYs(png_ptr,info_ptr,&res_x,&res_y,&res_unit_type);

				if (res_unit_type == 1) {
					FreeImage_SetDotsPerMeterX(dib, res_x);
					FreeImage_SetDotsPerMeterY(dib, res_y);
				}
			}

			// get possible ICC profile

			if (png_get_valid(png_ptr, info_ptr, PNG_INFO_iCCP)) {
				png_charp profile_name = NULL;
				png_charp profile_data = NULL;
				png_uint_32 profile_length = 0;
				int  compression_type;

				png_get_iCCP(png_ptr, info_ptr, &profile_name, &compression_type, &profile_data, &profile_length);

				// copy ICC profile data (must be done after FreeImage_Allocate)

				FreeImage_CreateICCProfile(dib, profile_data, profile_length);
			}


			// set the individual row_pointers to point at the correct offsets

			row_pointers = (png_bytepp)malloc(height * sizeof(png_bytep));

			if (!row_pointers) {
				if (palette)
					png_free(png_ptr, palette);				

				png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

				FreeImage_Unload(dib);
				return NULL;
			}

			// read in the bitmap bits via the pointer table

			for (png_uint_32 k = 0; k < height; k++)				
				row_pointers[height - 1 - k] = FreeImage_GetScanLine(dib, k);			

			png_read_image(png_ptr, row_pointers);

			// check if the bitmap contains transparency, if so enable it in the header

			if (FreeImage_GetBPP(dib) == 32)
				if (FreeImage_GetColorType(dib) == FIC_RGBALPHA)
					FreeImage_SetTransparent(dib, TRUE);
				else
					FreeImage_SetTransparent(dib, FALSE);
				
			// cleanup

			if (row_pointers) {
				free(row_pointers);
				row_pointers = NULL;
			}

			// read the rest of the file, getting any additional chunks in info_ptr

			png_read_end(png_ptr, info_ptr);

			// get possible metadata (it can be located both before and after the image data)

			ReadMetadata(png_ptr, info_ptr, dib);

			if (png_ptr) {
				// clean up after the read, and free any memory allocated - REQUIRED
				png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
			}

			return dib;
		} catch (const char *text) {
			if (png_ptr)
				png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
			
			if (row_pointers)
				free(row_pointers);

			if (dib)
				FreeImage_Unload(dib);			

			FreeImage_OutputMessageProc(s_format_id, text);
			
			return NULL;
		}
	}			

	return NULL;
}
Exemple #22
0
//
// In order to avoid CRT mismatches, we override all CRT functions libpng uses
// with our own. The alternative, using fopen and fread in our code and then
// passing a FILE* into libpng, isn't reliable because it crashes if libpng was
// compiled with a different CRT than lsapi.dll
//
HBITMAP LoadFromPNG(LPCSTR pszFilename)
{
    HBITMAP hDibSection = NULL;
    
    if (pszFilename != NULL)
    {
        FILE * hFile = fopen(pszFilename, "rb");
        
        if (hFile)
        {
            const size_t num_sig_bytes = 8;
            unsigned char sig[num_sig_bytes];
            
            fread(sig, 1, num_sig_bytes, hFile);
            
            if (png_check_sig(sig, num_sig_bytes))
            {
                PNGERROR PngError = { 0 };
                
                PngError.Wnd = GetForegroundWindow();
                
                png_structp Read = png_create_read_struct_2(
                    PNG_LIBPNG_VER_STRING, &PngError, PNGErrorHandler, NULL,
                    NULL, ls_png_malloc, ls_png_free);
                
                if (Read)
                {
                    png_infop Info = png_create_info_struct(Read);
                    
                    if (Info)
                    {
                        if (!setjmp(PngError.ErrorJump))
                        {
                            png_set_read_fn(Read, hFile, ls_png_read_data);
                            png_set_sig_bytes(Read, num_sig_bytes);
                            png_read_info(Read, Info);
                            
                            const unsigned char bit_depth = png_get_bit_depth(Read, Info);
                            const unsigned char color_type = png_get_color_type(Read, Info);
                            
                            if (color_type == PNG_COLOR_TYPE_PALETTE)
                            {
                                png_set_palette_to_rgb(Read);
                            }
                            
                            if ((color_type == PNG_COLOR_TYPE_GRAY) ||
                                (color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
                            {
                                if (bit_depth < 8)
                                {
                                    png_set_gray_1_2_4_to_8(Read);
                                }
                                png_set_gray_to_rgb(Read);
                            }
                            
                            if (png_get_valid(Read, Info, PNG_INFO_tRNS))
                            {
                                png_set_tRNS_to_alpha(Read);
                            }
                            
                            if (color_type & PNG_COLOR_MASK_COLOR)
                            {
                                png_set_bgr(Read);
                            }
                            
                            if (bit_depth == 16)
                            {
                                png_set_strip_16(Read);
                            }
                            
                            double image_gamma = 1 / 2.2;
                            png_get_gAMA(Read, Info, &image_gamma);
                            png_set_gamma(Read, 2.2, image_gamma);
                            
                            const int num_passes = png_set_interlace_handling(Read);
                            
                            png_read_update_info(Read, Info);
                            
                            BITMAPINFO bmi = { {0} };
                            bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
                            bmi.bmiHeader.biWidth = (LONG)png_get_image_width(Read, Info);
                            bmi.bmiHeader.biHeight = -(LONG)png_get_image_height(Read, Info);
                            bmi.bmiHeader.biBitCount = (WORD)(png_get_channels(Read, Info) * png_get_bit_depth(Read, Info));
                            bmi.bmiHeader.biPlanes = 1;
                            bmi.bmiHeader.biCompression = BI_RGB;
                            
                            unsigned char* bits;
                            hDibSection = CreateDIBSection(NULL, &bmi, 0,
                                reinterpret_cast<LPVOID*>(&bits), NULL, 0);
                            
                            if (!bits)
                            {
                                longjmp(PngError.ErrorJump, 1);
                            }
                            
                            unsigned int dib_bytes_per_scanline = \
                                (((bmi.bmiHeader.biWidth * bmi.bmiHeader.biBitCount) + 31) & ~31) >> 3;
                            
                            for (int Pass = 0; Pass < num_passes; ++Pass)
                            {
                                for (int y = 0; y < -bmi.bmiHeader.biHeight; ++y)
                                {
                                    unsigned char* Scanline = \
                                        reinterpret_cast<unsigned char*>(bits + (y * dib_bytes_per_scanline));
                                    
                                    png_read_row(Read, Scanline, NULL);
                                }
                            }
                            
                            png_read_end(Read, Info);
                            png_destroy_read_struct(&Read, &Info, NULL);
                        }
                        else
                        {
                            png_destroy_read_struct(&Read, &Info, NULL);
                        }
                    }
                    else
                    {
                        png_destroy_read_struct(&Read, NULL, NULL);
                    }
                }
Exemple #23
0
  static FT_Error
  Load_SBit_Png( FT_Bitmap*       map,
                 FT_Int           x_offset,
                 FT_Int           y_offset,
                 FT_Int           pix_bits,
                 TT_SBit_Metrics  metrics,
                 FT_Memory        memory,
                 FT_Byte*         data,
                 FT_UInt          png_len )
  {
    FT_Error      error = FT_Err_Ok;
    FT_StreamRec  stream;

    png_structp  png;
    png_infop    info;
    png_uint_32  imgWidth, imgHeight;

    int         bitdepth, color_type, interlace;
    FT_Int      i;
    png_byte*  *rows;


    if ( x_offset < 0 || x_offset + metrics->width  > map->width ||
         y_offset < 0 || y_offset + metrics->height > map->rows  ||
         pix_bits != 32 || map->pixel_mode != FT_PIXEL_MODE_BGRA )
    {
      error = FT_THROW( Invalid_Argument );
      goto Exit;
    }

    FT_Stream_OpenMemory( &stream, data, png_len );

    png = png_create_read_struct( PNG_LIBPNG_VER_STRING,
                                  &error,
                                  error_callback,
                                  warning_callback );
    if ( !png )
    {
      error = FT_THROW( Out_Of_Memory );
      goto Exit;
    }

    info = png_create_info_struct( png );
    if ( !info )
    {
      error = FT_THROW( Out_Of_Memory );
      png_destroy_read_struct( &png, NULL, NULL );
      goto Exit;
    }

    if ( ft_setjmp( png_jmpbuf( png ) ) )
    {
      error = FT_THROW( Invalid_File_Format );
      goto DestroyExit;
    }

    png_set_read_fn( png, &stream, read_data_from_FT_Stream );

    png_read_info( png, info );
    png_get_IHDR( png, info,
                  &imgWidth, &imgHeight,
                  &bitdepth, &color_type, &interlace,
                  NULL, NULL );

    if ( error != FT_Err_Ok                   ||
         (FT_Int)imgWidth  != metrics->width  ||
         (FT_Int)imgHeight != metrics->height )
      goto DestroyExit;

    /* convert palette/gray image to rgb */
    if ( color_type == PNG_COLOR_TYPE_PALETTE )
      png_set_palette_to_rgb( png );

    /* expand gray bit depth if needed */
    if ( color_type == PNG_COLOR_TYPE_GRAY )
    {
#if PNG_LIBPNG_VER >= 10209
      png_set_expand_gray_1_2_4_to_8( png );
#else
      png_set_gray_1_2_4_to_8( png );
#endif
    }

    /* transform transparency to alpha */
    if ( png_get_valid(png, info, PNG_INFO_tRNS ) )
      png_set_tRNS_to_alpha( png );

    if ( bitdepth == 16 )
      png_set_strip_16( png );

    if ( bitdepth < 8 )
      png_set_packing( png );

    /* convert grayscale to RGB */
    if ( color_type == PNG_COLOR_TYPE_GRAY       ||
         color_type == PNG_COLOR_TYPE_GRAY_ALPHA )
      png_set_gray_to_rgb( png );

    if ( interlace != PNG_INTERLACE_NONE )
      png_set_interlace_handling( png );

    png_set_filler( png, 0xFF, PNG_FILLER_AFTER );

    /* recheck header after setting EXPAND options */
    png_read_update_info(png, info );
    png_get_IHDR( png, info,
                  &imgWidth, &imgHeight,
                  &bitdepth, &color_type, &interlace,
                  NULL, NULL );

    if ( bitdepth != 8                              ||
        !( color_type == PNG_COLOR_TYPE_RGB       ||
           color_type == PNG_COLOR_TYPE_RGB_ALPHA ) )
    {
      error = FT_THROW( Invalid_File_Format );
      goto DestroyExit;
    }

    switch ( color_type )
    {
    default:
      /* Shouldn't happen, but fall through. */

    case PNG_COLOR_TYPE_RGB_ALPHA:
      png_set_read_user_transform_fn( png, premultiply_data );
      break;

    case PNG_COLOR_TYPE_RGB:
      /* Humm, this smells.  Carry on though. */
      png_set_read_user_transform_fn( png, convert_bytes_to_data );
      break;
    }

    if ( FT_NEW_ARRAY( rows, imgHeight ) )
    {
      error = FT_THROW( Out_Of_Memory );
      goto DestroyExit;
    }

    for ( i = 0; i < (FT_Int)imgHeight; i++ )
      rows[i] = map->buffer + ( y_offset + i ) * map->pitch + x_offset * 4;

    png_read_image( png, rows );

    FT_FREE( rows );

    png_read_end( png, info );

  DestroyExit:
    png_destroy_read_struct( &png, &info, NULL );
    FT_Stream_Close( &stream );

  Exit:
    return error;
  }
Exemple #24
0
WL_EXPORT uint32_t *
weston_load_image(const char *filename,
		  int32_t *width_arg, int32_t *height_arg,
		  uint32_t *stride_arg)
{
	png_struct *png;
	png_info *info;
	png_byte *data;
	png_byte **row_pointers = NULL;
	png_uint_32 width, height;
	int depth, color_type, interlace, stride;
	unsigned int i;
	FILE *fp;

	fp = fopen(filename, "rb");
	if (fp == NULL)
		return NULL;

	png = png_create_read_struct(PNG_LIBPNG_VER_STRING,
				     NULL, NULL, NULL);
	if (!png) {
		fclose(fp);
		return NULL;
	}

	info = png_create_info_struct(png);
	if (!info) {
		png_destroy_read_struct(&png, &info, NULL);
		fclose(fp);
		return NULL;
	}

	png_set_read_fn(png, fp, read_func);
	png_read_info(png, info);
	png_get_IHDR(png, info,
		     &width, &height, &depth,
		     &color_type, &interlace, NULL, NULL);

	if (color_type == PNG_COLOR_TYPE_PALETTE)
		png_set_palette_to_rgb(png);

	if (color_type == PNG_COLOR_TYPE_GRAY)
		png_set_expand_gray_1_2_4_to_8(png);

	if (png_get_valid(png, info, PNG_INFO_tRNS))
		png_set_tRNS_to_alpha(png);

	if (depth == 16)
		png_set_strip_16(png);

	if (depth < 8)
		png_set_packing(png);

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

	if (interlace != PNG_INTERLACE_NONE)
		png_set_interlace_handling(png);

	png_set_filler(png, 0xff, PNG_FILLER_AFTER);
	png_set_read_user_transform_fn(png, premultiply_data);
	png_read_update_info(png, info);
	png_get_IHDR(png, info,
		     &width, &height, &depth,
		     &color_type, &interlace, NULL, NULL);

	stride = width * 4;
	data = malloc(stride * height);
	if (!data) {
		png_destroy_read_struct(&png, &info, NULL);
		fclose(fp);
		return NULL;
	}

	row_pointers = malloc(height * sizeof row_pointers[0]);
	if (row_pointers == NULL) {
		free(data);
		png_destroy_read_struct(&png, &info, NULL);
		fclose(fp);
		return NULL;
	}

	for (i = 0; i < height; i++)
		row_pointers[i] = &data[i * stride];

	png_read_image(png, row_pointers);
	png_read_end(png, info);

	free(row_pointers);
	png_destroy_read_struct(&png, &info, NULL);
	fclose(fp);

	*width_arg = width;
	*height_arg = height;
	*stride_arg = stride;

	return (uint32_t *) data;
}
Exemple #25
0
int png_load_img(img I) {
    unsigned char **p, **q;
    png_structp png_ptr;
    png_infop info_ptr;
    png_uint_32 width, height;
    int i, j, bit_depth, color_type, interlace_type;
    png_bytepp row_pointers;

    img_alloc(I);

    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
        NULL, NULL, NULL);

    if (png_ptr == NULL) {
        I->err = IE_HDRFORMAT;
        return 0;
    }

    info_ptr = png_create_info_struct(png_ptr);

    if (info_ptr == NULL) {
        png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
        I->err = IE_HDRFORMAT;
        return 0;
    }
    
    rewind(I->fp);
    png_init_io(png_ptr, I->fp);

    png_read_info(png_ptr, info_ptr);

    /* Get image specific data */
    png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
        &interlace_type, NULL, NULL);

    /* Convert greyscale images to 8-bit RGB */
    if (color_type == PNG_COLOR_TYPE_GRAY ||
        color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
        if (bit_depth < 8) {
            //png_set_gray_1_2_4_to_8(png_ptr);
            png_set_expand_gray_1_2_4_to_8(png_ptr);
        }
        png_set_gray_to_rgb(png_ptr);
    }

    /* Change paletted images to RGB */
    if (color_type == PNG_COLOR_TYPE_PALETTE)
        png_set_expand(png_ptr);

    if (bit_depth < 8)
        png_set_expand(png_ptr);

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

    /* The gdk img widget appears to expect 8-bit RGB followed by a 
     * filler byte. */
    png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
    
    /* Update the info structure after the transforms */
    png_read_update_info(png_ptr, info_ptr); 
/*    png_set_rows(png_ptr, info_ptr, row_pointers)*/

    /* Allocate space before reading the image */
    row_pointers = png_malloc(png_ptr, height * sizeof(png_bytep));
    for (i = 0; i < height; i++) {
        row_pointers[i] = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
    }
    
    /* Read in the image and copy it to the gdk img structure */
    png_read_image(png_ptr, row_pointers);
    
    p = (unsigned char **)I->data;
    q = (unsigned char **)row_pointers;

    for (i = 0; i < height; i++) {
        for (j = 0; j < png_get_rowbytes(png_ptr, info_ptr); j++) {
           p[i][j] = q[i][j];
        }
    }

    png_read_end(png_ptr, info_ptr);

    /* Clean up */
    png_free(png_ptr, row_pointers);
    png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);

    return 1;
}
int image_png_load(MediaScanImage *i) {
  int bit_depth, color_type, num_passes, x, y;
  int ofs;
  volatile unsigned char *ptr = NULL; // volatile = won't be rolled back if longjmp is called
  PNGData *p = (PNGData *)i->_png;

  if (setjmp(png_jmpbuf(p->png_ptr))) {
    if (ptr != NULL)
      free((void *)ptr);
    image_png_destroy(i);
    return 0;
  }

  // XXX If reusing the object a second time, we need to completely create a new png struct

  bit_depth = png_get_bit_depth(p->png_ptr, p->info_ptr);
  color_type = png_get_color_type(p->png_ptr, p->info_ptr);

  if (color_type == PNG_COLOR_TYPE_PALETTE) {
    png_set_expand(p->png_ptr); // png_set_palette_to_rgb(p->png_ptr);
    i->channels = 4;
  }
  else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
    png_set_expand(p->png_ptr); // png_set_expand_gray_1_2_4_to_8(p->png_ptr);
  else if (png_get_valid(p->png_ptr, p->info_ptr, PNG_INFO_tRNS))
    png_set_expand(p->png_ptr); // png_set_tRNS_to_alpha(p->png_ptr);

  if (bit_depth == 16)
    png_set_strip_16(p->png_ptr);
  else if (bit_depth < 8)
    png_set_packing(p->png_ptr);

  // Make non-alpha RGB/Palette 32-bit and Gray 16-bit for easier handling
  if (!(color_type & PNG_COLOR_MASK_ALPHA)) {
    png_set_add_alpha(p->png_ptr, 0xFF, PNG_FILLER_AFTER);
  }

  num_passes = png_set_interlace_handling(p->png_ptr);

  LOG_DEBUG("png bit_depth %d, color_type %d, channels %d, num_passes %d\n",
            bit_depth, color_type, i->channels, num_passes);

  png_read_update_info(p->png_ptr, p->info_ptr);

  image_alloc_pixbuf(i, i->width, i->height);

  ptr = (unsigned char *)malloc(png_get_rowbytes(p->png_ptr, p->info_ptr));

  ofs = 0;

  if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { // Grayscale (Alpha)
    if (num_passes == 1) {      // Non-interlaced
      for (y = 0; y < i->height; y++) {
        png_read_row(p->png_ptr, (unsigned char *)ptr, NULL);
        for (x = 0; x < i->width; x++) {
          i->_pixbuf[ofs++] = COL_FULL(ptr[x * 2], ptr[x * 2], ptr[x * 2], ptr[x * 2 + 1]);
        }
      }
    }
    else if (num_passes == 7) { // Interlaced
      image_png_interlace_pass_gray(i, (unsigned char *)ptr, 0, 8, 0, 8);
      image_png_interlace_pass_gray(i, (unsigned char *)ptr, 0, 8, 4, 8);
      image_png_interlace_pass_gray(i, (unsigned char *)ptr, 4, 8, 0, 4);
      image_png_interlace_pass_gray(i, (unsigned char *)ptr, 0, 4, 2, 4);
      image_png_interlace_pass_gray(i, (unsigned char *)ptr, 2, 4, 0, 2);
      image_png_interlace_pass_gray(i, (unsigned char *)ptr, 0, 2, 1, 2);
      image_png_interlace_pass_gray(i, (unsigned char *)ptr, 1, 2, 0, 1);
    }
  }
  else {                        // RGB(A)
    if (num_passes == 1) {      // Non-interlaced
      for (y = 0; y < i->height; y++) {
        png_read_row(p->png_ptr, (unsigned char *)ptr, NULL);
        for (x = 0; x < i->width; x++) {
          i->_pixbuf[ofs++] = COL_FULL(ptr[x * 4], ptr[x * 4 + 1], ptr[x * 4 + 2], ptr[x * 4 + 3]);
        }
      }
    }
    else if (num_passes == 7) { // Interlaced
      // The first pass will return an image 1/8 as wide as the entire image
      // (every 8th column starting in column 0)
      // and 1/8 as high as the original (every 8th row starting in row 0)
      image_png_interlace_pass(i, (unsigned char *)ptr, 0, 8, 0, 8);

      // The second will be 1/8 as wide (starting in column 4)
      // and 1/8 as high (also starting in row 0)
      image_png_interlace_pass(i, (unsigned char *)ptr, 0, 8, 4, 8);

      // The third pass will be 1/4 as wide (every 4th pixel starting in column 0)
      // and 1/8 as high (every 8th row starting in row 4)
      image_png_interlace_pass(i, (unsigned char *)ptr, 4, 8, 0, 4);

      // The fourth pass will be 1/4 as wide and 1/4 as high
      // (every 4th column starting in column 2, and every 4th row starting in row 0)
      image_png_interlace_pass(i, (unsigned char *)ptr, 0, 4, 2, 4);

      // The fifth pass will return an image 1/2 as wide,
      // and 1/4 as high (starting at column 0 and row 2)
      image_png_interlace_pass(i, (unsigned char *)ptr, 2, 4, 0, 2);

      // The sixth pass will be 1/2 as wide and 1/2 as high as the original
      // (starting in column 1 and row 0)
      image_png_interlace_pass(i, (unsigned char *)ptr, 0, 2, 1, 2);

      // The seventh pass will be as wide as the original, and 1/2 as high,
      // containing all of the odd numbered scanlines.
      image_png_interlace_pass(i, (unsigned char *)ptr, 1, 2, 0, 1);
    }
    else {
      FATAL("Unsupported PNG interlace type (%d passes)\n", num_passes);
    }
  }

  free((void *)ptr);

  // This is not required, so we can save some time by not reading post-image chunks
  //png_read_end(p->png_ptr, p->info_ptr);

  return 1;
}
Exemple #27
0
pngquant_error rwpng_read_image24_libpng(FILE *infile, png24_image *mainprog_ptr)
{
    png_structp  png_ptr = NULL;
    png_infop    info_ptr = NULL;
    png_size_t   rowbytes;
    int          color_type, bit_depth;

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

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

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

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

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

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


    /* alternatively, could make separate calls to png_get_image_width(),
     * etc., but want bit_depth and color_type for later [don't care about
     * compression_type and filter_type => NULLs] */

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


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

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

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

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


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

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

    png_set_interlace_handling(png_ptr);

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

    png_read_update_info(png_ptr, info_ptr);

    rowbytes = png_get_rowbytes(png_ptr, info_ptr);

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

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

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

    png_read_image(png_ptr, row_pointers);

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

    png_read_end(png_ptr, NULL);

    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

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

    return SUCCESS;
}
Exemple #28
0
pdf_obj *start_png_image (FILE *file, char *res_name)
{
  pdf_obj *result = NULL, *dict = NULL;
  png_structp png_ptr;
  png_infop info_ptr;
  unsigned long width, height;
  unsigned bit_depth, color_type;
  rewind (file);
  if (!(png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,    
					  NULL, NULL, NULL)) ||
      !(info_ptr = png_create_info_struct (png_ptr))) {
    fprintf (stderr, "\n\nLibpng failed to initialize\n");
    if (png_ptr)
      png_destroy_read_struct(&png_ptr, NULL, NULL);
    return NULL;
  }
  png_init_io (png_ptr, file);
  /*  png_set_sig_bytes (png_ptr, 0); */
  /* Read PNG header */
  png_read_info (png_ptr, info_ptr);
  {
    png_color_16 default_background;
    png_color_16p file_background;

    default_background.red=255; default_background.green=255;
    default_background.blue=255; default_background.gray=0;
    default_background.index = 0;

    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);
    bit_depth = png_get_bit_depth(png_ptr, info_ptr);
    /* Convert paletted images to true color */
    if (color_type == PNG_COLOR_TYPE_PALETTE) {
      png_set_expand(png_ptr);
    }
    /* Limit image component depth to 8 bits */
    if (bit_depth == 16) {
      png_set_strip_16 (png_ptr);
    }
    if (png_get_bKGD(png_ptr, info_ptr, &file_background)) {
      png_set_background(png_ptr, file_background,
			 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
    } else {
      png_set_background(png_ptr, &default_background,
			 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
    }
  }
  { /* Read the image in raw RGB format */
    int i, rowbytes, pdf_bit_depth;
    png_bytep *rows;
    png_read_update_info(png_ptr, info_ptr);
    rows = NEW (height, png_bytep);
    rowbytes = png_get_rowbytes(png_ptr, info_ptr);
    rows[0] = NEW (rowbytes*height, png_byte);
    for (i=1; i<height; i++) {
      rows[i] = rows[0] + rowbytes * i;
    }
    png_read_image(png_ptr, rows);
    result = pdf_new_stream(STREAM_COMPRESS);
    dict = pdf_stream_dict(result);
    pdf_add_dict (dict, pdf_new_name ("Width"),
		  pdf_new_number(width));
    pdf_add_dict (dict, pdf_new_name ("Height"),
		  pdf_new_number(height));
    if (color_type == PNG_COLOR_TYPE_GRAY) {
      pdf_bit_depth = bit_depth;
    } else {
      pdf_bit_depth = 8;
    }
    pdf_add_dict (dict, pdf_new_name ("BitsPerComponent"),
		  pdf_new_number(pdf_bit_depth));
    if (color_type == PNG_COLOR_TYPE_GRAY ||
	color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
      pdf_add_dict (dict, pdf_new_name ("ColorSpace"),
		    pdf_new_name ("DeviceGray"));
    } else{
      pdf_add_dict (dict, pdf_new_name ("ColorSpace"),
		    pdf_new_name ("DeviceRGB"));
    }
    pdf_add_stream (result, (char *)rows[0], rowbytes*height);
    RELEASE (rows[0]);
    RELEASE (rows);
  }
  { /* Cleanup  */
    if (info_ptr)
      png_destroy_info_struct(png_ptr, &info_ptr);
    if (png_ptr)
      png_destroy_read_struct(&png_ptr, NULL, NULL);
  }
  return result;
}
Exemple #29
0
void png_reader::read(unsigned x0, unsigned y0,image_data_32& image) 
{
    FILE *fp=fopen(fileName_.c_str(),"rb");
    if (!fp) throw image_reader_exception("cannot open image file "+fileName_);

    png_structp png_ptr = png_create_read_struct
        (PNG_LIBPNG_VER_STRING,0,0,0);

    if (!png_ptr) 
    {
        fclose(fp);
        throw image_reader_exception("failed to allocate png_ptr");
    }

    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
    {
        png_destroy_read_struct(&png_ptr,0,0);
        fclose(fp);
        throw image_reader_exception("failed to create info_ptr");
    }

    png_set_read_fn(png_ptr, (png_voidp)fp, png_read_data);
    png_read_info(png_ptr, info_ptr);

    if (color_type_ == PNG_COLOR_TYPE_PALETTE)
        png_set_expand(png_ptr);
    if (color_type_ == PNG_COLOR_TYPE_GRAY && bit_depth_ < 8)
        png_set_expand(png_ptr);
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
        png_set_expand(png_ptr);
    if (bit_depth_ == 16)
        png_set_strip_16(png_ptr);
    if (color_type_ == PNG_COLOR_TYPE_GRAY ||
        color_type_ == PNG_COLOR_TYPE_GRAY_ALPHA)
        png_set_gray_to_rgb(png_ptr);

    // quick hack -- only work in >=libpng 1.2.7
    png_set_add_alpha(png_ptr,0xff,PNG_FILLER_AFTER); //rgba
        
    double gamma;
    if (png_get_gAMA(png_ptr, info_ptr, &gamma))
        png_set_gamma(png_ptr, 2.2, gamma);

    png_read_update_info(png_ptr, info_ptr);

    //START read image rows
    unsigned w=std::min(unsigned(image.width()),width_);
    unsigned h=std::min(unsigned(image.height()),height_);
    unsigned rowbytes=png_get_rowbytes(png_ptr, info_ptr);
    boost::scoped_array<png_byte> row(new png_byte[rowbytes]);
    for (unsigned i=0;i<height_;++i)
    {
        png_read_row(png_ptr,row.get(),0);
        if (i>=y0 && i<h) 
        {
            image.setRow(i-y0,reinterpret_cast<unsigned*>(&row[x0]),w);
        } 
    }
    //END
    png_read_end(png_ptr,0);
    png_destroy_read_struct(&png_ptr, &info_ptr,0);
    fclose(fp);
}
Exemple #30
0
int ImageFormatPNG::load(const char *name, int& width, int& height, int& format) {
 	printf("ImageFormatPNG::load\n");

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

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

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

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

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

 	png_set_read_fn(pngPtr,file, file_read_function);

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

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

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

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

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

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

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

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

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

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

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

    // create temporary file for glue code javascript
    ImageFormat::flip_y((unsigned char *)img_data_decoded,width,height,format);
    
    FILE* raw = fopen(kTempararyName,"wb");
    if (raw) {
        fwrite(img_data_decoded,width * height * format ,1 , raw);
        fclose(raw);
    }
     
    delete img_data_decoded;
    
    fclose(file);
    
	return 1;
}