1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 5 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2009 The PHP Group |
6 : +----------------------------------------------------------------------+
7 : | This source file is subject to version 3.01 of the PHP license, |
8 : | that is bundled with this package in the file LICENSE, and is |
9 : | available through the world-wide-web at the following url: |
10 : | http://www.php.net/license/3_01.txt |
11 : | If you did not receive a copy of the PHP license and are unable to |
12 : | obtain it through the world-wide-web, please send a note to |
13 : | license@php.net so we can mail you a copy immediately. |
14 : +----------------------------------------------------------------------+
15 : | Authors: Stanislav Malyshev <stas@php.net> |
16 : +----------------------------------------------------------------------+
17 : */
18 :
19 : /* $Id: gd_ctx.c 272370 2008-12-31 11:15:49Z sebastian $ */
20 :
21 : #include "php_gd.h"
22 :
23 : #define CTX_PUTC(c,ctx) ctx->putC(ctx, c)
24 :
25 : static void _php_image_output_putc(struct gdIOCtx *ctx, int c)
26 27 : {
27 : /* without the following downcast, the write will fail
28 : * (i.e., will write a zero byte) for all
29 : * big endian architectures:
30 : */
31 27 : unsigned char ch = (unsigned char) c;
32 : TSRMLS_FETCH();
33 27 : php_write(&ch, 1 TSRMLS_CC);
34 27 : }
35 :
36 : static int _php_image_output_putbuf(struct gdIOCtx *ctx, const void* buf, int l)
37 316 : {
38 : TSRMLS_FETCH();
39 316 : return php_write((void *)buf, l TSRMLS_CC);
40 : }
41 :
42 : static void _php_image_output_ctxfree(struct gdIOCtx *ctx)
43 27 : {
44 27 : if(ctx) {
45 27 : efree(ctx);
46 : }
47 27 : }
48 :
49 : /* {{{ _php_image_output_ctx */
50 : static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, void (*func_p)())
51 80 : {
52 : zval *imgind;
53 80 : char *file = NULL;
54 80 : int file_len = 0;
55 : long quality, basefilter;
56 : gdImagePtr im;
57 80 : FILE *fp = NULL;
58 80 : int argc = ZEND_NUM_ARGS();
59 80 : int q = -1, i;
60 80 : int f = -1;
61 : gdIOCtx *ctx;
62 :
63 : /* The third (quality) parameter for Wbmp stands for the threshold when called from image2wbmp().
64 : * The third (quality) parameter for Wbmp and Xbm stands for the foreground color index when called
65 : * from imagey<type>().
66 : */
67 :
68 80 : if (image_type == PHP_GDIMG_TYPE_XBM) {
69 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs!|ll", &imgind, &file, &file_len, &quality, &basefilter) == FAILURE) {
70 0 : return;
71 : }
72 : } else {
73 : /* PHP_GDIMG_TYPE_GIF
74 : * PHP_GDIMG_TYPE_PNG
75 : * PHP_GDIMG_TYPE_JPG
76 : * PHP_GDIMG_TYPE_WBM */
77 80 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|s!ll", &imgind, &file, &file_len, &quality, &basefilter) == FAILURE) {
78 0 : return;
79 : }
80 : }
81 :
82 80 : ZEND_FETCH_RESOURCE(im, gdImagePtr, &imgind, -1, "Image", phpi_get_le_gd());
83 :
84 80 : if (argc > 1) {
85 70 : if (argc >= 3) {
86 18 : q = quality; /* or colorindex for foreground of BW images (defaults to black) */
87 18 : if (argc == 4) {
88 0 : f = basefilter;
89 : }
90 : }
91 : }
92 :
93 133 : if (argc > 1 && file_len) {
94 53 : PHP_GD_CHECK_OPEN_BASEDIR(file, "Invalid filename");
95 :
96 53 : fp = VCWD_FOPEN(file, "wb");
97 53 : if (!fp) {
98 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open '%s' for writing: %s", file, strerror(errno));
99 0 : RETURN_FALSE;
100 : }
101 :
102 53 : ctx = gdNewFileCtx(fp);
103 : } else {
104 27 : ctx = emalloc(sizeof(gdIOCtx));
105 27 : ctx->putC = _php_image_output_putc;
106 27 : ctx->putBuf = _php_image_output_putbuf;
107 : #if HAVE_LIBGD204
108 27 : ctx->gd_free = _php_image_output_ctxfree;
109 : #else
110 : ctx->free = _php_image_output_ctxfree;
111 : #endif
112 :
113 : #if APACHE && defined(CHARSET_EBCDIC)
114 : /* XXX this is unlikely to work any more thies@thieso.net */
115 : /* This is a binary file already: avoid EBCDIC->ASCII conversion */
116 : ap_bsetflag(php3_rqst->connection->client, B_EBCDIC2ASCII, 0);
117 : #endif
118 : }
119 :
120 80 : switch(image_type) {
121 : case PHP_GDIMG_CONVERT_WBM:
122 0 : if(q<0||q>255) {
123 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid threshold value '%d'. It must be between 0 and 255", q);
124 : }
125 : case PHP_GDIMG_TYPE_JPG:
126 8 : (*func_p)(im, ctx, q);
127 8 : break;
128 : case PHP_GDIMG_TYPE_PNG:
129 60 : (*func_p)(im, ctx, q, f);
130 60 : break;
131 : case PHP_GDIMG_TYPE_XBM:
132 : case PHP_GDIMG_TYPE_WBM:
133 1 : if (argc < 3) {
134 1 : for(i=0; i < gdImageColorsTotal(im); i++) {
135 0 : if(!gdImageRed(im, i) && !gdImageGreen(im, i) && !gdImageBlue(im, i)) break;
136 : }
137 1 : q = i;
138 : }
139 1 : if (image_type == PHP_GDIMG_TYPE_XBM) {
140 0 : (*func_p)(im, file, q, ctx);
141 : } else {
142 1 : (*func_p)(im, q, ctx);
143 : }
144 1 : break;
145 : default:
146 11 : (*func_p)(im, ctx);
147 : break;
148 : }
149 :
150 : #if HAVE_LIBGD204
151 80 : ctx->gd_free(ctx);
152 : #else
153 : ctx->free(ctx);
154 : #endif
155 :
156 80 : if(fp) {
157 53 : fflush(fp);
158 53 : fclose(fp);
159 : }
160 :
161 80 : RETURN_TRUE;
162 : }
163 : /* }}} */
164 :
165 : /*
166 : * Local variables:
167 : * tab-width: 4
168 : * c-basic-offset: 4
169 : * End:
170 : * vim600: sw=4 ts=4 fdm=marker
171 : * vim<600: sw=4 ts=4
172 : */
|