Index: trunk/pngds/pngwriter.c |
— | — | @@ -0,0 +1,139 @@ |
| 2 | +#include <stdlib.h> |
| 3 | +#include <stdio.h> |
| 4 | +#include <string.h> |
| 5 | + |
| 6 | +#include "pngreader.h" |
| 7 | +#include "pngresize.h" |
| 8 | +#include "pngutil.h" |
| 9 | +#include "pngcmd.h" |
| 10 | +#include "pngwriter.h" |
| 11 | + |
| 12 | +#define BUFFER_OUT_SIZE 32768 |
| 13 | + |
| 14 | +void png_write_chunk(pngreader *info, char *type, void *ptr, u_int32_t size); |
| 15 | + |
| 16 | +void png_write_header(void *_info) |
| 17 | +{ |
| 18 | + pngreader *info = (pngreader*)_info; |
| 19 | + pngheader header; |
| 20 | + |
| 21 | + memcpy(&header, info->header, 13); |
| 22 | + if (info->extra1 != NULL) |
| 23 | + { |
| 24 | + pngresize *rinfo = (pngresize*)info->extra1; |
| 25 | + header.width = rinfo->width; |
| 26 | + header.height = rinfo->height; |
| 27 | + } |
| 28 | + png_fwrite("\x89PNG\r\n\x1a\n", 8, info->fout, NULL); |
| 29 | + |
| 30 | + u_int32_t crc = crc32(0, Z_NULL, 0); |
| 31 | + png_write_int(13, info->fout, NULL); |
| 32 | + png_fwrite("IHDR", 4, info->fout, &crc); |
| 33 | + png_write_int(header.width, info->fout, &crc); |
| 34 | + png_write_int(header.height, info->fout, &crc); |
| 35 | + png_fwrite((char*)&header + 8, 5, info->fout, &crc); |
| 36 | + png_write_int(crc, info->fout, NULL); |
| 37 | + |
| 38 | + pngwriter *winfo = calloc(sizeof(pngwriter), 1); |
| 39 | + winfo->zst.zalloc = Z_NULL; |
| 40 | + winfo->zst.zfree = Z_NULL; |
| 41 | + winfo->zst.opaque = Z_NULL; |
| 42 | + if (deflateInit(&winfo->zst, Z_DEFAULT_COMPRESSION) != Z_OK) |
| 43 | + png_die("zlib_init_error", NULL); |
| 44 | + winfo->in = malloc(header.width * info->bpp + 1); |
| 45 | + winfo->out = malloc(BUFFER_OUT_SIZE); |
| 46 | + winfo->zst.next_out = winfo->out; |
| 47 | + winfo->zst.avail_out = BUFFER_OUT_SIZE; |
| 48 | + |
| 49 | + info->extra2 = winfo; |
| 50 | +} |
| 51 | + |
| 52 | +void png_write_chunk(pngreader *info, char *type, void *ptr, u_int32_t size) |
| 53 | +{ |
| 54 | + u_int32_t crc = crc32(0, Z_NULL, 0); |
| 55 | + png_write_int(size, info->fout, NULL); |
| 56 | + png_fwrite(type, 4, info->fout, &crc); |
| 57 | + png_fwrite(ptr, size, info->fout, &crc); |
| 58 | + png_write_int(crc, info->fout, NULL); |
| 59 | +} |
| 60 | + |
| 61 | +void png_write_scanline(unsigned char *scanline, unsigned char *previous_scanline, |
| 62 | + u_int32_t length, void *info_) |
| 63 | +{ |
| 64 | + pngreader *info = (pngreader*)info_; |
| 65 | + pngwriter *winfo = (pngwriter*)info->extra2; |
| 66 | + |
| 67 | + // Filter type |
| 68 | + winfo->in[0] = FILTER_NONE; |
| 69 | + memcpy(winfo->in + 1, scanline, length); |
| 70 | + |
| 71 | + int ret; |
| 72 | + winfo->zst.next_in = winfo->in; |
| 73 | + winfo->zst.avail_in = length + 1; |
| 74 | + |
| 75 | + while (winfo->zst.avail_in > 0) |
| 76 | + { |
| 77 | + ret = deflate(&winfo->zst, Z_NO_FLUSH); |
| 78 | + if (ret == Z_STREAM_ERROR) |
| 79 | + png_die("deflate_error", NULL); |
| 80 | + if (ret == Z_BUF_ERROR) |
| 81 | + png_die("deflate_buffer_error", NULL); |
| 82 | + |
| 83 | + if (winfo->zst.avail_out == 0) |
| 84 | + { |
| 85 | + // Flush to disk |
| 86 | + png_write_chunk(info, "IDAT", winfo->out, BUFFER_OUT_SIZE - winfo->zst.avail_out); |
| 87 | + winfo->zst.next_out = winfo->out; |
| 88 | + winfo->zst.avail_out = BUFFER_OUT_SIZE; |
| 89 | + } |
| 90 | + } |
| 91 | + |
| 92 | +} |
| 93 | + |
| 94 | +void png_write_end(void *_info) |
| 95 | +{ |
| 96 | + pngreader *info = (pngreader*)_info; |
| 97 | + pngwriter *winfo = (pngwriter*)info->extra2; |
| 98 | + |
| 99 | + int ret; |
| 100 | + do |
| 101 | + { |
| 102 | + ret = deflate(&winfo->zst, Z_FINISH); |
| 103 | + if (ret == Z_STREAM_ERROR) |
| 104 | + png_die("deflate_finish_error", NULL); |
| 105 | + if (ret == Z_BUF_ERROR) |
| 106 | + png_die("deflate_finish_buffer_error", NULL); |
| 107 | + |
| 108 | + // Flush to disk |
| 109 | + png_write_chunk(info, "IDAT", winfo->out, BUFFER_OUT_SIZE - winfo->zst.avail_out); |
| 110 | + winfo->zst.next_out = winfo->out; |
| 111 | + winfo->zst.avail_out = BUFFER_OUT_SIZE; |
| 112 | + } |
| 113 | + while (ret != Z_STREAM_END); |
| 114 | + |
| 115 | + deflateEnd(&winfo->zst); |
| 116 | + |
| 117 | + png_write_chunk(info, "IEND", NULL, 0); |
| 118 | +} |
| 119 | + |
| 120 | +#ifdef PNGDS |
| 121 | +int main(int argc, char **argv) |
| 122 | +{ |
| 123 | + char **opts = pngcmd_getopts(argc, argv); |
| 124 | + FILE *in, *out; |
| 125 | + png_open_streams(opts, &in, &out); |
| 126 | + |
| 127 | + pngcallbacks callbacks; |
| 128 | + callbacks.completed_scanline = &png_write_scanline; |
| 129 | + callbacks.read_header = &png_write_header; |
| 130 | + callbacks.done = &png_write_end; |
| 131 | + |
| 132 | + png_resize(in, out, *((u_int32_t*)opts[PNGOPT_WIDTH]), |
| 133 | + *((u_int32_t*)opts[PNGOPT_HEIGHT]), &callbacks); |
| 134 | + |
| 135 | + fclose(in); fclose(out); |
| 136 | + |
| 137 | + return 0; |
| 138 | +} |
| 139 | +#endif |
| 140 | + |
Property changes on: trunk/pngds/pngwriter.c |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 141 | + native |
Index: trunk/pngds/pngutil.c |
— | — | @@ -44,6 +44,24 @@ |
45 | 45 | return size; |
46 | 46 | } |
47 | 47 | |
| 48 | +unsigned int png_fwrite(void *ptr, unsigned int size, |
| 49 | + FILE *stream, u_int32_t *crc) |
| 50 | +{ |
| 51 | + if (size == 0) return 0; |
| 52 | + |
| 53 | + if (fwrite(ptr, 1, size, stream) != size || |
| 54 | + ferror(stream)) |
| 55 | + png_die("write_error", stream); |
| 56 | + if (crc != NULL) |
| 57 | + *crc = crc32(*crc, ptr, size); |
| 58 | +} |
| 59 | +void png_write_int(u_int32_t value, FILE *stream, u_int32_t *crc) |
| 60 | +{ |
| 61 | + signed char i; |
| 62 | + for (i = 3; i >= 0; i--) |
| 63 | + png_fwrite((char*)(&value) + i, 1, stream, crc); |
| 64 | +} |
| 65 | + |
48 | 66 | void png_open_streams(char **opts, FILE **in, FILE **out) |
49 | 67 | { |
50 | 68 | if (!*(opts[PNGOPT_STDIN]) && opts[PNGOPT_IN] == NULL) |
Index: trunk/pngds/pngresize.c |
— | — | @@ -26,13 +26,17 @@ |
27 | 27 | |
28 | 28 | |
29 | 29 | if (callbacks == NULL) |
30 | | - { |
31 | | - callbacks = malloc(sizeof(callbacks)); |
32 | | - } |
| 30 | + info.callbacks = calloc(sizeof(pngcallbacks), 1); |
| 31 | + else |
| 32 | + info.callbacks = callbacks; |
| 33 | + callbacks = malloc(sizeof(pngcallbacks)); |
33 | 34 | callbacks->completed_scanline = &png_resize_line; |
34 | 35 | callbacks->read_header = &png_resize_init; |
35 | 36 | callbacks->done = &png_resize_done; |
36 | 37 | |
| 38 | + if (info.callbacks->completed_scanline == NULL) |
| 39 | + info.callbacks->completed_scanline = &png_write_scanline_raw; |
| 40 | + |
37 | 41 | png_read(fin, fout, callbacks, &info); |
38 | 42 | } |
39 | 43 | |
— | — | @@ -76,6 +80,8 @@ |
77 | 81 | rinfo->written_lines = 0; |
78 | 82 | rinfo->last_line = calloc(rinfo->width * info->bpp * sizeof(char), 1); |
79 | 83 | |
| 84 | + if (rinfo->callbacks->read_header != NULL) |
| 85 | + (*rinfo->callbacks->read_header)(info); |
80 | 86 | } |
81 | 87 | |
82 | 88 | void png_resize_line(unsigned char *scanline, unsigned char *previous_scanline, |
— | — | @@ -118,7 +124,8 @@ |
119 | 125 | scanline[i] += rinfo->scanlines[j][i] / rinfo->line_count; |
120 | 126 | } |
121 | 127 | rinfo->line_count = 0; |
122 | | - png_write_scanline(scanline, rinfo->last_line, rinfo->width * info->bpp, info); |
| 128 | + (*rinfo->callbacks->completed_scanline)(scanline, |
| 129 | + rinfo->last_line, rinfo->width * info->bpp, info); |
123 | 130 | memcpy(rinfo->last_line, scanline, rinfo->width * info->bpp); |
124 | 131 | rinfo->written_lines++; |
125 | 132 | } |
— | — | @@ -131,9 +138,13 @@ |
132 | 139 | |
133 | 140 | while (rinfo->written_lines < rinfo->height) |
134 | 141 | { |
135 | | - png_write_scanline(rinfo->last_line, rinfo->last_line, rinfo->width * info->bpp, info); |
| 142 | + (*rinfo->callbacks->completed_scanline)( |
| 143 | + rinfo->last_line, rinfo->last_line, |
| 144 | + rinfo->width * info->bpp, info); |
136 | 145 | rinfo->written_lines++; |
137 | 146 | } |
| 147 | + if (rinfo->callbacks->done != NULL) |
| 148 | + (*rinfo->callbacks->done)(info); |
138 | 149 | } |
139 | 150 | |
140 | 151 | #ifdef PNGRESIZE |
Index: trunk/pngds/pngwriter.h |
— | — | @@ -0,0 +1,11 @@ |
| 2 | +typedef struct |
| 3 | +{ |
| 4 | + char *in; |
| 5 | + char *out; |
| 6 | + z_stream zst; |
| 7 | + |
| 8 | +} pngwriter; |
| 9 | + |
| 10 | +void png_write_header(void *_info); |
| 11 | +void png_write_end(void *_info); |
| 12 | +void png_write_scanline(unsigned char *scanline, unsigned char *previous_scanline, u_int32_t length, void *info_); |
Property changes on: trunk/pngds/pngwriter.h |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 13 | + native |
Index: trunk/pngds/pngreader.c |
— | — | @@ -32,7 +32,7 @@ |
33 | 33 | callbacks->done = NULL; |
34 | 34 | } |
35 | 35 | if (callbacks->completed_scanline == NULL) |
36 | | - callbacks->completed_scanline = &png_write_scanline; |
| 36 | + callbacks->completed_scanline = &png_write_scanline_raw; |
37 | 37 | info.callbacks = callbacks; |
38 | 38 | |
39 | 39 | info.extra1 = extra1; |
— | — | @@ -293,7 +293,7 @@ |
294 | 294 | png_fread(&buf, 1, info->fin, &info->crc); |
295 | 295 | } |
296 | 296 | |
297 | | -void png_write_scanline(unsigned char *scanline, unsigned char *previous_scanline, |
| 297 | +void png_write_scanline_raw(unsigned char *scanline, unsigned char *previous_scanline, |
298 | 298 | u_int32_t length, void *info_) |
299 | 299 | { |
300 | 300 | pngreader *info = (pngreader*)info_; |
Index: trunk/pngds/pngutil.h |
— | — | @@ -5,5 +5,7 @@ |
6 | 6 | void png_read_int(u_int32_t *ptr, FILE *stream, u_int32_t *crc); |
7 | 7 | unsigned int png_fread(void *ptr, unsigned int size, FILE *stream, u_int32_t *crc); |
8 | 8 | void png_open_streams(char **options, FILE **in, FILE **out); |
| 9 | +void png_write_int(u_int32_t value, FILE *stream, u_int32_t *crc); |
| 10 | +unsigned int png_fwrite(void *ptr, unsigned int size, FILE *stream, u_int32_t *crc); |
9 | 11 | |
10 | 12 | #endif |
Index: trunk/pngds/pngcmd.c |
— | — | @@ -34,7 +34,7 @@ |
35 | 35 | *res[PNGOPT_STDIN] = 1; |
36 | 36 | else if (strcmp(argv[i], "--to-stdout") == 0) |
37 | 37 | *res[PNGOPT_STDOUT] = 1; |
38 | | -#ifdef PNGRESIZE |
| 38 | +#ifndef PNGREADER |
39 | 39 | else if (strcmp(argv[i], "--height") == 0 || |
40 | 40 | strcmp(argv[i], "--width") == 0) |
41 | 41 | ; // Do nothing |
— | — | @@ -74,6 +74,10 @@ |
75 | 75 | "pngresize [--from-stdin] [--to-stdout] [<source>] [<target>]\n" |
76 | 76 | " [--width <width>] [--height <height>]\n" |
77 | 77 | #endif |
| 78 | +#ifdef PNGDS |
| 79 | + "pngds [--from-stdin] [--to-stdout] [<source>] [<target>]\n" |
| 80 | + " [--width <width>] [--height <height>]\n" |
| 81 | +#endif |
78 | 82 | "\n"); |
79 | 83 | exit(0); |
80 | 84 | } |
Index: trunk/pngds/pngresize.h |
— | — | @@ -13,4 +13,5 @@ |
14 | 14 | u_int32_t written_lines; |
15 | 15 | unsigned char *last_line; |
16 | 16 | |
| 17 | + pngcallbacks *callbacks; |
17 | 18 | } pngresize; |
Index: trunk/pngds/Makefile |
— | — | @@ -1,15 +1,16 @@ |
2 | 2 | CC = cc |
3 | 3 | CFLAGS = -g -lz |
4 | | -PROG = pngds |
5 | | -SRCS = pngreader.c pngcmd.c pngresize.c pngutil.c |
| 4 | +SRCS = pngreader.c pngcmd.c pngresize.c pngutil.c pngwriter.c |
6 | 5 | OBJS = $(SRCS:.c=.o) |
7 | 6 | |
8 | | -all: pngreader pngresize |
| 7 | +all: pngds |
9 | 8 | |
10 | 9 | pngreader: |
11 | 10 | $(CC) $(CFLAGS) $(SRCS) -o pngreader -DPNGREADER |
12 | 11 | pngresize: |
13 | 12 | $(CC) $(CFLAGS) $(SRCS) -o pngresize -DPNGRESIZE |
| 13 | +pngds: |
| 14 | + $(CC) $(CFLAGS) $(SRCS) -o pngds -DPNGDS |
14 | 15 | |
15 | 16 | clean: |
16 | | - rm -rf pngreader pngresize |
| 17 | + rm -rf pngreader pngresize pngds |
Index: trunk/pngds/pngreader.h |
— | — | @@ -97,6 +97,6 @@ |
98 | 98 | * Functions |
99 | 99 | */ |
100 | 100 | void png_read(FILE* fin, FILE* fout, pngcallbacks* callbacks, void* extra1); |
101 | | -void png_write_scanline(unsigned char *scanline, unsigned char *previous_scanline, u_int32_t length, void *info_); |
| 101 | +void png_write_scanline_raw(unsigned char *scanline, unsigned char *previous_scanline, u_int32_t length, void *info_); |
102 | 102 | |
103 | 103 | #endif |