Beispiel #1
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;
}
Beispiel #2
0
int PngSize(
    FILE * fd,
    long *width,
    long *height)
{
    png_structp png_read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
                                                      (png_voidp) NULL,
                                                      /* we would need to point to error handlers
                                                         here to do it properly */
                                                      (png_error_ptr) NULL,
                                                      (png_error_ptr) NULL);

    png_infop info_ptr = png_create_info_struct(png_read_ptr);

    (*width) = 0;
    (*height) = 0;

/* this is to make compile on aix work since they seem to define jmpbuf
   to be _jmpbuf which breaks compilation */

#ifndef png_jmpbuf
#ifdef PNG_SETJMP_SUPPORTED
#  define png_jmpbuf(png_ptr)   ((png_ptr)->PNG_jmpbuf)
#else
#ifdef jmpbuf
#undef jmpbuf
#endif
#  define png_jmpbuf(png_ptr)   ((png_ptr)->jmpbuf)
#endif
#endif

    if (setjmp(png_jmpbuf(png_read_ptr))) {
        png_destroy_read_struct(&png_read_ptr, &info_ptr, (png_infopp) NULL);
        return 0;
    }

    png_init_io(png_read_ptr, fd);
    png_read_info(png_read_ptr, info_ptr);
    (*width) = png_get_image_width(png_read_ptr, info_ptr);
    (*height) = png_get_image_height(png_read_ptr, info_ptr);

    png_destroy_read_struct(&png_read_ptr, &info_ptr, NULL);
    if (*width > 0 && *height > 0)
        return 1;
    else
        return 0;
}
Beispiel #3
0
int oil_libpng_init(struct oil_libpng *ol, png_structp rpng, png_infop rinfo,
	int out_width, int out_height)
{
	int ret, in_width, in_height, buf_len;
	enum oil_colorspace cs;

	ol->rpng = rpng;
	ol->rinfo = rinfo;
	ol->in_vpos = 0;
	ol->inbuf = NULL;
	ol->inimage = NULL;

	cs = png_cs_to_oil(png_get_color_type(rpng, rinfo));
	if (cs == OIL_CS_UNKNOWN) {
		return -1;
	}

	in_width = png_get_image_width(rpng, rinfo);
	in_height = png_get_image_height(rpng, rinfo);
	ret = oil_scale_init(&ol->os, in_height, out_height, in_width,
		out_width, cs);
	if (ret!=0) {
		free(ol->inbuf);
		return ret;
	}

	buf_len = png_get_rowbytes(rpng, rinfo);
	switch (png_get_interlace_type(rpng, rinfo)) {
	case PNG_INTERLACE_NONE:
		ol->inbuf = malloc(buf_len);
		if (!ol->inbuf) {
			oil_scale_free(&ol->os);
			return -2;
		}
		break;
	case PNG_INTERLACE_ADAM7:
		ol->inimage = alloc_full_image_buf(in_height, buf_len);
		if (!ol->inimage) {
			oil_scale_free(&ol->os);
			return -2;
		}
		png_read_image(rpng, ol->inimage);
		break;
	}

	return 0;
}
Beispiel #4
0
static void readPng(gambatte::uint_least32_t *const out, const char *const filename) {
    const struct PngContext {
        png_structp png;
        png_infop info;
        png_infop endinfo;

        PngContext() :
            png(png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0)),
            info(png ? png_create_info_struct(png) : 0),
            endinfo(png ? png_create_info_struct(png) : 0)
        {
            assert(png);
            assert(info);
            assert(endinfo);
        }

        ~PngContext() {
            png_destroy_read_struct(&png, &info, &endinfo);
        }
    } pngCtx;

    const struct FileCtx {
        std::FILE *f;
        FileCtx(const char *filename) : f(std::fopen(filename, "rb")) {
            assert(f);
        }
        ~FileCtx() {
            std::fclose(f);
        }
    } fileCtx(filename);

    if (setjmp(png_jmpbuf(pngCtx.png)))
        std::abort();

    png_init_io(pngCtx.png, fileCtx.f);
    png_read_png(pngCtx.png, pngCtx.info, 0, 0);

    assert(png_get_image_height(pngCtx.png, pngCtx.info) == 144);
    assert(png_get_rowbytes(pngCtx.png, pngCtx.info) == 160 * 4);

    png_bytep *const rows = png_get_rows(pngCtx.png, pngCtx.info);

    for (std::size_t y = 0; y < 144; ++y)
        for (std::size_t x = 0; x < 160; ++x)
            out[y * 160 + x] = rows[y][x * 4] << 16 | rows[y][x * 4 + 1] << 8 | rows[y][x * 4 + 2];
}
Beispiel #5
0
Texture* TextureReader::read()
{
    verifySignature(reader);
    initialisePNGReader(reader);

    const unsigned char* data = readImageData();
    const unsigned int width = png_get_image_width(_png, _pngInfo);
    const unsigned int height = png_get_image_height(_png, _pngInfo);

    _data = (GLubyte*)data;
    Texture* texture = new Texture(_data, width, height, 0);
    texture->setData(data);
    delete[] data;
    png_destroy_read_struct(&_png, &_pngInfo, NULL);

    return texture;
}
Beispiel #6
0
int png_load_hdr(img I) {
    unsigned char sig[PNG_SIG_LEN];
    png_structp png_ptr;
    png_infop info_ptr;

    rewind(I->fp);

    if (fread(sig, sizeof(sig[0]), PNG_SIG_LEN, I->fp) != PNG_SIG_LEN) {
        return(0);
    }

    /* Check the PNG signature of the file */
    if (png_sig_cmp(sig, (png_size_t)0, PNG_SIG_LEN)) {
        I->err = IE_HDRFORMAT;
        return 0;
    }

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

    I->width = png_get_image_width(png_ptr, info_ptr);
    I->height = png_get_image_height(png_ptr, info_ptr);
    
    png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);

    return(1);
}
Beispiel #7
0
static int loadPNGDecode(unsigned char **pixels, int *width, int *height, int flags,
						 png_structp png_ptr, png_infop info_ptr,  png_infop end_info, 
						 const char *callerStr) {
	// get header info
    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);
	int color_type = png_get_color_type(png_ptr, info_ptr);
    int bit_depth = png_get_bit_depth(png_ptr, info_ptr);

    if (color_type == PNG_COLOR_TYPE_PALETTE && bit_depth <= 8) 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);

	// decode
	if (pixels) {
		if (!(flags & PNG_NO_ALLOC))
			*pixels = (unsigned char*)malloc(3 * (*width) * (*height) * sizeof(unsigned char));
		unsigned char **row_pointers = (unsigned char **)malloc(2 * (*height) * sizeof(unsigned char*));

		if ((*pixels == NULL) || (row_pointers == NULL)) {
			cprintf("%s: memory allocation error\n", callerStr);
			if ((!(flags & PNG_NO_ALLOC)) && (*pixels)) free(*pixels);
			if (row_pointers) free(row_pointers);
			return -1;
		}

		int i;
		for (i = 0; i < 2 * (*height); i++) {
			row_pointers[i] = *pixels;
		}
		for (i = 0; i < *height; i++) {
			row_pointers[i] = (*pixels) + (i) * (*width) * 3;
		}
		png_read_image(png_ptr, row_pointers);
		free(row_pointers);

		png_read_end(png_ptr, end_info);
	}
	return 0;
}
Beispiel #8
0
int svlImageCodecPNG::ReadDimensions(std::istream &stream, unsigned int &width, unsigned int &height)
{
    // check file for signature
    png_byte pngsig[PNG_SIG_SIZE];
    if (stream.read(reinterpret_cast<char*>(pngsig), PNG_SIG_SIZE).fail() ||
        png_sig_cmp(pngsig, 0, PNG_SIG_SIZE) != 0) {
        return SVL_FAIL;
    }

    // create read structure
    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
    if (png_ptr == 0) return SVL_FAIL;

    // create info structure
    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == 0) {
        png_destroy_read_struct(&png_ptr, reinterpret_cast<png_infopp>(0), reinterpret_cast<png_infopp>(0));
        return SVL_FAIL;
    }

    width = 0;
    height = 0;

    // setup error handling
    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_read_struct(&png_ptr, &info_ptr, reinterpret_cast<png_infopp>(0));
        return SVL_OK;
    }
    PNG_source_stream source;
    source.stream = &stream;
    source.error = false;
    png_set_read_fn(png_ptr, &source, PNG_read_data_stream);

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

    // check file header
    width = static_cast<unsigned int>(png_get_image_width(png_ptr, info_ptr));
    height = static_cast<unsigned int>(png_get_image_height(png_ptr, info_ptr));

    // clean up
    png_destroy_read_struct(&png_ptr, &info_ptr,reinterpret_cast<png_infopp>(0));

    return SVL_OK;
}
Beispiel #9
0
/* read the png image to fill row_pointers */
int read_png(FILE *fp, png_bytep **row_pointers, png_uint_32 *width, png_uint_32 *height) {
    png_structp png_ptr;
    png_infop info_ptr;
    png_uint_32 color_type;
    unsigned char header[PNG_HEADER_SIZE];

    /* check if it's a png file */
    size_t bytes_read = fread(header, sizeof(unsigned char), PNG_HEADER_SIZE, fp);
    if (ferror(fp) || (bytes_read != PNG_HEADER_SIZE)) {
        return 0;
    }
    if (png_sig_cmp(header, 0, PNG_HEADER_SIZE) != 0) {
        return 0;
    }

    /* initialize libpng stuff */
    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL);
    info_ptr = png_create_info_struct(png_ptr);
    png_init_io(png_ptr, fp);
    png_set_sig_bytes(png_ptr, PNG_HEADER_SIZE); // because of the check above
    png_read_info(png_ptr, info_ptr);

    *height = png_get_image_height(png_ptr, info_ptr);
    *width = png_get_image_width(png_ptr, info_ptr);
    *row_pointers = png_malloc(png_ptr, *height*sizeof(png_bytep));
    for (int i=0; i<*height; i++) {
        (*row_pointers)[i] = png_malloc(png_ptr, *width*PIXEL_SIZE);
    }
    png_set_rows(png_ptr, info_ptr, *row_pointers);

    color_type = png_get_color_type(png_ptr, info_ptr);
    /* we don't need alpha channel */
    if (color_type & PNG_COLOR_MASK_ALPHA) {
        png_set_strip_alpha(png_ptr);
    }
    png_read_update_info(png_ptr, info_ptr);

    /* and ... finally read the image */
    png_read_image(png_ptr, *row_pointers);
    png_read_end(png_ptr, NULL);
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

    return 1;
}
Beispiel #10
0
int
png_get_bbox (FILE *png_file, uint32_t *width, uint32_t *height,
	       double *xdensity, double *ydensity)
{
  png_structp png_ptr;
  png_infop   png_info_ptr;

  rewind (png_file);
  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, warn);
  if (png_ptr == NULL ||
      (png_info_ptr = png_create_info_struct (png_ptr)) == NULL) {
    WARN("%s: Creating Libpng read/info struct failed.", PNG_DEBUG_STR);
    if (png_ptr)
      png_destroy_read_struct(&png_ptr, NULL, NULL);
    return -1;
  }

  /* Inititializing file IO. */
  png_init_io (png_ptr, png_file);

  /* Read PNG info-header and get some info. */
  png_read_info(png_ptr, png_info_ptr);
  *width      = png_get_image_width (png_ptr, png_info_ptr);
  *height     = png_get_image_height(png_ptr, png_info_ptr);

  if (compat_mode)
    *xdensity = *ydensity = 72.0 / 100.0;
  else
  {
    png_uint_32 xppm = png_get_x_pixels_per_meter(png_ptr, png_info_ptr);
    png_uint_32 yppm = png_get_y_pixels_per_meter(png_ptr, png_info_ptr);

    *xdensity = xppm ? 72.0 / 0.0254 / xppm : 1.0;
    *ydensity = yppm ? 72.0 / 0.0254 / yppm : 1.0;
  }

  /* Cleanup */
  if (png_info_ptr)
    png_destroy_info_struct(png_ptr, &png_info_ptr);
  if (png_ptr)
    png_destroy_read_struct(&png_ptr, NULL, NULL);

  return 0;
}
Beispiel #11
0
int svlImageCodecPNG::ReadDimensions(const unsigned char *buffer, const size_t buffersize, unsigned int &width, unsigned int &height)
{
    if (!buffer || buffersize < static_cast<unsigned int>(PNG_SIG_SIZE)) return SVL_FAIL;

    // check file for signature
    if (png_sig_cmp(const_cast<unsigned char*>(buffer), 0, PNG_SIG_SIZE) != 0) return SVL_FAIL;

    // create read structure
    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
    if (png_ptr == 0) return SVL_FAIL;

    // create info structure
    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == 0) {
        png_destroy_read_struct(&png_ptr, reinterpret_cast<png_infopp>(0), reinterpret_cast<png_infopp>(0));
        return SVL_FAIL;
    }

    width = 0;
    height = 0;

    // setup error handling
    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_read_struct(&png_ptr, &info_ptr, reinterpret_cast<png_infopp>(0));
        return SVL_OK;
    }
    _PNG_source_memory source;
    source.buffer = const_cast<unsigned char*>(buffer + PNG_SIG_SIZE);
    source.buffersize = static_cast<unsigned int>(buffersize - PNG_SIG_SIZE);
    source.error = false;
    png_set_read_fn(png_ptr, &source, PNG_read_data_memory);

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

    // check file header
    width = static_cast<unsigned int>(png_get_image_width(png_ptr, info_ptr));
    height = static_cast<unsigned int>(png_get_image_height(png_ptr, info_ptr));

    // clean up
    png_destroy_read_struct(&png_ptr, &info_ptr,reinterpret_cast<png_infopp>(0));

    return SVL_OK;
}
Beispiel #12
0
static int getSizePng(const char *file, unsigned int *width, unsigned int *height)
{
	FILE *fp = fopen(file, "rb");
	if(!fp){
		printf("Couldn't open file: %s\n", file);
		return false;
	}

	unsigned char header[8];
	fread(header, 1, sizeof(header), fp);
	if(png_sig_cmp(header, 0, sizeof(header))){
		printf("File supplied is not a valid PNG: %s\n", file);
		return false;
	}

	png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if(!png){
		return false;
	}

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

	if(setjmp(png_jmpbuf(png))){
		png_destroy_read_struct(&png, &info, NULL);
		fclose(fp);
		return false;
	}

	png_init_io(png, fp);
	png_set_sig_bytes(png, sizeof(header));

	png_read_info(png, info);

	*width = png_get_image_width(png, info);
	*height = png_get_image_height(png, info);

	return true;
}
Beispiel #13
0
unsigned char* TextureReader::readImageData()
{
    const int transforms = PNG_TRANSFORM_PACKING | PNG_TRANSFORM_STRIP_16;
    png_read_png(_png, _pngInfo, transforms, NULL);

    const unsigned int height = png_get_image_height(_png, _pngInfo);
    const unsigned int rowSize = png_get_rowbytes(_png, _pngInfo);
    unsigned char* data = new unsigned char[height * rowSize];
    unsigned char* row = data;
    unsigned char** rows = png_get_rows(_png, _pngInfo);

    for(unsigned int i = height - 1u; i != UINT32_MAX; --i)
    {
        std::copy(rows[i], rows[i] + rowSize, row);
        row += rowSize;
    }

    return data;
}
Beispiel #14
0
static HPDF_STATUS
ReadPngData_Interlaced  (HPDF_Dict    image,
                         png_structp  png_ptr,
                         png_infop    info_ptr)
{
    png_uint_32 len = png_get_rowbytes(png_ptr, info_ptr);
    png_uint_32 height = png_get_image_height(png_ptr, info_ptr);
    png_bytep* row_pointers = HPDF_GetMem (image->mmgr,
                height * sizeof (png_bytep));

    if (row_pointers) {
        HPDF_UINT i;

        HPDF_MemSet (row_pointers, 0, height * sizeof (png_bytep));
        for (i = 0; i < (HPDF_UINT)height; i++) {
            row_pointers[i] = HPDF_GetMem (image->mmgr, len);

            if (image->error->error_no != HPDF_OK)
                break;
        }

        if (image->error->error_no == HPDF_OK) {
            png_read_image(png_ptr, row_pointers);
            if (image->error->error_no == HPDF_OK) {       /* add this line */
                for (i = 0; i < (HPDF_UINT)height; i++) {
                    if (HPDF_Stream_Write (image->stream, row_pointers[i], len) !=
                            HPDF_OK)
                        break;
                }
            }
        }

        /* clean up */
        for (i = 0; i < (HPDF_UINT)height; i++) {
            HPDF_FreeMem (image->mmgr, row_pointers[i]);
        }

        HPDF_FreeMem (image->mmgr, row_pointers);
    }

    return image->error->error_no;
}
Beispiel #15
0
Datei: png.c Projekt: rtandy/meh
struct image *png_open(FILE *f){
	struct png_t *p;

	rewind(f);
	if(!ispng(f))
		return NULL;

	p = malloc(sizeof(struct png_t));
	if((p->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL){
		free(p);
		return NULL;
	}
	if((p->info_ptr = png_create_info_struct(p->png_ptr)) == NULL){
		png_destroy_read_struct(&p->png_ptr, (png_infopp)NULL, (png_infopp)NULL);
		free(p);
		return NULL;
	}
	if((p->end_info = png_create_info_struct(p->png_ptr)) == NULL){
		png_destroy_read_struct(&p->png_ptr, &p->info_ptr, (png_infopp)NULL);
		free(p);
		return NULL;
	}
	if(setjmp(png_jmpbuf(p->png_ptr))){
		png_destroy_read_struct(&p->png_ptr, &p->info_ptr, &p->end_info);
		free(p);
		return NULL;
	}

	p->f = f;
	rewind(f);
	png_init_io(p->png_ptr, f);

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

	p->img.bufwidth = png_get_image_width(p->png_ptr, p->info_ptr);
	p->img.bufheight = png_get_image_height(p->png_ptr, p->info_ptr);

	p->img.fmt = &libpng;

	return (struct image *)p;
}
Beispiel #16
0
void GL::Image::load(const unsigned char *buf, size_t bufSize)
{
    GLBufferReader reader((const uint8_t*)buf, bufSize);
    png_byte sig[8];
    if (reader.read(sig, sizeof(sig)) == sizeof(sig)) {
        if (png_sig_cmp(sig, 0, sizeof(sig)) == 0) {
            png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
            png_infop info_ptr = png_create_info_struct(png_ptr);
            png_infop end_info = png_create_info_struct(png_ptr);
            if (setjmp(png_jmpbuf(png_ptr))) {
                png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
            }
            png_set_sig_bytes(png_ptr, sizeof(sig));
            png_set_read_fn(png_ptr, &reader, pngReader);
            png_read_info(png_ptr, info_ptr);
            
            // color type should be PNG_COLOR_TYPE_PALETTE
            width_ = png_get_image_width(png_ptr, info_ptr);
            height_ = png_get_image_height(png_ptr, info_ptr);
            
            png_set_expand(png_ptr);
            png_set_bgr(png_ptr); // for BGR for OpenGL texture
 
            png_read_update_info(png_ptr, info_ptr);
            png_byte color_type = png_get_color_type(png_ptr, info_ptr);
            
            png_size_t rowbytes = png_get_rowbytes(png_ptr, info_ptr);
            png_byte *image_data = new png_byte[rowbytes * height_];
            png_bytep row_pointers[height_];
            for (int y = 0; y < height_; ++y) {
                row_pointers[y] = image_data + (y * rowbytes);
            }
            png_read_image(png_ptr, row_pointers);
            png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
            loadTextureData_(image_data, color_type == PNG_COLOR_TYPE_RGB_ALPHA);
            delete[] image_data;
        }
    }
}
Beispiel #17
0
static VALUE
write_png2(VALUE *args)
{
    struct io_write *data;
    png_structp png_ptr = (png_structp)args[0];
    png_infop info_ptr = (png_infop)args[1];
    VALUE scanline, image_in = args[2];
    size_t i;

    write_configure(image_in, png_ptr, info_ptr);
    png_write_info(png_ptr, info_ptr);

    for (i = 0; i < png_get_image_height(png_ptr, info_ptr); i++) {
	scanline = rb_funcall(image_in, id_gets, 0);
	write_scanline(scanline, png_ptr, info_ptr);
    }
    png_write_end(png_ptr, info_ptr);

    data = (struct io_write *)png_get_io_ptr(png_ptr);

    return INT2FIX(data->total);
}
Beispiel #18
0
png_bytep delete_alpha(png_structp* png_ptr, png_infop* info_ptr, png_bytep pixeldata)
{
        png_bytep dataBlock;
        png_uint_32 height, width;

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

        dataBlock = (png_bytep)malloc(sizeof(png_bytep)*width*height*3);

        for(png_uint_32 i = 0; i<height; i++)
        {
                for(png_uint_32 j = 0; j<width; j++)
                {
                        *(dataBlock + i*width*3 + j*3) = *(pixeldata + i*width*4 + j*4);
                        *(dataBlock + i*width*3 + j*3 + 1) = *(pixeldata + i*width*4 + j*4 + 1);
                        *(dataBlock + i*width*3 + j*3 + 2) = *(pixeldata + i*width*4 + j*4 + 2);
                }
        }

        return dataBlock;
}
Beispiel #19
0
QVariant QPngHandler::option(ImageOption option) const
{
    if (d->state == QPngHandlerPrivate::Error)
        return QVariant();
    if (d->state == QPngHandlerPrivate::Ready && !d->readPngHeader())
        return QVariant();

    if (option == Gamma)
        return d->gamma == 0.0 ? d->fileGamma : d->gamma;
    else if (option == Quality)
        return d->quality;
    else if (option == Description)
        return d->description;
    else if (option == Size)
        return QSize(png_get_image_width(d->png_ptr, d->info_ptr),
                     png_get_image_height(d->png_ptr, d->info_ptr));
    else if (option == ScaledSize)
        return d->scaledSize;
    else if (option == ImageFormat)
        return d->readImageFormat();
    return QVariant();
}
Beispiel #20
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);
}
void CL_PNGProvider_Generic::read_data()
{
	// initial fileinfo
	png_read_info(png_ptr, info_ptr); 
	
	// reduce 16bit/channel to 8Bit/channel
	png_set_strip_16(png_ptr);  
	
	// reread infostruct to reflect the made settings
	png_read_update_info(png_ptr, info_ptr); 

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

	switch (color_type)
	{
	case PNG_COLOR_TYPE_GRAY:
		read_data_grayscale ();
		break;
	case PNG_COLOR_TYPE_GRAY_ALPHA:
		read_data_grayscale_alpha ();
		break;
	case PNG_COLOR_TYPE_PALETTE:
		read_data_palette ();
		break;
	case PNG_COLOR_TYPE_RGB:
		read_data_rgb ();
		break;

	case PNG_COLOR_TYPE_RGB_ALPHA:
		read_data_rgba ();
		break;
	default:
		throw CL_Error ("CL_PNGProvider_Generic: Unsupported PNG format!");
		break;
	}
}
/* Given PNG-formatted data at bd, read the data into a buffer that we allocate 
* and return (row_pointers, here).
*
* Note: caller must free the returned value. */
png_bytep* read_png_file(png_structp png_ptr, png_infop * info_ptr, struct bufdata * bd)
{
	int y;

	int height;
	png_byte bit_depth;

	png_bytep * row_pointers;

	if (png_sig_cmp(bd->buf, 0, 8))
	abort_("[read_png_file] Input is not recognized as a PNG file");
	
	*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");

	bd->pos = 0;
	png_set_read_fn(png_ptr, bd, read_cb);
	png_read_info(png_ptr, *info_ptr);
	height = png_get_image_height(png_ptr, *info_ptr);
	bit_depth = png_get_bit_depth(png_ptr, *info_ptr);
	if (bit_depth != 8)
	abort_("[read_png_file] bit depth 16 PNG files unsupported");

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

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

	png_read_image(png_ptr, row_pointers);

	return row_pointers;
}
Beispiel #23
0
int Graph_GetPNGSize( const char *filepath, int *width, int *height )
{
#ifdef USE_LIBPNG
	int ret;
	png_infop info_ptr;
	png_structp png_ptr;
	char buf[PNG_BYTES_TO_CHECK];
	FILE *fp = fopen( filepath, "rb" );
	if( !fp ) {
		return FILE_ERROR_OPEN_ERROR;
	}
	png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 );
	info_ptr = png_create_info_struct( png_ptr );
	setjmp( png_jmpbuf( png_ptr ) );
	ret = fread( buf, 1, PNG_BYTES_TO_CHECK, fp );
	if( ret < PNG_BYTES_TO_CHECK ) {
		fclose( fp );
		png_destroy_read_struct( &png_ptr, &info_ptr, 0 );
		return FILE_ERROR_UNKNOWN_FORMAT;
	}
	ret = png_sig_cmp( (png_bytep)buf, (png_size_t)0, PNG_BYTES_TO_CHECK );
	if( ret != 0 ) {
		fclose( fp );
		png_destroy_read_struct( &png_ptr, &info_ptr, 0 );
		return FILE_ERROR_UNKNOWN_FORMAT;
	}
	rewind( fp );
	png_init_io( png_ptr, fp );
	png_read_png( png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0 );
	*width = png_get_image_width( png_ptr, info_ptr );
	*height = png_get_image_height( png_ptr, info_ptr );
	fclose( fp );
	png_destroy_read_struct( &png_ptr, &info_ptr, 0 );
#else
	_DEBUG_MSG( "warning: not PNG support!" );
#endif
	return ret;
}
Beispiel #24
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;
}
Beispiel #25
0
void print_image(png_structp png_ptr, png_infop info_ptr)
{
	long int width, height;
	png_bytepp row_pointers;
	int x,y;

	/* Get information about image. */
	width = png_get_image_width(png_ptr, info_ptr);
	height = png_get_image_height(png_ptr, info_ptr);

	printf("%ld x %ld \n", width, height);

	/* Retrieves the image data. */
	row_pointers = png_get_rows(png_ptr, info_ptr);
	for (y=0; y<height; y++) {
		png_byte* row = row_pointers[y];
		for (x=0; x<width; x++) {
			png_byte* ptr = &(row[x*4]);
			printf("Pixel at position [ %d - %d ] has RGBA values: %d - %d - %d - %d\n", 
				x, y, ptr[0], ptr[1], ptr[2], ptr[3]);
		}
	}
}
Beispiel #26
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;
}
Beispiel #27
0
bool PNGReadPixels(png_structp png, png_infop info, void* pixels, unsigned width, unsigned height, unsigned stride) {
	if (setjmp(png_jmpbuf(png))) {
		return false;
	}

	uint8_t* pixelData = pixels;
	unsigned pngHeight = png_get_image_height(png, info);
	if (height < pngHeight) {
		pngHeight = height;
	}

	unsigned pngWidth = png_get_image_width(png, info);
	if (width < pngWidth) {
		pngWidth = width;
	}

	unsigned i;
	png_bytep row = malloc(png_get_rowbytes(png, info));
	for (i = 0; i < pngHeight; ++i) {
		png_read_row(png, row, 0);
		unsigned x;
		for (x = 0; x < pngWidth; ++x) {

#if defined(__POWERPC__) || defined(__PPC__)
			pixelData[stride * i * 4 + x * 4 + 3] = row[x * 3];
			pixelData[stride * i * 4 + x * 4 + 2] = row[x * 3 + 1];
			pixelData[stride * i * 4 + x * 4 + 1] = row[x * 3 + 2];
#else
			pixelData[stride * i * 4 + x * 4] = row[x * 3];
			pixelData[stride * i * 4 + x * 4 + 1] = row[x * 3 + 1];
			pixelData[stride * i * 4 + x * 4 + 2] = row[x * 3 + 2];
#endif
		}
	}
	free(row);
	return true;
}
Beispiel #28
0
/**
 * info_callback -- PNG header has been completely received, prepare to process
 * image data
 */
static void info_callback(png_structp png_s, png_infop info)
{
	int interlace;
	png_uint_32 width, height;
	nspng_content *png_c = png_get_progressive_ptr(png_s);

	width = png_get_image_width(png_s, info);
	height = png_get_image_height(png_s, info);
	interlace = png_get_interlace_type(png_s, info);

	png_c->base.width = width;
	png_c->base.height = height;
	png_c->base.size += width * height * 4;

	/* see if progressive-conversion should continue */
	if (image_cache_speculate((struct content *)png_c) == false) {
		longjmp(png_jmpbuf(png_s), CBERR_NOPRE);
	}

	/* Claim the required memory for the converted PNG */
	png_c->bitmap = bitmap_create(width, height, BITMAP_NEW);
	if (png_c->bitmap == NULL) {
		/* Failed to create bitmap skip pre-conversion */
		longjmp(png_jmpbuf(png_s), CBERR_NOPRE);
	}

	png_c->rowstride = bitmap_get_rowstride(png_c->bitmap);
	png_c->bpp = bitmap_get_bpp(png_c->bitmap);

	nspng_setup_transforms(png_s, info);

	png_c->rowbytes = png_get_rowbytes(png_s, info);
	png_c->interlace = (interlace == PNG_INTERLACE_ADAM7);

	LOG(("size %li * %li, rowbytes %zu", (unsigned long)width,
	     (unsigned long)height, png_c->rowbytes));
}
Beispiel #29
0
int begin(char* base_file_name, unsigned char *png_buf, long long png_length) {

  MY_PNG_READ_OFFSET = 0;
  PNG_LENGTH = png_length; 
  ENTIRE_PNG_BUF = png_buf;

  if (png_sig_cmp(ENTIRE_PNG_BUF, 0, 8) != 0) {
    error(-1, "png_sig_cmp", E_INVALID);
    return -1;
  }

  DEBUG_PRINT(("Initial png size is %lld bytes\n", PNG_LENGTH));

  my_png_meta *pm = calloc(1, sizeof(my_png_meta));
  my_init_libpng(pm);

  //If libpng errors, we end up here
  if (setjmp(png_jmpbuf(pm->read_ptr))) {
    DEBUG_PRINT(("libpng called setjmp!\n"));
    my_deinit_libpng(pm);
    free(ENTIRE_PNG_BUF);
    error(-1, "libpng", "libpng encountered an error\n");
    return -1;
  }

  //Normally a file, but instead make it our buffer
  void *read_io_ptr = png_get_io_ptr(pm->read_ptr);
  png_set_read_fn(pm->read_ptr, read_io_ptr, my_png_read_fn);

  //Transform all PNG image types to RGB
  int transforms = 
    PNG_TRANSFORM_GRAY_TO_RGB |
    PNG_TRANSFORM_STRIP_ALPHA | 
    PNG_TRANSFORM_EXPAND;

  png_read_png(pm->read_ptr, pm->info_ptr, transforms, NULL);

  //Now that it was read and transformed, its size will differ
  PNG_LENGTH = 0; 

  //Lets collect our metadata
  struct ihdr_infos_s ihdr_infos;
  ihdr_infos.bit_depth        = png_get_bit_depth(pm->read_ptr, pm->info_ptr);
  ihdr_infos.color_type       = png_get_color_type(pm->read_ptr, pm->info_ptr);
  ihdr_infos.filter_method    = png_get_filter_type(pm->read_ptr, pm->info_ptr);
  ihdr_infos.compression_type = png_get_compression_type(pm->read_ptr, pm->info_ptr);
  ihdr_infos.interlace_type   = png_get_interlace_type(pm->read_ptr, pm->info_ptr);
  ihdr_infos.height           = png_get_image_height(pm->read_ptr, pm->info_ptr);
  ihdr_infos.width            = png_get_image_width(pm->read_ptr, pm->info_ptr);

  if (ihdr_infos.color_type != 2) {
    DEBUG_PRINT((E_INVALID));
    free(ENTIRE_PNG_BUF);
    my_deinit_libpng(pm);
    DEBUG_PRINT(("Looks like libpng could not correctly convert to RGB\n"));
    return -1;
  }

  //Just in case we want to enable alpha, etc
  switch(ihdr_infos.color_type) {
    case 0:  //greyscale
    case 3:  //indexed
      ihdr_infos.bytes_per_pixel = 1;
      break;
    case 4: ihdr_infos.bytes_per_pixel = 2; break; //greyscale w/ alpha 
    case 2: ihdr_infos.bytes_per_pixel = 3; break; //Truecolour (RGB)
    case 6: ihdr_infos.bytes_per_pixel = 4; break; //Truecolour w/ alpha
    default: error_fatal(1, "ihdr_infos", "Unknown image type"); //should never happen
  }

  ihdr_infos.scanline_len = (ihdr_infos.bytes_per_pixel * ihdr_infos.width) + 1;

  DEBUG_PRINT(("HEIGHT: %u\n", ihdr_infos.height));
  DEBUG_PRINT(("WIDTH: %u\n", ihdr_infos.width));
  DEBUG_PRINT(("BIT_DEPTH: %u\n", ihdr_infos.bit_depth));

  // Don't compress, since we are merely copying it to memory,
  // we will be decompressing it again anyway
  png_set_compression_level(pm->write_ptr, Z_NO_COMPRESSION);

  void *write_io_ptr = png_get_io_ptr(pm->write_ptr);
  png_set_write_fn(pm->write_ptr, write_io_ptr, my_png_write_fn, my_png_dummy_flush);

  //Make sure we use all filters
  png_set_filter(pm->write_ptr, 0,
      PNG_FILTER_NONE  | PNG_FILTER_VALUE_NONE |
      PNG_FILTER_SUB   | PNG_FILTER_VALUE_SUB  |
      PNG_FILTER_UP    | PNG_FILTER_VALUE_UP   |
      PNG_FILTER_AVG   | PNG_FILTER_VALUE_AVG  |
      PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH);

  //Set our comment
  struct png_text_struct comment_struct;

  comment_struct.compression = -1;
  comment_struct.key = " Glitched by pnglitch.xyz ";
  comment_struct.text = NULL;
  comment_struct.text_length = 0;
  
  png_set_text(pm->write_ptr, pm->info_ptr, &comment_struct, 1);

  //Buffer is Written using callback my_png_write_fn to buffer
  //ENTIRE_PNG_BUF. PNG_LENGTH will be updated automatically by it
  png_write_png(pm->write_ptr, pm->info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

  my_deinit_libpng(pm);

  DEBUG_PRINT(("libpng output buf is %lld bytes\n", PNG_LENGTH));

  //Now that libpng has converted the image
  //and we have it in a buffer, we process it by hand with zlib
  struct z_stream_s inflate_stream;
  my_init_zlib(&inflate_stream);
  inflateInit(&inflate_stream);

  //Pointer to keep track of where we are
  unsigned char *pngp = ENTIRE_PNG_BUF;

  //Skip PNG Signature
  pngp += 8; 

  //Get Header
  unsigned char ihdr_bytes_buf[4+4+13+4]; // size + label + content + crc
  buf_read(ihdr_bytes_buf, &pngp, 4+4+13+4);

  //When we run into non-idat chunks, we will want to preserve them.
  //The spec says there's no chunk that needs to go after IDAT,
  //so we can simply concatenate all of these chunks into a buffer
  //then write them all at once after the IHDR
  
  //ancillary chunks, eg comments
  unsigned char *ancil_chunks_buf = calloc(1,1);
  long long ancil_chunks_len = 0;

  unsigned char *unzip_idats_buf = calloc(1, 1);
  long unzip_buf_len = 1;
  long unzip_buf_offset = 0;

  long long zipped_idats_len = 0; //Length of all idats as we read them

  unsigned long accum_png_len = 8 + (4+4+13+4);

  int chunk_count = 0;

  printf("Uncompressing image data...\n");
  while (1) {
    unsigned char chunk_label[4];
    unsigned char chunk_len_buf[4];

    buf_read(chunk_len_buf, &pngp, 4);

    //first 4 bytes are the length of data section
    long chunk_len = four_bytes_to_int(chunk_len_buf);

    accum_png_len += chunk_len + 4 + 4 + 4; // plus len, crc, label
    DEBUG_PRINT(("at %lu --> %lld\n", accum_png_len, PNG_LENGTH));

    //leave at end of buffer
    if (accum_png_len >= PNG_LENGTH)
      break;

    //read the chunk label (name of this header)
    buf_read(chunk_label, &pngp, 4);

    DEBUG_PRINT(("Reading chunk %d with label '%c%c%c%c', size %ld\n",
          chunk_count, chunk_label[0], chunk_label[1], chunk_label[2],
          chunk_label[3], chunk_len));

    chunk_count += 1;

    if (memcmp(chunk_label, "IDAT", 4) == 0) {

      zipped_idats_len += chunk_len;

      //read the chunk's data section
      unsigned char *raw_chunk_buf = calloc(chunk_len, 1);
      buf_read(raw_chunk_buf, &pngp, chunk_len);

      //Tell inflate to uncompress it
      inflate_stream.next_in = raw_chunk_buf; 
      inflate_stream.avail_in = chunk_len; 

      //Now uncompress it (resizes buffer automatically)
      unsigned char *check_uncompress = uncompress_buffer(&inflate_stream, 
          unzip_idats_buf, &unzip_buf_len, &unzip_buf_offset);

      //Stop if error
      if (check_uncompress == NULL) {
        DEBUG_PRINT((E_GLITCH));
        free(ancil_chunks_buf);
        free(raw_chunk_buf);
        free(unzip_idats_buf);
        free(ENTIRE_PNG_BUF);
        return -1;
      }

      //Moving on
      unzip_idats_buf = check_uncompress;
      free(raw_chunk_buf);
      pngp += 4; // skip CRC

    } else { //This is not an idat

      ancil_chunks_buf = realloc(ancil_chunks_buf, 
          ancil_chunks_len + 4 + 4 + chunk_len + 4); //make room for new data

      //append length and label bytes
      append_bytes(ancil_chunks_buf, chunk_len_buf, &ancil_chunks_len, 4);
      append_bytes(ancil_chunks_buf, chunk_label, &ancil_chunks_len, 4);

      //append chunk data
      unsigned char *raw_chunk_buf = calloc(chunk_len, 1);
      buf_read(raw_chunk_buf, &pngp, chunk_len);
      append_bytes(ancil_chunks_buf, raw_chunk_buf, &ancil_chunks_len, chunk_len );

      //append chunk crc
      unsigned char chunk_crc_buf[4];
      buf_read(chunk_crc_buf, &pngp, 4);
      append_bytes(ancil_chunks_buf, chunk_crc_buf, &ancil_chunks_len, 4);

      free(raw_chunk_buf);

      DEBUG_PRINT(("ancillary chunks length: %lld\n", ancil_chunks_len));

    }
  }

  //buf contains all idats uncompressed, concatenated
  unsigned long unzipped_idats_len = inflate_stream.total_out; 
  unzip_idats_buf = realloc(unzip_idats_buf, unzipped_idats_len);

  //we already have ancillary chunks and idats, don't need the original
  free(ENTIRE_PNG_BUF);
  inflateEnd(&inflate_stream);

  printf("Uncompressed %lld bytes to %ld bytes\n", zipped_idats_len, unzipped_idats_len);

  printf("Glitching image data...\n");

  for (int g=0;g<NUM_OUTPUT_FILES;g++) {

    //do glitches
    switch(g) {
      case 5:
        glitch_random(unzip_idats_buf, unzipped_idats_len,
            ihdr_infos.scanline_len, 0.0005);
        break;
      case 6:
        glitch_random_filter(unzip_idats_buf, unzipped_idats_len,
            ihdr_infos.scanline_len);
        break;
      default:
        glitch_filter(unzip_idats_buf, unzipped_idats_len,
            ihdr_infos.scanline_len, g);
    }

    //recompress so we can write them to file
    long long glitched_idats_len = 0;
    unsigned char *glitched_idats = zip_idats(unzip_idats_buf,
        unzipped_idats_len, &glitched_idats_len);

    if (glitched_idats == NULL) {
      DEBUG_PRINT((E_GLITCH));
      free (unzip_idats_buf);
      free (ancil_chunks_buf);
      return -1;
    }

    char path[MAX_PATH_LENGTH];
    bzero(path, MAX_PATH_LENGTH);

    snprintf(path, MAX_PATH_LENGTH, "%s%s%s-%d.png", OUTPUT_DIRECTORY, DIR_SEP,
        base_file_name, g);

    DEBUG_PRINT(("Output file name is %s\n", path));

    FILE *outfp = fopen(path, "wb");

    write_glitched_image(glitched_idats, glitched_idats_len, ihdr_bytes_buf,
        ancil_chunks_buf, ancil_chunks_len, outfp);

    printf("%s\n", path);
    fflush(stdout);

    fclose(outfp);
    free(glitched_idats);
  }

  free(ancil_chunks_buf);
  free(unzip_idats_buf);
  return 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
    }
}