/* * Grace - GRaphing, Advanced Computation and Exploration of data * * Home page: http://plasma-gate.weizmann.ac.il/Grace/ * * Copyright (c) 1991-1995 Paul J Turner, Portland, OR * Copyright (c) 1996-2002 Grace Development Team * * Maintained by Evgeny Stambulchik * * * All Rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * Grace generic raster format driver */ #include #include #include #include #include "defines.h" #include "utils.h" #include "draw.h" #include "device.h" #include "devlist.h" #include "patterns.h" #include "rstdrv.h" #include "protos.h" #include "gd.h" #ifdef HAVE_LIBJPEG # define JPEG_INTERNAL_OPTIONS # include #endif #ifdef HAVE_LIBPNG # include #endif #ifndef NONE_GUI # include "motifinc.h" #endif static void rstImagePnm(gdImagePtr ihandle, FILE *prstream); extern FILE *prstream; /* Declare the image */ static gdImagePtr ihandle = NULL; static int curformat = DEFAULT_RASTER_FORMAT; static int rst_colors[MAXCOLORS]; static int rst_drawbrush, rst_fillbrush; static Pen rstpen; static int rstlines, rstlinew; static int rst_dash_array_length; static unsigned long page_scale; #ifdef HAVE_LIBJPEG static void rstImageJpg(gdImagePtr ihandle, FILE *prstream); static int jpg_setup_quality = 75; static int jpg_setup_grayscale = FALSE; static int jpg_setup_baseline = FALSE; static int jpg_setup_progressive = FALSE; static int jpg_setup_optimize = FALSE; static int jpg_setup_smoothing = 0; static int jpg_setup_dct = JPEG_DCT_DEFAULT; #endif #ifdef HAVE_LIBPNG static void rstImagePng(gdImagePtr ihandle, FILE *prstream); static int png_setup_interlaced = FALSE; static int png_setup_transparent = FALSE; static int png_setup_compression = 4; #endif static Device_entry dev_pnm = {DEVICE_FILE, "PNM", pnminitgraphics, pnm_op_parser, pnm_gui_setup, "pnm", FALSE, TRUE, {DEFAULT_PAGE_WIDTH, DEFAULT_PAGE_HEIGHT, 72.0}, NULL }; #ifdef HAVE_LIBJPEG static Device_entry dev_jpg = {DEVICE_FILE, "JPEG", jpginitgraphics, jpg_op_parser, jpg_gui_setup, "jpg", FALSE, TRUE, {DEFAULT_PAGE_WIDTH, DEFAULT_PAGE_HEIGHT, 72.0}, NULL }; #endif #ifdef HAVE_LIBPNG static Device_entry dev_png = {DEVICE_FILE, "PNG", pnginitgraphics, png_op_parser, png_gui_setup, "png", FALSE, TRUE, {DEFAULT_PAGE_WIDTH, DEFAULT_PAGE_HEIGHT, 72.0}, NULL }; #endif int register_pnm_drv(void) { return register_device(dev_pnm); } #ifdef HAVE_LIBJPEG int register_jpg_drv(void) { return register_device(dev_jpg); } #endif #ifdef HAVE_LIBPNG int register_png_drv(void) { return register_device(dev_png); } #endif static void rst_updatecmap(void) { int i, c; RGB *prgb; int red, green, blue; if (!ihandle) { return; } for (i = 0; i < number_of_colors(); i++) { prgb = get_rgb(i); if (prgb != NULL) { red = prgb->red >> (GRACE_BPP - 8); green = prgb->green >> (GRACE_BPP - 8); blue = prgb->blue >> (GRACE_BPP - 8); if ((c = gdImageColorExact(ihandle, red, green, blue)) == -1 && (c = gdImageColorAllocate(ihandle, red, green, blue)) == -1 && (c = gdImageColorClosest(ihandle, red, green, blue)) == -1) { c = rst_colors[0]; } rst_colors[i] = c; } } } static gdPoint VPoint2gdPoint(VPoint vp) { gdPoint gdp; gdp.x = (int) rint(page_scale * vp.x); gdp.y = (int) rint(page_height - page_scale * vp.y); return (gdp); } void rst_setdrawbrush(void) { static gdImagePtr brush = NULL; int i, j, k; int *tmp_dash_array; RGB *prgb; int red, green, blue, bcolor; int scale; int on, off; rstpen = getpen(); rstlinew = MAX2((int) rint(getlinewidth()*page_scale), 1); rstlines = getlinestyle(); if (rstlines == 0 || rstpen.pattern == 0) { /* Should never come to here */ rst_drawbrush = gdTransparent; return; } if (rstlinew > 1) { if (brush != NULL) { gdImageDestroy(brush); } brush = gdImageCreate(rstlinew, rstlinew); prgb = get_rgb(rstpen.color); red = prgb->red >> (GRACE_BPP - 8); green = prgb->green >> (GRACE_BPP - 8); blue = prgb->blue >> (GRACE_BPP - 8); bcolor = gdImageColorAllocate(brush, red, green, blue); gdImageFilledRectangle(brush, 0, 0, rstlinew, rstlinew, bcolor); gdImageSetBrush(ihandle, brush); } if (rstlines > 1) { rst_dash_array_length = 0; for (i = 0; i < dash_array_length[rstlines]; i++) { rst_dash_array_length += dash_array[rstlines][i]; } if (rstlinew <= 1) { scale = 1; on = rstpen.color; off = gdTransparent; rst_drawbrush = gdStyled; } else { scale = rstlinew; on = 1; off = 0; rst_drawbrush = gdStyledBrushed; } tmp_dash_array = (int *) xmalloc((scale*rst_dash_array_length + 1)*SIZEOF_INT); if (tmp_dash_array == NULL) { return; } k = 0; for (i = 0; i < dash_array_length[rstlines]; i++) { if (i % 2 == 0) { /* black */ for (j = 0; j < (dash_array[rstlines][i] - 1)*scale + 1; j++) { tmp_dash_array[k++] = on; } } else { /* white */ for (j = 0; j < (dash_array[rstlines][i] + 1)*scale - 1; j++) { tmp_dash_array[k++] = off; } } } gdImageSetStyle(ihandle, tmp_dash_array, k); xfree(tmp_dash_array); } else { if (rstlinew <= 1) { rst_drawbrush = rst_colors[rstpen.color]; } else { rst_drawbrush = gdBrushed; } } } void rst_setfillbrush(void) { static gdImagePtr brush = NULL; int i, j, k; RGB *prgb; int red, green, blue, fgcolor, bgcolor; unsigned char p; rstpen = getpen(); if (rstpen.pattern == 0) { /* Should never come to here */ rst_fillbrush = gdTransparent; } else if (rstpen.pattern == 1) { rst_fillbrush = rst_colors[rstpen.color]; } else { /* TODO */ if (brush != NULL) { gdImageDestroy(brush); } brush = gdImageCreate(16, 16); prgb = get_rgb(rstpen.color); red = prgb->red >> (GRACE_BPP - 8); green = prgb->green >> (GRACE_BPP - 8); blue = prgb->blue >> (GRACE_BPP - 8); fgcolor = gdImageColorAllocate(brush, red, green, blue); prgb = get_rgb(getbgcolor()); red = prgb->red >> (GRACE_BPP - 8); green = prgb->green >> (GRACE_BPP - 8); blue = prgb->blue >> (GRACE_BPP - 8); bgcolor = gdImageColorAllocate(brush, red, green, blue); for (k = 0; k < 16; k++) { for (j = 0; j < 2; j++) { for (i = 0; i < 8; i++) { p = pat_bits[rstpen.pattern][k*2+j]; if ((p >> i) & 0x01) { gdImageSetPixel(brush, 8*j + i, k, fgcolor); } else { gdImageSetPixel(brush, 8*j + i, k, bgcolor); } } } } gdImageSetTile(ihandle, brush); rst_fillbrush = gdTiled; } } static int rst_initgraphics(int format) { Page_geometry pg; curformat = format; /* device-dependent routines */ devupdatecmap = rst_updatecmap; devdrawpixel = rst_drawpixel; devdrawpolyline = rst_drawpolyline; devfillpolygon = rst_fillpolygon; devdrawarc = rst_drawarc; devfillarc = rst_fillarc; devputpixmap = rst_putpixmap; devleavegraphics = rst_leavegraphics; pg = get_page_geometry(); page_scale = MIN2(pg.height,pg.width); /* Allocate the image */ ihandle = gdImageCreate(pg.width, pg.height); if (ihandle == NULL) { return RETURN_FAILURE; } rst_updatecmap(); return RETURN_SUCCESS; } void rst_drawpixel(VPoint vp) { gdPoint gdp; gdp = VPoint2gdPoint(vp); gdImageSetPixel(ihandle, gdp.x, gdp.y, rst_colors[getcolor()]); } void rst_drawpolyline(VPoint *vps, int n, int mode) { int i; gdPointPtr gdps; gdps = (gdPointPtr) xmalloc(n*sizeof(gdPoint)); if (gdps == NULL) { return; } for (i = 0; i < n; i++) { gdps[i] = VPoint2gdPoint(vps[i]); } rst_setdrawbrush(); if (mode == POLYLINE_CLOSED) { gdImagePolygon(ihandle, gdps, n, rst_drawbrush); } else { for (i = 0; i < n - 1; i++) { gdImageLine(ihandle, gdps[i].x, gdps[i].y, gdps[i + 1].x, gdps[i + 1].y, rst_drawbrush); } } xfree(gdps); } void rst_fillpolygon(VPoint *vps, int nc) { int i; gdPointPtr gdps; gdps = (gdPointPtr) xmalloc(nc*sizeof(gdPoint)); if (gdps == NULL) { return; } for (i = 0; i < nc; i++) { gdps[i] = VPoint2gdPoint(vps[i]); } rst_setfillbrush(); gdImageFilledPolygon(ihandle, gdps, nc, rst_fillbrush); xfree(gdps); } void rst_drawarc(VPoint vp1, VPoint vp2, int a1, int a2) { gdPoint gdp1, gdp2, gdc; int w, h; gdp1 = VPoint2gdPoint(vp1); gdp2 = VPoint2gdPoint(vp2); gdc.x = (gdp1.x + gdp2.x)/2; gdc.y = (gdp1.y + gdp2.y)/2; w = (gdp2.x - gdp1.x); h = (gdp2.y - gdp1.y); rst_setdrawbrush(); gdImageArc(ihandle, gdc.x, gdc.y, w, h, a1, a2, rst_drawbrush); } void rst_fillarc(VPoint vp1, VPoint vp2, int a1, int a2, int mode) { gdPoint gdp1, gdp2, gdc; int w, h; gdp1 = VPoint2gdPoint(vp1); gdp2 = VPoint2gdPoint(vp2); gdc.x = (gdp1.x + gdp2.x)/2; gdc.y = (gdp1.y + gdp2.y)/2; w = (gdp2.x - gdp1.x); h = (gdp2.y - gdp1.y); rst_setfillbrush(); gdImageFilledArc(ihandle, gdc.x, gdc.y, w, h, a1, a2, mode == ARCFILL_CHORD ? gdArcFillChord:gdArcFillPieSlice, rst_fillbrush); } void rst_putpixmap(VPoint vp, int width, int height, char *databits, int pixmap_bpp, int bitmap_pad, int pixmap_type) { int cindex, bg; int color, bgcolor; int i, k, j; long paddedW; gdPoint gdp; int x, y; bg = getbgcolor(); bgcolor = rst_colors[bg]; gdp = VPoint2gdPoint(vp); y = gdp.y; if (pixmap_bpp == 1) { color = getcolor(); paddedW = PAD(width, bitmap_pad); for (k = 0; k < height; k++) { x = gdp.x; y++; for (j = 0; j < paddedW/bitmap_pad; j++) { for (i = 0; i < bitmap_pad && j*bitmap_pad + i < width; i++) { x++; if (bin_dump(&(databits)[k*paddedW/bitmap_pad+j], i, bitmap_pad)) { gdImageSetPixel(ihandle, x, y, color); } else { if (pixmap_type == PIXMAP_OPAQUE) { gdImageSetPixel(ihandle, x, y, bgcolor); } } } } } } else { for (k = 0; k < height; k++) { x = gdp.x; y++; for (j = 0; j < width; j++) { x++; cindex = (databits)[k*width+j]; if (cindex != bg || pixmap_type == PIXMAP_OPAQUE) { color = rst_colors[cindex]; gdImageSetPixel(ihandle, x, y, color); } } } } } void rst_leavegraphics(void) { /* Output the image to the disk file. */ switch (curformat) { case RST_FORMAT_PNM: rstImagePnm(ihandle, prstream); break; #ifdef HAVE_LIBJPEG case RST_FORMAT_JPG: rstImageJpg(ihandle, prstream); break; #endif #ifdef HAVE_LIBPNG case RST_FORMAT_PNG: if (png_setup_transparent == TRUE) { gdImageColorTransparent(ihandle, rst_colors[getbgcolor()]); } gdImageInterlace(ihandle, png_setup_interlaced); rstImagePng(ihandle, prstream); break; #endif default: errmsg("Invalid raster format"); break; } /* Destroy the image in memory. */ gdImageDestroy(ihandle); ihandle = NULL; } int pnminitgraphics(void) { int result; result = rst_initgraphics(RST_FORMAT_PNM); if (result == RETURN_SUCCESS) { curformat = RST_FORMAT_PNM; } return (result); } static int pnm_setup_format = DEFAULT_PNM_FORMAT; static int pnm_setup_rawbits = TRUE; static void rstImagePnm(gdImagePtr ihandle, FILE *prstream) { int w, h; int i, j, k; int c; unsigned char r, g, b; unsigned char y, pbm_buf; if (pnm_setup_rawbits == TRUE) { switch (pnm_setup_format) { case PNM_FORMAT_PBM: fprintf(prstream, "P4\n"); break; case PNM_FORMAT_PGM: fprintf(prstream, "P5\n"); break; case PNM_FORMAT_PPM: fprintf(prstream, "P6\n"); break; } } else { switch (pnm_setup_format) { case PNM_FORMAT_PBM: fprintf(prstream, "P1\n"); break; case PNM_FORMAT_PGM: fprintf(prstream, "P2\n"); break; case PNM_FORMAT_PPM: fprintf(prstream, "P3\n"); break; } } fprintf(prstream, "#Creator: %s\n", bi_version_string()); w = gdImageSX(ihandle); h = gdImageSY(ihandle); fprintf(prstream, "%d %d\n", w, h); if (pnm_setup_format != PNM_FORMAT_PBM) { fprintf(prstream, "255\n"); } k = 0; pbm_buf = 0; for (i = 0; i < h; i++) { for (j = 0; j < w; j++) { c = gdImageGetPixel(ihandle, j, i); r = (unsigned char) gdImageRed(ihandle, c); g = (unsigned char) gdImageGreen(ihandle, c); b = (unsigned char) gdImageBlue(ihandle, c); if (pnm_setup_rawbits == TRUE) { switch (pnm_setup_format) { case PNM_FORMAT_PBM: y = (r == 255 && g == 255 && b == 255 ? 0x00:0x01); pbm_buf |= (y << (7 - k)); k++; /* completed byte or padding line */ if (k == 8 || j == w - 1) { fwrite(&pbm_buf, 1, 1, prstream); k = 0; pbm_buf = 0; } break; case PNM_FORMAT_PGM: y = INTENSITY(r, g, b); fwrite(&y, 1, 1, prstream); break; case PNM_FORMAT_PPM: fwrite(&r, 1, 1, prstream); fwrite(&g, 1, 1, prstream); fwrite(&b, 1, 1, prstream); break; } } else { switch (pnm_setup_format) { case PNM_FORMAT_PBM: y = (r == 255 && g == 255 && b == 255 ? 0:1); fprintf(prstream, "%1d\n", y); break; case PNM_FORMAT_PGM: y = INTENSITY(r, g, b); fprintf(prstream, "%3d\n", y); break; case PNM_FORMAT_PPM: fprintf(prstream, "%3d %3d %3d\n", r, g, b); break; } } } } } #ifdef HAVE_LIBJPEG int jpginitgraphics(void) { int result; result = rst_initgraphics(RST_FORMAT_JPG); if (result == RETURN_SUCCESS) { curformat = RST_FORMAT_JPG; } return (result); } static void rstImageJpg(gdImagePtr ihandle, FILE *prstream) { struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; J_DCT_METHOD dct_method; JSAMPROW row_pointer; /* pointer to a single row */ int w, h; int i, j, k; int c; int r, g, b; unsigned char y; w = gdImageSX(ihandle); h = gdImageSY(ihandle); cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_stdio_dest(&cinfo, prstream); cinfo.image_width = w; cinfo.image_height = h; if (jpg_setup_grayscale) { cinfo.input_components = 1; cinfo.in_color_space = JCS_GRAYSCALE; } else { cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; } jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, jpg_setup_quality, jpg_setup_baseline); cinfo.smoothing_factor = jpg_setup_smoothing; switch (jpg_setup_dct) { case JPEG_DCT_IFAST: dct_method = JDCT_IFAST; break; case JPEG_DCT_ISLOW: dct_method = JDCT_ISLOW; break; case JPEG_DCT_FLOAT: dct_method = JDCT_FLOAT; break; default: dct_method = JDCT_DEFAULT; } cinfo.dct_method = dct_method; if (jpg_setup_progressive) { #ifdef C_PROGRESSIVE_SUPPORTED jpeg_simple_progression(&cinfo); #else errmsg("jpeglib: sorry, progressive output was not compiled"); #endif } if (jpg_setup_optimize) { #ifdef ENTROPY_OPT_SUPPORTED cinfo.optimize_coding = TRUE; #else errmsg("jpeglib: sorry, entropy optimization was not compiled"); #endif } jpeg_start_compress(&cinfo, TRUE); if (jpg_setup_grayscale) { row_pointer = xmalloc(w); } else { row_pointer = xmalloc(3*w); } while ((i = cinfo.next_scanline) < h) { k = 0; for (j = 0; j < w; j++) { c = gdImageGetPixel(ihandle, j, i); r = gdImageRed(ihandle, c); g = gdImageGreen(ihandle, c); b = gdImageBlue(ihandle, c); if (jpg_setup_grayscale) { y = INTENSITY(r, g, b); row_pointer[k++] = y; } else { row_pointer[k++] = r; row_pointer[k++] = g; row_pointer[k++] = b; } } jpeg_write_scanlines(&cinfo, &row_pointer, 1); } xfree(row_pointer); jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); } int jpg_op_parser(char *opstring) { char *bufp; if (!strcmp(opstring, "grayscale")) { jpg_setup_grayscale = TRUE; return RETURN_SUCCESS; } else if (!strcmp(opstring, "color")) { jpg_setup_grayscale = FALSE; return RETURN_SUCCESS; } else if (!strcmp(opstring, "optimize:on")) { jpg_setup_optimize = TRUE; return RETURN_SUCCESS; } else if (!strcmp(opstring, "optimize:off")) { jpg_setup_optimize = FALSE; return RETURN_SUCCESS; } else if (!strcmp(opstring, "baseline:on")) { jpg_setup_baseline = TRUE; return RETURN_SUCCESS; } else if (!strcmp(opstring, "baseline:off")) { jpg_setup_baseline = FALSE; return RETURN_SUCCESS; } else if (!strcmp(opstring, "progressive:on")) { jpg_setup_progressive = TRUE; return RETURN_SUCCESS; } else if (!strcmp(opstring, "progressive:off")) { jpg_setup_progressive = FALSE; return RETURN_SUCCESS; } else if (!strcmp(opstring, "dct:ifast")) { jpg_setup_dct = JPEG_DCT_IFAST; return RETURN_SUCCESS; } else if (!strcmp(opstring, "dct:islow")) { jpg_setup_dct = JPEG_DCT_ISLOW; return RETURN_SUCCESS; } else if (!strcmp(opstring, "dct:float")) { jpg_setup_dct = JPEG_DCT_FLOAT; return RETURN_SUCCESS; } else if (!strncmp(opstring, "quality:", 8)) { bufp = strchr(opstring, ':'); bufp++; if (bufp != NULL && *bufp != '\0') { jpg_setup_quality = atoi(bufp); return RETURN_SUCCESS; } else { return RETURN_FAILURE; } } else if (!strncmp(opstring, "smoothing:", 10)) { bufp = strchr(opstring, ':'); bufp++; if (bufp != NULL && *bufp != '\0') { jpg_setup_smoothing = atoi(bufp); return RETURN_SUCCESS; } else { return RETURN_FAILURE; } } else { return RETURN_FAILURE; } } #endif int pnm_op_parser(char *opstring) { if (!strcmp(opstring, "rawbits:on")) { pnm_setup_rawbits = TRUE; return RETURN_SUCCESS; } else if (!strcmp(opstring, "rawbits:off")) { pnm_setup_rawbits = FALSE; return RETURN_SUCCESS; } else if (!strcmp(opstring, "format:pbm")) { pnm_setup_format = PNM_FORMAT_PBM; return RETURN_SUCCESS; } else if (!strcmp(opstring, "format:pgm")) { pnm_setup_format = PNM_FORMAT_PGM; return RETURN_SUCCESS; } else if (!strcmp(opstring, "format:ppm")) { pnm_setup_format = PNM_FORMAT_PPM; return RETURN_SUCCESS; } else { return RETURN_FAILURE; } } #ifdef HAVE_LIBPNG int pnginitgraphics(void) { int result; result = rst_initgraphics(RST_FORMAT_PNG); if (result == RETURN_SUCCESS) { curformat = RST_FORMAT_PNG; } return (result); } static void rstImagePng(gdImagePtr ihandle, FILE *prstream) { png_structp png_ptr; png_infop info_ptr; int w, h; int interlace_type; int i, num_palette; png_color *palette; png_byte trans; int num_text; png_text text_ptr[4]; char *s; png_uint_32 res_meter; png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { return; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_write_struct(&png_ptr, NULL); return; } if (setjmp(png_ptr->jmpbuf)) { png_destroy_write_struct(&png_ptr, &info_ptr); return; } png_init_io(png_ptr, prstream); /* set the zlib compression level */ png_set_compression_level(png_ptr, png_setup_compression); w = gdImageSX(ihandle); h = gdImageSY(ihandle); if (png_setup_interlaced) { interlace_type = PNG_INTERLACE_ADAM7; } else { interlace_type = PNG_INTERLACE_NONE; } png_set_IHDR(png_ptr, info_ptr, w, h, 8, PNG_COLOR_TYPE_PALETTE, interlace_type, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); num_palette = gdImageColorsTotal(ihandle); palette = xmalloc(num_palette*sizeof(png_color)); if (palette == NULL) { return; } for (i = 0; i < num_palette; i++) { palette[i].red = gdImageRed(ihandle, i); palette[i].green = gdImageGreen(ihandle, i); palette[i].blue = gdImageBlue(ihandle, i); } png_set_PLTE(png_ptr, info_ptr, palette, num_palette); res_meter = (png_uint_32) rint(page_dpi/MM_PER_INCH*1000.0); png_set_pHYs(png_ptr, info_ptr, res_meter, res_meter, PNG_RESOLUTION_METER); #ifdef PNG_WRITE_tRNS_SUPPORTED if (png_setup_transparent) { trans = gdImageGetTransparent(ihandle); png_set_tRNS(png_ptr, info_ptr, &trans, 1, NULL); } #endif #if (defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)) text_ptr[0].key = "Title"; text_ptr[0].text = get_docname(); text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE; text_ptr[1].key = "Author"; text_ptr[1].text = get_username(); text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE; text_ptr[2].key = "Software"; text_ptr[2].text = bi_version_string(); text_ptr[2].compression = PNG_TEXT_COMPRESSION_NONE; num_text = 3; if ((s = get_project_description())) { text_ptr[3].key = "Description"; text_ptr[3].text = s; if (strlen(s) > 1024) { text_ptr[3].compression = PNG_TEXT_COMPRESSION_zTXt; } else { text_ptr[3].compression = PNG_TEXT_COMPRESSION_NONE; } num_text++; } png_set_text(png_ptr, info_ptr, text_ptr, num_text); #endif png_write_info(png_ptr, info_ptr); png_write_image(png_ptr, (png_byte **) ihandle->pixels); png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); xfree(palette); } int png_op_parser(char *opstring) { char *bufp; if (!strcmp(opstring, "interlaced:on")) { png_setup_interlaced = TRUE; return RETURN_SUCCESS; } else if (!strcmp(opstring, "interlaced:off")) { png_setup_interlaced = FALSE; return RETURN_SUCCESS; } else if (!strcmp(opstring, "transparent:on")) { png_setup_transparent = TRUE; return RETURN_SUCCESS; } else if (!strcmp(opstring, "transparent:off")) { png_setup_transparent = FALSE; return RETURN_SUCCESS; } else if (!strncmp(opstring, "compression:", 12)) { bufp = strchr(opstring, ':'); bufp++; if (bufp != NULL && *bufp != '\0') { png_setup_compression = atoi(bufp); return RETURN_SUCCESS; } else { return RETURN_FAILURE; } } else { return RETURN_FAILURE; } } #endif #ifndef NONE_GUI static void update_pnm_setup_frame(void); static int set_pnm_setup_proc(void *data); static Widget pnm_setup_frame; static Widget pnm_setup_rawbits_item; static Widget *pnm_setup_format_item; #ifdef HAVE_LIBPNG static void update_png_setup_frame(void); static int set_png_setup_proc(void *data); static Widget png_setup_frame; static Widget png_setup_interlaced_item; static Widget png_setup_transparent_item; static SpinStructure *png_setup_compression_item; void png_gui_setup(void) { set_wait_cursor(); if (png_setup_frame == NULL) { Widget fr, rc; png_setup_frame = CreateDialogForm(app_shell, "PNG options"); fr = CreateFrame(png_setup_frame, "PNG options"); rc = CreateVContainer(fr); png_setup_interlaced_item = CreateToggleButton(rc, "Interlaced"); png_setup_transparent_item = CreateToggleButton(rc, "Transparent"); png_setup_compression_item = CreateSpinChoice(rc, "Compression:", 1, SPIN_TYPE_INT, (double) Z_NO_COMPRESSION, (double) Z_BEST_COMPRESSION, 1.0); CreateAACDialog(png_setup_frame, fr, set_png_setup_proc, NULL); } update_png_setup_frame(); RaiseWindow(GetParent(png_setup_frame)); unset_wait_cursor(); } static void update_png_setup_frame(void) { if (png_setup_frame) { SetToggleButtonState(png_setup_interlaced_item, png_setup_interlaced); SetToggleButtonState(png_setup_transparent_item, png_setup_transparent); SetSpinChoice(png_setup_compression_item, png_setup_compression); } } static int set_png_setup_proc(void *data) { png_setup_interlaced = GetToggleButtonState(png_setup_interlaced_item); png_setup_transparent = GetToggleButtonState(png_setup_transparent_item); png_setup_compression = GetSpinChoice(png_setup_compression_item); return RETURN_SUCCESS; } #endif void pnm_gui_setup(void) { set_wait_cursor(); if (pnm_setup_frame == NULL) { Widget fr, rc; pnm_setup_frame = CreateDialogForm(app_shell, "PNM options"); fr = CreateFrame(pnm_setup_frame, "PNM options"); rc = CreateVContainer(fr); pnm_setup_format_item = CreatePanelChoice(rc, "Format: ", 4, "1-bit mono (PBM)", "8-bit grayscale (PGM)", "8-bit color (PPM)", NULL); pnm_setup_rawbits_item = CreateToggleButton(rc, "\"Rawbits\""); CreateAACDialog(pnm_setup_frame, fr, set_pnm_setup_proc, NULL); } update_pnm_setup_frame(); RaiseWindow(GetParent(pnm_setup_frame)); unset_wait_cursor(); } static void update_pnm_setup_frame(void) { if (pnm_setup_frame) { SetChoice(pnm_setup_format_item, pnm_setup_format); SetToggleButtonState(pnm_setup_rawbits_item, pnm_setup_rawbits); } } static int set_pnm_setup_proc(void *data) { pnm_setup_format = GetChoice(pnm_setup_format_item); pnm_setup_rawbits = GetToggleButtonState(pnm_setup_rawbits_item); return RETURN_SUCCESS; } #ifdef HAVE_LIBJPEG static void update_jpg_setup_frame(void); static int set_jpg_setup_proc(void *data); static Widget jpg_setup_frame; static Widget jpg_setup_grayscale_item; static Widget jpg_setup_baseline_item; static Widget jpg_setup_optimize_item; static Widget jpg_setup_progressive_item; static SpinStructure *jpg_setup_quality_item; static SpinStructure *jpg_setup_smoothing_item; static Widget *jpg_setup_dct_item; void jpg_gui_setup(void) { set_wait_cursor(); if (jpg_setup_frame == NULL) { Widget jpg_setup_rc, fr, rc; jpg_setup_frame = CreateDialogForm(app_shell, "JPEG options"); jpg_setup_rc = CreateVContainer(jpg_setup_frame); fr = CreateFrame(jpg_setup_rc, "JPEG options"); rc = CreateVContainer(fr); jpg_setup_quality_item = CreateSpinChoice(rc, "Quality:", 3, SPIN_TYPE_INT, 0.0, 100.0, 5.0); jpg_setup_optimize_item = CreateToggleButton(rc, "Optimize"); jpg_setup_progressive_item = CreateToggleButton(rc, "Progressive"); jpg_setup_grayscale_item = CreateToggleButton(rc, "Grayscale"); fr = CreateFrame(jpg_setup_rc, "JPEG advanced options"); rc = CreateVContainer(fr); jpg_setup_smoothing_item = CreateSpinChoice(rc, "Smoothing:", 3, SPIN_TYPE_INT, 0.0, 100.0, 10.0); jpg_setup_baseline_item = CreateToggleButton(rc, "Force baseline"); jpg_setup_dct_item = CreatePanelChoice(rc, "DCT: ", 4, "Fast integer", "Slow integer", "Float", NULL); CreateAACDialog(jpg_setup_frame, jpg_setup_rc, set_jpg_setup_proc, NULL); } update_jpg_setup_frame(); RaiseWindow(GetParent(jpg_setup_frame)); unset_wait_cursor(); } static void update_jpg_setup_frame(void) { if (jpg_setup_frame) { SetToggleButtonState(jpg_setup_grayscale_item, jpg_setup_grayscale); SetToggleButtonState(jpg_setup_baseline_item, jpg_setup_baseline); SetToggleButtonState(jpg_setup_optimize_item, jpg_setup_optimize); SetToggleButtonState(jpg_setup_progressive_item, jpg_setup_progressive); SetSpinChoice(jpg_setup_quality_item, jpg_setup_quality); SetSpinChoice(jpg_setup_smoothing_item, jpg_setup_smoothing); SetChoice(jpg_setup_dct_item, jpg_setup_dct); } } static int set_jpg_setup_proc(void *data) { jpg_setup_grayscale = GetToggleButtonState(jpg_setup_grayscale_item); jpg_setup_baseline = GetToggleButtonState(jpg_setup_baseline_item); jpg_setup_optimize = GetToggleButtonState(jpg_setup_optimize_item); jpg_setup_progressive = GetToggleButtonState(jpg_setup_progressive_item); jpg_setup_quality = (int) GetSpinChoice(jpg_setup_quality_item); jpg_setup_smoothing = (int) GetSpinChoice(jpg_setup_smoothing_item); jpg_setup_dct = GetChoice(jpg_setup_dct_item); return RETURN_SUCCESS; } #endif #endif