Пример #1
0
void save_to_png(char* filename) {
    int i;
    // use malloc rather than the stack since an array of several million bytes will overflow the stack
    uint8_t *pixels = malloc(width * height * 3 * sizeof(uint8_t));
    // switch the framebuffer in order to force the full texture to be saved
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffers[fb]);
    glViewport(0, 0, width, height);
    // copy pixels from screen
    glActiveTexture(0);
    glBindTexture(GL_TEXTURE_2D, textures[fb]);
    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, width, height);
    glPixelStorei(GL_PACK_ALIGNMENT, 1);
    glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid *)pixels);
    // use libpng to write the pixels to a png image
    png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png) goto png_fail;
    png_infop info = png_create_info_struct(png);
    if (!info) {
        png_destroy_write_struct(&png, &info);
        goto png_fail;
    }
    if(filename == NULL) {
        // filename => current time in milliseconds
        char tmp[256];
        snprintf(tmp, 256, "%llu.png", get_time_us() * 1000);
        filename = tmp;
    }
    FILE *file = fopen(filename, "wb");
    if (!file) {
        png_destroy_write_struct(&png, &info);
        goto png_fail;
    }
    png_init_io(png, file);
    png_set_IHDR(png, info, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, 
            PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
    png_colorp palette = png_malloc(png, PNG_MAX_PALETTE_LENGTH * sizeof(png_color));
    if (!palette) {
        fclose(file);
        png_destroy_write_struct(&png, &info);
        goto png_fail;
    }
    png_set_PLTE(png, info, palette, PNG_MAX_PALETTE_LENGTH);
    png_write_info(png, info);
    png_set_packing(png);
    png_bytepp rows = (png_bytepp)png_malloc(png, height * sizeof(png_bytep));
    for (i = 0; i < height; ++i) {
        rows[i] = (png_bytep)(pixels + (height - i - 1) * width * 3);
    }
    png_write_image(png, rows);
    png_write_end(png, info);
    png_free(png, palette);
    png_destroy_write_struct(&png, &info);
    fclose(file);
    free(pixels);
    printf("PNG: finished at %llu\n", get_time_us());
    render_prepare_screen();
    return;
png_fail:
    fail("Failed to create PNG\n");
}
Пример #2
0
static int write_png_palette(
    png_struct *png_ptr, png_info *info_ptr, SDL_Surface *scr)
{
  int i, result = -1;
  png_color *palette;

  palette = malloc(sizeof(*palette) * scr->format->palette->ncolors);

  if (palette)
  {
    // Convert SDL palette to libpng
    for (i = 0; i < scr->format->palette->ncolors; i++) {
      palette[i].red   = scr->format->palette->colors[i].r;
      palette[i].green = scr->format->palette->colors[i].g;
      palette[i].blue  = scr->format->palette->colors[i].b;
    }

    png_set_PLTE(png_ptr, info_ptr,
        palette, scr->format->palette->ncolors);

    free(palette);
    result = 0;
  }
  return result;
}
Пример #3
0
pngquant_error rwpng_write_image8(FILE *outfile, png8_image *mainprog_ptr)
{
    png_structp png_ptr;
    png_infop info_ptr;

    pngquant_error retval = rwpng_write_image_init((png_image*)mainprog_ptr, &png_ptr, &info_ptr, outfile);
    if (retval) return retval;

    /* set the image parameters appropriately */
    int sample_depth;
    if (mainprog_ptr->num_palette <= 2)
        sample_depth = 1;
    else if (mainprog_ptr->num_palette <= 4)
        sample_depth = 2;
    else if (mainprog_ptr->num_palette <= 16)
        sample_depth = 4;
    else
        sample_depth = 8;

    png_set_IHDR(png_ptr, info_ptr, mainprog_ptr->width, mainprog_ptr->height,
      sample_depth, PNG_COLOR_TYPE_PALETTE,
      0, PNG_COMPRESSION_TYPE_DEFAULT,
      PNG_FILTER_TYPE_BASE);

    png_set_PLTE(png_ptr, info_ptr, &mainprog_ptr->palette[0], mainprog_ptr->num_palette);

    if (mainprog_ptr->num_trans > 0)
        png_set_tRNS(png_ptr, info_ptr, mainprog_ptr->trans, mainprog_ptr->num_trans, NULL);

    rwpng_write_end(&info_ptr, &png_ptr, (png_image*)mainprog_ptr);

    return SUCCESS;
}
Пример #4
0
static int save_png_sub(RefImage *image, Value w)
{
    png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    png_infop info_ptr = png_create_info_struct(png_ptr);
    png_bytepp rows = malloc(sizeof(png_bytep) * image->height);
    png_bytep data = (png_bytep)image->data;
    int color_type = PNG_COLOR_TYPE_RGB;
    int i;

    png_set_write_fn(png_ptr, &w, png_write_callback, png_flush_callback);

    switch (image->bands) {
    case BAND_L:
        color_type = PNG_COLOR_TYPE_GRAY;
        break;
    case BAND_LA:
        color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
        break;
    case BAND_P:
        color_type = PNG_COLOR_TYPE_PALETTE;
        break;
    case BAND_RGB:
        color_type = PNG_COLOR_TYPE_RGB;
        break;
    case BAND_RGBA:
        color_type = PNG_COLOR_TYPE_RGB_ALPHA;
        break;
    }
    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_write_struct(&png_ptr,  &info_ptr);
        free(rows);
        return FALSE;
    }

    png_set_IHDR(png_ptr, info_ptr,
            image->width, image->height, 8, color_type,
            PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

    for (i = 0; i < image->height; i++) {
        rows[i] = data + image->pitch * i;
    }

    if (image->bands == BAND_P) {
        uint32_t *pal = image->palette;
        uint8_t trans[PALETTE_NUM];
        png_color pcolor[PALETTE_NUM];
        if (palette_has_alpha(pal)) {
            for (i = 0; i < PALETTE_NUM; i++) {
                trans[i] = (pal[i] & COLOR_A_MASK) >> COLOR_A_SHIFT;
            }
            png_set_tRNS(png_ptr, info_ptr, trans, PALETTE_NUM, NULL);
        }
        for (i = 0; i < PALETTE_NUM; i++) {
            pcolor[i].red   = (pal[i] & COLOR_R_MASK) >> COLOR_R_SHIFT;
            pcolor[i].green = (pal[i] & COLOR_G_MASK) >> COLOR_G_SHIFT;
            pcolor[i].blue  = (pal[i] & COLOR_B_MASK) >> COLOR_B_SHIFT;
        }
        png_set_PLTE(png_ptr, info_ptr, pcolor, PALETTE_NUM);
    }
void writeSetup2(png_structp png_ptr_write, png_infop info_ptr_write,
                 png_structp png_ptr_read, png_infop info_ptr_read)
{
    /* IHDR */
    png_uint_32 width;
    png_uint_32 height;
    int bit_depth;
    int colour_type;
    int interlace_method;
    int compression_method;
    int filter_method;
    
    /* PLTE */
    png_colorp palette = NULL;
    int palette_size = 0;
    
    /* gAMA */
    double gamma;
    
    /* tRNS */
    png_bytep trans;
    int num_trans;
    png_color_16p trans_values;
    
    /* bKGD */
    png_color_16p background;
    
    png_get_IHDR(png_ptr_read, info_ptr_read, &width, &height,
                 &bit_depth, &colour_type, &interlace_method,
                 &compression_method, &filter_method);
    png_set_IHDR(png_ptr_write, info_ptr_write,  width, height,
                 bit_depth, colour_type, interlace_method,
                 compression_method, filter_method);
    
    if(png_get_valid(png_ptr_read, info_ptr_read, PNG_INFO_PLTE))
    {
        png_get_PLTE(png_ptr_read, info_ptr_read, &palette, &palette_size);
        png_set_PLTE(png_ptr_write, info_ptr_write, palette, palette_size);
    }
    
    if(png_get_valid(png_ptr_read, info_ptr_read, PNG_INFO_gAMA))
    {
        png_get_gAMA(png_ptr_read, info_ptr_read, &gamma);
        png_set_gAMA(png_ptr_write, info_ptr_write, gamma);
    }
    
    if(png_get_valid(png_ptr_read, info_ptr_read, PNG_INFO_tRNS))
    {
        png_get_tRNS(png_ptr_read, info_ptr_read, &trans, &num_trans, &trans_values);
        png_set_tRNS(png_ptr_write, info_ptr_write, trans, num_trans, trans_values);
    }
    
    if(png_get_valid(png_ptr_read, info_ptr_read, PNG_INFO_bKGD))
    {
        png_get_bKGD(png_ptr_read, info_ptr_read, &background);
        png_set_bKGD(png_ptr_write, info_ptr_write, background);
    }
}
Пример #6
0
/** Write out the PLTE (and possibly tRNS) chunk to the png. This will create the
 *  palette data to set in the PLTE chunk and set it, and if the colorkey is set
 *  for the surface an appropriate tRNS chunk is generated.
 *
 *  \param png_ptr  A pointer to the png write structure.
 *  \param info_ptr A pointer to the png info structure.
 *  \param surf     The surface that is being written to the png.
 *  \return -1 on error, 0 if the palette chunk was written without problems.
 */
static int write_palette_chunk(png_structp png_ptr, png_infop info_ptr, SDL_Surface *surf)
{
    png_colorp palette;
    Uint8     *alphas;
    int        slot;

    SDL_PixelFormat *fmt = surf -> format;
    SDL_Color *sourcepal = fmt -> palette -> colors;

    // Write the image header first...
    png_set_IHDR(png_ptr, info_ptr, surf -> w, surf -> h, 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

    // now sort out the palette
    if(!(palette = (png_colorp)malloc(fmt -> palette -> ncolors * sizeof(png_color)))) {
        SDL_SetError("Unable to create memory for palette storage");
        return -1;
    }

    // Copy the palette over. Can't just use a straight 
    // memcpy as sdl palettes have pad bytes.
    for(slot = 0; slot < fmt -> palette -> ncolors; ++slot) {
        memcpy(&palette[slot], &sourcepal[slot], 3);
    }
    
    // Set it...
    png_set_PLTE(png_ptr, info_ptr, palette, fmt -> palette -> ncolors);

    // Done with the palette now
    free(palette);

    Uint32 colorkey;
    int ck = SDL_GetColorKey(surf, &colorkey);

    // If we have a colour key, we need to set up the alphas for each palette colour
    if(ck == 0) {
        // According the the PNG spec (section 4.2.1.1) we only need enough entries
        // to store transparencies up to the transparent pixel.
        if(!(alphas = (Uint8 *)malloc((colorkey + 1) * sizeof(Uint8)))) {
            SDL_SetError("Unable to create memory for transparency storage");
            return -1;
        }

        // Set all of the alpha values to full
        memset(alphas, 255, (colorkey + 1) * sizeof(Uint8));

        // And handle the transparent pixel
        alphas[colorkey] = 0;

        // Write the chunk, and then we're done with the transparencies
        png_set_tRNS(png_ptr, info_ptr, alphas, colorkey + 1, NULL);
        free(alphas);
    }

    return 0;
}
Пример #7
0
/*
 * Saves a byte array stored in pixels of width w and height h as a png into
 * filename
 */
GLuint save_png (const char * filename, GLubyte * pixels, GLuint w, GLuint h)
{
	png_structp png;
	png_infop info;
	png_colorp palette;
	png_bytepp rows;
	FILE * fp;

	GLuint i;

	png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (!png) return 1;

	info = png_create_info_struct(png);
	if(!info) {
		png_destroy_write_struct(&png, NULL);
		return 1;
	}

	fp = fopen(filename, "wb");
	if (!fp) {
		png_destroy_write_struct(&png, &info);
		return 1;
	}

	png_init_io(png, fp);
	png_set_IHDR(png, info, w, h, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
			PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
	palette = (png_colorp) png_malloc(png, PNG_MAX_PALETTE_LENGTH
			* sizeof(png_color));
	if (!palette) {
		fclose(fp);
		png_destroy_write_struct(&png, &info);
		return 1;
	}

	png_set_PLTE(png, info, palette, PNG_MAX_PALETTE_LENGTH);
	png_write_info(png, info);
	png_set_packing(png);

	rows = (png_bytepp) png_malloc(png, h * sizeof(png_bytep));
	
	for (i = 0; i < h; ++i)
		rows[i] = (png_bytep) (pixels + (h - i - 1) * w * 3);

	png_write_image(png, rows);
	png_write_end(png, info);
	png_free(png, palette);
	png_destroy_write_struct(&png, &info);

	fclose(fp);
	free(rows);
	
	return 0;
}
Пример #8
0
Файл: gdpng.c Проект: blair/orca
void gdImagePng(gdImagePtr im, FILE *out)
{
    int i;
    png_colorp palette;
    png_structp png_write_ptr =
        png_create_write_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_write_ptr);

    if (setjmp(gdPngJmpbufStruct.jmpbuf)) {
        png_destroy_write_struct(&png_write_ptr, &info_ptr);
        return;
    }

    palette = (png_colorp)png_malloc (png_write_ptr,
                                      im->colorsTotal*sizeof(png_color));
    if (palette == NULL) {
        png_destroy_write_struct(&png_write_ptr, &info_ptr);
        return;
    }


    png_init_io(png_write_ptr, out);
    png_set_write_status_fn(png_write_ptr, NULL);
    png_set_IHDR(png_write_ptr,info_ptr,
                 im->sx,im->sy,im->colorsTotal > 16 ? 8:4,
                 PNG_COLOR_TYPE_PALETTE,
                 im->interlace ? PNG_INTERLACE_ADAM7: PNG_INTERLACE_NONE ,
                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
    for(i=0; i<im->colorsTotal; i++) {
        palette[i].red = im->red[i];
        palette[i].green = im->green[i];
        palette[i].blue = im->blue[i];
    }
    png_set_PLTE(png_write_ptr, info_ptr, palette, im->colorsTotal);

    /* choose between speed (1) and space (9) optimization */
    /* we want to be fast ... */
    png_set_compression_level(png_write_ptr,1);
    png_set_filter(png_write_ptr,PNG_FILTER_TYPE_BASE,PNG_NO_FILTERS);
    /* store file info */
    png_write_info(png_write_ptr, info_ptr);
    png_set_packing(png_write_ptr);
    png_write_image(png_write_ptr, im->pixels);
    png_write_end(png_write_ptr, info_ptr);
    png_free(png_write_ptr, palette);
    png_destroy_write_struct(&png_write_ptr, &info_ptr);
}
/*
 * Change the size of the palette buffer.
 * Changing info_ptr->num_palette directly, avoiding reallocation, should
 * have been sufficient, but can't be done using the current libpng API.
 */
static void opng_realloc_PLTE(png_structp png_ptr, png_infop info_ptr, int num_palette)
{
   png_colorp palette;
   int src_num_palette = 0;
   png_get_PLTE(png_ptr, info_ptr, &palette, &src_num_palette);
   if (num_palette == src_num_palette)
   {return;}
   png_color buffer[PNG_MAX_PALETTE_LENGTH];
   memcpy(buffer, palette, num_palette * sizeof(png_color));
   if (num_palette > src_num_palette)
      memset(buffer + src_num_palette, 0,
         (num_palette - src_num_palette) * sizeof(png_color));
   png_set_PLTE(png_ptr, info_ptr, buffer, num_palette);
}
Пример #10
0
extern void bitmap_write(struct bitmap *bitmap)
{
	if (!output_path && is_tty_stdout())
		message_fatal("Data cannot be written to a terminal");

	FILE *fp = output_path ? fopen(output_path, "wb") : stdout;

	if (fp == NULL)
		message_fatal("Unable to open file for writing");

	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
					NULL, NULL, NULL);

	if (png_ptr == NULL)
		message_fatal("Unable to create png struct");

	png_infop info_ptr = png_create_info_struct(png_ptr);

	if (info_ptr == NULL)
		message_fatal("Unable to create png info struct");

	if (setjmp(png_jmpbuf(png_ptr))) {
		fclose(fp);
		png_destroy_write_struct(&png_ptr, &info_ptr);
		message_fatal("Error writing png file");
	}

	png_init_io(png_ptr, fp);

	png_set_IHDR(png_ptr, info_ptr, bitmap->width, bitmap->height, 8,
		PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
		PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

	png_color *palette = palette_create();
	png_set_PLTE(png_ptr, info_ptr, palette, 256);

	png_bytep row_pointers[bitmap->height];

	for (unsigned y = 0; y < bitmap->height; y++)
		row_pointers[y] = bitmap->data + bitmap->width * y;

	png_write_info(png_ptr, info_ptr);
	png_write_image(png_ptr, row_pointers);
	png_write_end(png_ptr, info_ptr);

	palette_release(palette);
	png_destroy_write_struct(&png_ptr, &info_ptr);
	fclose(fp);
}
Пример #11
0
static void
pngx_set_GIF_palette(png_structp png_ptr, png_infop info_ptr,
   unsigned char *color_table, unsigned int num_colors)
{
   png_color palette[256];
   unsigned int i;

   PNGX_ASSERT(color_table != NULL && num_colors <= 256);
   for (i = 0; i < num_colors; ++i)
   {
      palette[i].red   = color_table[3 * i];
      palette[i].green = color_table[3 * i + 1];
      palette[i].blue  = color_table[3 * i + 2];
   }
   png_set_PLTE(png_ptr, info_ptr, palette, (int)num_colors);
}
Пример #12
0
/*
 * bta_transparent_toPNG
 */
void bta_transparent_toPNG(bta_cell_t *in, btstring_t *fname)
{
	FILE		*outfp;
	png_structp	png_ptr;
	png_infop	info_ptr;
	uint32_t	i;
	int		trans = 0;

	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (!png_ptr) {
		printf("Failed allocating png_ptr\n");
		return;
	}

	info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr) {
		printf("Failed allocating info_ptr\n");
		return;
	}

	outfp = fopen(fname->buf, "wb");
	if (outfp == NULL) {
		printf("Error opening %s\n", fname->buf);
		return;
	}

	png_init_io(png_ptr, outfp);
	png_set_IHDR(png_ptr, info_ptr, in->width, in->height, 8, \
		PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, \
		PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);


	png_set_PLTE(png_ptr, info_ptr, egapalette, 16);
	png_set_tRNS(png_ptr, info_ptr, (png_bytep)&trans, 1, NULL);

	png_write_info(png_ptr, info_ptr);

	for (i = 0; i < in->height; i++)  
		png_write_row(png_ptr, &in->gfx->buf[i * in->width]);

	png_write_end(png_ptr, info_ptr);

	png_destroy_write_struct(&png_ptr, &info_ptr);

	fclose(outfp);
	bts_free(fname);
}
Пример #13
0
void SetPngPalette(png_structp png_ptr, png_infop info_ptr, struct Palette *palette)
{
	png_colorp colors = malloc(palette->numColors * sizeof(png_color));

	if (colors == NULL)
		FATAL_ERROR("Failed to allocate PNG palette.\n");

	for (int i = 0; i < palette->numColors; i++) {
		colors[i].red = palette->colors[i].red;
		colors[i].green = palette->colors[i].green;
		colors[i].blue = palette->colors[i].blue;
	}

	png_set_PLTE(png_ptr, info_ptr, colors, palette->numColors);

	free(colors);
}
Пример #14
0
	void Texture::SaveTexture( const OutPutTextureData& saveto )
	{
		unsigned long i;
		png_structp png_ptr;
		png_infop info_ptr;
		png_colorp palette;
		png_byte *image;
		png_bytep *row_pointers;

		IFile* writefile = IOSystem::Instance().FileFactory(saveto.m_Path);
		writefile->OpenFile( IFile::AT_READ );


		png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
		info_ptr = png_create_info_struct(png_ptr);
		png_set_write_fn( png_ptr, writefile, png_rw, png_flush );
		//png_init_io(png_ptr, writefile.BaseFile() );

		int colortype, bitesize;
		switch( saveto.m_Pixel )
		{
		case Device::PF_R8G8B8: colortype = PNG_COLOR_TYPE_RGB; bitesize = 3; break;
		case Device::PF_R8G8B8A8: colortype = PNG_COLOR_TYPE_RGBA; bitesize = 4; break;
		}
		png_set_IHDR(png_ptr, info_ptr, saveto.m_Size.m_x, saveto.m_Size.m_y, 8, colortype,
			PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
		palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH * sizeof (png_color));
		png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH);
		png_write_info(png_ptr, info_ptr);
		png_set_packing(png_ptr);
		row_pointers = (png_bytep *)malloc(saveto.m_Size.m_y * sizeof(png_bytep));

		for (i = 0; i < saveto.m_Size.m_y; i++)
		{
			row_pointers[i] = (png_bytep)&saveto.m_Data[i * saveto.m_Size.m_y * bitesize];
		}
		png_write_image(png_ptr, row_pointers);
		png_write_end(png_ptr, info_ptr);
		png_free(png_ptr, palette);
		palette = NULL;
		png_destroy_write_struct(&png_ptr, &info_ptr);
		free(row_pointers);
		row_pointers = NULL;
		writefile->CloseFile( );
		IOSystem::Instance().FileDestroy( writefile );
	}
Пример #15
0
int savePNG(const char * fileName,uint32_t width,uint32_t height,void * ptr,uint8_t*pal,unsigned pn){
	//saves a 24bit png with rgb byte order
	png_byte * dat=(png_byte*)ptr;//convert to uint8_t
	FILE * fp=fopen(fileName,"wb");
	if (!fp)
		return 1;
	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)0,0,0);
	if (!png_ptr){
		fclose(fp);
		return 1;
	}
	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr){
		png_destroy_write_struct(&png_ptr,(png_infopp)NULL);
		return 1;
	}
	if (setjmp(png_jmpbuf(png_ptr))){
		png_destroy_write_struct(&png_ptr, &info_ptr);
		fclose(fp);
		return 1;
	}
	png_init_io(png_ptr, fp);
	png_set_IHDR(png_ptr, info_ptr, width, height,8,pal?PNG_COLOR_TYPE_PALETTE:PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);//must be called before other png_set_*() functions
	png_color_struct*palTmp=0;
	if(pal){
		palTmp=(png_color_struct*)malloc(pn*sizeof(png_color_struct));
		for(unsigned i=0;i<pn;++i){
			palTmp[i].red=pal[i*3];
			palTmp[i].green=pal[i*3+1];
			palTmp[i].blue=pal[i*3+2];
		}
		png_set_PLTE(png_ptr,info_ptr,palTmp,pn);
	}
	png_set_compression_level(png_ptr,Z_BEST_COMPRESSION);
	uint32_t y;
	png_set_user_limits(png_ptr, width, height);
	png_write_info(png_ptr, info_ptr);
	for (y=0;y<height;++y)
		png_write_row(png_ptr, &dat[(y*width*(pal?1:3))]);
	png_write_end(png_ptr, info_ptr);
	png_destroy_write_struct(&png_ptr, &info_ptr);
	fclose(fp);//done with file
	free(palTmp);
	return 0;//will return 0 on success non-zero in error
}
Пример #16
0
        void write() const
        {
            assert(m_png);
            assert(m_info);

            sync_ihdr();
            if (m_color_type == color_type_palette)
            {
                if (! m_palette.empty())
                {
                    png_set_PLTE(m_png, m_info,
                                 const_cast< color* >(& m_palette[0]),
                                 (int) m_palette.size());
                }
                if (! m_tRNS.empty())
                {
#ifdef PNG_tRNS_SUPPORTED
                    png_set_tRNS(m_png, m_info,
                                 const_cast< byte* >(& m_tRNS[0]),
                                 m_tRNS.size(),
                                 NULL);
#else
                    throw error("attempted to write tRNS chunk; recompile with PNG_tRNS_SUPPORTED");
#endif
                }
            }

            if (m_gamma > 0)
            {
#ifdef PNG_gAMA_SUPPORTED
#ifdef PNG_FLOATING_POINT_SUPPORTED
                png_set_gAMA(m_png, m_info, m_gamma);
#else
                png_set_gAMA_fixed(m_png, m_info,
                                   (png_fixed_point)(m_gamma * 100000));
#endif
#else
                throw error("attempted to write gAMA chunk; recompile with PNG_gAMA_SUPPORTED");
#endif
            }

            png_write_info(m_png, m_info);
        }
Пример #17
0
pngquant_error rwpng_write_image8(FILE *outfile, png8_image *mainprog_ptr)
{
    png_structp png_ptr;
    png_infop info_ptr;

    pngquant_error retval = rwpng_write_image_init((png_image*)mainprog_ptr, &png_ptr, &info_ptr, outfile);
    if (retval) return retval;

    // Palette images generally don't gain anything from filtering
    png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_FILTER_VALUE_NONE);

    rwpng_set_gamma(info_ptr, png_ptr, mainprog_ptr->gamma);

    /* set the image parameters appropriately */
    int sample_depth;
    if (mainprog_ptr->num_palette <= 2)
        sample_depth = 1;
    else if (mainprog_ptr->num_palette <= 4)
        sample_depth = 2;
    else if (mainprog_ptr->num_palette <= 16)
        sample_depth = 4;
    else
        sample_depth = 8;

    png_set_IHDR(png_ptr, info_ptr, mainprog_ptr->width, mainprog_ptr->height,
      sample_depth, PNG_COLOR_TYPE_PALETTE,
      0, PNG_COMPRESSION_TYPE_DEFAULT,
      PNG_FILTER_TYPE_BASE);

    png_set_PLTE(png_ptr, info_ptr, &mainprog_ptr->palette[0], mainprog_ptr->num_palette);

    if (mainprog_ptr->num_trans > 0)
        png_set_tRNS(png_ptr, info_ptr, mainprog_ptr->trans, mainprog_ptr->num_trans, NULL);


    png_bytepp row_pointers = rwpng_create_row_pointers(info_ptr, png_ptr, mainprog_ptr->indexed_data, mainprog_ptr->height, mainprog_ptr->width);

    rwpng_write_end(&info_ptr, &png_ptr, row_pointers);

    free(row_pointers);

    return SUCCESS;
}
UT_Error IE_ImpGraphic_Win32Native::Convert_BMP_Palette(UT_ByteBuf* pBB)
{
    /* Reset error handling for libpng */
    if (setjmp(m_pPNG->jmpbuf))
	{
		png_destroy_write_struct(&m_pPNG, &m_pPNGInfo);
		return UT_ERROR;
	}
    
    png_set_IHDR ( m_pPNG,
				   m_pPNGInfo,
				   m_iWidth,
				   m_iHeight,
				   m_iBitsPerPlane,
				   PNG_COLOR_TYPE_PALETTE,
				   PNG_INTERLACE_NONE,
				   PNG_COMPRESSION_TYPE_DEFAULT,
				   PNG_FILTER_TYPE_DEFAULT );
    
    UT_uint32 iOffset = m_iHeaderSize + 14;
    UT_uint32 numClrs = (m_iClrUsed > 0) ?
		m_iClrUsed :
		(m_iOffset - iOffset)/((m_bOldBMPFormat)?3:4);
    
    png_colorp palette = static_cast<png_colorp>(png_malloc(m_pPNG, numClrs * sizeof(png_color)));
    
    for (UT_uint32 i=0; i < numClrs; i++)
	{
		palette[i].blue  = ReadByte(pBB,iOffset++);
		palette[i].green = ReadByte(pBB,iOffset++);
		palette[i].red   = ReadByte(pBB,iOffset++);
		if(!m_bOldBMPFormat) iOffset++;
	}
    if (iOffset > m_iOffset) return UT_IE_BOGUSDOCUMENT;
    
    png_set_PLTE( m_pPNG, m_pPNGInfo, palette, numClrs );
    
    return UT_OK;
}
Пример #19
0
int spupng_write_png(struct spupng_t *sp, struct eia608_screen* data,
		png_structp png_ptr, png_infop info_ptr,
		png_bytep image,
		png_bytep* row_pointer,
		unsigned int ww, unsigned int wh)
{
	unsigned int i;

	if (setjmp(png_jmpbuf(png_ptr)))
		return 0;

	png_init_io (png_ptr, sp->fppng);

	png_set_IHDR (png_ptr,
			info_ptr,
			ww,
			wh,
			/* bit_depth */ 8,
			PNG_COLOR_TYPE_PALETTE,
			PNG_INTERLACE_NONE,
			PNG_COMPRESSION_TYPE_DEFAULT,
			PNG_FILTER_TYPE_DEFAULT);

	png_set_PLTE (png_ptr, info_ptr, palette, sizeof(palette) / sizeof(palette[0]));
	png_set_tRNS (png_ptr, info_ptr, alpha, sizeof(alpha) / sizeof(alpha[0]), NULL);

	png_set_gAMA (png_ptr, info_ptr, 1.0 / 2.2);

	png_write_info (png_ptr, info_ptr);

	for (i = 0; i < wh; i++)
		row_pointer[i] = image + i * ww;

	png_write_image (png_ptr, row_pointer);

	png_write_end (png_ptr, info_ptr);

	return 1;
}
Пример #20
0
bool CCImage::_saveImageToPNG(const char * pszFilePath, bool bIsToRGB)
{
	bool bRet = false;
	do 
	{
		CC_BREAK_IF(NULL == pszFilePath);

		FILE *fp;
		png_structp png_ptr;
		png_infop info_ptr;
		png_colorp palette;
		png_bytep *row_pointers;

		fp = fopen(pszFilePath, "wb");
		CC_BREAK_IF(NULL == fp);

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

		if (NULL == png_ptr)
		{
			fclose(fp);
			break;
		}

		info_ptr = png_create_info_struct(png_ptr);
		if (NULL == info_ptr)
		{
			fclose(fp);
			png_destroy_write_struct(&png_ptr, NULL);
			break;
		}
#if (CC_TARGET_PLATFORM != CC_PLATFORM_BADA)
		if (setjmp(png_jmpbuf(png_ptr)))
		{
			fclose(fp);
			png_destroy_write_struct(&png_ptr, &info_ptr);
			break;
		}
#endif
		png_init_io(png_ptr, fp);

		if (!bIsToRGB && m_bHasAlpha)
		{
			png_set_IHDR(png_ptr, info_ptr, m_nWidth, m_nHeight, 8, PNG_COLOR_TYPE_RGB_ALPHA,
				PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
		} 
		else
		{
			png_set_IHDR(png_ptr, info_ptr, m_nWidth, m_nHeight, 8, PNG_COLOR_TYPE_RGB,
				PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
		}

		palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH * sizeof (png_color));
		png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH);

		png_write_info(png_ptr, info_ptr);

		png_set_packing(png_ptr);

		row_pointers = (png_bytep *)malloc(m_nHeight * sizeof(png_bytep));
		if(row_pointers == NULL)
		{
			fclose(fp);
			png_destroy_write_struct(&png_ptr, &info_ptr);
			break;
		}

		if (!m_bHasAlpha)
		{
			for (int i = 0; i < (int)m_nHeight; i++)
			{
				row_pointers[i] = (png_bytep)m_pData + i * m_nWidth * 3;
			}

			png_write_image(png_ptr, row_pointers);

			free(row_pointers);
			row_pointers = NULL;
		}
		else
		{
			if (bIsToRGB)
			{
				unsigned char *pTempData = new unsigned char[m_nWidth * m_nHeight * 3];
				if (NULL == pTempData)
				{
					fclose(fp);
					png_destroy_write_struct(&png_ptr, &info_ptr);
					break;
				}

				for (int i = 0; i < m_nHeight; ++i)
				{
					for (int j = 0; j < m_nWidth; ++j)
					{
						pTempData[(i * m_nWidth + j) * 3] = m_pData[(i * m_nWidth + j) * 4];
						pTempData[(i * m_nWidth + j) * 3 + 1] = m_pData[(i * m_nWidth + j) * 4 + 1];
						pTempData[(i * m_nWidth + j) * 3 + 2] = m_pData[(i * m_nWidth + j) * 4 + 2];
					}
				}

				for (int i = 0; i < (int)m_nHeight; i++)
				{
					row_pointers[i] = (png_bytep)pTempData + i * m_nWidth * 3;
				}

				png_write_image(png_ptr, row_pointers);

				free(row_pointers);
				row_pointers = NULL;

				CC_SAFE_DELETE_ARRAY(pTempData);
			} 
			else
			{
				for (int i = 0; i < (int)m_nHeight; i++)
				{
					row_pointers[i] = (png_bytep)m_pData + i * m_nWidth * 4;
				}

				png_write_image(png_ptr, row_pointers);

				free(row_pointers);
				row_pointers = NULL;
			}
		}

		png_write_end(png_ptr, info_ptr);

		png_free(png_ptr, palette);
		palette = NULL;

		png_destroy_write_struct(&png_ptr, &info_ptr);

		fclose(fp);

		bRet = true;
	} while (0);
	return bRet;
}
Пример #21
0
int write_bar_graph(FILE *f, double perc, int width, int height, int border, int spacers)
{
  static png_color palette[4] =
  {
    {  0,   0,   0},		/* RGB color for border */
    {255, 255, 255},		/* RGB color for separators */
    {214, 136, 131},		/* RGB color for unfilled part of graph */
    {204, 204, 227},		/* RGB color for filled part of graph */
  };
  int bwidth, bheight;		/* Width and height including border */
  double frac;
  int spacer, fspacer;
  int x, y;
  int color;
  png_structp png_ptr = NULL;
  png_infop info_ptr  = NULL;
  png_byte *border_row;
  png_byte *bar_row;
  png_byte *bp;
  int status = 1;		/* Assume failure */

  bwidth = width + border*2;
  bheight = height + border*2;

  border_row   = alloca(sizeof(png_byte) * bwidth);
  bar_row      = alloca(sizeof(png_byte) * bwidth);

  if ( !border_row || !bar_row )
    goto barf;

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

  if ( !png_ptr )
    goto barf;

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

  if ( setjmp(png_jmpbuf((png_ptr))) ) {
    status = 1;
    goto barf;			/* libpng abort */
  }

  png_init_io(png_ptr, f);

  png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);

  png_set_IHDR(png_ptr, info_ptr, bwidth, bheight,
	       2, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
	       PNG_COMPRESSION_TYPE_DEFAULT,
	       PNG_FILTER_TYPE_DEFAULT);

  png_set_PLTE(png_ptr, info_ptr, palette, 4);

  png_write_info(png_ptr, info_ptr);

  png_set_packing(png_ptr);

  /* Now we actually produce the data */

  /* Generate the border row */
  memset(border_row, 0, bwidth);

  /* Generate the bar row */
  bp = bar_row;
  for ( x = 0 ; x < border ; x++ )
    *bp++ = 0;			/* Border color */

  spacer = 0;
  for ( x = 1 ; x <= width ; x++ ) {
    frac = (double)x/(double)width;
    fspacer = (int)(spacers*frac);
    if ( x < width && spacer < fspacer ) {
      color = 1;		/* Spacer color */
    } else if ( perc < frac ) {
      color = 3;		/* Bar color */
    } else {
      color = 2;		/* Background color */
    }
    *bp++ = color;
    spacer = fspacer;
  }
  
  for ( x = 0 ; x < border ; x++ )
    *bp++ = 0;			/* Border color */

  /* Write output */
  for ( y = 0 ; y < border ; y++ )
    png_write_row(png_ptr, border_row);
  for ( y = 0 ; y < height ; y++ )
    png_write_row(png_ptr, bar_row);
  for ( y = 0 ; y < border ; y++ )
    png_write_row(png_ptr, border_row);

  /* Done writing */
  png_write_end(png_ptr, info_ptr);
  status = 0;			/* Success! */

 barf:				/* Jump here on fatal error */
  png_destroy_write_struct(&png_ptr, &info_ptr);
  return status;
}
Пример #22
0
bool MCImageEncodePNG(MCImageIndexedBitmap *p_indexed, IO_handle p_stream, uindex_t &r_bytes_written)
{
	bool t_success = true;

	MCPNGWriteContext t_context;
	t_context.stream = p_stream;
	t_context.byte_count = 0;

	png_structp t_png_ptr = nil;
	png_infop t_info_ptr = nil;
	png_color *t_png_palette = nil;
	png_byte *t_png_transparency = nil;

	png_bytep t_data_ptr = nil;
	uindex_t t_stride = 0;

	/*init png stuff*/
	if (t_success)
	{
		t_success = nil != (t_png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
			(png_voidp)NULL, (png_error_ptr)NULL,
			(png_error_ptr)NULL));
	}

	if (t_success)
		t_success = nil != (t_info_ptr = png_create_info_struct(t_png_ptr));

	/*in case of png error*/
	if (setjmp(png_jmpbuf(t_png_ptr)))
		t_success = false;

	if (t_success)
		png_set_write_fn(t_png_ptr,(png_voidp)&t_context,fakewrite,fakeflush);

	if (t_success)
	{
		png_set_IHDR(t_png_ptr, t_info_ptr, p_indexed->width, p_indexed->height, 8,
					 PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
					 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
		png_set_gAMA(t_png_ptr, t_info_ptr, 1/MCgamma);
	}

	if (t_success)
		t_success = MCMemoryNewArray(p_indexed->palette_size, t_png_palette);

	/*create palette for 8 bit*/
	if (t_success)
	{
		for (uindex_t i = 0; i < p_indexed->palette_size ; i++)
		{
			t_png_palette[i].red   = p_indexed->palette[i].red >> 8;
			t_png_palette[i].green = p_indexed->palette[i].green >> 8;
			t_png_palette[i].blue  = p_indexed->palette[i].blue >> 8;
		}

		png_set_PLTE(t_png_ptr, t_info_ptr, t_png_palette, p_indexed->palette_size);
	}

	if (MCImageIndexedBitmapHasTransparency(p_indexed))
	{
		if (t_success)
			t_success = MCMemoryAllocate(p_indexed->palette_size, t_png_transparency);
		if (t_success)
		{
			memset(t_png_transparency, 0xFF, p_indexed->palette_size);
			t_png_transparency[p_indexed->transparent_index] = 0x00;
			png_set_tRNS(t_png_ptr, t_info_ptr, t_png_transparency, p_indexed->palette_size, NULL);
		}
	}
	if (t_success)
		png_write_info(t_png_ptr, t_info_ptr);

	if (t_success)
	{
		t_data_ptr = (png_bytep)p_indexed->data;
		t_stride = p_indexed->stride;
	}

	if (t_success)
	{
		for (uindex_t i = 0; i < p_indexed->height; i++)
		{
			png_write_row(t_png_ptr, t_data_ptr);
			t_data_ptr += t_stride;
		}
	}

	if (t_success)
		png_write_end(t_png_ptr, t_info_ptr);

	if (t_png_ptr != nil)
		png_destroy_write_struct(&t_png_ptr, &t_info_ptr);
	if (t_png_palette != nil)
		MCMemoryDeleteArray(t_png_palette);
	if (t_png_transparency != nil)
		MCMemoryDeallocate(t_png_transparency);

	if (t_success)
		r_bytes_written = t_context.byte_count;

	return t_success;
}
Пример #23
0
void save_as_png(T & file, std::vector<mapnik::rgb> const& palette,
                 mapnik::image_gray8 const& image,
                 unsigned width,
                 unsigned height,
                 unsigned color_depth,
                 std::vector<unsigned> const&alpha,
                 png_options const& opts)
{
    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,static_cast<png_infopp>(0));
        return;
    }
    jmp_buf* jmp_context = static_cast<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<T>, &flush_data<T>);

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

    png_set_IHDR(png_ptr, info_ptr,width,height,color_depth,
                 PNG_COLOR_TYPE_PALETTE,PNG_INTERLACE_NONE,
                 PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT);

    png_color* pal = const_cast<png_color*>(reinterpret_cast<const png_color*>(&palette[0]));
    png_set_PLTE(png_ptr, info_ptr, pal, static_cast<unsigned>(palette.size()));

    // make transparent lowest indexes, so tRNS is small
    if (alpha.size()>0)
    {
        std::vector<png_byte> trans(alpha.size());
        unsigned alphaSize=0;//truncate to nonopaque values
        for(unsigned i=0; i < alpha.size(); i++)
        {
            trans[i]=alpha[i];
            if (alpha[i]<255)
            {
                alphaSize = i+1;
            }
        }
        if (alphaSize>0)
        {
            png_set_tRNS(png_ptr, info_ptr, static_cast<png_bytep>(&trans[0]), alphaSize, 0);
        }
    }

    png_write_info(png_ptr, info_ptr);
    for (unsigned i=0;i<height;i++)
    {
        png_write_row(png_ptr,const_cast<png_bytep>(image.get_row(i)));
    }

    png_write_end(png_ptr, info_ptr);
    png_destroy_write_struct(&png_ptr, &info_ptr);
}
Пример #24
0
static int writePNG(QRcode *qrcode, const char *outfile)
{
	static FILE *fp; // avoid clobbering by setjmp.
	png_structp png_ptr;
	png_infop info_ptr;
	png_colorp palette;
	png_byte alpha_values[2];
	unsigned char *row, *p, *q;
	int x, y, xx, yy, bit;
	int realwidth;

	realwidth = (qrcode->width + margin * 2) * size;
	row = (unsigned char *)malloc((realwidth + 7) / 8);
	if(row == NULL) {
		fprintf(stderr, "Failed to allocate memory.\n");
		exit(EXIT_FAILURE);
	}

	if(outfile[0] == '-' && outfile[1] == '\0') {
		fp = stdout;
	} else {
		fp = fopen(outfile, "wb");
		if(fp == NULL) {
			fprintf(stderr, "Failed to create file: %s\n", outfile);
			perror(NULL);
			exit(EXIT_FAILURE);
		}
	}

	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if(png_ptr == NULL) {
		fprintf(stderr, "Failed to initialize PNG writer.\n");
		exit(EXIT_FAILURE);
	}

	info_ptr = png_create_info_struct(png_ptr);
	if(info_ptr == NULL) {
		fprintf(stderr, "Failed to initialize PNG write.\n");
		exit(EXIT_FAILURE);
	}

	if(setjmp(png_jmpbuf(png_ptr))) {
		png_destroy_write_struct(&png_ptr, &info_ptr);
		fprintf(stderr, "Failed to write PNG image.\n");
		exit(EXIT_FAILURE);
	}

	palette = (png_colorp) malloc(sizeof(png_color) * 2);
	if(palette == NULL) {
		fprintf(stderr, "Failed to allocate memory.\n");
		exit(EXIT_FAILURE);
	}
	palette[0].red   = fg_color[0];
	palette[0].green = fg_color[1];
	palette[0].blue  = fg_color[2];
	palette[1].red   = bg_color[0];
	palette[1].green = bg_color[1];
	palette[1].blue  = bg_color[2];
	alpha_values[0] = fg_color[3];
	alpha_values[1] = bg_color[3];
	png_set_PLTE(png_ptr, info_ptr, palette, 2);
	png_set_tRNS(png_ptr, info_ptr, alpha_values, 2, NULL);

	png_init_io(png_ptr, fp);
	png_set_IHDR(png_ptr, info_ptr,
			realwidth, realwidth,
			1,
			PNG_COLOR_TYPE_PALETTE,
			PNG_INTERLACE_NONE,
			PNG_COMPRESSION_TYPE_DEFAULT,
			PNG_FILTER_TYPE_DEFAULT);
	png_set_pHYs(png_ptr, info_ptr,
			dpi * INCHES_PER_METER,
			dpi * INCHES_PER_METER,
			PNG_RESOLUTION_METER);
	png_write_info(png_ptr, info_ptr);

	/* top margin */
	memset(row, 0xff, (realwidth + 7) / 8);
	for(y=0; y<margin * size; y++) {
		png_write_row(png_ptr, row);
	}

	/* data */
	p = qrcode->data;
	for(y=0; y<qrcode->width; y++) {
		bit = 7;
		memset(row, 0xff, (realwidth + 7) / 8);
		q = row;
		q += margin * size / 8;
		bit = 7 - (margin * size % 8);
		for(x=0; x<qrcode->width; x++) {
			for(xx=0; xx<size; xx++) {
				*q ^= (*p & 1) << bit;
				bit--;
				if(bit < 0) {
					q++;
					bit = 7;
				}
			}
			p++;
		}
		for(yy=0; yy<size; yy++) {
			png_write_row(png_ptr, row);
		}
	}
	/* bottom margin */
	memset(row, 0xff, (realwidth + 7) / 8);
	for(y=0; y<margin * size; y++) {
		png_write_row(png_ptr, row);
	}

	png_write_end(png_ptr, info_ptr);
	png_destroy_write_struct(&png_ptr, &info_ptr);

	fclose(fp);
	free(row);
	free(palette);

	return 0;
}
Пример #25
0
static BOOL DLL_CALLCONV
Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
	png_structp png_ptr;
	png_infop info_ptr;
	png_colorp palette = NULL;
	png_uint_32 width, height;
	BOOL has_alpha_channel = FALSE;

	RGBQUAD *pal;					// pointer to dib palette
	int bit_depth, pixel_depth;		// pixel_depth = bit_depth * channels
	int palette_entries;
	int	interlace_type;

	fi_ioStructure fio;
    fio.s_handle = handle;
	fio.s_io = io;

	if ((dib) && (handle)) {
		try {
			// create the chunk manage structure

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

			if (!png_ptr)  {
				return FALSE;
			}

			// allocate/initialize the image information data.

			info_ptr = png_create_info_struct(png_ptr);

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

			// 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 reading the file

				png_destroy_write_struct(&png_ptr, &info_ptr);

				return FALSE;
			}

			// init the IO
            
			png_set_write_fn(png_ptr, &fio, _WriteProc, _FlushProc);

			// set physical resolution

			png_uint_32 res_x = (png_uint_32)FreeImage_GetDotsPerMeterX(dib);
			png_uint_32 res_y = (png_uint_32)FreeImage_GetDotsPerMeterY(dib);

			if ((res_x > 0) && (res_y > 0))  {
				png_set_pHYs(png_ptr, info_ptr, res_x, res_y, PNG_RESOLUTION_METER);
			}
	
			// Set the image information here.  Width and height are up to 2^31,
			// bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
			// the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
			// PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
			// or PNG_COLOR_TYPE_RGB_ALPHA.  interlace is either PNG_INTERLACE_NONE or
			// PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
			// currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED

			width = FreeImage_GetWidth(dib);
			height = FreeImage_GetHeight(dib);
			pixel_depth = FreeImage_GetBPP(dib);

			BOOL bInterlaced = FALSE;
			if( (flags & PNG_INTERLACED) == PNG_INTERLACED) {
				interlace_type = PNG_INTERLACE_ADAM7;
				bInterlaced = TRUE;
			} else {
				interlace_type = PNG_INTERLACE_NONE;
			}

			// set the ZLIB compression level or default to PNG default compression level (ZLIB level = 6)
			int zlib_level = flags & 0x0F;
			if((zlib_level >= 1) && (zlib_level <= 9)) {
				png_set_compression_level(png_ptr, zlib_level);
			} else if((flags & PNG_Z_NO_COMPRESSION) == PNG_Z_NO_COMPRESSION) {
				png_set_compression_level(png_ptr, Z_NO_COMPRESSION);
			}

			// filtered strategy works better for high color images
			if(pixel_depth >= 16){
				png_set_compression_strategy(png_ptr, Z_FILTERED);
				png_set_filter(png_ptr, 0, PNG_FILTER_NONE|PNG_FILTER_SUB|PNG_FILTER_PAETH);
			} else {
				png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY);
			}

			FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
			if(image_type == FIT_BITMAP) {
				// standard image type
				bit_depth = (pixel_depth > 8) ? 8 : pixel_depth;
			} else {
				// 16-bit greyscale or 16-bit RGB(A)
				bit_depth = 16;
			}

			switch (FreeImage_GetColorType(dib)) {
				case FIC_MINISWHITE:
					// Invert monochrome files to have 0 as black and 1 as white (no break here)
					png_set_invert_mono(png_ptr);

				case FIC_MINISBLACK:
					png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, 
						PNG_COLOR_TYPE_GRAY, interlace_type, 
						PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

					break;

				case FIC_PALETTE:
				{
					png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, 
						PNG_COLOR_TYPE_PALETTE, interlace_type, 
						PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

					// set the palette

					palette_entries = 1 << bit_depth;
					palette = (png_colorp)png_malloc(png_ptr, palette_entries * sizeof (png_color));
					pal = FreeImage_GetPalette(dib);

					for (int i = 0; i < palette_entries; i++) {
						palette[i].red   = pal[i].rgbRed;
						palette[i].green = pal[i].rgbGreen;
						palette[i].blue  = pal[i].rgbBlue;
					}
					
					png_set_PLTE(png_ptr, info_ptr, palette, palette_entries);

					// You must not free palette here, because png_set_PLTE only makes a link to
					// the palette that you malloced.  Wait until you are about to destroy
					// the png structure.

					break;
				}

				case FIC_RGBALPHA :
					has_alpha_channel = TRUE;

					png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, 
						PNG_COLOR_TYPE_RGBA, interlace_type, 
						PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
					// flip BGR pixels to RGB
					if(image_type == FIT_BITMAP) {
						png_set_bgr(png_ptr);
					}
#endif
					break;
	
				case FIC_RGB:
					png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, 
						PNG_COLOR_TYPE_RGB, interlace_type, 
						PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
					// flip BGR pixels to RGB
					if(image_type == FIT_BITMAP) {
						png_set_bgr(png_ptr);
					}
#endif
					break;
					
				case FIC_CMYK:
					break;
			}

			// write possible ICC profile

			FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(dib);
			if (iccProfile->size && iccProfile->data) {
				png_set_iCCP(png_ptr, info_ptr, "Embedded Profile", 0, (png_const_bytep)iccProfile->data, iccProfile->size);
			}

			// write metadata

			WriteMetadata(png_ptr, info_ptr, dib);

			// Optional gamma chunk is strongly suggested if you have any guess
			// as to the correct gamma of the image.
			// png_set_gAMA(png_ptr, info_ptr, gamma);

			// set the transparency table

			if (FreeImage_IsTransparent(dib) && (FreeImage_GetTransparencyCount(dib) > 0)) {
				png_set_tRNS(png_ptr, info_ptr, FreeImage_GetTransparencyTable(dib), FreeImage_GetTransparencyCount(dib), NULL);
			}

			// set the background color

			if(FreeImage_HasBackgroundColor(dib)) {
				png_color_16 image_background;
				RGBQUAD rgbBkColor;

				FreeImage_GetBackgroundColor(dib, &rgbBkColor);
				memset(&image_background, 0, sizeof(png_color_16));
				image_background.blue  = rgbBkColor.rgbBlue;
				image_background.green = rgbBkColor.rgbGreen;
				image_background.red   = rgbBkColor.rgbRed;
				image_background.index = rgbBkColor.rgbReserved;

				png_set_bKGD(png_ptr, info_ptr, &image_background);
			}
			
			// Write the file header information.

			png_write_info(png_ptr, info_ptr);

			// write out the image data

#ifndef FREEIMAGE_BIGENDIAN
			if (bit_depth == 16) {
				// turn on 16 bit byte swapping
				png_set_swap(png_ptr);
			}
#endif

			int number_passes = 1;
			if (bInterlaced) {
				number_passes = png_set_interlace_handling(png_ptr);
			}

			if ((pixel_depth == 32) && (!has_alpha_channel)) {
				BYTE *buffer = (BYTE *)malloc(width * 3);

				// transparent conversion to 24-bit
				// the number of passes is either 1 for non-interlaced images, or 7 for interlaced images
				for (int pass = 0; pass < number_passes; pass++) {
					for (png_uint_32 k = 0; k < height; k++) {
						FreeImage_ConvertLine32To24(buffer, FreeImage_GetScanLine(dib, height - k - 1), width);			
						png_write_row(png_ptr, buffer);
					}
				}
				free(buffer);
			} else {
				// the number of passes is either 1 for non-interlaced images, or 7 for interlaced images
				for (int pass = 0; pass < number_passes; pass++) {
					for (png_uint_32 k = 0; k < height; k++) {			
						png_write_row(png_ptr, FreeImage_GetScanLine(dib, height - k - 1));					
					}
				}
			}

			// It is REQUIRED to call this to finish writing the rest of the file
			// Bug with png_flush

			png_write_end(png_ptr, info_ptr);

			// clean up after the write, and free any memory allocated
			if (palette) {
				png_free(png_ptr, palette);
			}

			png_destroy_write_struct(&png_ptr, &info_ptr);

			return TRUE;
		} catch (const char *text) {
			FreeImage_OutputMessageProc(s_format_id, text);
		}
	}

	return FALSE;
}
Пример #26
0
/*
 * Reduce the image type from grayscale(+alpha) or RGB(+alpha) to palette,
 * if possible.
 * The parameter reductions indicates the intended reductions.
 * The function returns the successful reductions.
 */
png_uint_32 /* PRIVATE */
opng_reduce_to_palette(png_structp png_ptr, png_infop info_ptr,
   png_uint_32 reductions)
{
   png_uint_32 result;
   png_bytepp row_ptr;
   png_bytep sample_ptr, alpha_row;
   png_uint_32 height, width, channels, i, j;
   unsigned int color_type, dest_bit_depth;
   png_color palette[256];
   png_byte trans_alpha[256];
   int num_palette, num_trans, index;
   png_color_16p background;
   unsigned int gray, red, green, blue, alpha;
   unsigned int prev_gray, prev_red, prev_green, prev_blue, prev_alpha;

   opng_debug(1, "in opng_reduce_to_palette");

   if (info_ptr->bit_depth != 8)
      return OPNG_REDUCE_NONE;  /* nothing is done in this case */

   color_type = info_ptr->color_type;
   OPNG_ASSERT(!(info_ptr->color_type & PNG_COLOR_MASK_PALETTE));

   row_ptr   = info_ptr->row_pointers;
   height    = info_ptr->height;
   width     = info_ptr->width;
   channels  = info_ptr->channels;
   alpha_row = (png_bytep)png_malloc(png_ptr, width);

   /* Analyze the possibility of this reduction. */
   num_palette = num_trans = 0;
   prev_gray = prev_red = prev_green = prev_blue = prev_alpha = 256;
   for (i = 0; i < height; ++i, ++row_ptr)
   {
      sample_ptr = *row_ptr;
      opng_get_alpha_row(png_ptr, info_ptr, *row_ptr, alpha_row);
      if (color_type & PNG_COLOR_MASK_COLOR)
      {
         for (j = 0; j < width; ++j, sample_ptr += channels)
         {
            red   = sample_ptr[0];
            green = sample_ptr[1];
            blue  = sample_ptr[2];
            alpha = alpha_row[j];
            /* Check the cache first. */
            if (red != prev_red || green != prev_green || blue != prev_blue ||
                alpha != prev_alpha)
            {
               prev_red   = red;
               prev_green = green;
               prev_blue  = blue;
               prev_alpha = alpha;
               if (opng_insert_palette_entry(palette, &num_palette,
                   trans_alpha, &num_trans, 256,
                   red, green, blue, alpha, &index) < 0)  /* overflow */
               {
                  OPNG_ASSERT(num_palette < 0);
                  i = height;  /* forced exit from outer loop */
                  break;
               }
            }
         }
      }
      else  /* grayscale */
      {
         for (j = 0; j < width; ++j, sample_ptr += channels)
         {
            gray  = sample_ptr[0];
            alpha = alpha_row[j];
            /* Check the cache first. */
            if (gray != prev_gray || alpha != prev_alpha)
            {
               prev_gray  = gray;
               prev_alpha = alpha;
               if (opng_insert_palette_entry(palette, &num_palette,
                   trans_alpha, &num_trans, 256,
                   gray, gray, gray, alpha, &index) < 0)  /* overflow */
               {
                  OPNG_ASSERT(num_palette < 0);
                  i = height;  /* forced exit from outer loop */
                  break;
               }
            }
         }
      }
   }
#if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
   if ((num_palette >= 0) && (info_ptr->valid & PNG_INFO_bKGD))
   {
      /* bKGD has an alpha-agnostic palette entry. */
      background = &info_ptr->background;
      if (color_type & PNG_COLOR_MASK_COLOR)
      {
         red   = background->red;
         green = background->green;
         blue  = background->blue;
      }
      else
         red = green = blue = background->gray;
      opng_insert_palette_entry(palette, &num_palette,
         trans_alpha, &num_trans, 256,
         red, green, blue, 256, &index);
      if (index >= 0)
         background->index = (png_byte)index;
   }
#endif

   /* Continue only if the uncompressed indexed image (pixels + PLTE + tRNS)
    * is smaller than the uncompressed RGB(A) image.
    * Casual overhead (headers, CRCs, etc.) is ignored.
    *
    * Compare:
    * num_pixels * (src_bit_depth * channels - dest_bit_depth) / 8
    * vs.
    * sizeof(PLTE) + sizeof(tRNS)
    */
   if (num_palette >= 0)
   {
      OPNG_ASSERT(num_palette > 0 && num_palette <= 256);
      OPNG_ASSERT(num_trans >= 0 && num_trans <= num_palette);
      if (num_palette <= 2)
         dest_bit_depth = 1;
      else if (num_palette <= 4)
         dest_bit_depth = 2;
      else if (num_palette <= 16)
         dest_bit_depth = 4;
      else
         dest_bit_depth = 8;
      /* Do the comparison in a way that does not cause overflow. */
      if (channels * 8 == dest_bit_depth ||
          (3 * num_palette + num_trans) * 8 / (channels * 8 - dest_bit_depth)
             / width / height >= 1)
         num_palette = -1;
   }

   if (num_palette < 0)  /* can't reduce */
   {
      png_free(png_ptr, alpha_row);
      return OPNG_REDUCE_NONE;
   }

   /* Reduce. */
   row_ptr = info_ptr->row_pointers;
   index = -1;
   prev_red = prev_green = prev_blue = prev_alpha = (unsigned int)(-1);
   for (i = 0; i < height; ++i, ++row_ptr)
   {
      sample_ptr = *row_ptr;
      opng_get_alpha_row(png_ptr, info_ptr, *row_ptr, alpha_row);
      if (color_type & PNG_COLOR_MASK_COLOR)
      {
         for (j = 0; j < width; ++j, sample_ptr += channels)
         {
            red   = sample_ptr[0];
            green = sample_ptr[1];
            blue  = sample_ptr[2];
            alpha = alpha_row[j];
            /* Check the cache first. */
            if (red != prev_red || green != prev_green || blue != prev_blue ||
                alpha != prev_alpha)
            {
               prev_red   = red;
               prev_green = green;
               prev_blue  = blue;
               prev_alpha = alpha;
               if (opng_insert_palette_entry(palette, &num_palette,
                   trans_alpha, &num_trans, 256,
                   red, green, blue, alpha, &index) != 0)
                  index = -1;  /* this should not happen */
            }
            OPNG_ASSERT(index >= 0);
            (*row_ptr)[j] = (png_byte)index;
         }
      }
      else  /* grayscale */
      {
         for (j = 0; j < width; ++j, sample_ptr += channels)
         {
            gray  = sample_ptr[0];
            alpha = alpha_row[j];
            /* Check the cache first. */
            if (gray != prev_gray || alpha != prev_alpha)
            {
               prev_gray  = gray;
               prev_alpha = alpha;
               if (opng_insert_palette_entry(palette, &num_palette,
                   trans_alpha, &num_trans, 256,
                   gray, gray, gray, alpha, &index) != 0)
                  index = -1;  /* this should not happen */
            }
            OPNG_ASSERT(index >= 0);
            (*row_ptr)[j] = (png_byte)index;
         }
      }
   }

   /* Update the image info. */
   png_ptr->rowbytes    = info_ptr->rowbytes    = 0;
   png_ptr->color_type  = info_ptr->color_type  = PNG_COLOR_TYPE_PALETTE;
   png_ptr->channels    = info_ptr->channels    = 1;
   png_ptr->pixel_depth = info_ptr->pixel_depth = 8;
   png_set_PLTE(png_ptr, info_ptr, palette, num_palette);
   if (num_trans > 0)
      png_set_tRNS(png_ptr, info_ptr, trans_alpha, num_trans, NULL);
   /* bKGD (if present) is already updated. */

   png_free(png_ptr, alpha_row);

   result = OPNG_REDUCE_RGB_TO_PALETTE;
   if (reductions & OPNG_REDUCE_8_TO_4_2_1)
      result |= opng_reduce_palette_bits(png_ptr, info_ptr, reductions);
   return result;
}
Пример #27
0
/*!
 *  pixWriteStreamPng()
 *
 *      Input:  stream
 *              pix
 *              gamma (use 0.0 if gamma is not defined)
 *      Return: 0 if OK; 1 on error
 *
 *  Notes:
 *      (1) If called from pixWriteStream(), the stream is positioned
 *          at the beginning of the file.
 *      (2) To do sequential writes of png format images to a stream,
 *          use pixWriteStreamPng() directly.
 *      (3) gamma is an optional png chunk.  If no gamma value is to be
 *          placed into the file, use gamma = 0.0.  Otherwise, if
 *          gamma > 0.0, its value is written into the header.
 *      (4) The use of gamma in png is highly problematic.  For an illuminating
 *          discussion, see:  http://hsivonen.iki.fi/png-gamma/
 *      (5) What is the effect/meaning of gamma in the png file?  This
 *          gamma, which we can call the 'source' gamma, is the
 *          inverse of the gamma that was used in enhance.c to brighten
 *          or darken images.  The 'source' gamma is supposed to indicate
 *          the intensity mapping that was done at the time the
 *          image was captured.  Display programs typically apply a
 *          'display' gamma of 2.2 to the output, which is intended
 *          to linearize the intensity based on the response of
 *          thermionic tubes (CRTs).  Flat panel LCDs have typically
 *          been designed to give a similar response as CRTs (call it
 *          "backward compatibility").  The 'display' gamma is
 *          in some sense the inverse of the 'source' gamma.
 *          jpeg encoders attached to scanners and cameras will lighten
 *          the pixels, applying a gamma corresponding to approximately
 *          a square-root relation of output vs input:
 *                output = input^(gamma)
 *          where gamma is often set near 0.4545  (1/gamma is 2.2).
 *          This is stored in the image file.  Then if the display
 *          program reads the gamma, it will apply a display gamma,
 *          typically about 2.2; the product is 1.0, and the
 *          display program produces a linear output.  This works because
 *          the dark colors were appropriately boosted by the scanner,
 *          as described by the 'source' gamma, so they should not
 *          be further boosted by the display program.
 *      (6) As an example, with xv and display, if no gamma is stored,
 *          the program acts as if gamma were 0.4545, multiplies this by 2.2,
 *          and does a linear rendering.  Taking this as a baseline
 *          brightness, if the stored gamma is:
 *              > 0.4545, the image is rendered lighter than baseline
 *              < 0.4545, the image is rendered darker than baseline
 *          In contrast, gqview seems to ignore the gamma chunk in png.
 *      (7) The only valid pixel depths in leptonica are 1, 2, 4, 8, 16
 *          and 32.  However, it is possible, and in some cases desirable,
 *          to write out a png file using an rgb pix that has 24 bpp.
 *          For example, the open source xpdf SplashBitmap class generates
 *          24 bpp rgb images.  Consequently, we anble writing 24 bpp pix.
 *          To generate such a pix, you can make a 24 bpp pix without data
 *          and assign the data array to the pix; e.g.,
 *              pix = pixCreateHeader(w, h, 24);
 *              pixSetData(pix, rgbdata);
 *          See pixConvert32To24() for an example, where we get rgbdata
 *          from the 32 bpp pix.  Caution: do not call pixSetPadBits(),
 *          because the alignment is wrong and you may erase part of the
 *          last pixel on each line.
 */
l_int32
pixWriteStreamPng(FILE      *fp,
                  PIX       *pix,
                  l_float32  gamma)
{
char         commentstring[] = "Comment";
l_int32      i, j, k;
l_int32      wpl, d, cmflag;
l_int32      ncolors;
l_int32     *rmap, *gmap, *bmap;
l_uint32    *data, *ppixel;
png_byte     bit_depth, color_type;
png_uint_32  w, h;
png_uint_32  xres, yres;
png_bytep   *row_pointers;
png_bytep    rowbuffer;
png_structp  png_ptr;
png_infop    info_ptr;
png_colorp   palette;
PIX         *pixt;
PIXCMAP     *cmap;
char        *text;

    PROCNAME("pixWriteStreamPng");

    if (!fp)
        return ERROR_INT("stream not open", procName, 1);
    if (!pix)
        return ERROR_INT("pix not defined", procName, 1);

        /* Allocate the 2 data structures */
    if ((png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
                   (png_voidp)NULL, NULL, NULL)) == NULL)
        return ERROR_INT("png_ptr not made", procName, 1);

    if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) {
        png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
        return ERROR_INT("info_ptr not made", procName, 1);
    }

        /* Set up png setjmp error handling */
    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_write_struct(&png_ptr, &info_ptr);
        return ERROR_INT("internal png error", procName, 1);
    }

    png_init_io(png_ptr, fp);

        /* With best zlib compression (9), get between 1 and 10% improvement
         * over default (5), but the compression is 3 to 10 times slower.
         * Our default compression is the zlib default (5). */
    png_set_compression_level(png_ptr, var_ZLIB_COMPRESSION);

    w = pixGetWidth(pix);
    h = pixGetHeight(pix);
    d = pixGetDepth(pix);
    if ((cmap = pixGetColormap(pix)))
        cmflag = 1;
    else
        cmflag = 0;

        /* Set the color type and bit depth. */
    if (d == 32 && var_PNG_WRITE_ALPHA == 1) {
        bit_depth = 8;
        color_type = PNG_COLOR_TYPE_RGBA;   /* 6 */
        cmflag = 0;  /* ignore if it exists */
    }
    else if (d == 24 || d == 32) {
        bit_depth = 8;
        color_type = PNG_COLOR_TYPE_RGB;   /* 2 */
        cmflag = 0;  /* ignore if it exists */
    }
    else {
        bit_depth = d;
        color_type = PNG_COLOR_TYPE_GRAY;  /* 0 */
    }
    if (cmflag)
        color_type = PNG_COLOR_TYPE_PALETTE;  /* 3 */

#if  DEBUG
    fprintf(stderr, "cmflag = %d, bit_depth = %d, color_type = %d\n",
            cmflag, bit_depth, color_type);
#endif  /* DEBUG */

    png_set_IHDR(png_ptr, info_ptr, w, h, bit_depth, color_type,
                 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
                 PNG_FILTER_TYPE_BASE);

        /* Store resolution in ppm, if known */
    xres = (png_uint_32)(39.37 * (l_float32)pixGetXRes(pix) + 0.5);
    yres = (png_uint_32)(39.37 * (l_float32)pixGetYRes(pix) + 0.5);
    if ((xres == 0) || (yres == 0))
        png_set_pHYs(png_ptr, info_ptr, 0, 0, PNG_RESOLUTION_UNKNOWN);
    else
        png_set_pHYs(png_ptr, info_ptr, xres, yres, PNG_RESOLUTION_METER);

    if (cmflag) {
        pixcmapToArrays(cmap, &rmap, &gmap, &bmap);
        ncolors = pixcmapGetCount(cmap);

            /* Make and save the palette */
        if ((palette = (png_colorp)(CALLOC(ncolors, sizeof(png_color))))
                == NULL)
            return ERROR_INT("palette not made", procName, 1);

        for (i = 0; i < ncolors; i++) {
            palette[i].red = (png_byte)rmap[i];
            palette[i].green = (png_byte)gmap[i];
            palette[i].blue = (png_byte)bmap[i];
        }

        png_set_PLTE(png_ptr, info_ptr, palette, (int)ncolors);
        FREE(rmap);
        FREE(gmap);
        FREE(bmap);
    }

        /* 0.4545 is treated as the default by some image
         * display programs (not gqview).  A value > 0.4545 will
         * lighten an image as displayed by xv, display, etc. */
    if (gamma > 0.0)
        png_set_gAMA(png_ptr, info_ptr, (l_float64)gamma);

    if ((text = pixGetText(pix))) {
        png_text text_chunk;
        text_chunk.compression = PNG_TEXT_COMPRESSION_NONE;
        text_chunk.key = commentstring;
        text_chunk.text = text;
        text_chunk.text_length = strlen(text);
#ifdef PNG_ITXT_SUPPORTED
        text_chunk.itxt_length = 0;
        text_chunk.lang = NULL;
        text_chunk.lang_key = NULL;
#endif
        png_set_text(png_ptr, info_ptr, &text_chunk, 1);
    }

        /* Write header and palette info */
    png_write_info(png_ptr, info_ptr);

    if ((d != 32) && (d != 24)) {  /* not rgb color */
            /* Generate a temporary pix with bytes swapped.
             * For a binary image, there are two conditions in
             * which you must first invert the data for writing png:
             *    (a) no colormap
             *    (b) colormap with BLACK set to 0
             * png writes binary with BLACK = 0, unless contradicted
             * by a colormap.  If the colormap has BLACK = "1"
             * (typ. about 255), do not invert the data.  If there
             * is no colormap, you must invert the data to store
             * in default BLACK = 0 state.  */
        if (d == 1 &&
            (!cmap || (cmap && ((l_uint8 *)(cmap->array))[0] == 0x0))) {
            pixt = pixInvert(NULL, pix);
            pixEndianByteSwap(pixt);
        }
        else
            pixt = pixEndianByteSwapNew(pix);
        if (!pixt) {
            png_destroy_write_struct(&png_ptr, &info_ptr);
            return ERROR_INT("pixt not made", procName, 1);
        }

            /* Make and assign array of image row pointers */
        if ((row_pointers = (png_bytep *)CALLOC(h, sizeof(png_bytep))) == NULL)
            return ERROR_INT("row-pointers not made", procName, 1);
        wpl = pixGetWpl(pixt);
        data = pixGetData(pixt);
        for (i = 0; i < h; i++)
            row_pointers[i] = (png_bytep)(data + i * wpl);
        png_set_rows(png_ptr, info_ptr, row_pointers);

            /* Transfer the data */
        png_write_image(png_ptr, row_pointers);
        png_write_end(png_ptr, info_ptr);

        if (cmflag)
            FREE(palette);
        FREE(row_pointers);
        pixDestroy(&pixt);
        png_destroy_write_struct(&png_ptr, &info_ptr);
        return 0;
    }

        /* For rgb, compose and write a row at a time */
    data = pixGetData(pix);
    wpl = pixGetWpl(pix);
    if (d == 24) {  /* See note 7 above: special case of 24 bpp rgb */
        for (i = 0; i < h; i++) {
            ppixel = data + i * wpl;
            png_write_rows(png_ptr, (png_bytepp)&ppixel, 1);
        }
    }
    else {  /* 32 bpp rgb and rgba */
        if ((rowbuffer = (png_bytep)CALLOC(w, 4)) == NULL)
            return ERROR_INT("rowbuffer not made", procName, 1);
        for (i = 0; i < h; i++) {
            ppixel = data + i * wpl;
            for (j = k = 0; j < w; j++) {
                rowbuffer[k++] = GET_DATA_BYTE(ppixel, COLOR_RED);
                rowbuffer[k++] = GET_DATA_BYTE(ppixel, COLOR_GREEN);
                rowbuffer[k++] = GET_DATA_BYTE(ppixel, COLOR_BLUE);
                if (var_PNG_WRITE_ALPHA == 1)
                    rowbuffer[k++] = GET_DATA_BYTE(ppixel, L_ALPHA_CHANNEL);
                ppixel++;
            }

            png_write_rows(png_ptr, &rowbuffer, 1);
        }
        FREE(rowbuffer);
    }

    png_write_end(png_ptr, info_ptr);

    if (cmflag)
        FREE(palette);
    png_destroy_write_struct(&png_ptr, &info_ptr);
    return 0;

}
Пример #28
0
  void write_png (std::string filename)
  {
    FILE* fp;
    png_structp png_ptr;
    png_infop info_ptr;
    png_colorp palette;
    //png_uint_32 bytes_per_pixel = 1;

   fp = fopen(filename.c_str (), "wb");
   if (fp == NULL)
     assert (false);

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

   png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
   info_ptr = png_create_info_struct(png_ptr);
   png_init_io(png_ptr, fp);

   png_set_IHDR(png_ptr, info_ptr, m_width, m_height, 8 /* bitdepth */,
		PNG_COLOR_TYPE_PALETTE,
		PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

   palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH
				    * sizeof (png_color));

   std::cout << "MAX: " << PNG_MAX_PALETTE_LENGTH << std::endl;
   for (unsigned int i = 0; i < m_palette.size(); ++i)
     {
       palette[i].red   = m_palette[i].red;
       palette[i].green = m_palette[i].green;
       palette[i].blue  = m_palette[i].blue;
     }

   /** insert palette converter here */
   png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH);

   png_write_info(png_ptr, info_ptr);


   png_uint_32 height = m_height, width = m_width;
   png_byte image[height * width /* *bytes_per_pixel */];
   png_bytep row_pointers[height];

   // fill the image with data
   for (unsigned int i = 0; i < m_image.size (); ++i)
     {
       image[i] = m_image[i];
     }

   for (unsigned int k = 0; k < height; k++)
     row_pointers[k] = image + k * width /* * bytes_per_pixel*/;

   png_write_image(png_ptr, row_pointers);

   png_write_end(png_ptr, info_ptr);
   png_free(png_ptr, palette);
   //png_free(png_ptr, trans);
   png_destroy_write_struct(&png_ptr, &info_ptr);
   fclose(fp);
  }
Пример #29
0
/* Saves an SDL surface to a png file.
* TODO: support screen formats. 
*/
int sdl_surface_savepng(SDL_Surface * surf, const char * filename) {
  png_bytep       * rows  = NULL;
  png_colorp        pale  = NULL; 
  FILE            * fout  = NULL;
  png_structp       png   = NULL;
  png_infop         info  = NULL;
  int               colortype;
  int               i     = 0;
  Uint8           * tran  = NULL;
  SDL_PixelFormat * fmt   = NULL;
  SDL_Surface     * temp  = NULL;
  
  if (!surf) { return save_fail("Surface was NULL."); }
  if (!filename) { return save_fail("Filename was NULL."); }
    
  rows  =  gymalloc(sizeof(png_bytep)*surf->h);
  if (!rows) { return save_fail("Out of memory."); }
  
  for (i = 0; i < surf->h; i++) { 
    rows[i] = ((Uint8 *)surf->pixels) + i*surf->pitch;
  }
  
  /* Create palette and transparency table if needed. */
  fmt = surf->format;
  if (fmt->palette) {
    pale = malloc(fmt->palette->ncolors * sizeof(png_color));
    if (!pale) {
      savepng_done(rows, fout, png, info, temp, pale, tran);
      return save_fail("Out of memory in saving palette.");
    }    
    for (i = 0; i < fmt->palette->ncolors; i++) {
      pale[i].red    = fmt->palette->colors[i].r;
      pale[i].green  = fmt->palette->colors[i].g;
      pale[i].blue   = fmt->palette->colors[i].b;
    }
    
    if (surf->flags & SDL_SRCCOLORKEY) {
      tran = malloc(fmt->palette->ncolors * sizeof(Uint8));
      if(!tran) {
        savepng_done(rows, fout, png, info, temp, pale, tran);
        return save_fail("Out of memory in saving palette transparency.");
      }
      for (i = 0; i < fmt->palette->ncolors; i++) {
        tran[i] = (((unsigned)i) == fmt->colorkey) ? 255 : 0;
      }
    }
  }
    
  fout = fopen(filename, "wb");
  if(!fout) {
    savepng_done(rows, fout, png, info, temp, pale, tran);    
    return save_fail("Couldn't open file for writing."); 
  }
  
  png  = png_create_write_struct(PNG_LIBPNG_VER_STRING,  NULL, NULL, NULL);
  if (!png) {
    savepng_done(rows, fout, png, info, temp, pale, tran);
    return save_fail("Couldn't create png_structp");
  }  
  
  info = png_create_info_struct(png);
  if (!info) {
    savepng_done(rows, fout, png, info, temp, pale, tran);
    return save_fail("Couldn't create png_infop");
  }
  
  /* libpng rudely uses longjump to terminate on errors. 
    This in turns causes warning of pissbli clobered variables. Could it suck 
    more? */
  if (setjmp(png->jmpbuf)) {
    /* This give a warning, but it seems to be unavoidable. */
    savepng_done(rows, fout, png, info, temp, pale, tran);
    return save_fail("Error writing png file.");
  }
  
  /* Set file pointer. */
  png_init_io(png, fout);
  
  colortype = sdl_surface_pngcolortype(surf);
  png_set_IHDR(png, info, surf->w, surf->h, 8, colortype, PNG_INTERLACE_NONE, 
               PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
  
  /* Write palette if needed. */
  if(pale) { 
    png_set_PLTE(png, info, pale, fmt->palette->ncolors);
  }
    
  /* Write transparency table if needed. */
  if (tran) {  
    png_set_tRNS(png, info, tran, fmt->palette->ncolors, NULL);
  }
  
  /* Write the image. */
  png_write_info(png, info);
  png_set_packing(png);
  if(SDL_MUSTLOCK(surf)) {  SDL_LockSurface(surf);  }
  png_write_image(png, rows);
  if(SDL_MUSTLOCK(surf)) { SDL_UnlockSurface(surf); }
  png_write_end(png, info);
  
  
  /* Clean up. */
  savepng_done(rows, fout, png, info, temp, pale, tran);
  return 0;
}
Пример #30
0
    void write_header( const View& view )
    {
        using png_rw_info_t = detail::png_write_support
            <
                typename channel_type<typename get_pixel_type<View>::type>::type,
                typename color_space_type<View>::type
            >;

        // Set the image information here.  Width and height are up to 2^31,
        // bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
        // the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
        // PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
        // or PNG_COLOR_TYPE_RGB_ALPHA.  interlace is either PNG_INTERLACE_NONE or
        // PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
        // currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
        png_set_IHDR( get_struct()
                    , get_info()
                    , static_cast< png_image_width::type  >( view.width()  )
                    , static_cast< png_image_height::type >( view.height() )
                    , static_cast< png_bitdepth::type     >( png_rw_info_t::_bit_depth )
                    , static_cast< png_color_type::type   >( png_rw_info_t::_color_type )
                    , _info._interlace_method
                    , _info._compression_type
                    , _info._filter_method
                    );

#ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
        if( _info._valid_cie_colors )
        {
            png_set_cHRM( get_struct()
                        , get_info()
                        , _info._white_x
                        , _info._white_y
                        , _info._red_x
                        , _info._red_y
                        , _info._green_x
                        , _info._green_y
                        , _info._blue_x
                        , _info._blue_y
                        );
        }

        if( _info._valid_file_gamma )
        {
            png_set_gAMA( get_struct()
                        , get_info()
                        , _info._file_gamma
                        );
        }
#else
        if( _info._valid_cie_colors )
        {
            png_set_cHRM_fixed( get_struct()
                              , get_info()
                              , _info._white_x
                              , _info._white_y
                              , _info._red_x
                              , _info._red_y
                              , _info._green_x
                              , _info._green_y
                              , _info._blue_x
                              , _info._blue_y
                              );
        }

        if( _info._valid_file_gamma )
        {
            png_set_gAMA_fixed( get_struct()
                              , get_info()
                              , _info._file_gamma
                              );
        }
#endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED

        if( _info._valid_icc_profile )
        {
#if PNG_LIBPNG_VER_MINOR >= 5
            png_set_iCCP( get_struct()
                        , get_info()
                        , const_cast< png_charp >( _info._icc_name.c_str() )
                        , _info._iccp_compression_type
                        , reinterpret_cast< png_const_bytep >( & (_info._profile.front ()) )
                        , _info._profile_length
                        );
#else
            png_set_iCCP( get_struct()
                        , get_info()
                        , const_cast< png_charp >( _info._icc_name.c_str() )
                        , _info._iccp_compression_type
                        , const_cast< png_charp >( & (_info._profile.front()) )
                        , _info._profile_length
                        );
#endif
        }

        if( _info._valid_intent )
        {
            png_set_sRGB( get_struct()
                        , get_info()
                        , _info._intent
                        );
        }

        if( _info._valid_palette )
        {
            png_set_PLTE( get_struct()
                        , get_info()
                        , const_cast< png_colorp >( &_info._palette.front() )
                        , _info._num_palette
                        );
        }

        if( _info._valid_background )
        {
            png_set_bKGD( get_struct()
                        , get_info()
                        , const_cast< png_color_16p >( &_info._background )
                        );
        }

        if( _info._valid_histogram )
        {
            png_set_hIST( get_struct()
                        , get_info()
                        , const_cast< png_uint_16p >( &_info._histogram.front() )
                        );
        }

        if( _info._valid_offset )
        {
            png_set_oFFs( get_struct()
                        , get_info()
                        , _info._offset_x
                        , _info._offset_y
                        , _info._off_unit_type
                        );
        }

        if( _info._valid_pixel_calibration )
        {
            std::vector< const char* > params( _info._num_params );
            for( std::size_t i = 0; i < params.size(); ++i )
            {
                params[i] = _info._params[ i ].c_str();
            }

            png_set_pCAL( get_struct()
                        , get_info()
                        , const_cast< png_charp >( _info._purpose.c_str() )
                        , _info._X0
                        , _info._X1
                        , _info._cal_type
                        , _info._num_params
                        , const_cast< png_charp  >( _info._units.c_str() )
                        , const_cast< png_charpp >( &params.front()     )
                        );
        }

        if( _info._valid_resolution )
        {
            png_set_pHYs( get_struct()
                        , get_info()
                        , _info._res_x
                        , _info._res_y
                        , _info._phy_unit_type
                        );
        }

        if( _info._valid_significant_bits )
        {
            png_set_sBIT( get_struct()
                        , get_info()
                        , const_cast< png_color_8p >( &_info._sig_bits )
                        );
        }

#ifndef BOOST_GIL_IO_PNG_1_4_OR_LOWER

#ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
        if( _info._valid_scale_factors )
        {
            png_set_sCAL( get_struct()
                        , get_info()
                        , this->_info._scale_unit
                        , this->_info._scale_width
                        , this->_info._scale_height
                        );
        }
#else
#ifdef BOOST_GIL_IO_PNG_FIXED_POINT_SUPPORTED
        if( _info._valid_scale_factors )
        {
            png_set_sCAL_fixed( get_struct()
                              , get_info()
                              , this->_info._scale_unit
                              , this->_info._scale_width
                              , this->_info._scale_height
                              );
        }
#else
        if( _info._valid_scale_factors )
        {
            png_set_sCAL_s( get_struct()
                          , get_info()
                          , this->_info._scale_unit
                          , const_cast< png_charp >( this->_info._scale_width.c_str()  )
                          , const_cast< png_charp >( this->_info._scale_height.c_str() )
                          );
        }

#endif // BOOST_GIL_IO_PNG_FIXED_POINT_SUPPORTED
#endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
#endif // BOOST_GIL_IO_PNG_1_4_OR_LOWER

        if( _info._valid_text )
        {
            std::vector< png_text > texts( _info._num_text );
            for( std::size_t i = 0; i < texts.size(); ++i )
            {
                png_text pt;
                pt.compression = _info._text[i]._compression;
                pt.key         = const_cast< png_charp >( this->_info._text[i]._key.c_str()  );
                pt.text        = const_cast< png_charp >( this->_info._text[i]._text.c_str() );
                pt.text_length = _info._text[i]._text.length();

                texts[i] = pt;
            }

            png_set_text( get_struct()
                        , get_info()
                        , &texts.front()
                        , _info._num_text
                        );
        }

        if( _info._valid_modification_time )
        {
            png_set_tIME( get_struct()
                        , get_info()
                        , const_cast< png_timep >( &_info._mod_time )
                        );
        }

        if( _info._valid_transparency_factors )
        {
            int sample_max = ( 1u << _info._bit_depth );

            /* libpng doesn't reject a tRNS chunk with out-of-range samples */
            if( !(  (  _info._color_type == PNG_COLOR_TYPE_GRAY
                    && (int) _info._trans_values[0].gray > sample_max
                    )
                 || (  _info._color_type == PNG_COLOR_TYPE_RGB
                    &&(  (int) _info._trans_values[0].red   > sample_max
                      || (int) _info._trans_values[0].green > sample_max
                      || (int) _info._trans_values[0].blue  > sample_max
                      )
                    )
                 )
              )
            {
                //@todo Fix that once reading transparency values works
/*
                png_set_tRNS( get_struct()
                            , get_info()
                            , trans
                            , num_trans
                            , trans_values
                            );
*/
            }
        }

        // Compression Levels - valid values are [0,9]
        png_set_compression_level( get_struct()
                                 , _info._compression_level
                                 );

        png_set_compression_mem_level( get_struct()
                                     , _info._compression_mem_level
                                     );

        png_set_compression_strategy( get_struct()
                                    , _info._compression_strategy
                                    );

        png_set_compression_window_bits( get_struct()
                                       , _info._compression_window_bits
                                       );

        png_set_compression_method( get_struct()
                                  , _info._compression_method
                                  );

        png_set_compression_buffer_size( get_struct()
                                       , _info._compression_buffer_size
                                       );

#ifdef BOOST_GIL_IO_PNG_DITHERING_SUPPORTED
        // Dithering
        if( _info._set_dithering )
        {
            png_set_dither( get_struct()
                          , &_info._dithering_palette.front()
                          , _info._dithering_num_palette
                          , _info._dithering_maximum_colors
                          , &_info._dithering_histogram.front()
                          , _info._full_dither
                          );
        }
#endif // BOOST_GIL_IO_PNG_DITHERING_SUPPORTED

        // Filter
        if( _info._set_filter )
        {
            png_set_filter( get_struct()
                          , 0
                          , _info._filter
                          );
        }

        // Invert Mono
        if( _info._invert_mono )
        {
            png_set_invert_mono( get_struct() );
        }

        // True Bits
        if( _info._set_true_bits )
        {
            png_set_sBIT( get_struct()
                        , get_info()
                        , &_info._true_bits.front()
                        );
        }

        // sRGB Intent
        if( _info._set_srgb_intent )
        {
            png_set_sRGB( get_struct()
                        , get_info()
                        , _info._srgb_intent
                        );
        }

        // Strip Alpha
        if( _info._strip_alpha )
        {
            png_set_strip_alpha( get_struct() );
        }

        // Swap Alpha
        if( _info._swap_alpha )
        {
            png_set_swap_alpha( get_struct() );
        }


        png_write_info( get_struct()
                      , get_info()
                      );
    }