Пример #1
0
int saveMMBitmapAsPNG(MMBitmapRef bitmap, const char *path)
{
	FILE *fp = fopen(path, "wb");
	PNGWriteInfoRef info;
	if (fp == NULL) return -1;

	if ((info = createPNGWriteInfo(bitmap)) == NULL) {
		fclose(fp);
		return -1;
	}

	png_init_io(info->png_ptr, fp);
	png_write_png(info->png_ptr, info->info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
	fclose(fp);

	destroyPNGWriteInfo(info);
	return 0;
}
Пример #2
0
uint8_t *createPNGData(MMBitmapRef bitmap, size_t *len)
{
	PNGWriteInfoRef info = NULL;
	struct io_data data = {NULL, 0, 0};

	assert(bitmap != NULL);
	assert(len != NULL);

	if ((info = createPNGWriteInfo(bitmap)) == NULL) return NULL;

	png_set_write_fn(info->png_ptr, &data, &png_append_data, NULL);
	png_write_png(info->png_ptr, info->info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

	destroyPNGWriteInfo(info);

	*len = data.size;
	return data.buffer;
}
Пример #3
0
/*
bool savePNGSprite (FILE * fp, struct spriteBank *sprites, int index, bool sig) {
		
	png_structp png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (!png_ptr) {
		fclose (fp);
		return false;
	}
	
	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr){
		png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
		fclose (fp);
		return false;
	}	
	
	png_init_io(png_ptr, fp);
	
	if (!sig) png_set_sig_bytes(png_ptr, 8);
	
	const int h = 21, w = 21;
	
	png_set_IHDR(png_ptr, info_ptr, w, h,
				 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);		
	
	unsigned char * row_pointers[h];

	unsigned char data[w*h*4];
	
	for (int i = 0; i < h; i++) {
		row_pointers[i] = data + 4 * i * w;
		if (!(i % 20) || (i > (h-2))) {
			for (int x = 0; x < w; x++) {
				*(unsigned char *)(row_pointers[i]+x*4) = 255;
				*(unsigned char *)(row_pointers[i]+x*4+1) = 0;
				*(unsigned char *)(row_pointers[i]+x*4+2) = 
				*(unsigned char *)(row_pointers[i]+x*4+3) = 255;
			}			
		} else {
			for (int x = 0; x < w; x++) {
				if (x % 20 && x < (w-1)) {
					*(unsigned char *)(row_pointers[i]+x*4) =
					*(unsigned char *)(row_pointers[i]+x*4+1) =
					*(unsigned char *)(row_pointers[i]+x*4+2) = 0;
					*(unsigned char *)(row_pointers[i]+x*4+3) = 0;
				} else {
					*(unsigned char *)(row_pointers[i]+x*4) = 255;
					*(unsigned char *)(row_pointers[i]+x*4+1) = 0;
					*(unsigned char *)(row_pointers[i]+x*4+2) = 255;
					*(unsigned char *)(row_pointers[i]+x*4+3) = 255;
				}
			}
		}			
	}

	
	png_set_rows(png_ptr, info_ptr, row_pointers);	
    png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);	
	return true;
}
*/
bool savePNGSprite (FILE * fp, struct spriteBank *sprites, int index, bool sig) {
	
	if (sprites->sprites[index].width < 1) return errorBox ("Error saving", "Can't save a sprite that has no width.");
	if (sprites->sprites[index].height < 1) {
		sprites->sprites[index].height = 1;
		unsigned char * d = new unsigned char [sprites->sprites[index].width*4];
		if (!d) return errorBox ("Error saving", "Out of RAM memory.");
		for (int i = 0; i < sprites->sprites[index].width*4; i++) {
			d[i] = 0;
		}
		delete sprites->sprites[index].data;
		sprites->sprites[index].data = d;
	}
	
	png_structp png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (!png_ptr) {
		fclose (fp);
		return false;
	}
	
	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr){
		png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
		fclose (fp);
		return false;
	}	
	
	png_init_io(png_ptr, fp);
	
	if (!sig) png_set_sig_bytes(png_ptr, 8);
	
	png_set_IHDR(png_ptr, info_ptr, sprites->sprites[index].width, sprites->sprites[index].height,
				 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);		
	
	unsigned char * row_pointers[sprites->sprites[index].height];
	
	for (int i = 0; i < sprites->sprites[index].height; i++) {
		row_pointers[i] = sprites->sprites[index].data + 4*i*sprites->sprites[index].width;
	}
	
	png_set_rows(png_ptr, info_ptr, row_pointers);	
    png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);	
	return true;
}
Пример #4
0
 int dummyFunc() {

	// For Broken Sword 2.5
 	volatile int i;
	i = clock();
	rename("dummyA", "dummyB");
	
	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	png_set_write_fn(png_ptr, NULL, NULL, NULL);
	png_infop info_ptr;
	png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
	png_destroy_write_struct(&png_ptr, &info_ptr);
	
	// For lua's usage of libc: very heavy usage so it pulls in sockets?
	setsockopt(0, 0, 0, NULL, 0);
	getsockopt(0, 0, 0, NULL, NULL);
	
	return i;
}
Пример #5
0
void write_png(char* filename, unsigned w, unsigned h,
               unsigned char** data, png_text* comments) {
  FILE* fp = fopen(filename, "wb");
  if (!fp) {
    fprintf(stderr, "ERROR: Could not open output file %s\n", filename);
    exit(-1);
  }
  
  png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
   if (!png_ptr) {
     fprintf(stderr, "ERROR: Could not open output file %s\n", filename);
     fclose(fp);
     exit(-1);
   }

   png_infop info_ptr = png_create_info_struct(png_ptr);
   if (!info_ptr) {
     png_destroy_read_struct(&png_ptr, 0, 0);
     fprintf(stderr, "ERROR: Could not open output file %s\n", filename);
     fclose(fp);
     exit(-1);
   }
   
   if (setjmp(png_jmpbuf(png_ptr))) {
     png_destroy_write_struct(&png_ptr, &info_ptr);
     fprintf(stderr, "ERROR: Could not open output file %s\n", filename);
     fclose(fp);
     exit(-1);
   }
   
   png_init_io(png_ptr, fp);
   png_set_IHDR(png_ptr, info_ptr, w, h, 8, PNG_COLOR_TYPE_RGB_ALPHA,
                PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
                PNG_FILTER_TYPE_DEFAULT);
  png_set_text(png_ptr, info_ptr, comments, 1);
  
   png_set_rows(png_ptr, info_ptr, data);
   png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
   
   fclose(fp);
}
Пример #6
0
void image_write(Image * image, const char *filename)
{
   FILE           *file;
   png_structp     png_ptr;
   png_infop       info_ptr;
   png_bytep      *row_pointers;
   int             i;

   file = fopen(filename, "wb");
   assert(file != NULL);

   png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
   assert(png_ptr != NULL);

   info_ptr = png_create_info_struct(png_ptr);
   assert(info_ptr != NULL);

   assert(setjmp(png_jmpbuf(png_ptr)) == 0);

   png_init_io(png_ptr, file);

   png_set_IHDR(png_ptr, info_ptr, image->width, image->height, 8,
         PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE,
         PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

   row_pointers = png_malloc(png_ptr, image->height * sizeof(png_bytep));
   assert(row_pointers != NULL);
   for (i = 0; i < image->height; i++)
      row_pointers[i] = (png_bytep)(&image->pixel[i*image->width]);
   png_set_rows(png_ptr, info_ptr, row_pointers);

   png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

   png_free(png_ptr, row_pointers);

   png_destroy_write_struct(&png_ptr, &info_ptr);

   fclose(file);
}
Пример #7
0
int write_image_png(handle_t handle, picture_t *pic, config_t *config)
{
    png_output_t *h = handle;
    uint8_t *out_data = malloc(config->width * config->height * 4);
    uint8_t **rows = calloc(config->height, sizeof(*rows));
    picture_t pic_out;
    struct SwsContext *sws_ctx;
    int i;

    pic_out.img.plane[0] = out_data;
    pic_out.img.plane[1] = pic_out.img.plane[2] = pic_out.img.plane[3] = NULL;
    pic_out.img.stride[0] = 3 * config->width;
    pic_out.img.stride[1] = pic_out.img.stride[2] = pic_out.img.stride[3] = 0;

    sws_ctx = sws_getContext(config->width, config->height, PIX_FMT_YUV420P,
                             config->width, config->height, PIX_FMT_RGB24,
                             SWS_FAST_BILINEAR | SWS_ACCURATE_RND,
                             NULL, NULL, NULL);

    sws_scale(sws_ctx, pic->img.plane, pic->img.stride, 0, config->height, pic_out.img.plane, pic_out.img.stride);

    __asm__ volatile ("emms\n\t");

    png_set_IHDR(h->png, h->info, config->width, config->height,
                 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

    for (i = 0; i < config->height; i++)
        rows[i] = pic_out.img.plane[0] + i * pic_out.img.stride[0];

    png_set_rows(h->png, h->info, rows);

    png_write_png(h->png, h->info, 0, NULL);

    free(rows);
    free(out_data);

    return 0;
}
Пример #8
0
  void PngWriter::Compress(unsigned int width,
                           unsigned int height,
                           unsigned int pitch,
                           PixelFormat format)
  {
    png_set_IHDR(pimpl_->png_, pimpl_->info_, width, height,
                 pimpl_->bitDepth_, pimpl_->colorType_, PNG_INTERLACE_NONE,
                 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

    png_write_info(pimpl_->png_, pimpl_->info_);

    if (height > 0)
    {
      switch (format)
      {
      case PixelFormat_Grayscale16:
      case PixelFormat_SignedGrayscale16:
      {
        int transforms = 0;
        if (Toolbox::DetectEndianness() == Endianness_Little)
        {
          transforms = PNG_TRANSFORM_SWAP_ENDIAN;
        }

        png_set_rows(pimpl_->png_, pimpl_->info_, &pimpl_->rows_[0]);
        png_write_png(pimpl_->png_, pimpl_->info_, transforms, NULL);

        break;
      }

      default:
        png_write_image(pimpl_->png_, &pimpl_->rows_[0]);
      }
    }

    png_write_end(pimpl_->png_, NULL);
  }
Пример #9
0
// split out of png_encode to simplify resource cleanup and avoid
// "dtor / setjmp interaction" warning.
static Status png_encode_impl(Tex* t, png_structp png_ptr, png_infop info_ptr, DynArray* da)
{
	const png_uint_32 w = (png_uint_32)t->w, h = (png_uint_32)t->h;
	const size_t pitch = w * t->bpp / 8;

	int colour_type;
	switch(t->flags & (TEX_GREY|TEX_ALPHA))
	{
	case TEX_GREY|TEX_ALPHA:
		colour_type = PNG_COLOR_TYPE_GRAY_ALPHA;
		break;
	case TEX_GREY:
		colour_type = PNG_COLOR_TYPE_GRAY;
		break;
	case TEX_ALPHA:
		colour_type = PNG_COLOR_TYPE_RGB_ALPHA;
		break;
	default:
		colour_type = PNG_COLOR_TYPE_RGB;
		break;
	}

	png_set_write_fn(png_ptr, da, io_write, io_flush);
	png_set_IHDR(png_ptr, info_ptr, w, h, 8, colour_type,
		PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

	u8* data = tex_get_data(t);
	std::vector<RowPtr> rows = tex_codec_alloc_rows(data, h, pitch, t->flags, TEX_TOP_DOWN);

	// PNG is native RGB.
	const int png_transforms = (t->flags & TEX_BGR)? PNG_TRANSFORM_BGR : PNG_TRANSFORM_IDENTITY;

	png_set_rows(png_ptr, info_ptr, (png_bytepp)&rows[0]);
	png_write_png(png_ptr, info_ptr, png_transforms, 0);

	return INFO::OK;
}
Пример #10
0
void writePNG(const char * filename, const uchar3 * imgData, const int width, const int height) {

    FILE * fp = fopen(filename,"wb");

    png_byte* rowPointers[height];

    mainprog_info progInfo;

    png_structp pngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, &progInfo, png_error_handler, NULL);
    png_infop infoPtr = png_create_info_struct(pngPtr);

    if (setjmp(png_jmpbuf(pngPtr))) {
        goto png_failure;
    }

    png_set_IHDR( pngPtr,
                  infoPtr,
                  width,
                  height,
                  sizeof(unsigned char)*8,
                  PNG_COLOR_TYPE_RGB,
                  PNG_INTERLACE_NONE,
                  PNG_COMPRESSION_TYPE_DEFAULT,
                  PNG_FILTER_TYPE_DEFAULT);

    for (int y = 0; y<height; ++y) {
        rowPointers[y] = (png_byte*)&imgData[y*width];
    }

    png_init_io(pngPtr, fp);
    png_set_rows(pngPtr,infoPtr,rowPointers);
    png_write_png(pngPtr,infoPtr,PNG_TRANSFORM_SWAP_ENDIAN,NULL);

png_failure:
    png_destroy_write_struct(&pngPtr,&infoPtr);
    fclose(fp);
}
Пример #11
0
void wrPng(BYTE *bits, int w, int h, int line, FILE *f)
{
	png_structp png_ptr;
	png_infop info_ptr;

	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
	if(png_ptr){
		info_ptr = png_create_info_struct(png_ptr);
		if(info_ptr){
			if(!setjmp(png_jmpbuf(png_ptr))){
				png_init_io(png_ptr, f);
				png_set_IHDR(png_ptr, info_ptr, w, h, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
				BYTE **row_pointers = (BYTE**)png_malloc(png_ptr, h*png_sizeof(png_bytep));
				for(int i=0; i<h; i++){
					row_pointers[i]= bits+(h-i-1)*line;
				}
				png_set_rows(png_ptr, info_ptr, row_pointers);
				png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_BGR, 0);
				png_free(png_ptr, row_pointers);
			}
		}
		png_destroy_write_struct(&png_ptr, &info_ptr);
	}
}
Пример #12
0
		WritePng(const char *file_name, grid<T> &grd){
			transforms = PNG_TRANSFORM_IDENTITY;
			status = PENDING;
			this->grd = &grd;
			FILE *fp = fopen(file_name, "wb");
			if (!fp){
				status = FILE_ERROR;
				return;
			}

			png_ptr = png_create_write_struct(
				PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL);
    		if (!png_ptr){
       			status = PNG_ERROR;
       			return;
       		}

       		info_ptr = png_create_info_struct(png_ptr);
    		if (!info_ptr){
       			png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
       			status = PNG_ERROR;
       			return;
    		}

    		png_init_io(png_ptr, fp);

    		setup_png();

    		setup_rows();
    		png_set_rows(png_ptr, info_ptr, rows);

			png_write_png(png_ptr, info_ptr, transforms, NULL);
			status = OK;
			fclose(fp);
			return;
		};
Пример #13
0
/**
* RGB byte [8 bits per channel] buffer to PNG file.
*
* @param    uint8_t *buffer
* @param    int width
* @param    int height
* @param    char *path
* @return   -1 on error
**/
int buffer_to_png(uint8_t *buffer, int width, int height, char *path)
{
    int x, y, i;
    int bytes_per_row = width * 3;
    
    /* libpng stuff */
    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL;
    png_byte **row_pointers = NULL;

    FILE *fp = fopen(path, "wb");
    if (!fp) {
        return -1;
    }
    
    /* Initialize */
    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (png_ptr == NULL) {
        fclose(fp);
        return -1;
    }

    info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL) {
        png_destroy_write_struct(&png_ptr, NULL);
        fclose(fp);
        return -1;
    }

    /* Error Handling */
    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_write_struct(&png_ptr, &info_ptr);
        fclose(fp);
        return -1;
    }
    
    png_set_IHDR(png_ptr, info_ptr, width, height, 8,
        PNG_COLOR_TYPE_RGB,
        PNG_INTERLACE_NONE,
        PNG_COMPRESSION_TYPE_DEFAULT,
        PNG_FILTER_TYPE_DEFAULT);

    /* Copy RGB buffer into PNG buffer */
    row_pointers = png_malloc(png_ptr, height * sizeof(png_byte *));
    i = 0;
    for (y = 0; y < height; ++y) {
        uint8_t *data = png_malloc(png_ptr, sizeof(uint8_t) * bytes_per_row);
        row_pointers[y] = (png_byte *)data;
        
        for (x = 0; x < width; ++x) {
            *data++ = buffer[i++];
            *data++ = buffer[i++];
            *data++ = buffer[i++];
        }
    }

    /* Write file */
    png_init_io(png_ptr, fp);
    png_set_rows(png_ptr, info_ptr, row_pointers);
    png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

    /* Free memory, cleanup */
    for (y = 0; y < height; y++) {
        png_free(png_ptr, row_pointers[y]);
    }
    
    png_free(png_ptr, row_pointers);
    png_destroy_write_struct(&png_ptr, &info_ptr);
    fclose(fp);
    return 0;
}
Пример #14
0
int RE_SavePNG( const char *filename, byte *buf, size_t width, size_t height, int byteDepth ) {
	fileHandle_t fp;
	png_structp png_ptr = NULL;
	png_infop info_ptr = NULL;
	unsigned int x, y;
	png_byte ** row_pointers = NULL;
	/* "status" contains the return value of this function. At first
	it is set to a value which means 'failure'. When the routine
	has finished its work, it is set to a value which means
	'success'. */
	int status = -1;
	/* The following number is set by trial and error only. I cannot
	see where it it is documented in the libpng manual.
	*/
	int depth = 8;

	fp = ri->FS_FOpenFileWrite( filename );
	if ( !fp ) {
		goto fopen_failed;
	}

	png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (png_ptr == NULL) {
		goto png_create_write_struct_failed;
	}

	info_ptr = png_create_info_struct (png_ptr);
	if (info_ptr == NULL) {
		goto png_create_info_struct_failed;
	}

	/* Set up error handling. */

	if (setjmp (png_jmpbuf (png_ptr))) {
		goto png_failure;
	}

	/* Set image attributes. */

	png_set_IHDR (png_ptr,
		info_ptr,
		width,
		height,
		depth,
		PNG_COLOR_TYPE_RGB,
		PNG_INTERLACE_NONE,
		PNG_COMPRESSION_TYPE_DEFAULT,
		PNG_FILTER_TYPE_DEFAULT);

	/* Initialize rows of PNG. */

	row_pointers = (png_byte **)png_malloc (png_ptr, height * sizeof (png_byte *));
	for ( y=0; y<height; ++y ) {
		png_byte *row = (png_byte *)png_malloc (png_ptr, sizeof (uint8_t) * width * byteDepth);
		row_pointers[height-y-1] = row;
		for (x = 0; x < width; ++x) {
			byte *px = buf + (width * y + x)*3;
			*row++ = px[0];
			*row++ = px[1];
			*row++ = px[2];
		}
	}

	/* Write the image data to "fp". */

//	png_init_io (png_ptr, fp);
	png_set_write_fn( png_ptr, (png_voidp)&fp, user_write_data, user_flush_data );
	png_set_rows (png_ptr, info_ptr, row_pointers);
	png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

	/* The routine has successfully written the file, so we set
	"status" to a value which indicates success. */

	status = 0;

	for (y = 0; y < height; y++) {
		png_free (png_ptr, row_pointers[y]);
	}
	png_free (png_ptr, row_pointers);

png_failure:
png_create_info_struct_failed:
	png_destroy_write_struct (&png_ptr, &info_ptr);
png_create_write_struct_failed:
	ri->FS_FCloseFile( fp );
fopen_failed:
	return status;
}
Пример #15
0
/**
* Save PNG file from RGB24 buffer
*
* @param    uint32_t *buffer
* @param    int width
* @param    int height
* @param    char *path
* @return   -1 on error
**/
int rgb24_to_png(uint32_t *buffer, int width, int height, char *path)
{
    int x, y;
    int bytes_per_row = width * 3;
    
    uint8_t r, g, b;
    uint32_t *in = buffer;
    
    /* libpng stuff */
    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL;
    png_byte **row_pointers = NULL;

    FILE *fp = fopen(path, "wb");
    if (!fp) {
        return -1;
    }
    
    /* Initialize */
    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (png_ptr == NULL) {
        fclose(fp);
        return -1;
    }

    info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL) {
        png_destroy_write_struct(&png_ptr, NULL);
        fclose(fp);
        return -1;
    }

    /* Error Handling */
    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_write_struct(&png_ptr, &info_ptr);
        fclose(fp);
        return -1;
    }
    
    png_set_IHDR(png_ptr, info_ptr, width, height, 8,
        PNG_COLOR_TYPE_RGB,
        PNG_INTERLACE_NONE,
        PNG_COMPRESSION_TYPE_DEFAULT,
        PNG_FILTER_TYPE_DEFAULT);

    /* Copy RGB buffer into PNG buffer */
    row_pointers = png_malloc(png_ptr, height * sizeof(png_byte *));
    
    for (y = 0; y < height; y++) {
        /* Allocate */
        row_pointers[y] = png_malloc(png_ptr, sizeof(uint8_t) * bytes_per_row);
        
        for (x = 0; x < width; x++) {
            /* Unpack pixels */
            UNPACK_RGB(r, g, b, tvxx_rgb_format_rgb24, *in);
            /*UNPACK_RGB(r, g, b, tvxx_rgb_format_rgb15, *in);
            
            r *= (255/31);
            g *= (255/31);
            b *= (255/31);*/
            
            /* Copy */
            row_pointers[y][(x * 3) + 0] = r;
            row_pointers[y][(x * 3) + 1] = g;
            row_pointers[y][(x * 3) + 2] = b;
            
            /* Increment RGB24 pointer */
            in++;
        }
    }

    /* Write file */
    png_init_io(png_ptr, fp);
    png_set_rows(png_ptr, info_ptr, row_pointers);
    png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

    /* Free memory, cleanup */
    for (y = 0; y < height; y++) {
        png_free(png_ptr, row_pointers[y]);
    }
    
    png_free(png_ptr, row_pointers);
    png_destroy_write_struct(&png_ptr, &info_ptr);
    fclose(fp);
    return 0;
}
Пример #16
0
bool save_heightmap_png(long double lat, long double lon, long double span_h, long double span_w, const char *outfile)
{
   int x1, x2, y1, y2;
   bool ret = false;
   FILE *fp = NULL;
   png_structp png_ptr = NULL;
   png_infop info_ptr = NULL;
   size_t x, y, w, h, skip;
   png_bytepp row_pointers;
   png_bytep row;
   int16_t elevation, height;

   /* Pointer to humongous (7GB) S_MAPW x S_MAPH 16-bit map data (see map.c) */
   int16_t *mapp = (int16_t *)map[0];

   /* Map longitude/latidude to pixel coordinates in source image */
   x1 = ((lon + 180.0) / (long double)360) * S_MAPW;
   x2 = (((lon + span_w) + 180.0) / (long double)360) * S_MAPW - 1;
   y1 = ((90 - lat) / (long double)180) * S_MAPH;
   y2 = ((90 - (lat - span_h)) / (long double)180) * S_MAPH - 1;

   w = x2 - x1 + 1;
   h = y2 - y1 + 1;

   printf("%s: %dx%d ... ", outfile, (int)w, (int)h);
   fflush(stdout);

   /* Advance mapp to first pixel */
   mapp += (uint64_t)x1 + (uint64_t)S_MAPW * (uint64_t)y1;

   /* Skip this many int16_t:s to get to next line */
   skip = S_MAPW - w;

   /* libpng stuff below */

   png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
   if (png_ptr == NULL) {
      goto out;
   }

   info_ptr = png_create_info_struct(png_ptr);
   if (info_ptr == NULL) {
      png_destroy_write_struct(&png_ptr, NULL);
      goto out;
   }

   if (setjmp(png_jmpbuf(png_ptr))) {
      png_destroy_write_struct(&png_ptr, &info_ptr);
      goto out;
   }

   /* Specify 16-bit grayscale in png header */
   png_set_IHDR(png_ptr, info_ptr,
                w, h,
                16,
                PNG_COLOR_TYPE_GRAY,
                PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);


   /* Alloc mem for png image data */
   row_pointers = (png_bytepp)png_malloc(png_ptr, h * png_sizeof(png_bytep));
   for (y = 0; y < h; y++) {
      row_pointers[y] = png_malloc(png_ptr, w * 2);
   }

   /* Copy image data from mapp to row_pointers */
   for (y = 0; y < h; y++) {
      row = row_pointers[y];
      for (x = 0; x < w; x++) {

         /* Read 2 big endian source bytes */
         elevation = *mapp++;

         /* Clamp negative heights to 0 */
         height = ntohs(elevation); /* swap bytes if little endian */
         if (height < 0) {
            elevation = 0;
         }

         /* Write 2 bytes to destination */
         *row++ = (png_byte)(elevation & 0xff);
         *row++ = (png_byte)(elevation >> 8);
      }
      mapp += skip;
   }

   /* Write image data to fp */

   if (!(fp = fopen(outfile, "w"))) {
      perror(outfile);
      goto out2;
   }

   png_init_io(png_ptr, fp);
   png_set_rows(png_ptr, info_ptr, row_pointers);
   png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

   ret = true;

 out2:

   /* Cleanup. */
   for (y = 0; y < h; y++) {
      png_free(png_ptr, row_pointers[y]);
   }
   png_free(png_ptr, row_pointers);
   png_destroy_write_struct(&png_ptr, &info_ptr);

   if (fp) {
      fclose(fp);
   }

 out:

   if (ret) {
      puts("ok");
   } else {
      puts("fail");
   }

   return ret;
}
Пример #17
0
bool CImageWriterPNG::writeImage(io::IWriteFile* file, IImage* image,u32 param) const
{
#ifdef _IRR_COMPILE_WITH_LIBPNG_
	if (!file || !image)
		return false;

	// Allocate the png write struct
	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
		NULL, (png_error_ptr)png_cpexcept_error, NULL);
	if (!png_ptr)
	{
		os::Printer::log("PNGWriter: Internal PNG create write struct failure\n", file->getFileName(), ELL_ERROR);
		return false;
	}

	// Allocate the png info struct
	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr)
	{
		os::Printer::log("PNGWriter: Internal PNG create info struct failure\n", file->getFileName(), ELL_ERROR);
		png_destroy_write_struct(&png_ptr, NULL);
		return false;
	}

	// for proper error handling
	if (setjmp(png_jmpbuf(png_ptr)))
	{
		png_destroy_write_struct(&png_ptr, &info_ptr);
		return false;
	}

	png_set_write_fn(png_ptr, file, user_write_data_fcn, NULL);

	// Set info
	switch(image->getColorFormat())
	{
		case ECF_A8R8G8B8:
		case ECF_A1R5G5B5:
			png_set_IHDR(png_ptr, info_ptr,
				image->getDimension().Width, image->getDimension().Height,
				8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
				PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
		break;
		default:
			png_set_IHDR(png_ptr, info_ptr,
				image->getDimension().Width, image->getDimension().Height,
				8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
				PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
	}

	s32 lineWidth=image->getDimension().Width;
	switch(image->getColorFormat())
	{
	case ECF_R8G8B8:
	case ECF_R5G6B5:
		lineWidth*=3;
		break;
	case ECF_A8R8G8B8:
	case ECF_A1R5G5B5:
		lineWidth*=4;
		break;
	}
	u8* tmpImage = new u8[image->getDimension().Height*lineWidth];
	if (!tmpImage)
	{
		os::Printer::log("PNGWriter: Internal PNG create image failure\n", file->getFileName(), ELL_ERROR);
		png_destroy_write_struct(&png_ptr, &info_ptr);
		return false;
	}

	u8* data = (u8*)image->lock();
	switch(image->getColorFormat())
	{
	case ECF_R8G8B8:
		CColorConverter::convert_R8G8B8toR8G8B8(data,image->getDimension().Height*image->getDimension().Width,tmpImage);
		break;
	case ECF_A8R8G8B8:
		CColorConverter::convert_A8R8G8B8toA8R8G8B8(data,image->getDimension().Height*image->getDimension().Width,tmpImage);
		break;
	case ECF_R5G6B5:
		CColorConverter::convert_R5G6B5toR8G8B8(data,image->getDimension().Height*image->getDimension().Width,tmpImage);
		break;
	case ECF_A1R5G5B5:
		CColorConverter::convert_A1R5G5B5toA8R8G8B8(data,image->getDimension().Height*image->getDimension().Width,tmpImage);
		break;
	}
	image->unlock();

	// Create array of pointers to rows in image data

	//Used to point to image rows
	u8** RowPointers = new png_bytep[image->getDimension().Height];
	if (!RowPointers)
	{
		os::Printer::log("PNGWriter: Internal PNG create row pointers failure\n", file->getFileName(), ELL_ERROR);
		png_destroy_write_struct(&png_ptr, &info_ptr);
		delete [] tmpImage;
		return false;
	}

	data=tmpImage;
	// Fill array of pointers to rows in image data
	for (u32 i=0; i<image->getDimension().Height; ++i)
	{
		RowPointers[i]=data;
		data += lineWidth;
	}
	// for proper error handling
	if (setjmp(png_jmpbuf(png_ptr)))
	{
		png_destroy_write_struct(&png_ptr, &info_ptr);
		delete [] RowPointers;
		delete [] tmpImage;
		return false;
	}

	png_set_rows(png_ptr, info_ptr, RowPointers);

	if (image->getColorFormat()==ECF_A8R8G8B8 || image->getColorFormat()==ECF_A1R5G5B5)
		png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_BGR, NULL);
	else
	{
		png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
	}

	delete [] RowPointers;
	delete [] tmpImage;
	png_destroy_write_struct(&png_ptr, &info_ptr);
	return true;
#else
	return false;
#endif
}
Пример #18
0
        void impl_save_png (
            const std::string& file_name,
            std::vector<unsigned char*>& row_pointers,
            const long width,
            const png_type type,
            const int bit_depth
        )
        {

            FILE *fp;
            png_structp png_ptr;
            png_infop info_ptr;

            /* Open the file */
            fp = fopen(file_name.c_str(), "wb");
            if (fp == NULL)
                throw image_save_error("Unable to open " + file_name + " for writing.");

            /* Create and initialize the png_struct with the desired error handler
            * functions.  If you want to use the default stderr and longjump method,
            * you can supply NULL for the last three parameters.  We also check that
            * the library version is compatible with the one used at compile time,
            * in case we are using dynamically linked libraries.  REQUIRED.
            */
            png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, &png_reader_user_error_fn_silent, &png_reader_user_warning_fn_silent);

            if (png_ptr == NULL)
            {
                fclose(fp);
                throw image_save_error("Error while writing PNG file " + file_name);
            }

            /* Allocate/initialize the image information data.  REQUIRED */
            info_ptr = png_create_info_struct(png_ptr);
            if (info_ptr == NULL)
            {
                fclose(fp);
                png_destroy_write_struct(&png_ptr,  NULL);
                throw image_save_error("Error while writing PNG file " + file_name);
            }

            /* Set error handling.  REQUIRED if you aren't supplying your own
            * error handling functions in the png_create_write_struct() call.
            */
            if (setjmp(png_jmpbuf(png_ptr)))
            {
                /* If we get here, we had a problem writing the file */
                fclose(fp);
                png_destroy_write_struct(&png_ptr, &info_ptr);
                throw image_save_error("Error while writing PNG file " + file_name);
            }

            int color_type = 0;
            switch(type)
            {
                case png_type_rgb:       color_type = PNG_COLOR_TYPE_RGB; break;
                case png_type_rgb_alpha: color_type = PNG_COLOR_TYPE_RGB_ALPHA; break;
                case png_type_gray:      color_type = PNG_COLOR_TYPE_GRAY; break;
                default:
                    {
                        fclose(fp);
                        png_destroy_write_struct(&png_ptr, &info_ptr);
                        throw image_save_error("Invalid color type");
                    }
            }


            /* Set up the output control if you are using standard C streams */
            png_init_io(png_ptr, fp);


            const int png_transforms = PNG_TRANSFORM_IDENTITY;
            const long height = row_pointers.size();


            png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
            png_set_rows(png_ptr, info_ptr, &row_pointers[0]);
            png_write_png(png_ptr, info_ptr, png_transforms, NULL);

            /* Clean up after the write, and free any memory allocated */
            png_destroy_write_struct(&png_ptr, &info_ptr);

            /* Close the file */
            fclose(fp);
        }
Пример #19
0
void save_as_png(T1 & file,
                 T2 const& image,
                 int compression = Z_DEFAULT_COMPRESSION,
                 int strategy = Z_DEFAULT_STRATEGY,
                 int alpha = false,
                 bool use_miniz = false)
{
    if (use_miniz) {
        MiniZ::PNGWriter writer(compression);
        if (alpha) {
            writer.writeIHDR(image.width(), image.height(), 32);
            writer.writeIDAT(image);
        } else {
            writer.writeIHDR(image.width(), image.height(), 24);
            writer.writeIDATStripAlpha(image);
        }
        writer.writeIEND();
        writer.toStream(file);
        return;
    }

    png_voidp error_ptr=0;
    png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING,
                        error_ptr,0, 0);

    if (!png_ptr) return;

    // switch on optimization only if supported
#if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200) && defined(PNG_MMX_CODE_SUPPORTED)
    png_uint_32 mask, flags;
    flags = png_get_asm_flags(png_ptr);
    mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE);
    png_set_asm_flags(png_ptr, flags | mask);
#endif
    png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_FILTER_NONE);
    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
    {
        png_destroy_write_struct(&png_ptr,(png_infopp)0);
        return;
    }
    jmp_buf* jmp_context = (jmp_buf*) png_get_error_ptr(png_ptr);
    if (jmp_context)
    {
        png_destroy_write_struct(&png_ptr, &info_ptr);
        return;
    }
    png_set_write_fn (png_ptr, &file, &write_data<T1>, &flush_data<T1>);

    png_set_compression_level(png_ptr, compression);
    png_set_compression_strategy(png_ptr, strategy);
    png_set_compression_buffer_size(png_ptr, 32768);

    png_set_IHDR(png_ptr, info_ptr, image.width(), image.height(), 8,
                 alpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB,
                 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
                 PNG_FILTER_TYPE_DEFAULT);

    png_bytep row_pointers[image.height()];
    for (unsigned int i = 0; i < image.height(); i++) {
        row_pointers[i] = (png_bytep)image.getRow(i);
    }
    png_set_rows(png_ptr, info_ptr, (png_bytepp)&row_pointers);
    png_write_png(png_ptr, info_ptr, alpha ? PNG_TRANSFORM_IDENTITY : PNG_TRANSFORM_STRIP_FILLER_AFTER, NULL);
    png_destroy_write_struct(&png_ptr, &info_ptr);
}
Пример #20
0
void SavePng(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, const std::string& filename, bool top_line_first)
{
    PANGOLIN_UNUSED(image);
    PANGOLIN_UNUSED(filename);
    PANGOLIN_UNUSED(top_line_first);

    // Check image has supported bit depth
    for(unsigned int i=1; i < fmt.channels; ++i) {
        if( fmt.channel_bits[i] != fmt.channel_bits[0] ) {
            throw std::runtime_error("PNG Saving only supported for images where each channel has the same bit depth.");
        }
    }

#ifdef HAVE_PNG
    FILE *fp;
    png_structp png_ptr;
    png_infop info_ptr;

    // Open file for writing (binary mode)
    fp = fopen(filename.c_str(), "wb");
    if (fp == NULL) {
        throw std::runtime_error( "PNG Error: Could not open file '" + filename + "' for writing" );
    }

    // Initialize write structure
    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (png_ptr == NULL) {
        fclose(fp);
        throw std::runtime_error( "PNG Error: Could not allocate write struct." );
    }

    // Initialize info structure
    info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL) {
        png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
        fclose(fp);
        throw std::runtime_error( "PNG Error: Could not allocate info struct." );
    }

    // Setup Exception handling
    if (setjmp(png_jmpbuf(png_ptr))) {
        png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
        png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
        fclose(fp);
        throw std::runtime_error( "PNG Error: Error during png creation." );
    }

    png_init_io(png_ptr, fp);

    const int bit_depth = fmt.channel_bits[0];

    int colour_type;
    switch (fmt.channels) {
    case 1: colour_type = PNG_COLOR_TYPE_GRAY; break;
    case 2: colour_type = PNG_COLOR_TYPE_GRAY_ALPHA; break;
    case 3: colour_type = PNG_COLOR_TYPE_RGB; break;
    case 4: colour_type = PNG_COLOR_TYPE_RGBA; break;
    default:
        throw std::runtime_error( "PNG Error: unexpected image channel number");
    }

    // Write header
    png_set_IHDR(
        png_ptr, info_ptr, (png_uint_32)image.w, (png_uint_32)image.h, bit_depth, colour_type,
        PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT
    );

    // Setup rows to write:
    std::vector<png_bytep> rows(image.h);
    if(top_line_first) {
        for (unsigned int y = 0; y< image.h; y++) {
            rows[y] = image.ptr + y*image.pitch;
        }
    }else{
        for (unsigned int y = 0; y< image.h; y++) {
            rows[y] = image.ptr + (image.h-1-y)*image.pitch;
        }
    }
    png_set_rows(png_ptr,info_ptr, &rows[0]);

    // Write image data: switch to little-endian byte order, to match host.
    png_write_png(png_ptr,info_ptr, PNG_TRANSFORM_SWAP_ENDIAN, 0);

    // Free resources
    fclose(fp);
    png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
    png_destroy_write_struct(&png_ptr, (png_infopp)NULL);

#else
    throw std::runtime_error("PNG Support not enabled. Please rebuild Pangolin.");
#endif
}
Пример #21
0
/* Save the two dimensional array as a png image
 * Arguments:
 *   double *data is a pointer to an array of nx*ny values
 *   int nx is the number of COLUMNS to be written
 *   int ny is the number of ROWS to be written
 *   char *fname is the name of the picture
 *   char lang is either 'c' or 'f' denoting the memory
 *             layout. That is, if 'f' is given, then rows
 *             and columns are swapped.
 */
int save_png(double *data, const int height, const int width,
             const char *fname, const char lang)
{
    FILE *fp;
    png_structp pngstruct_ptr = NULL;
    png_infop pnginfo_ptr = NULL;
    png_byte **row_pointers = NULL;
    int i, j;

    /* Default return status is failure */
    int status = -1;

    int pixel_size = 3;
    int depth = 8;

    fp = fopen(fname, "wb");
    if (fp == NULL)
        goto fopen_failed;

    pngstruct_ptr =
        png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

    if (pngstruct_ptr == NULL)
        goto pngstruct_create_failed;

    pnginfo_ptr = png_create_info_struct(pngstruct_ptr);

    if (pnginfo_ptr == NULL)
        goto pnginfo_create_failed;

    if (setjmp(png_jmpbuf(pngstruct_ptr)))
        goto setjmp_failed;

    png_set_IHDR(pngstruct_ptr, pnginfo_ptr, (size_t) width,
                 (size_t) height, depth, PNG_COLOR_TYPE_RGB,
                 PNG_INTERLACE_NONE,
                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

    row_pointers = png_malloc(pngstruct_ptr, height * sizeof(png_byte *));

    for (i = 0; i < height; i++) {
        png_byte *row = png_malloc(pngstruct_ptr,
                                   sizeof(uint8_t) * width * pixel_size);
        row_pointers[i] = row;

        // Branch according to the memory layout
        if (lang == 'c' || lang == 'C') {
            for (j = 0; j < width; j++) {
                pixel_t pixel;
                // Scale the values so that values between
                // 0 and 100 degrees are mapped to values
                // between 0 and 255
                cmap(data[j + i * width], 2.55, 0.0, &pixel);
                *row++ = pixel.red;
                *row++ = pixel.green;
                *row++ = pixel.blue;
            }
        } else {
            for (j = 0; j < width; j++) {
                pixel_t pixel;
                // Scale the values so that values between
                // 0 and 100 degrees are mapped to values
                // between 0 and 255
                cmap(data[i + j * height], 2.55, 0.0, &pixel);
                *row++ = pixel.red;
                *row++ = pixel.green;
                *row++ = pixel.blue;
            }
        }
    }

    png_init_io(pngstruct_ptr, fp);
    png_set_rows(pngstruct_ptr, pnginfo_ptr, row_pointers);
    png_write_png(pngstruct_ptr, pnginfo_ptr,
                  PNG_TRANSFORM_IDENTITY, NULL);

    status = 0;

    for (i = 0; i < height; i++) {
        png_free(pngstruct_ptr, row_pointers[i]);
    }
    png_free(pngstruct_ptr, row_pointers);

  setjmp_failed:
  pnginfo_create_failed:
    png_destroy_write_struct(&pngstruct_ptr, &pnginfo_ptr);
  pngstruct_create_failed:
    fclose(fp);
  fopen_failed:
    return status;
}
Пример #22
0
void SavePNG( Img const& img, RGBx const* palette, const char* filename )
{
    assert(img.Format()==Img::INDEXED8BIT);
    // TODO: set error handler to capture error msg?

    FILE *fp = fopen(filename, "wb");
    if (!fp)
    {
        throw Wobbly( "open failed: %s", strerror(errno) );
    }

    png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, (png_voidp)0,0,0 );
    if (!png_ptr)
    {
        fclose(fp);
        throw Wobbly( "failed writing PNG (png_create_write() failed)" );
    }

    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
    {
        fclose(fp);
        png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
        throw Wobbly( "failed writing PNG (png_create_info_struct() failed)" );
    }

    if (setjmp(png_jmpbuf(png_ptr)))
    {
        png_destroy_write_struct(&png_ptr, &info_ptr);
        fclose(fp);
        throw Wobbly( "failed writing PNG" );
    }

    png_init_io(png_ptr, fp);

    png_set_IHDR( png_ptr,
        info_ptr,
        img.W(), img.H(),
        8,
        PNG_COLOR_TYPE_PALETTE,
        PNG_INTERLACE_NONE,
        PNG_COMPRESSION_TYPE_DEFAULT,
        PNG_FILTER_TYPE_DEFAULT );

    {
        png_color tmp_palette[256];
        int i;
        for(i=0;i<256;++i)
        {
            tmp_palette[i].red = palette[i].r;
            tmp_palette[i].green = palette[i].g;
            tmp_palette[i].blue = palette[i].b;
        }
        png_set_PLTE( png_ptr, info_ptr, tmp_palette, 256 );
    }

    //png_set_bKGD( png_ptr, info_ptr, 0 );

    {
        png_bytep row_pointers[ img.H() ];
        int y;
        for( y=0;y<img.H();++y)
            row_pointers[y] = (png_bytep)img.PtrConst(0,y);

        png_set_rows( png_ptr, info_ptr, row_pointers );

        png_write_png(png_ptr, info_ptr, 0, NULL);
    }

    png_destroy_write_struct(&png_ptr, &info_ptr);
    fclose(fp);
}
Пример #23
0
void saveCorePNG  (FILE * writer, GLuint texture, int w, int h) {
	GLint tw, th;

	glBindTexture (GL_TEXTURE_2D, texture);
	getTextureDimensions(texture, &tw, &th);

	GLubyte* image = new GLubyte [tw*th*4];
	if (! checkNew (image)) return;

	glPixelStorei (GL_PACK_ALIGNMENT, 1);
//	glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, image);

	setPixelCoords (true);
		

	//glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

	const GLfloat texCoords[] = { 
		0.0f, 0.0f,
		1.0f, 0.0f,
		0.0f, 1.0f,
		1.0f, 1.0f
	}; 

	int xoffset = 0;
	while (xoffset < tw) {
		int w = (tw-xoffset < viewportWidth) ? tw-xoffset : viewportWidth;

		int yoffset = 0;
		while (yoffset < th) {
			int h = (th-yoffset < viewportHeight) ? th-yoffset : viewportHeight;
			
			glClear(GL_COLOR_BUFFER_BIT);	// Clear The Screen

			const GLfloat vertices[] = { 
				(GLfloat)-xoffset, (GLfloat)-yoffset, 0., 
				(GLfloat)tw-xoffset, (GLfloat)-yoffset, 0., 
				(GLfloat)-xoffset, (GLfloat)-yoffset+th, 0.,
				(GLfloat)tw-xoffset, (GLfloat)-yoffset+th, 0.
			};

			glUseProgram(shader.texture);
			setPMVMatrix(shader.texture);

			drawQuad(shader.texture, vertices, 1, texCoords);

			glUseProgram(0);

			for (int i = 0; i<h; i++)	{
				glReadPixels(viewportOffsetX, viewportOffsetY+i, w, 1, GL_RGBA, GL_UNSIGNED_BYTE, image+xoffset*4+(yoffset+i)*4*tw);
			}
			
			yoffset += viewportHeight;
		}
		
		xoffset += viewportWidth;
	}
	
	setPixelCoords (false);
	
	
	
	png_structp png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (!png_ptr) {
		fatal ("Error saving image!");
		return;
	}

	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr){
		png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
		fatal ("Error saving image!");
		return;
	}

	png_init_io(png_ptr, writer);

	png_set_IHDR(png_ptr, info_ptr, w, h,
				 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

	unsigned char * row_pointers[h];

	for (int i = 0; i < h; i++) {
		row_pointers[i] = image + 4*i*tw;
	}

	png_set_rows(png_ptr, info_ptr, row_pointers);
    png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

	delete [] image;
	image = NULL;
}
Пример #24
0
int
writepng(char *fname, uint16_t *data, size_t width, size_t height)
{
    int i;
    FILE *fp;
    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL;
    png_byte **row_pointers = NULL;

    fp = fopen(fname, "wb");
    if(!fp) {
        return -1;
    }

    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if(!png_ptr) {
        fclose(fp);
        return -1;
    }

    info_ptr = png_create_info_struct(png_ptr);
    if(!info_ptr) {
        png_destroy_write_struct(&png_ptr, NULL);
        fclose(fp);
        return -1;
    }

    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_write_struct(&png_ptr, &info_ptr);
        fclose(fp);
        return -1;
    }

    png_set_IHDR(png_ptr,
                 info_ptr,
                 width,
                 height,
                 16,
                 PNG_COLOR_TYPE_GRAY,
                 PNG_INTERLACE_NONE,
                 PNG_COMPRESSION_TYPE_DEFAULT,
                 PNG_FILTER_TYPE_DEFAULT);

    row_pointers = png_malloc(png_ptr, height * sizeof(png_byte *));

    for (i = 0; i < height; i++) {
        uint8_t *row = png_malloc(png_ptr, width * 2);
        row_pointers[i] = (png_byte *)row;
        memcpy(row_pointers[i], &data[i * width], width * 2);
    }

    png_init_io(png_ptr, fp);
    png_set_rows(png_ptr, info_ptr, row_pointers);
    png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

    for (i = 0; i < height; i++) {
        png_free(png_ptr, row_pointers[i]);
    }
    png_free(png_ptr, row_pointers);

    png_destroy_write_struct(&png_ptr, &info_ptr);
    fclose(fp);
    return 0;
}
Пример #25
0
void Screendump(const char* destFile, const int width, const int height)
{
	std::string dir = FileSystem::GetUserDir("screenshots");
	FileSystem::rawFileSystem.MakeDirectory(dir);
	std::string fname = FileSystem::JoinPathBelow(dir, destFile);

	// pad rows to 4 bytes, which is the default row alignment for OpenGL
	const int stride = (3*width + 3) & ~3;

	std::vector<png_byte> pixel_data(stride * height);
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
	glPixelStorei(GL_PACK_ALIGNMENT, 4); // never trust defaults
	glReadBuffer(GL_FRONT);
	glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, &pixel_data[0]);
	glFinish();

	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
	if (!png_ptr) {
		fprintf(stderr, "Couldn't create png_write_struct\n");
		return;
	}

	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr) {
		png_destroy_write_struct(&png_ptr, 0);
		fprintf(stderr, "Couldn't create png_info_struct\n");
		return;
	}

	//http://www.libpng.org/pub/png/libpng-1.2.5-manual.html#section-3.1
	if (setjmp(png_jmpbuf(png_ptr))) {
		png_destroy_write_struct(&png_ptr, &info_ptr);
		fprintf(stderr, "Couldn't set png jump buffer\n");
		return;
	}

	FILE *out = fopen(fname.c_str(), "wb");
	if (!out) {
		png_destroy_write_struct(&png_ptr, &info_ptr);
		fprintf(stderr, "Couldn't open %s for writing\n", fname.c_str());
		return;
	}

	png_init_io(png_ptr, out);
	png_set_filter(png_ptr, 0, PNG_FILTER_NONE);
	png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB,
		PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
		PNG_FILTER_TYPE_DEFAULT);

	png_bytepp rows = new png_bytep[height];

	for (int i = 0; i < height; ++i) {
		rows[i] = reinterpret_cast<png_bytep>(&pixel_data[(height-i-1) * stride]);
	}
	png_set_rows(png_ptr, info_ptr, rows);
	png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, 0);

	png_destroy_write_struct(&png_ptr, &info_ptr);

	delete[] rows;

	fclose(out);
	printf("Screenshot %s saved\n", fname.c_str());
}
Пример #26
0
bool SavePng(std::string filename, const DepthImage& img)
{
    // Open up a file for writing
    FILE* output = fopen(filename.c_str(), "wb");
    if (output == NULL)
    {
        printf("Failed to open PNG file for writing (errno = %i)\n", errno);
        return false;
    }

    // Create a png pointer with the callbacks above
    png_structp png_ptr = png_create_write_struct(
        PNG_LIBPNG_VER_STRING, NULL, on_png_error, on_png_warn);
    if (png_ptr == NULL)
    {
        fprintf(stderr, "Failed to allocate png write_struct\n");
        fclose(output);
        return false;
    }

    // Create an info pointer
    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL)
    {
        fprintf(stderr, "Failed to create png info_struct");
        png_destroy_write_struct(&png_ptr, &info_ptr);
        fclose(output);
        return false;
    }

    // Set physical vars
    png_set_IHDR(png_ptr, info_ptr, img.cols(), img.rows(), 16,
                 PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE,
                 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

    png_init_io(png_ptr, output);

    const float zmax = img.maxCoeff();
    const float zmin = (img == -std::numeric_limits<float>::infinity())
            .select(DepthImage::Constant(img.rows(), img.cols(), zmax),
                    img)
            .minCoeff();

    auto scaled = (zmax == zmin)
        ? DepthImage((img - zmin) + 65535)
        : DepthImage((img - zmin) * 65534 / (zmax - zmin) + 1);
    Eigen::Array<uint16_t, Eigen::Dynamic, Eigen::Dynamic>
        pixels = scaled.cast<uint16_t>().transpose();

    std::vector<uint16_t*> rows;
    for (int i=pixels.cols() - 1; i >= 0; --i)
    {
        rows.push_back(pixels.data() + i * pixels.rows());
    }

    png_set_rows(png_ptr, info_ptr, reinterpret_cast<png_bytepp>(&rows[0]));
    png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_SWAP_ENDIAN, NULL);
    fclose(output);

    png_destroy_write_struct(&png_ptr, &info_ptr);
    return true;
}
Пример #27
0
// Note: Calls req.Respond().  Other data can be added afterward.
static bool StreamBufferToDataURI(DebuggerRequest &req, const GPUDebugBuffer &buf, bool includeAlpha, int stackWidth) {
#ifdef USING_QT_UI
	req.Fail("Not supported on Qt yet, pull requests accepted");
	return false;
#else
	u8 *flipbuffer = nullptr;
	u32 w = (u32)-1;
	u32 h = (u32)-1;
	const u8 *buffer = ConvertBufferToScreenshot(buf, includeAlpha, flipbuffer, w, h);
	if (!buffer) {
		req.Fail("Internal error converting buffer for PNG encode");
		return false;
	}

	if (stackWidth > 0) {
		u32 totalPixels = w * h;
		w = stackWidth;
		while ((totalPixels % w) != 0)
			--w;
		h = totalPixels / w;
	}

	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
	if (!png_ptr) {
		req.Fail("Internal error setting up PNG encoder (png_ptr)");
		return false;
	}
	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr) {
		png_destroy_write_struct(&png_ptr, nullptr);
		req.Fail("Internal error setting up PNG encoder (info_ptr)");
		return false;
	}

	// Speed.  Wireless N should give 35 KB/ms.  For most devices, zlib/filters will cost more.
	png_set_compression_strategy(png_ptr, Z_RLE);
	png_set_compression_level(png_ptr, 1);
	png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_FILTER_NONE);

	auto &json = req.Respond();
	json.writeInt("width", w);
	json.writeInt("height", h);

	// Start a value...
	json.writeRaw("uri", "");
	req.Flush();
	// Now we'll write it directly to the stream.
	req.ws->AddFragment(false, "\"data:image/png;base64,");

	struct Context {
		DebuggerRequest *req;
		uint8_t buf[3];
		size_t bufSize;
	};
	Context ctx = { &req, {}, 0 };

	auto write = [](png_structp png_ptr, png_bytep data, png_size_t length) {
		auto ctx = (Context *)png_get_io_ptr(png_ptr);
		auto &req = *ctx->req;

		// If we buffered some bytes, fill to 3 bytes for a clean base64 encode.
		// This way we don't have padding.
		while (length > 0 && ctx->bufSize > 0 && ctx->bufSize != 3) {
			ctx->buf[ctx->bufSize++] = data[0];
			data++;
			length--;
		}

		if (ctx->bufSize == 3) {
			req.ws->AddFragment(false, Base64Encode(ctx->buf, ctx->bufSize));
			ctx->bufSize = 0;
		}
		assert(ctx->bufSize == 0 || length == 0);

		// Save bytes that would result in padding for next time.
		size_t toBuffer = length % 3;
		for (size_t i = 0; i < toBuffer; ++i) {
			ctx->buf[i] = data[length - toBuffer + i];
			ctx->bufSize++;
		}

		if (length > toBuffer) {
			req.ws->AddFragment(false, Base64Encode(data, length - toBuffer));
		}
	};
	auto flush = [](png_structp png_ptr) {
		// Nothing, just here to prevent stdio flush.
	};

	png_bytep *row_pointers = new png_bytep[h];
	u32 stride = includeAlpha ? w * 4 : w * 3;
	for (u32 i = 0; i < h; ++i) {
		row_pointers[i] = (u8 *)buffer + stride * i;
	}

	png_set_write_fn(png_ptr, &ctx, write, flush);
	int colorType = includeAlpha ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB;
	png_set_IHDR(png_ptr, info_ptr, w, h, 8, colorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
	png_set_rows(png_ptr, info_ptr, row_pointers);
	png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, nullptr);

	png_destroy_write_struct(&png_ptr, &info_ptr);
	delete [] row_pointers;
	delete [] flipbuffer;

	if (ctx.bufSize > 0) {
		req.ws->AddFragment(false, Base64Encode(ctx.buf, ctx.bufSize));
		ctx.bufSize = 0;
	}

	// End the string.
	req.ws->AddFragment(false, "\"");
	return true;
#endif
}
Пример #28
0
bool writePNG(Common::WriteStream &out, const Graphics::Surface &input, const bool bottomUp) {
#ifdef USE_PNG
	const Graphics::PixelFormat requiredFormat_3byte(3, 8, 8, 8, 0, 16, 8, 0, 0);
	const Graphics::PixelFormat requiredFormat_4byte(4, 8, 8, 8, 8, 0, 8, 16, 24);

	if (input.format.bytesPerPixel == 3) {
		if (input.format != requiredFormat_3byte) {
			warning("Cannot currently write PNG with 3-byte pixel format other than %s", requiredFormat_3byte.toString().c_str());
			return false;
		}
	} else if (input.format.bytesPerPixel != 4) {
		warning("Cannot currently write PNG with pixel format of bpp other than 3, 4");
		return false;
	}

	int colorType;
	Graphics::Surface *tmp = NULL;
	const Graphics::Surface *surface;

	if (input.format == requiredFormat_3byte) {
		surface = &input;
		colorType = PNG_COLOR_TYPE_RGB;
	} else {
		if (input.format == requiredFormat_4byte) {
			surface = &input;
		} else {
			surface = tmp = input.convertTo(requiredFormat_4byte);
		}
		colorType = PNG_COLOR_TYPE_RGB_ALPHA;
	}

	png_structp pngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (!pngPtr) {
		return false;
	}
	png_infop infoPtr = png_create_info_struct(pngPtr);
	if (!infoPtr) {
		png_destroy_write_struct(&pngPtr, NULL);
		return false;
	}

	png_set_error_fn(pngPtr, NULL, pngError, pngWarning);
	// TODO: The manual says errors should be handled via setjmp

	png_set_write_fn(pngPtr, &out, pngWriteToStream, pngFlushStream);

	png_set_IHDR(pngPtr, infoPtr, surface->w, surface->h, 8, colorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

	Common::Array<const uint8 *> rows;
	rows.reserve(surface->h);
	if (bottomUp) {
		for (uint y = surface->h; y-- > 0;) {
			rows.push_back((const uint8 *)surface->getBasePtr(0, y));
		}
	} else {
		for (uint y = 0; y < surface->h; ++y) {
			rows.push_back((const uint8 *)surface->getBasePtr(0, y));
		}
	}

	png_set_rows(pngPtr, infoPtr, const_cast<uint8 **>(&rows.front()));
	png_write_png(pngPtr, infoPtr, 0, NULL);
	png_destroy_write_struct(&pngPtr, &infoPtr);

	// free tmp surface
	if (tmp) {
		tmp->free();
		delete tmp;
	}

	return true;
#else
	return false;
#endif
}
Пример #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;
}
Пример #30
0
/* Write "bitmap" to a PNG file specified by "path"; returns 0 on
 success, non-zero on error. */
int save_png_to_file (Bitmap *bitmap, const char *path)
{
    FILE * fp;
    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL;
    size_t x, y;
    png_bytep *row_pointers = NULL;

    /* "status" contains the return value of this function. At first
     it is set to a value which means 'failure'. When the routine
     has finished its work, it is set to a value which means
     'success'. */
    int status = -1;
    
    /* The following number is set by trial and error only. I cannot
     see where it it is documented in the libpng manual.
     */
    int pixel_size = 3;
    int depth = 8;
    
    fp = fopen (path, "wb");
    if (! fp) {
        goto fopen_failed;
    }
    
    png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (png_ptr == NULL) {
        goto png_create_write_struct_failed;
    }
    
    info_ptr = png_create_info_struct (png_ptr);
    if (info_ptr == NULL) {
        goto png_create_info_struct_failed;
    }
    
    /* Set up error handling. */
    
    if (setjmp (png_jmpbuf (png_ptr))) {
        goto png_failure;
    }
    
    /* Set image attributes. */
    
    png_set_IHDR (png_ptr,
                  info_ptr,
                  bitmap->width,
                  bitmap->height,
                  depth,
                  PNG_COLOR_TYPE_RGB,
                  PNG_INTERLACE_NONE,
                  PNG_COMPRESSION_TYPE_DEFAULT,
                  PNG_FILTER_TYPE_DEFAULT);
    
    /* Initialize rows of PNG. */
    row_pointers = (png_bytep*) png_malloc(png_ptr, bitmap->height*sizeof(png_byte *));

    for (y = 0; y < bitmap->height; ++y) {
        png_byte *row = (png_byte *)png_malloc (png_ptr, sizeof (uint8_t) * bitmap->width * pixel_size);
        row_pointers[y] = row;
        for (x = 0; x < bitmap->width; ++x) {
            WPixel* pixel = pixel_at(bitmap, x, y);
            *row++ = pixel->red;
            *row++ = pixel->green;
            *row++ = pixel->blue;
        }
    }
    
    /* Write the image data to "fp". */
    
    png_init_io (png_ptr, fp);
    png_set_rows (png_ptr, info_ptr, row_pointers);
    png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
    
    /* The routine has successfully written the file, so we set
     "status" to a value which indicates success. */
    
    status = 0;
    
    for (y = 0; y < bitmap->height; y++) {
        png_free (png_ptr, row_pointers[y]);
    }
    png_free (png_ptr, row_pointers);
    
png_failure:
png_create_info_struct_failed:
    png_destroy_write_struct (&png_ptr, &info_ptr);
png_create_write_struct_failed:
    fclose (fp);
fopen_failed:
    return status;
}