Esempio n. 1
0
/**
 * Reads the heightmap and/or size of the heightmap from a PNG file.
 * If map == NULL only the size of the PNG is read, otherwise a map
 * with grayscale pixels is allocated and assigned to *map.
 */
static bool ReadHeightmapPNG(char *filename, uint *x, uint *y, byte **map)
{
	FILE *fp;
	png_structp png_ptr = NULL;
	png_infop info_ptr  = NULL;

	fp = FioFOpenFile(filename, "rb");
	if (fp == NULL) {
		ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_PNGMAP_FILE_NOT_FOUND, WL_ERROR);
		return false;
	}

	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (png_ptr == NULL) {
		ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_PNGMAP_MISC, WL_ERROR);
		fclose(fp);
		return false;
	}

	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL || setjmp(png_jmpbuf(png_ptr))) {
		ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_PNGMAP_MISC, WL_ERROR);
		fclose(fp);
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		return false;
	}

	png_init_io(png_ptr, fp);

	/* Allocate memory and read image, without alpha or 16-bit samples
	 * (result is either 8-bit indexed/grayscale or 24-bit RGB) */
	png_set_packing(png_ptr);
	png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_PACKING | PNG_TRANSFORM_STRIP_ALPHA | PNG_TRANSFORM_STRIP_16, NULL);

	/* Maps of wrong colour-depth are not used.
	 * (this should have been taken care of by stripping alpha and 16-bit samples on load) */
	if ((png_get_channels(png_ptr, info_ptr) != 1) && (png_get_channels(png_ptr, info_ptr) != 3) && (png_get_bit_depth(png_ptr, info_ptr) != 8)) {
		ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_PNGMAP_IMAGE_TYPE, WL_ERROR);
		fclose(fp);
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		return false;
	}

	if (map != NULL) {
		*map = MallocT<byte>(png_get_image_width(png_ptr, info_ptr) * png_get_image_height(png_ptr, info_ptr));
		ReadHeightmapPNGImageData(*map, png_ptr, info_ptr);
	}

	*x = png_get_image_width(png_ptr, info_ptr);
	*y = png_get_image_height(png_ptr, info_ptr);

	fclose(fp);
	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
	return true;
}
Esempio n. 2
0
/**
 * The PNG Heightmap loader.
 */
static void ReadHeightmapPNGImageData(byte *map, png_structp png_ptr, png_infop info_ptr)
{
	uint x, y;
	byte gray_palette[256];
	png_bytep *row_pointers = NULL;

	/* Get palette and convert it to grayscale */
	if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE) {
		int i;
		int palette_size;
		png_color *palette;
		bool all_gray = true;

		png_get_PLTE(png_ptr, info_ptr, &palette, &palette_size);
		for (i = 0; i < palette_size && (palette_size != 16 || all_gray); i++) {
			all_gray &= palette[i].red == palette[i].green && palette[i].red == palette[i].blue;
			gray_palette[i] = RGBToGrayscale(palette[i].red, palette[i].green, palette[i].blue);
		}

		/**
		 * For a non-gray palette of size 16 we assume that
		 * the order of the palette determines the height;
		 * the first entry is the sea (level 0), the second one
		 * level 1, etc.
		 */
		if (palette_size == 16 && !all_gray) {
			for (i = 0; i < palette_size; i++) {
				gray_palette[i] = 256 * i / palette_size;
			}
		}
	}

	row_pointers = png_get_rows(png_ptr, info_ptr);

	/* Read the raw image data and convert in 8-bit grayscale */
	for (x = 0; x < png_get_image_width(png_ptr, info_ptr); x++) {
		for (y = 0; y < png_get_image_height(png_ptr, info_ptr); y++) {
			byte *pixel = &map[y * png_get_image_width(png_ptr, info_ptr) + x];
			uint x_offset = x * png_get_channels(png_ptr, info_ptr);

			if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE) {
				*pixel = gray_palette[row_pointers[y][x_offset]];
			} else if (png_get_channels(png_ptr, info_ptr) == 3) {
				*pixel = RGBToGrayscale(row_pointers[y][x_offset + 0],
						row_pointers[y][x_offset + 1], row_pointers[y][x_offset + 2]);
			} else {
				*pixel = row_pointers[y][x_offset];
			}
		}
	}
}
Esempio n. 3
0
bool PngLoader::basicImageLoad() {
	DEBUG_ENTER_FUNC();
	_pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (!_pngPtr)
		return false;

	png_set_error_fn(_pngPtr, (png_voidp) NULL, (png_error_ptr) NULL, warningFn);

	_infoPtr = png_create_info_struct(_pngPtr);
	if (!_infoPtr) {
		png_destroy_read_struct(&_pngPtr, png_infopp_NULL, png_infopp_NULL);
		return false;
	}
	// Set the png lib to use our read function
	png_set_read_fn(_pngPtr, &_file, libReadFunc);

	unsigned int sig_read = 0;

	png_set_sig_bytes(_pngPtr, sig_read);
	png_read_info(_pngPtr, _infoPtr);
	int interlaceType;
	png_get_IHDR(_pngPtr, _infoPtr, (png_uint_32 *)&_width, (png_uint_32 *)&_height, &_bitDepth,
		&_colorType, &interlaceType, int_p_NULL, int_p_NULL);
	_channels = png_get_channels(_pngPtr, _infoPtr);

	if (_colorType & PNG_COLOR_MASK_PALETTE)
		_paletteSize = _infoPtr->num_palette;

	return true;
}
Esempio n. 4
0
/**
 * @brief Reads the png data as 32 bit format.
 */
png_bytep npng_readImage( npng_t *npng, png_bytep **rows, int *channels, int *pitch )
{
   png_bytep image_data;
   png_uint_32 width, height;
   png_bytep *row_pointers;
   png_uint_32  i, rowbytes;

   /* Get info. */
   npng_dim( npng, &width, &height );
   rowbytes = npng_pitch( npng );

   /* Create the array of pointers to image data */
   image_data = malloc( rowbytes * height );
   if (image_data == NULL)
      ERR( "Out of Memory" );
   row_pointers = malloc( sizeof(png_bytep) * height );
   if (row_pointers == NULL)
      ERR( "Out of Memory" );
   for (i=0; i<height; i++)
      row_pointers[i] = image_data + i*rowbytes;

   /* Return data. */
   if (channels != NULL)
      *channels = png_get_channels( npng->png_ptr, npng->info_ptr );
   if (pitch != NULL)
      *pitch = rowbytes;
   if (rows != NULL)
      *rows = row_pointers;
   else
      free( row_pointers );
   return image_data;
}
Esempio n. 5
0
File: png.c Progetto: ender672/oil
static VALUE each_interlace_none(struct each_args *args)
{
    struct readerdata *reader;
    unsigned char *inwidthbuf, *outwidthbuf, *yinbuf;
    struct xscaler *xs;
    struct yscaler *ys;
    uint32_t i, scaley;
    int cmp;

    reader = args->reader;
    xs = &args->xs;
    inwidthbuf = xscaler_psl_pos0(xs);
    outwidthbuf = args->outwidthbuf;
    ys = &args->ys;
    scaley = reader->scale_height;
    cmp = png_get_channels(reader->png, reader->info);

    png_write_info(args->wpng, args->winfo);

    for(i=0; i<scaley; i++) {
        while ((yinbuf = yscaler_next(ys))) {
            png_read_row(reader->png, inwidthbuf, NULL);
            xscaler_scale(xs, yinbuf);
        }
        yscaler_scale(ys, outwidthbuf, i, cmp, 0);
        png_write_row(args->wpng, outwidthbuf);
    }

    png_write_end(args->wpng, args->winfo);
    return Qnil;
}
Esempio n. 6
0
File: png.c Progetto: ender672/oil
static VALUE each_interlace(struct each_args *args)
{
    struct readerdata *reader;
    unsigned char *inwidthbuf, *outwidthbuf;
    uint32_t i, width, height, scaley;
    int cmp;
    struct xscaler *xs;

    reader = args->reader;
    xs = &args->xs;
    inwidthbuf = xscaler_psl_pos0(xs);
    outwidthbuf = args->outwidthbuf;
    scaley = reader->scale_height;
    cmp = png_get_channels(reader->png, reader->info);
    width = png_get_image_width(reader->png, reader->info);
    height = png_get_image_height(reader->png, reader->info);

    png_write_info(args->wpng, args->winfo);
    png_read_image(args->reader->png, (png_bytepp)args->scanlines);

    for (i=0; i<scaley; i++) {
        yscaler_prealloc_scale(height, scaley,
                               (uint8_t **)args->scanlines, (uint8_t *)inwidthbuf,
                               i, width, cmp, 0);
        xscaler_scale(xs, outwidthbuf);
        png_write_row(args->wpng, outwidthbuf);
    }
    png_write_end(args->wpng, args->winfo);
    return Qnil;
}
Esempio n. 7
0
//
////////////////////////////////////////////////////
//
// Image* readPNGIntoImage()
//
////////////////////////////////////////////////////
//
Image* PNGCodec::readPNGIntoImage(png_structp &png, png_infop &pngInfo)
{
	uint8 **buf;
	int y;
	png_uint_32 iWidth, iHeight, iRowLength;
	png_byte iColourType, iBitsPerChannel, iNumChannels;
	png_bytepp pngRows;
	Image* imgPNG;

	png_read_png(png, pngInfo, PNG_TRANSFORM_BGR | PNG_TRANSFORM_STRIP_ALPHA, png_voidp_NULL);
	
	// pixels are in info_ptr->row_pointers
	// where row_pointers is:
	//   png_bytep row_pointers[height];
	// and is probably not contiguous

	iColourType = png_get_color_type(png, pngInfo);
	//	if (iColourType != PNG_COLOR_TYPE_RGB_ALPHA)
	if (iColourType != PNG_COLOR_TYPE_RGB)
		throw new std::runtime_error("Colour type not supported - RGB only, PNGCodec::readPNGIntoImage()");



	iBitsPerChannel = png_get_bit_depth(png, pngInfo);
	iNumChannels = png_get_channels(png, pngInfo);

	iHeight = png_get_image_height(png, pngInfo);
	iWidth = png_get_image_width(png, pngInfo);

	iRowLength = iWidth * (iBitsPerChannel * iNumChannels) / 8; // Should be same as iWidth

	// 07-Jul-2009: Directly load the PNG into a pre-created image's
	//     buffer. Otherwise ImageRGB24 will make a copy of the buf, which
	//     is a waste of space (and problematic for very large PNGs!)
	imgPNG = new Image;
    imgPNG->width = iWidth;
    imgPNG->height = iHeight;
    imgPNG->data = new unsigned char*[iHeight];
	for (y = 0; y < iHeight; y++) {
        imgPNG->data[y] = new unsigned char[iRowLength];
    }

	buf = imgPNG->data;
	pngRows = png_get_rows(png, pngInfo);
	for (y = 0; y < iHeight; y++) {
		//		for (x = 0; x < iWidth; x++) {
		// This assumes BGR order, in readiness for the ImageRGB24 constructor
		// It also assumes 24-bit, no alpha
        // Yes, this is not good...
		memcpy(buf[y], pngRows[y], iRowLength);
		//memcpy((buf + (y * iRowLength)), pngRows[y], iRowLength);
	}
			

	// Clean up
	png_destroy_read_struct(&png, &pngInfo, png_infopp_NULL);

	return imgPNG;
}
Esempio n. 8
0
File: png.c Progetto: ender672/oil
static VALUE each(int argc, VALUE *argv, VALUE self)
{
	struct readerdata *reader;
	png_infop winfo;
	png_structp wpng;
	VALUE opts;
	int cmp, state, ret;
	struct each_args args;
	png_byte ctype;

	rb_scan_args(argc, argv, "01", &opts);

	Data_Get_Struct(self, struct readerdata, reader);

	raise_if_locked(reader);
	reader->locked = 1;

	cmp = png_get_channels(reader->png, reader->info);
	ctype = png_get_color_type(reader->png, reader->info);

	wpng = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,
		(png_error_ptr)error, (png_error_ptr)warning);
	winfo = png_create_info_struct(wpng);
	png_set_write_fn(wpng, 0, write_data_fn, flush_data_fn);

	png_set_IHDR(wpng, winfo, reader->scale_width, reader->scale_height, 8,
		ctype, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
		PNG_FILTER_TYPE_DEFAULT);

	args.reader = reader;
	args.wpng = wpng;
	args.winfo = winfo;
	args.outwidthbuf = malloc(reader->scale_width * cmp);
	if (!args.outwidthbuf) {
		rb_raise(rb_eRuntimeError, "Unable to allocate memory.");
	}

	ret = oil_libpng_init(&args.ol, reader->png, reader->info,
		reader->scale_width, reader->scale_height);
	if (ret!=0) {
		free(args.outwidthbuf);
		rb_raise(rb_eRuntimeError, "Unable to allocate memory.");
	}

	rb_protect((VALUE(*)(VALUE))each2, (VALUE)&args, &state);

	oil_libpng_free(&args.ol);
	free(args.outwidthbuf);
	png_destroy_write_struct(&wpng, &winfo);

	if (state) {
		rb_jump_tag(state);
	}

	return self;
}
Esempio n. 9
0
// Read out the image meta-data
void LLPngWrapper::updateMetaData()
{
	png_read_update_info(mReadPngPtr, mReadInfoPtr);
    mWidth = png_get_image_width(mReadPngPtr, mReadInfoPtr);
    mHeight = png_get_image_height(mReadPngPtr, mReadInfoPtr);
    mBitDepth = png_get_bit_depth(mReadPngPtr, mReadInfoPtr);
    mColorType = png_get_color_type(mReadPngPtr, mReadInfoPtr);
	mChannels = png_get_channels(mReadPngPtr, mReadInfoPtr);
	mHasBKGD = png_get_bKGD(mReadPngPtr, mReadInfoPtr, &mBackgroundColor);
}
Esempio n. 10
0
void pngSetHeader(PngStream* stream)
{
	stream->info.imageWidth = png_get_image_width(stream->png_ptr, stream->info_ptr);
	stream->info.imageHeight = png_get_image_height(stream->png_ptr, stream->info_ptr);
	stream->info.numComponents = png_get_channels(stream->png_ptr, stream->info_ptr);
	stream->info.colorSpace = getPngDecColourType(png_get_color_type(stream->png_ptr, stream->info_ptr));
	stream->info.bitDepth = png_get_bit_depth(stream->png_ptr, stream->info_ptr);
	stream->info.interlaceMethod = png_get_interlace_type(stream->png_ptr, stream->info_ptr);
	stream->info.chunkInformation = pngDecGetChunkInformation(stream);
}
Esempio n. 11
0
// Read out the image meta-data
void LLPngWrapper::updateMetaData()
{
	png_set_interlace_handling(mReadPngPtr); // <alchemy/>
	png_read_update_info(mReadPngPtr, mReadInfoPtr);
    mWidth = png_get_image_width(mReadPngPtr, mReadInfoPtr);
    mHeight = png_get_image_height(mReadPngPtr, mReadInfoPtr);
    mBitDepth = png_get_bit_depth(mReadPngPtr, mReadInfoPtr);
    mColorType = png_get_color_type(mReadPngPtr, mReadInfoPtr);
	mChannels = png_get_channels(mReadPngPtr, mReadInfoPtr);
}
Esempio n. 12
0
PngImage::PngImage(const ByteBuffer &compressed_bytes) {
    if (png_sig_cmp((png_bytep)compressed_bytes.raw(), 0, 8))
        panic("not png file");

    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr)
        panic("unable to create png read struct");

    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
        panic("unable to create png info struct");

    // don't call any png_* functions outside of this function D:
    if (setjmp(png_jmpbuf(png_ptr)))
        panic("libpng has jumped the shark");

    png_set_sig_bytes(png_ptr, 8);

    PngIo png_io = {8, (unsigned char *)compressed_bytes.raw(), compressed_bytes.length()};
    png_set_read_fn(png_ptr, &png_io, read_png_data);

    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);

    if (_width <= 0 || _height <= 0)
        panic("spritesheet image has no pixels");

    // bits per channel (not per pixel)
    int bits_per_channel = png_get_bit_depth(png_ptr, info_ptr);
    if (bits_per_channel != 8)
        panic("expected 8 bits per channel");

    int channel_count = png_get_channels(png_ptr, info_ptr);
    if (channel_count != 4)
        panic("expected 4 channels");

    int color_type = png_get_color_type(png_ptr, info_ptr);
    if (color_type != PNG_COLOR_TYPE_RGBA)
        panic("expected RGBA");

    _pitch = _width * bits_per_channel * channel_count / 8;
    _image_data.resize(_height * _pitch);
    png_bytep *row_ptrs = ok_mem(allocate_zero<png_bytep>(_height));

    for (int i = 0; i < _height; i++) {
        png_uint_32 q = (_height - i - 1) * _pitch;
        row_ptrs[i] = (png_bytep)_image_data.raw() + q;
    }

    png_read_image(png_ptr, row_ptrs);
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    destroy(row_ptrs, _height);
}
Esempio n. 13
0
void ogl::texture::load_png(const void *buf, size_t len, std::vector<GLubyte>& p)
{
    // Initialize all PNG import data structures.

    png_structp rp = 0;
    png_infop   ip = 0;
    png_bytep  *bp = 0;

    if (!(rp = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0)))
        throw std::runtime_error("Failure creating PNG read structure");

    if (!(ip = png_create_info_struct(rp)))
        throw std::runtime_error("Failure creating PNG info structure");

    // Initialize the user-defined IO structure.

    struct png_user_io user;

    user.buf = (png_bytep)  buf;
    user.len = (png_size_t) len;

    png_set_read_fn(rp, &user, png_user_read);

    // Enable the default PNG error handler.

    if (setjmp(png_jmpbuf(rp)) == 0)
    {
        // Read the PNG header.

        png_read_png(rp, ip, PNG_TRANSFORM_EXPAND   |
                             PNG_TRANSFORM_PACKING  |
                             PNG_TRANSFORM_STRIP_16 |
                             PNG_TRANSFORM_SWAP_ENDIAN, 0);

        // Extract image properties.

        w = GLsizei(png_get_image_width (rp, ip));
        h = GLsizei(png_get_image_height(rp, ip));
        c = GLsizei(png_get_channels    (rp, ip));

        p.resize(w * h * c);

        // Read the pixel data.

        if ((bp = png_get_rows(rp, ip)))

            for (GLsizei i = 0, j = h - 1; i < h; ++i, --j)
                memcpy(&p[w * c * i], bp[j], (w * c));
    }

    // Release all resources.

    png_destroy_read_struct(&rp, &ip, 0);
}
Esempio n. 14
0
GrfArray* grf_image_read_png(const char* filename){
  png_structp png_ptr;
  png_infop info_ptr;
  unsigned char header[8];
  FILE* infile = fopen(filename, "rb");
  if(!infile)
    abort_("[read_png_file] File %s could not be opened for reading", filename);

  fread(header, 1, 8, infile);
  if(png_sig_cmp(header, 0, 8))
    abort_("[read_png_file] File %s is not recognized as a PNG file", filename);

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

  info_ptr = png_create_info_struct(png_ptr);
  if(!info_ptr)
    abort_("[read_png_file] png_create_info_struct failed");

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

  png_set_sig_bytes(png_ptr, 8);
  png_read_info(png_ptr, info_ptr);

  uint32_t* size = malloc(sizeof(uint32_t) * 3);
  size[0] = png_get_image_height(png_ptr, info_ptr);
  size[1] = png_get_image_width(png_ptr, info_ptr);
  size[2] = png_get_channels(png_ptr, info_ptr);
  uint8_t bit_depth = png_get_bit_depth(png_ptr, info_ptr);
  GrfDataType type;
  switch (bit_depth) {
  case 16:
    type = GRF_UINT16; break;
  default:
    type = GRF_UINT8;  break;
  }
  GrfArray* array = grf_array_new_with_size_type(3, size, type);
  png_read_update_info(png_ptr, info_ptr);

  // Read file
  if(setjmp(png_jmpbuf(png_ptr))) abort_("[read_png_file] Error during read_image");
  uint8_t**buffer   = (uint8_t**)malloc(sizeof(uint8_t*) * size[0]);
  size_t row_stride = png_get_rowbytes(png_ptr, info_ptr);
  uint32_t i;
  for(i = 0; i < size[0]; i++) buffer[i] = array->data_uint8 + row_stride * i;
  png_read_image(png_ptr, buffer);
  fclose(infile);
  free(buffer);
  return array;
}
Esempio n. 15
0
struct image* image_from_png(const unsigned char* data, size_t sz) {
    /* Check file data header */
    if (png_sig_cmp(data, 0, 8)) {
        set_last_asset_load_error("Incorrect png header");
        return 0;
    }

    /* Allocate needed structures */
    png_struct* png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
    png_info* info = png_create_info_struct(png);
    png_info* end_info = png_create_info_struct(png);

    /* Register custom reader function */
    struct png_read_callback_data cbdata;
    cbdata.src_buf = (unsigned char*)data;
    cbdata.sz = sz;
    png_set_read_fn(png, (void*)&cbdata, png_read_callback_fn);

    /* Read image info */
    png_set_sig_bytes(png, 0);
    png_read_info(png, info);

    /* Gather image info */
    int width = png_get_image_width(png, info);
    int height = png_get_image_height(png, info);
    /* Bits per CHANNEL not per pixel */
    /* int bit_depth = png_get_bit_depth(png, info); */
    int channels = png_get_channels(png, info);

    /* Image to be returned */
    struct image* im = image_blank(width, height, channels);

    /* Read by row */
    png_byte** row_ptrs = malloc(height * sizeof(png_byte*));
    const size_t stride = png_get_rowbytes(png, info);
    for (int i = 0; i < height; ++i) {
        int q = (height - i - 1) * stride;
        row_ptrs[i] = im->data + q;
    }
    png_read_image(png, row_ptrs);
    free(row_ptrs);

    /* Free allocated structures */
    png_destroy_read_struct(0, 0, &end_info);
    png_destroy_read_struct(0, &info, 0);
    png_destroy_read_struct(&png, 0, 0);

    /* Return read image */
    return im;
}
Esempio n. 16
0
struct image *read_png(char *s, int len) {
	png_structp png_ptr;
	png_infop info_ptr;

	struct read_state state;
	state.base = s;
	state.off = 0;
	state.len = len;

	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, fail, fail, fail);
	if (png_ptr == NULL) {
		fprintf(stderr, "PNG init failed\n");
		exit(EXIT_FAILURE);
	}

	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL) {
		fprintf(stderr, "PNG init failed\n");
		exit(EXIT_FAILURE);
	}

	png_set_read_fn(png_ptr, &state, user_read_data);
	png_set_sig_bytes(png_ptr, 0);

	png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, NULL);

	png_uint_32 width, height;
	int bit_depth;
	int color_type, interlace_type;

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

	struct image *i = malloc(sizeof(struct image));
	i->width = width;
	i->height = height; 
	i->depth = png_get_channels(png_ptr, info_ptr);
	i->buf = malloc(i->width * i->height * i->depth);

	unsigned int row_bytes = png_get_rowbytes(png_ptr, info_ptr);
	png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr);

	int n;
	for (n = 0; n < i->height; n++) {
		memcpy(i->buf + row_bytes * n, row_pointers[n], row_bytes);
	}

	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
	return i;
}
Esempio n. 17
0
int image_png_read_header(MediaScanImage *i, MediaScanResult *r) {
  int x;
  PNGData *p = malloc(sizeof(PNGData));
  i->_png = (void *)p;
  LOG_MEM("new PNGData @ %p\n", i->_png);

  p->buf = (Buffer *)r->_buf;
  p->fp = r->_fp;
  p->path = r->path;

  p->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp) p, image_png_error, image_png_warning);
  if (!p->png_ptr)
    FATAL("Could not initialize libpng\n");

  p->info_ptr = png_create_info_struct(p->png_ptr);
  if (!p->info_ptr) {
    png_destroy_read_struct(&p->png_ptr, (png_infopp) NULL, (png_infopp) NULL);
    FATAL("Could not initialize libpng\n");
  }

  if (setjmp(png_jmpbuf(p->png_ptr))) {
    image_png_destroy(i);
    return 0;
  }

  png_set_read_fn(p->png_ptr, p, image_png_read_buf);

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

  i->width = png_get_image_width(p->png_ptr, p->info_ptr);
  i->height = png_get_image_height(p->png_ptr, p->info_ptr);
  i->channels = png_get_channels(p->png_ptr, p->info_ptr);
  i->has_alpha = 1;
  r->mime_type = MIME_IMAGE_PNG;

  // Match with DLNA profile
  // DLNA does not support interlaced images
  if (png_get_interlace_type(p->png_ptr, p->info_ptr) == PNG_INTERLACE_NONE) {
    for (x = 0; png_profiles_mapping[x].profile; x++) {
      if (i->width <= png_profiles_mapping[x].max_width && i->height <= png_profiles_mapping[x].max_height) {
        r->dlna_profile = png_profiles_mapping[x].profile->id;
        break;
      }
    }
  }

  return 1;
}
Esempio n. 18
0
File: png.c Progetto: ender672/axon
static VALUE
write_scanline(VALUE scan_line, png_structp png_ptr, png_infop info_ptr)
{
    png_uint_32 width;
    png_byte components;

    if (TYPE(scan_line) != T_STRING)
	scan_line = rb_obj_as_string(scan_line);

    width = png_get_image_width(png_ptr, info_ptr);
    components = png_get_channels(png_ptr, info_ptr);
    if ((png_uint_32)RSTRING_LEN(scan_line) != width * components)
	rb_raise(rb_eRuntimeError, "Scanline has a bad size. Expected %d * %d but got %d.",
		 (int)width, (int)components, (int)RSTRING_LEN(scan_line));

    png_write_row(png_ptr, (png_bytep)RSTRING_PTR(scan_line));
    return Qnil;
}
Esempio n. 19
0
QImage::Format QPngHandlerPrivate::readImageFormat()
{
        QImage::Format format = QImage::Format_Invalid;
        png_uint_32 width, height;
        int bit_depth, color_type;
        png_colorp palette;
        int num_palette;
        png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
        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) {
                format = QImage::Format_Mono;
            } else if (bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
                format = QImage::Format_ARGB32;
            } else {
                format = QImage::Format_Indexed8;
            }
        } 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);
            format = bit_depth == 1 ? QImage::Format_Mono : QImage::Format_Indexed8;
        } else {
            // 32-bit
            if (bit_depth == 16)
                png_set_strip_16(png_ptr);

            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)) {
                // We want 4 bytes, but it isn't an alpha channel
                format = QImage::Format_RGB32;
            }
        }

        return format;
}
Esempio n. 20
0
void setformat_rgba8(
    png_structp png, png_infop info,
    int bitdepth, int colortype )
{
    double gamma;
    if( png_get_gAMA( png, info, &gamma ) )
    {
        png_set_gamma( png, 2.2, gamma );
    }
    else
    {
        png_set_gamma( png, 2.2, 0.45455 );
    }
    if( colortype == PNG_COLOR_TYPE_PALETTE )
    {
        png_set_palette_to_rgb( png );
    }
    if( colortype == PNG_COLOR_TYPE_GRAY && bitdepth < 8 )
    {
        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 );
    }
    else
    {
        int channels = png_get_channels( png, info );
        if( channels == 1 || channels == 3 )
        {
            png_set_add_alpha( png, 255, PNG_FILLER_AFTER );
        }
    }
    if( colortype == PNG_COLOR_TYPE_GRAY ||
            colortype == PNG_COLOR_TYPE_GRAY_ALPHA )
    {
        png_set_gray_to_rgb( png );
    }
    if( bitdepth == 16 )
    {
        png_set_scale_16( png );
    }
}
Esempio n. 21
0
/* This function is called (as set by png_set_progressive_read_fn() above) when enough data has been supplied so all of the header has been read.  */
void info_callback(png_structp png_ptr, png_infop info) {

  file_end=0;
  width = png_get_image_width(png_ptr,info);
  height = png_get_image_height(png_ptr,info);
  pixel_depth = png_get_bit_depth(png_ptr,info);
  
  channels = png_get_channels(png_ptr,info);
  
  color_type = png_get_color_type(png_ptr,info);
  if(color_type == PNG_COLOR_TYPE_GRAY)      {}
  if(color_type == PNG_COLOR_TYPE_GRAY_ALPHA){}
  if(color_type == PNG_COLOR_TYPE_RGB)       {}
  if(color_type == PNG_COLOR_TYPE_RGB_ALPHA) {}
  if(color_type == PNG_COLOR_TYPE_PALETTE )  {

    int r = png_get_PLTE(png_ptr,info,&palette,&num_palette);
    if(r == 0) {
    }
    
    png_uint_16p histogram = NULL;

    png_get_hIST(png_ptr, info, &histogram);
    png_set_expand(png_ptr);
    png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER);
    png_read_update_info(png_ptr, info);
    pixel_depth = 8;
  }

  int row_bytes = png_get_rowbytes(png_ptr,info);

  row_pointers = malloc(sizeof(png_bytep *) * height);
  for(size_t n=0;n<height;n++) {
    row_pointers[n] = malloc(row_bytes);
  }

  png_start_read_image(png_ptr);
}
Esempio n. 22
0
static void pngToPixels(png_structp png, png_infop info, Pixel** pixels, int* width, int* height)
{
    const int w = png_get_image_width(png, info);
    const int h = png_get_image_height(png, info);
    const int channels = png_get_channels(png, info);

    Pixel* const px = malloc(w * h * sizeof(Pixel));
    png_bytepp rows = png_get_rows(png, info);

    for(int i = 0; i < h; i++) {
        for(int j = 0; j < w; j++) {
            *(px + i * w + j) = a_pixel_make(
                rows[i][j * channels + 0],
                rows[i][j * channels + 1],
                rows[i][j * channels + 2]
            );
        }
    }

    *width = w;
    *height = h;
    *pixels = px;
}
Esempio n. 23
0
static void pngToPixels(png_structp Png, png_infop Info, APixel** Pixels, int* Width, int* Height)
{
    const int w = png_get_image_width(Png, Info);
    const int h = png_get_image_height(Png, Info);
    const int channels = png_get_channels(Png, Info);

    APixel* const px = a_mem_malloc(w * h * sizeof(APixel));
    png_bytepp rows = png_get_rows(Png, Info);

    for(int i = 0; i < h; i++) {
        for(int j = 0; j < w; j++) {
            *(px + i * w + j) = a_pixel_make(
                rows[i][j * channels + 0],
                rows[i][j * channels + 1],
                rows[i][j * channels + 2]
            );
        }
    }

    *Width = w;
    *Height = h;
    *Pixels = px;
}
Esempio n. 24
0
void PNGImageDecoder::headerAvailable()
{
    png_structp png = m_reader->pngPtr();
    png_infop info = m_reader->infoPtr();
    png_uint_32 width = png_get_image_width(png, info);
    png_uint_32 height = png_get_image_height(png, info);

    // Protect against large PNGs. See http://bugzil.la/251381 for more details.
    const unsigned long maxPNGSize = 1000000UL;
    if (width > maxPNGSize || height > maxPNGSize) {
        longjmp(JMPBUF(png), 1);
        return;
    }

    // Set the image size now that the image header is available.
    if (!setSize(width, height)) {
        longjmp(JMPBUF(png), 1);
        return;
    }

    int bitDepth, colorType, interlaceType, compressionType, filterType, channels;
    png_get_IHDR(png, info, &width, &height, &bitDepth, &colorType, &interlaceType, &compressionType, &filterType);

    // The options we set here match what Mozilla does.

    // Expand to ensure we use 24-bit for RGB and 32-bit for RGBA.
    if (colorType == PNG_COLOR_TYPE_PALETTE || (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8))
        png_set_expand(png);

    png_bytep trns = 0;
    int trnsCount = 0;
    if (png_get_valid(png, info, PNG_INFO_tRNS)) {
        png_get_tRNS(png, info, &trns, &trnsCount, 0);
        png_set_expand(png);
    }

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

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

#if USE(QCMSLIB)
    if ((colorType & PNG_COLOR_MASK_COLOR) && !m_ignoreGammaAndColorProfile) {
        // We only support color profiles for color PALETTE and RGB[A] PNG. Supporting
        // color profiles for gray-scale images is slightly tricky, at least using the
        // CoreGraphics ICC library, because we expand gray-scale images to RGB but we
        // do not similarly transform the color profile. We'd either need to transform
        // the color profile or we'd need to decode into a gray-scale image buffer and
        // hand that to CoreGraphics.
        bool sRGB = false;
        ColorProfile colorProfile;
        getColorProfile(png, info, colorProfile, sRGB);
        bool imageHasAlpha = (colorType & PNG_COLOR_MASK_ALPHA) || trnsCount;
        m_reader->createColorTransform(colorProfile, imageHasAlpha, sRGB);
        m_hasColorProfile = !!m_reader->colorTransform();
    }
#endif

    if (!m_hasColorProfile) {
        // Deal with gamma and keep it under our control.
        const double inverseGamma = 0.45455;
        const double defaultGamma = 2.2;
        double gamma;
        if (!m_ignoreGammaAndColorProfile && png_get_gAMA(png, info, &gamma)) {
            const double maxGamma = 21474.83;
            if ((gamma <= 0.0) || (gamma > maxGamma)) {
                gamma = inverseGamma;
                png_set_gAMA(png, info, gamma);
            }
            png_set_gamma(png, defaultGamma, gamma);
        } else {
            png_set_gamma(png, defaultGamma, inverseGamma);
        }
    }

    // Tell libpng to send us rows for interlaced pngs.
    if (interlaceType == PNG_INTERLACE_ADAM7)
        png_set_interlace_handling(png);

    // Update our info now.
    png_read_update_info(png, info);
    channels = png_get_channels(png, info);
    ASSERT(channels == 3 || channels == 4);

    m_reader->setHasAlpha(channels == 4);

    if (m_reader->decodingSizeOnly()) {
        // If we only needed the size, halt the reader.
#if PNG_LIBPNG_VER_MAJOR > 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR >= 5)
        // '0' argument to png_process_data_pause means: Do not cache unprocessed data.
        m_reader->setReadOffset(m_reader->currentBufferSize() - png_process_data_pause(png, 0));
#else
        m_reader->setReadOffset(m_reader->currentBufferSize() - png->buffer_size);
        png->buffer_size = 0;
#endif
    }
}
Esempio n. 25
0
static int open_png(const char* name, png_structp* png_ptr, png_infop* info_ptr,
                    png_uint_32* width, png_uint_32* height, png_byte* channels, FILE** fpp) {
    char resPath[256];
    unsigned char header[8];
    int result = 0;

    snprintf(resPath, sizeof(resPath)-1, TWRES "images/%s.png", name);
    printf("open_png %s\n", resPath);
    resPath[sizeof(resPath)-1] = '\0';
    FILE* fp = fopen(resPath, "rb");
    if (fp == NULL) {
        fp = fopen(name, "rb");
        if (fp == NULL) {
            result = -1;
            goto exit;
        }
    }

    size_t bytesRead = fread(header, 1, sizeof(header), fp);
    if (bytesRead != sizeof(header)) {
        result = -2;
        goto exit;
    }

    if (png_sig_cmp(header, 0, sizeof(header))) {
        result = -3;
        goto exit;
    }

    *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!*png_ptr) {
        result = -4;
        goto exit;
    }

    *info_ptr = png_create_info_struct(*png_ptr);
    if (!*info_ptr) {
        result = -5;
        goto exit;
    }

    if (setjmp(png_jmpbuf(*png_ptr))) {
        result = -6;
        goto exit;
    }

    png_init_io(*png_ptr, fp);
    png_set_sig_bytes(*png_ptr, sizeof(header));
    png_read_info(*png_ptr, *info_ptr);

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

    *channels = png_get_channels(*png_ptr, *info_ptr);

    /*if (bit_depth == 8 && *channels == 3 && color_type == PNG_COLOR_TYPE_RGB) {
        // 8-bit RGB images: great, nothing to do.
    } else if (bit_depth <= 8 && *channels == 1 && color_type == PNG_COLOR_TYPE_GRAY) {
        // 1-, 2-, 4-, or 8-bit gray images: expand to 8-bit gray.
        png_set_expand_gray_1_2_4_to_8(*png_ptr);
    } else if (bit_depth <= 8 && *channels == 1 && color_type == PNG_COLOR_TYPE_PALETTE) {
        // paletted images: expand to 8-bit RGB.  Note that we DON'T
        // currently expand the tRNS chunk (if any) to an alpha
        // channel, because minui doesn't support alpha channels in
        // general.
        png_set_palette_to_rgb(*png_ptr);
        *channels = 3;
    } else {
        fprintf(stderr, "minui doesn't support PNG depth %d channels %d color_type %d\n",
                bit_depth, *channels, color_type);
        result = -7;
        goto exit;
    }*/
    if (color_type == PNG_COLOR_TYPE_PALETTE) {
        png_set_palette_to_rgb(png_ptr);
    }

    *fpp = fp;
    return result;

  exit:
    if (result < 0) {
        png_destroy_read_struct(png_ptr, info_ptr, NULL);
    }
    if (fp != NULL) {
        fclose(fp);
    }

    return result;
}
Esempio n. 26
0
int Map::loadMapPng(std::string filename, const double& left,
    const double& top) {

  double x, y;

  size_t width, height;

  png_structp png_ptr;
  png_infop info_ptr;
  int number_of_passes;
  png_bytep * row_pointers;

  unsigned char header[8]; // 8 is the maximum size that can be checked

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

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

  if (!png_ptr)
    abort_("[read_png_file] png_create_read_struct failed");

  info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr)
    abort_("[read_png_file] png_create_info_struct failed");

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

  png_init_io(png_ptr, fp);
  png_set_sig_bytes(png_ptr, 8);

  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);

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

  /* read file */
  if (setjmp(png_jmpbuf(png_ptr)))
    abort_("[read_png_file] Error during read_image");

  row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
  for (size_t yi = 0; yi < height; yi++)
    row_pointers[yi] = (png_byte*) malloc(png_get_rowbytes(png_ptr, info_ptr));

  png_read_image(png_ptr, row_pointers);

  fclose(fp);

  double o;
  int c = png_get_channels(png_ptr, info_ptr);
  int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
  //std::cout << "channels: " << c << std::endl;
  //std::cout << "rowbytes: " << rowbytes << std::endl;
  size_t n = 0;
  unsigned char v;

  for (size_t yi = 0; yi < height; ++yi) {
    y = top - (yi * gridRes() + gridRes() / 2.0);

    for (size_t xi = 0; xi < rowbytes; xi += c) {
      x = left + xi * gridRes() + gridRes() / 2.0;
      v = row_pointers[yi][xi];
      if (v == 0) {
        o = MAX_ODDS;
      } else {
        o = PtoO(1.0 - (v / 255.0));
      }

      //std::cout << "(" << x << ", " << y << ") = " << o << " : " << v << std::endl;
      set(x, y, o);
    }
  }

  /* cleanup heap allocation */
  for (size_t yi = 0; yi < height; ++yi)
    free(row_pointers[yi]);
  free(row_pointers);

  return 0;
}
Esempio n. 27
0
// TODO: clean up error handling, too much dupe code right now 
bool PNG::_read_file(string const & file_name)

{ 
// unfortunately, we need to break down to the C-code level here, since 
// libpng is written in C itself 
// we need to open the file in binary mode 
FILE * fp = fopen(file_name.c_str(), "rb"); 
if (!fp)
{ 
epng_err("Failed to open " + file_name); 
return false; 
} 
// read in the header (max size of 8), use it to validate this as a PNG file 
png_byte header[8];

fread(header, 1, 8, fp);

if (png_sig_cmp(header, 0, 8)) 
{

epng_err("File is not a valid PNG file"); 
fclose(fp);

_init();

return false; 
}

// set up libpng structs for reading info 
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, 
NULL); if (!png_ptr) 
{

epng_err("Failed to create read struct"); 
fclose(fp);

_init();

return false; 
} 
png_infop info_ptr = png_create_info_struct(png_ptr); 
if (!info_ptr)
{ 
epng_err("Failed to create info struct"); 
png_destroy_read_struct(&png_ptr, NULL, NULL); 
fclose(fp);

_init(); 
return false; } 
// set error handling to not abort the entire program 
if (setjmp(png_jmpbuf(png_ptr))) 
{

epng_err("Error initializing libpng io"); 
png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 
fclose(fp);

_init();

return false; 
} 

// initialize png reading

png_init_io(png_ptr, fp);

// let it know we've already read the first 8 bytes 
png_set_sig_bytes(png_ptr, 8); 
// read in the basic image info 
png_read_info(png_ptr, info_ptr); 
// convert to 8 bits

png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr); 
if (bit_depth == 16) 
png_set_strip_16(png_ptr); 

// verify this is in RGBA format, and if not, convert it to RGBA

png_byte color_type = png_get_color_type(png_ptr, info_ptr);

if (color_type != PNG_COLOR_TYPE_RGBA && color_type != PNG_COLOR_TYPE_RGB) 
{ 
if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 
{ 
if (bit_depth < 8) 
png_set_expand(png_ptr); 
png_set_gray_to_rgb(png_ptr); 
} 
if (color_type == PNG_COLOR_TYPE_PALETTE) 
png_set_palette_to_rgb(png_ptr); 
}

// convert tRNS to alpha channel

if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) 
png_set_tRNS_to_alpha(png_ptr); 
_width = png_get_image_width(png_ptr, info_ptr); 
_height = png_get_image_height(png_ptr, info_ptr); 
png_read_update_info(png_ptr, info_ptr); 
// begin reading in the image

if (setjmp(png_jmpbuf(png_ptr))) 
{ 
epng_err("Error reading image with libpng"); 
png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 
fclose(fp);

_init(); 
return false; 
} 
int bpr = png_get_rowbytes(png_ptr, info_ptr); // number of bytes in a row 
int numchannels = png_get_channels(png_ptr, info_ptr); 
// initialie our image storage

_pixels = new RGBAPixel[_height * _width]; 
png_byte * row = new png_byte[bpr];

for (size_t y = 0; y < _height; y++)

{ 
png_read_row(png_ptr, row, NULL); 
png_byte * pix = row;

for (size_t x = 0; x < _width; x++)

{ 
RGBAPixel & pixel = _pixel(x,y);

if (numchannels == 1 || numchannels == 2) 
{ 
// monochrome

unsigned char color = (unsigned char) *pix++; 
pixel.red = color;

pixel.green = color;

pixel.blue = color;

if (numchannels == 2) 
pixel.alpha = (unsigned char) *pix++; 
else
pixel.alpha = 255; 
} 
else if (numchannels == 3 || numchannels == 4) 
{ 
pixel.red = (unsigned char) *pix++; 
pixel.green = (unsigned char) *pix++; 
pixel.blue = (unsigned char) *pix++; 
if (numchannels == 4) 
pixel.alpha = (unsigned char) *pix++; 
else 
pixel.alpha = 255; 
} 
} 
}
// cleanup

delete [] row;

png_read_end(png_ptr, NULL); 
png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 
fclose(fp);

return true; 
} 
Esempio n. 28
0
void PNGImageDecoder::headerAvailable()
{
    png_structp png = m_reader->pngPtr();
    png_infop info = m_reader->infoPtr();
    png_uint_32 width = png_get_image_width(png, info);
    png_uint_32 height = png_get_image_height(png, info);
    
    // Protect against large images.
    if (width > cMaxPNGSize || height > cMaxPNGSize) {
        longjmp(JMPBUF(png), 1);
        return;
    }
    
    // We can fill in the size now that the header is available.  Avoid memory
    // corruption issues by neutering setFailed() during this call; if we don't
    // do this, failures will cause |m_reader| to be deleted, and our jmpbuf
    // will cease to exist.  Note that we'll still properly set the failure flag
    // in this case as soon as we longjmp().
    m_doNothingOnFailure = true;
    bool result = setSize(width, height);
    m_doNothingOnFailure = false;
    if (!result) {
        longjmp(JMPBUF(png), 1);
        return;
    }

    int bitDepth, colorType, interlaceType, compressionType, filterType, channels;
    png_get_IHDR(png, info, &width, &height, &bitDepth, &colorType, &interlaceType, &compressionType, &filterType);

    if ((colorType == PNG_COLOR_TYPE_RGB || colorType == PNG_COLOR_TYPE_RGB_ALPHA) && !m_ignoreGammaAndColorProfile) {
        // We currently support color profiles only for RGB and RGBA PNGs.  Supporting
        // color profiles for gray-scale images is slightly tricky, at least using the
        // CoreGraphics ICC library, because we expand gray-scale images to RGB but we
        // don't similarly transform the color profile.  We'd either need to transform
        // the color profile or we'd need to decode into a gray-scale image buffer and
        // hand that to CoreGraphics.
        m_colorProfile = readColorProfile(png, info);
    }

    // The options we set here match what Mozilla does.

    // Expand to ensure we use 24-bit for RGB and 32-bit for RGBA.
    if (colorType == PNG_COLOR_TYPE_PALETTE || (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8))
        png_set_expand(png);
    
    png_bytep trns = 0;
    int trnsCount = 0;
    if (png_get_valid(png, info, PNG_INFO_tRNS)) {
        png_get_tRNS(png, info, &trns, &trnsCount, 0);
        png_set_expand(png);
    }

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

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

    // Deal with gamma and keep it under our control.
    double gamma;
    if (!m_ignoreGammaAndColorProfile && png_get_gAMA(png, info, &gamma)) {
        if ((gamma <= 0.0) || (gamma > cMaxGamma)) {
            gamma = cInverseGamma;
            png_set_gAMA(png, info, gamma);
        }
        png_set_gamma(png, cDefaultGamma, gamma);
    } else
        png_set_gamma(png, cDefaultGamma, cInverseGamma);

    // Tell libpng to send us rows for interlaced pngs.
    if (interlaceType == PNG_INTERLACE_ADAM7)
        png_set_interlace_handling(png);

    // Update our info now.
    png_read_update_info(png, info);
    channels = png_get_channels(png, info);
    ASSERT(channels == 3 || channels == 4);

    m_reader->setHasAlpha(channels == 4);

    if (m_reader->decodingSizeOnly()) {
        // If we only needed the size, halt the reader.
#if defined(PNG_LIBPNG_VER_MAJOR) && defined(PNG_LIBPNG_VER_MINOR) && (PNG_LIBPNG_VER_MAJOR > 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR >= 5))
        // '0' argument to png_process_data_pause means: Do not cache unprocessed data.
        m_reader->setReadOffset(m_reader->currentBufferSize() - png_process_data_pause(png, 0));
#else
        m_reader->setReadOffset(m_reader->currentBufferSize() - png->buffer_size);
        png->buffer_size = 0;
#endif
    }
}
Esempio n. 29
0
/**
* PNG File to RGB byte buffer (8 bits per channel).
*
* @param    char *path
* @param    int *width
* @param    int *height
* @return   pointer or NULL
**/
uint8_t *buffer_from_png(char *path, int *width, int *height)
{
    int x, y, i;
    int bytes_per_row;
    uint8_t *buffer;
    
    /* libpng stuff */
    png_structp png_ptr;
    png_infop info_ptr;
    png_byte channels;
    png_bytep *row_pointers;

    /* Open file */
    FILE *fp = fopen(path, "rb");
    if (!fp) {
        return NULL;
    }
    
    /* Initialize */
    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        png_destroy_read_struct(&png_ptr, NULL, NULL);
        return NULL;
    }
    
    /* Error handling */
    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        if (fp) {
            fclose(fp);
        }
        
        return NULL;
    }
    
    /* Init PNG stuff */
    png_init_io(png_ptr, fp);
    png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY | PNG_TRANSFORM_EXPAND, NULL);
    fclose(fp); fp = NULL;
    
    /* Get width / height, channels */
    *width = png_get_image_width(png_ptr, info_ptr);
    *height = png_get_image_height(png_ptr, info_ptr);
    channels = png_get_channels(png_ptr, info_ptr);
 
    /* Setup buffers */
    row_pointers = png_get_rows(png_ptr, info_ptr);
    buffer = malloc(((*width) * 3) * (*height));
    if (!buffer) {
        return NULL;
    }
    
    /*printf("Channels: %d\n", channels);*/
    
    /* Copy to buffer, removing alpha */
    bytes_per_row = (*width) * channels;
    i = 0;
    for (y = 0; y < (*height); ++y) {
        for (x = 0; x < bytes_per_row; ++x) {
            /* Skip over alpha channel, if present */
            if (channels < 4 || ((x + 1) % 4)) {
                buffer[i] = row_pointers[y][x];
                ++i;
            }
        }
    }
 
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    return buffer;
}
Esempio n. 30
0
/**
* Read PNG file to RGB24 Buffer
*
* @param    char *path
* @param    int *width
* @param    int *height
* @return   pointer or NULL
**/
uint32_t *rgb24_from_png(const char *path, int *width, int *height)
{
    int x, y;
    uint8_t r, g, b;
    uint32_t *buffer, *out;

    /* libpng stuff */
    png_structp png_ptr;
    png_infop info_ptr;
    png_byte channels;
    png_bytep *row_pointers;

    /* Open file */
    FILE *fp = fopen(path, "rb");
    if (!fp) {
        return NULL;
    }
    
    /* Initialize */
    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        png_destroy_read_struct(&png_ptr, NULL, NULL);
        return NULL;
    }
    
    /* Error handling */
    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        if (fp) {
            fclose(fp);
        }
        
        return NULL;
    }
    
    /* Init PNG stuff */
    png_init_io(png_ptr, fp);
    png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY | PNG_TRANSFORM_EXPAND, NULL);
    fclose(fp); fp = NULL;
    
    /* Get width / height, channels */
    *width = png_get_image_width(png_ptr, info_ptr);
    *height = png_get_image_height(png_ptr, info_ptr);
    channels = png_get_channels(png_ptr, info_ptr);
 
    /* Setup buffers */
    row_pointers = png_get_rows(png_ptr, info_ptr);
    
    buffer = malloc(sizeof(*buffer) * (*width) * (*height));
    if (!buffer) {
        return NULL;
    }
    
    /*printf("Channels: %d\n", channels);*/
    
    /* Copy to buffer, removing alpha */
    out = buffer;
    
    for (y = 0; y < *height; y++) {
        for (x = 0; x < *width; x++) {
            r = row_pointers[y][(x * channels) + 0],
            g = row_pointers[y][(x * channels) + 1],
            b = row_pointers[y][(x * channels) + 2];
            
            PACK_RGB(r, g, b, tvxx_rgb_format_rgb24, *out);
            out++;
        }
    }
 
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    return buffer;

}