- added wire color theme usage for drawing edges in editmode.
[blender.git] / source / blender / imbuf / intern / png_encode.c
1 /**
2  *
3  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. The Blender
9  * Foundation also sells licenses for use in proprietary software under
10  * the Blender License.  See http://www.blender.org/BL/ for information
11  * about this.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL/BL DUAL LICENSE BLOCK *****
30  * $Id$
31  */
32
33
34 #include "png.h"
35
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39
40 #ifdef WIN32
41 #include "BLI_winstuff.h"
42 #endif
43 #include "BLI_blenlib.h"
44
45 #include "imbuf.h"
46 #include "imbuf_patch.h"
47
48 #include "IMB_imbuf_types.h"
49 #include "IMB_imbuf.h"
50
51 #include "IMB_allocimbuf.h"
52 #include "IMB_cmap.h"
53
54 static void
55 WriteData(
56     png_structp png_ptr,
57     png_bytep data,
58     png_size_t length);
59
60 static void
61 Flush(
62     png_structp png_ptr);
63
64 static void
65 WriteData(
66     png_structp png_ptr,
67     png_bytep data,
68     png_size_t length)
69 {
70         ImBuf *ibuf = (ImBuf *) png_get_io_ptr(png_ptr);
71
72         // if buffer is to small increase it.
73         while (ibuf->encodedsize + length > ibuf->encodedbuffersize) {
74                 imb_enlargeencodedbufferImBuf(ibuf);
75         }
76
77         memcpy(ibuf->encodedbuffer + ibuf->encodedsize, data, length);
78         ibuf->encodedsize += length;
79 }
80
81 static void
82 Flush(
83     png_structp png_ptr)
84 {
85 }
86
87 short IMB_png_encode(struct ImBuf *ibuf, int file, int flags)
88 {
89         png_structp png_ptr;
90         png_infop info_ptr;
91         unsigned char *pixels = 0;
92         unsigned char *from, *to;
93         png_bytepp row_pointers = 0;
94         int i, bytesperpixel, color_type = PNG_COLOR_TYPE_GRAY;
95         FILE *fp = 0;
96
97         bytesperpixel = (ibuf->depth + 7) >> 3;
98         if ((bytesperpixel > 4) || (bytesperpixel == 2)) {
99                 printf("imb_png_encode: unsupported bytes per pixel: %d\n", bytesperpixel);
100                 return (0);
101         }
102
103         png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
104                 NULL, NULL, NULL);
105         if (png_ptr == NULL) {
106                 printf("Cannot png_create_write_struct\n");
107                 return 0;
108         }
109
110         info_ptr = png_create_info_struct(png_ptr);
111         if (info_ptr == NULL) {
112                 png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
113                 printf("Cannot png_create_info_struct\n");
114                 return 0;
115         }
116
117         if (setjmp(png_jmpbuf(png_ptr))) {
118                 png_destroy_write_struct(&png_ptr, &info_ptr);
119                 if (pixels) MEM_freeN(pixels);
120                 if (row_pointers) MEM_freeN(row_pointers);
121                 // printf("Aborting\n");
122                 if (fp) {
123                         fflush(fp);
124                         fclose(fp);
125                 }
126                 return 0;
127         }
128
129         // copy image data
130
131         pixels = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned char), "pixels");
132         if (pixels == NULL) {
133                 printf("Cannot allocate pixels array\n");
134                 return 0;
135         }
136
137         from = (unsigned char *) ibuf->rect;
138         to = pixels;
139
140         switch (bytesperpixel) {
141         case 4:
142                 color_type = PNG_COLOR_TYPE_RGBA;
143                 for (i = ibuf->x * ibuf->y; i > 0; i--) {
144                         to[0] = from[0];
145                         to[1] = from[1];
146                         to[2] = from[2];
147                         to[3] = from[3];
148                         to += 4; from += 4;
149                 }
150                 break;
151         case 3:
152                 color_type = PNG_COLOR_TYPE_RGB;
153                 for (i = ibuf->x * ibuf->y; i > 0; i--) {
154                         to[0] = from[0];
155                         to[1] = from[1];
156                         to[2] = from[2];
157                         to += 3; from += 4;
158                 }
159                 break;
160         case 1:
161                 color_type = PNG_COLOR_TYPE_GRAY;
162                 for (i = ibuf->x * ibuf->y; i > 0; i--) {
163                         to[0] = from[0];
164                         to++; from += 4;
165                 }
166                 break;
167         }
168
169         if (flags & IB_mem) {
170                 // create image in memory
171                 imb_addencodedbufferImBuf(ibuf);
172                 ibuf->encodedsize = 0;
173
174                 png_set_write_fn(png_ptr,
175                          (png_voidp) ibuf,
176                          WriteData,
177                          Flush);
178         } else {
179                 fp = fdopen(file, "wb");
180                 png_init_io(png_ptr, fp);
181         }
182
183         /*
184         png_set_filter(png_ptr, 0,
185                 PNG_FILTER_NONE  | PNG_FILTER_VALUE_NONE |
186                 PNG_FILTER_SUB   | PNG_FILTER_VALUE_SUB  |
187                 PNG_FILTER_UP    | PNG_FILTER_VALUE_UP   |
188                 PNG_FILTER_AVG   | PNG_FILTER_VALUE_AVG  |
189                 PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH|
190                 PNG_ALL_FILTERS);
191
192         png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
193         */
194
195         // png image settings
196         png_set_IHDR(png_ptr,
197                  info_ptr,
198                  ibuf->x,
199                  ibuf->y,
200                  8,
201                  color_type,
202                  PNG_INTERLACE_NONE,
203                  PNG_COMPRESSION_TYPE_DEFAULT,
204                  PNG_FILTER_TYPE_DEFAULT);
205
206         // write the file header information
207         png_write_info(png_ptr, info_ptr);
208
209         // allocate memory for an array of row-pointers
210         row_pointers = (png_bytepp) MEM_mallocN(ibuf->y * sizeof(png_bytep), "row_pointers");
211         if (row_pointers == NULL) {
212                         printf("Cannot allocate row-pointers array\n");
213                         return 0;
214         }
215
216         // set the individual row-pointers to point at the correct offsets
217         for (i = 0; i < ibuf->y; i++) {
218                 row_pointers[ibuf->y-1-i] = (png_bytep)
219                         ((unsigned char *)pixels + (i * ibuf->x) * bytesperpixel * sizeof(unsigned char));
220         }
221
222         // write out the entire image data in one call
223         png_write_image(png_ptr, row_pointers);
224
225         // write the additional chunks to the PNG file (not really needed)
226         png_write_end(png_ptr, info_ptr);
227
228         // clean up
229         MEM_freeN(pixels);
230         MEM_freeN(row_pointers);
231         png_destroy_write_struct(&png_ptr, &info_ptr);
232
233         if (fp) {
234                 fflush(fp);
235                 fclose(fp);
236         }
237
238         return(1);
239 }
240