Exemple #1
0
int R_SaveAsPng(void  *d, int width, int height,
                unsigned int (*gp)(void *, int, int),
                int bgr, FILE *fp, unsigned int transparent, int res)
{
    png_structp png_ptr;
    png_infop info_ptr;
    unsigned int  col, palette[256];
    png_color pngpalette[256];
    png_bytep pscanline;
    png_bytep scanline = (png_bytep) calloc((size_t)(4*width),sizeof(png_byte));
    png_byte trans[256];
    png_color_16 trans_values[1];
    int i, j, r, ncols, mid, high, low, withpalette, have_alpha;
    volatile DECLARESHIFTS;

    /* Have we enough memory?*/
    if (scanline == NULL)
        return 0;

    if (fp == NULL) {
        free(scanline);
        return 0;
    }

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

    /* Allocate/initialize the image information data.  REQUIRED */
    info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL) {
        free(scanline);
        png_destroy_write_struct(&png_ptr,  (png_infopp)NULL);
        return 0;
    }

    /* Set error handling.  REQUIRED if you aren't supplying your own
     * error handling functions in the png_create_write_struct() call.
     */
#if PNG_LIBPNG_VER < 10400
    if (setjmp(png_ptr->jmpbuf))
#else
    if (setjmp(png_jmpbuf(png_ptr)))
#endif
    {
        /* If we get here, we had a problem writing the file */
        free(scanline);
        png_destroy_write_struct(&png_ptr, &info_ptr);
        return 0;
    }
    png_set_error_fn(png_ptr, NULL, my_png_error, my_png_warning);

    /* I/O initialization functions is REQUIRED */
    png_init_io(png_ptr, fp);
    /* Have we less than 256 different colors? */
    ncols = 0;
    if(transparent) palette[ncols++] = transparent & 0xFFFFFF;
    mid = ncols;
    withpalette = 1;
    have_alpha = 0;
    for (i = 0; (i < height) && withpalette ; i++) {
        for (j = 0; (j < width) && withpalette ; j++) {
            col = gp(d,i,j);
            if (GETALPHA(col) < 255) have_alpha = 1;
            /* binary search the palette: */
            low = 0;
            high = ncols - 1;
            while (low <= high) {
                mid = (low + high)/2;
                if ( col < palette[mid] ) high = mid - 1;
                else if ( col > palette[mid] ) low  = mid + 1;
                else break;
            }
            if (high < low) {
                /* didn't find colour in palette, insert it: */
                if (ncols >= 256) {
                    withpalette = 0;
                } else {
                    for (r = ncols; r > low; r--)
                        palette[r] = palette[r-1] ;
                    palette[low] = col;
                    ncols ++;
                }
            }
        }
    }
    col = gp(d,0,0);
    //have_alpha &= (transparent == 0);

    /* 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(png_ptr, info_ptr, width, height, 8,
                 withpalette ? PNG_COLOR_TYPE_PALETTE :
                 (have_alpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB),
                 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
                 PNG_FILTER_TYPE_BASE);

    if (withpalette) {
        for (i = 0; i < ncols ; i++) {
            col = palette[i];
            if(transparent) {
                trans[i] = (col == transparent) ? 0:255;
                pngpalette[i].red = GETRED(col);
                pngpalette[i].green = GETGREEN(col);
                pngpalette[i].blue = GETBLUE(col);
            } else {
                /* PNG needs NON-premultiplied alpha */
                int a = GETALPHA(col);
                trans[i] = a;
                if(a == 255 || a == 0) {
                    pngpalette[i].red = GETRED(col);
                    pngpalette[i].green = GETGREEN(col);
                    pngpalette[i].blue = GETBLUE(col);
                } else {
                    pngpalette[i].red = 0.49 + 255.0*GETRED(col)/a;
                    pngpalette[i].green = 0.49 + 255.0*GETGREEN(col)/a;
                    pngpalette[i].blue = 0.49 + 255.0*GETBLUE(col)/a;

                }
            }
        }
        png_set_PLTE(png_ptr, info_ptr, pngpalette, ncols);
        if (transparent || have_alpha)
            png_set_tRNS(png_ptr, info_ptr, trans, ncols, trans_values);
    }
    /* Deal with transparency */
    if(transparent && !withpalette) {
        trans_values[0].red = GETRED(transparent);
        trans_values[0].blue = GETBLUE(transparent);
        trans_values[0].green = GETGREEN(transparent);
        png_set_tRNS(png_ptr, info_ptr, trans, ncols, trans_values);
    }

    if(res > 0)
        png_set_pHYs(png_ptr, info_ptr, res/0.0254, res/0.0254,
                     PNG_RESOLUTION_METER);

    /* Write the file header information.  REQUIRED */
    png_write_info(png_ptr, info_ptr);

    /*
     * Now, write the pixels
     */
    for (i = 0 ; i < height ; i++) {
        /* Build the scanline */
        pscanline = scanline;
        for (j = 0 ; j < width ; j++) {
            col = gp(d, i, j);
            if (withpalette) {
                /* binary search the palette (the colour must be there): */
                low = 0;
                high = ncols - 1;
                while (low <= high) {
                    mid = (low + high)/2;
                    if      (col < palette[mid]) high = mid - 1;
                    else if (col > palette[mid]) low  = mid + 1;
                    else break;
                }
                *pscanline++ = mid;
            } else {
                if(have_alpha) {
                    /* PNG needs NON-premultiplied alpha */
                    int a = GETALPHA(col);
                    if(a == 255 || a == 0) {
                        *pscanline++ = GETRED(col) ;
                        *pscanline++ = GETGREEN(col) ;
                        *pscanline++ = GETBLUE(col) ;
                        *pscanline++ =  a;
                    } else {
                        *pscanline++ = 0.49 + 255.0*GETRED(col)/a ;
                        *pscanline++ = 0.49 + 255.0*GETGREEN(col)/a ;
                        *pscanline++ = 0.49 + 255.0*GETBLUE(col)/a ;
                        *pscanline++ =  a;
                    }
                } else {
                    *pscanline++ = GETRED(col) ;
                    *pscanline++ = GETGREEN(col) ;
                    *pscanline++ = GETBLUE(col) ;
                }
            }
        }
        png_write_row(png_ptr, scanline);
    }

    /* 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 */
    free(scanline);
    png_destroy_write_struct(&png_ptr, &info_ptr);

    /* that's it */
    return 1;
}
Exemple #2
0
static void
handle_define(char *yyt)
{
    char namebuf[NSIZE];
    char args[NARGS][NSIZE];
    char mtext[MLEN];
    char *p, *q;

    p = yyt;
    (void)strcat(p, " ");
    q = namebuf;
    GETALPHA(p, q, namebuf+NSIZE-1);
    if (*p == '(')
    {       /* if "function macro" */
	int arg;
	int inid;
	char *ids = 0;
	p++;            /* skip '(' */
	SKIPWHITE;
	if (*p == ')')
	{
	    arg = 0;
	}
	else
	{
	    for (arg = 0; arg < NARGS; )
	    {
		q = args[arg];
		GETALPHA(p, q, args[arg] + NSIZE - 1);
		arg++;
		SKIPWHITE;
		if (*p == ')')
		    break;
		if (*p++ != ',')
		{
		    lexerror("Missing ',' in #define parameter list");
		    return;
		}
		SKIPWHITE;
	    }
	    if (arg == NARGS)
	    {
		lexerror("Too many macro arguments");
		return;
	    }
	}
	p++;            /* skip ')' */
	for (inid = 0, q = mtext; *p; )
	{
	    if (isalunum(*p))
	    {
		if (!inid)
		{
		    inid++;
		    ids = p;
		}
	    }
	    else
	    {
		if (inid)
		{
		    size_t l, idlen = p - ids;
		    int n;
		    
		    for (n = 0; n < arg; n++)
		    {
			l = strlen(args[n]);
			if (l == idlen && strncmp(args[n], ids, l) == 0)
			{
			    q -= idlen;
			    *q++ = MARKS;
			    *q++ = n+MARKS+1;
			    break;
			}
		    }
		    inid = 0;
		}
	    }
	    *q = *p;
	    if (*p++ == MARKS)
		*++q = MARKS;
	    if (q < mtext + MLEN - 2)
		q++;
	    else
	    {
		lexerror("Macro text too long");
		return;
	    }
	    if (!*p && p[-2] == '\\')
	    {
		q -= 2;
		refill();
		p = yytext;
	    }
	}
	*--q = 0;
	add_define(namebuf, arg, mtext);
    }
    else
    {
	for (q = mtext; *p; )
	{
	    *q = *p++;
	    if (q < mtext + MLEN - 2)
		q++;
	    else
	    {
		lexerror("Macro text too long");
		return;
	    }
	    if (!*p && p[-2] == '\\')
	    {
		q -= 2;
		refill();
		p = yytext;
	    }
	}
	*--q = 0;
	add_define(namebuf, -1, mtext);
    }
    return;
}
Exemple #3
0
int R_SaveAsTIFF(void  *d, int width, int height,
                 unsigned int (*gp)(void *, int, int),
                 int bgr, const char *outfile, int res, int compression)
{
    TIFF *out;
    int sampleperpixel;
    tsize_t linebytes;
    unsigned char *buf, *pscanline;
    unsigned int col, i, j;
    int have_alpha = 0;

    DECLARESHIFTS;

    for (i = 0; i < height; i++)
        for (j = 0; j < width; j++) {
            col = gp(d,i,j);
            if (GETALPHA(col) < 255) {
                have_alpha = 1;
                break;
            }
        }
    sampleperpixel = 3 + have_alpha;

    out = TIFFOpen(outfile, "w");
    if (!out) {
        warning("unable to open TIFF file '%s'", outfile);
        return 0;
    }
    TIFFSetField(out, TIFFTAG_IMAGEWIDTH, width);
    TIFFSetField(out, TIFFTAG_IMAGELENGTH, height);
    TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, sampleperpixel);
    TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 8);
    TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
    TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
    TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
#if 0
    /* Possible compression values
       COMPRESSION_NONE = 1;
       COMPRESSION_CCITTRLE = 2;
       COMPRESSION_CCITTFAX3 = COMPRESSION_CCITT_T4 = 3;
       COMPRESSION_CCITTFAX4 = COMPRESSION_CCITT_T6 = 4;
       COMPRESSION_LZW = 5;
       COMPRESSION_JPEG = 7;
       COMPRESSION_DEFLATE = 32946;
       COMPRESSION_ADOBE_DEFLATE = 8;
    */
    TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
#endif
    if(compression > 1)
        TIFFSetField(out, TIFFTAG_COMPRESSION, compression);

    if (res > 0) {
        TIFFSetField(out, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
        TIFFSetField(out, TIFFTAG_XRESOLUTION, (float) res);
        TIFFSetField(out, TIFFTAG_YRESOLUTION, (float) res);
    }

    linebytes = sampleperpixel * width;
    if (TIFFScanlineSize(out))
        buf =(unsigned char *)_TIFFmalloc(linebytes);
    else
        buf = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(out));

    for (i = 0; i < height; i++) {
        pscanline = buf;
        for(j = 0; j < width; j++) {
            col = gp(d, i, j);
            *pscanline++ = GETRED(col) ;
            *pscanline++ = GETGREEN(col) ;
            *pscanline++ = GETBLUE(col) ;
            if(have_alpha) *pscanline++ = GETALPHA(col) ;
        }
        TIFFWriteScanline(out, buf, i, 0);
    }
    TIFFClose(out);
    _TIFFfree(buf);
    return 1;
}