-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpngwrite.c
117 lines (99 loc) · 3.06 KB
/
pngwrite.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/*
Irrtum
Copyright (C) 2011-2015 kahrl <[email protected]>
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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "common_c.h"
#include "pngwrite.h"
#include <stdio.h>
#include <setjmp.h>
#include <errno.h>
/*
* Note: This file MUST be written in plain jane C so that setjmp doesn't
* interfere with C++'s exception handling / RAII / etc.
*/
void pngwrite(
u32 width,
u32 height,
u8* data,
const char* filename,
const char** error_msg,
const char** error_extra)
{
FILE* fp;
png_structp png_ptr;
png_infop info_ptr;
png_bytepp row_pointers;
u32 i;
*error_msg = 0;
*error_extra = 0;
/* Allocate memory for row pointers */
row_pointers = malloc(height * sizeof(png_bytep));
if (row_pointers == 0)
{
*error_msg = "Failed to allocate memory";
*error_extra = strerror(errno);
return;
}
for (i = 0; i < height; ++i)
{
row_pointers[i] = (png_bytep) (data + i * width * 4);
}
/* Open file for writing */
fp = fopen(filename, "wb");
if (fp == 0)
{
*error_msg = "Could not open file for writing: ";
*error_extra = strerror(errno);
free(row_pointers);
return;
}
/* Initialize PNG structures */
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
if (png_ptr == 0)
{
*error_msg = "Could not allocate PNG write structure";
fclose(fp);
free(row_pointers);
return;
}
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == 0)
{
*error_msg = "Could not allocate PNG info structure";
png_destroy_write_struct(&png_ptr, (png_infopp) 0);
fclose(fp);
free(row_pointers);
return;
}
/* libpng exception handling ^_^ */
if (setjmp(png_jmpbuf(png_ptr)))
{
*error_msg = "Could not write PNG stream";
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(fp);
free(row_pointers);
return;
}
png_init_io(png_ptr, fp);
png_set_IHDR(png_ptr, info_ptr, width, height, 8,
PNG_COLOR_TYPE_RGB_ALPHA,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
png_set_rows(png_ptr, info_ptr, row_pointers);
png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, 0);
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(fp);
free(row_pointers);
}