changeset 17 | 8e8b56b0e0f5 |
parent 15 | e7f0697814dc |
child 19 | d18606bb6f20 |
16:50995bbe442a | 17:8e8b56b0e0f5 |
---|---|
1 #include <stdlib.h> |
1 #include <stdlib.h> |
2 |
2 |
3 #include <png.h> |
3 #include <png.h> |
4 |
4 |
5 #include "common.h" |
5 #include "common.h" |
6 #include "render_internal.h" |
6 #include "render_struct.h" |
7 #include "render_png_struct.h" |
|
7 #include "render_png.h" |
8 #include "render_png.h" |
8 |
9 |
9 struct render_png { |
|
10 // libpng handles |
|
11 png_structp png_ptr; |
|
12 png_infop info_ptr; |
|
13 |
|
14 // some info that we need to keep from the struct render |
|
15 render_ctx_write_cb io_write_fn; |
|
16 render_ctx_flush_cb io_flush_fn; |
|
17 void *cb_arg; |
|
18 }; |
|
19 |
10 |
20 static void _render_png_write(png_structp png_ptr, png_bytep data, png_size_t length) { |
11 static void _render_png_write(png_structp png_ptr, png_bytep data, png_size_t length) { |
21 struct render_png *ctx = png_get_io_ptr(png_ptr); |
12 struct render_png *ctx = png_get_io_ptr(png_ptr); |
22 |
13 |
23 if (ctx->io_write_fn) |
14 if (ctx->io_write_fn) |
36 png_error(png_ptr, "_render_png_flush: io_flush_fn"); |
27 png_error(png_ptr, "_render_png_flush: io_flush_fn"); |
37 } |
28 } |
38 } |
29 } |
39 |
30 |
40 static void _render_png_free (struct render_png *ctx) { |
31 static void _render_png_free (struct render_png *ctx) { |
41 if (ctx) |
32 render_png_deinit(ctx); |
42 png_destroy_write_struct(&ctx->png_ptr, &ctx->info_ptr); |
33 |
43 |
34 if (ctx->owned_by_me) |
44 free(ctx); |
35 free(ctx); |
45 } |
36 } |
46 |
37 |
38 int render_png_deinit (struct render_png *ctx) { |
|
39 // not initialized? Just return a positive nonzero value |
|
40 if (!ctx->png_ptr) |
|
41 return 1; |
|
47 |
42 |
48 struct render_png *render_png_init (struct render *render) { |
43 // libpng error handling |
44 if (setjmp(png_jmpbuf(ctx->png_ptr))) |
|
45 ERROR("libpng"); |
|
46 |
|
47 png_destroy_write_struct(&ctx->png_ptr, &ctx->info_ptr); |
|
49 |
48 |
50 struct render_png *ctx = NULL; |
49 // success |
50 return 0; |
|
51 |
51 |
52 // calloc the render_png |
52 error: |
53 if (!(ctx = calloc(1, sizeof(struct render_png)))) |
53 free(ctx); |
54 ERROR("calloc"); |
54 return -1; |
55 } |
|
55 |
56 |
57 /* |
|
58 * Note that it's vitally important not to call any libpng functions directly, |
|
59 * the error-handling setjmp will be invalid. |
|
60 */ |
|
61 |
|
62 int render_png_init (struct render_png *ctx, struct render *render) { |
|
56 // store some info from the struct render |
63 // store some info from the struct render |
57 ctx->io_write_fn = render->io_write_fn; |
64 ctx->io_write_fn = render->io_write_fn; |
58 ctx->io_flush_fn = render->io_flush_fn; |
65 ctx->io_flush_fn = render->io_flush_fn; |
59 ctx->cb_arg = render->cb_arg; |
66 ctx->cb_arg = render->cb_arg; |
60 |
67 |
81 // some PNG metadata |
88 // some PNG metadata |
82 png_set_IHDR(ctx->png_ptr, ctx->info_ptr, render->img_w, render->img_h, 8, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); |
89 png_set_IHDR(ctx->png_ptr, ctx->info_ptr, render->img_w, render->img_h, 8, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); |
83 |
90 |
84 // write out the PNG header |
91 // write out the PNG header |
85 png_write_info(ctx->png_ptr, ctx->info_ptr); |
92 png_write_info(ctx->png_ptr, ctx->info_ptr); |
93 |
|
94 // success |
|
95 return 0; |
|
96 |
|
97 error: |
|
98 render_png_deinit(ctx); |
|
99 return -1; |
|
100 } |
|
101 |
|
102 struct render_png *render_png_alloc (struct render *render) { |
|
103 struct render_png *ctx = NULL; |
|
104 |
|
105 // calloc the render_png |
|
106 if (!(ctx = calloc(1, sizeof(struct render_png)))) |
|
107 ERROR("calloc"); |
|
108 |
|
109 // I need to free it |
|
110 ctx->owned_by_me = 1; |
|
111 |
|
112 // init it |
|
113 if (render_png_init(ctx, render)) |
|
114 goto error; |
|
86 |
115 |
87 // success |
116 // success |
88 return ctx; |
117 return ctx; |
89 |
118 |
90 error: |
119 error: |