DO NOT REPLY TO THIS MESSAGE. INSTEAD, POST ANY RESPONSES TO THE LINK BELOW.
[STR New]
Link: http://www.fltk.org/str.php?L2257
Version: 1.3-current
Link: http://www.fltk.org/str.php?L2257
Version: 1.3-current
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <png.h>
#include "write_png.h"
#ifndef PNG_UINT_32_MAX
# define PNG_UINT_32_MAX 0x7fffffffUL
# define png_sizeof sizeof
#endif
#ifndef png_infopp_NULL
# define png_infopp_NULL (png_infopp)NULL
#endif
/* State vars used to control some save defaults */
static int zi_use_BGR = 0; /* If > 0, assume data is BGR rather than RGB packed
*/
static int zi_mono_inverted = 0; /* If > 0, b/w invert greyscale images */
/********************************************************************************/
void set_png_bgr_state(int iv)
{
zi_use_BGR = iv;
}
/********************************************************************************/
int get_png_bgr_state(void)
{
return zi_use_BGR;
}
/********************************************************************************/
void set_png_mono_invert_state(int iv)
{
zi_mono_inverted = iv;
}
/********************************************************************************/
int get_png_mono_invert_state(void)
{
return zi_mono_inverted;
}
/********************************************************************************/
/* Throw away warnings (die on errors as usual) */
static void user_warning_fn (png_structp png_ptr, png_const_charp warning_msg)
{
puts("PNG writer warning");
fflush(stdout);
}
/********************************************************************************/
/* write a png file */
int write_png(const char *file_name, const unsigned char *datap, int width, int
height, int depth,
const char *keyword, const char *description)
{
FILE *fp;
png_structp png_ptr;
png_infop info_ptr;
int bit_depth = 8; /* Assume all our data is based on 8-bit chars */
int idx;
png_bytep row_pointers[height];
png_text text_chunk[1];
png_color_8 sig_bit;
/* open the file */
fp = fopen(file_name, "wb");
if (fp == NULL)
{
return (WRITE_DATA_ERROR);
}
/* 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, (void*)NULL,
NULL, user_warning_fn);
if (png_ptr == NULL)
{
fclose(fp);
return (WRITE_DATA_ERROR);
}
/* 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, png_infopp_NULL);
return (WRITE_DATA_ERROR);
}
/* 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 accessing the file */
fclose(fp);
png_destroy_write_struct(&png_ptr, &info_ptr);
return (WRITE_DATA_ERROR);
}
/* set up the output control if you are using standard C streams */
png_init_io(png_ptr, fp);
/* 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
*/
if (depth == 1)
{
png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
PNG_COLOR_TYPE_GRAY,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
PNG_FILTER_TYPE_BASE);
}
else if (depth == 2) /* Not sure we want to support this mode... */
{
png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
PNG_COLOR_TYPE_GRAY_ALPHA,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
PNG_FILTER_TYPE_BASE);
}
else if (depth == 3)
{
png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
PNG_COLOR_TYPE_RGB,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
PNG_FILTER_TYPE_BASE);
}
else if (depth == 4)
{
png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
PNG_COLOR_TYPE_RGB_ALPHA,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
PNG_FILTER_TYPE_BASE);
}
else
{
/* If we get here, the wrong data depth was passed */
fclose(fp);
png_destroy_write_struct(&png_ptr, &info_ptr);
return (WRITE_DATA_ERROR);
}
/* Configure the optional "significant bits" chunk */
if (depth == 1)
{
/* if we are dealing with a grayscale image */
sig_bit.gray = bit_depth;
}
else if (depth >= 3)
{
/* if we are dealing with a color image */
sig_bit.red = bit_depth;
sig_bit.green = bit_depth;
sig_bit.blue = bit_depth;
}
else if (depth == 4)
{
/* if the image has an alpha channel */
sig_bit.alpha = bit_depth;
}
png_set_sBIT(png_ptr, info_ptr, &sig_bit);
/* 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, 1.0);
/* Optionally write comments into the image */
text_chunk[0].key = keyword;
text_chunk[0].text = description;
text_chunk[0].compression = PNG_TEXT_COMPRESSION_NONE;
#ifdef PNG_iTXt_SUPPORTED
text_chunk[0].lang = NULL;
#endif
png_set_text(png_ptr, info_ptr, text_chunk, 1);
/* Write the file header information. REQUIRED */
png_write_info(png_ptr, info_ptr);
/* Set up any transformations you want. These are
* optional. Only set them if you need them. */
/* invert monochrome pixels */
if ((zi_mono_inverted > 0) && (depth == 1))
{
png_set_invert_mono(png_ptr);
}
/* flip BGR pixels to RGB */
if ((zi_use_BGR > 0) && (depth == 3))
{
png_set_bgr(png_ptr);
}
if (height > PNG_UINT_32_MAX / png_sizeof(png_bytep))
{
png_error (png_ptr, "Image is too tall to process in memory");
}
for (idx = 0; idx < height; idx++)
{
row_pointers[idx] = &datap[idx * width * depth];
}
/* write out the entire image data in one call */
png_write_image(png_ptr, row_pointers);
/* It is REQUIRED to call this to finish writing the rest of the file */
png_write_end(png_ptr, info_ptr);
/* clean up after the write, and free any memory allocated */
png_destroy_write_struct(&png_ptr, &info_ptr);
/* close the file */
fclose(fp);
/* that's it */
return (WRITE_DATA_OK);
}
/********************************************************************************/
#ifdef STANDALONE_WRITER_TEST
int main (void)
{
int w, h, d;
unsigned char * datap;
int idx, jdx;
int res;
char desc[512];
w = h = 256;
d = 3;
datap = malloc(w * h * d);
for (idx = 0; idx < h; idx ++)
{
for (jdx = 0; jdx < w; jdx++)
{
int cell = (idx * h * d) + (jdx * d);
datap[cell] = jdx;
datap[cell + 1] = (idx + jdx) & 0xFF;
datap[cell + 2] = idx;
}
}
sprintf(desc, "Test Image - version 0\nsize %d %d %d", w, h, d);
res = write_png("Test0.png", datap, w, h, d, "SS7K-imageV1", desc);
set_png_bgr_state(1);
res = write_png("Test1.png", datap, w, h, d, "SS7K-imageV2", "Fixed
Text String");
if (res) puts("T1 failed");
free(datap);
d = 1;
datap = malloc(w * h);
for (idx = 0; idx < h; idx ++)
{
for (jdx = 0; jdx < w; jdx++)
{
int cell = (idx * h) + jdx;
datap[cell] = jdx;
}
}
sprintf(desc, "Test Image - version 2\nsize %d %d %d\nThis is Flipped
Mono\ndone!", w, h, d);
set_png_mono_invert_state(1);
res = write_png("Test2.png", datap, w, h, d, "SS7K-image", desc);
sprintf(desc, "Test Image - version 3\nsize %d %d %d\nThis is
Mono\ndone!", w, h, d);
set_png_mono_invert_state(0);
res = write_png("Test3.png", datap, w, h, d, "SS7K-image", desc);
if (res) puts("T2 failed");
free(datap);
if(!res)
puts("PNG test OK");
return 0;
}
#endif
/********************************************************************************/
/* End of File */
_______________________________________________
fltk-bugs mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-bugs