1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stddef.h>
4 #include <unistd.h>
5 #include <errno.h>
6 #include <string.h>
7
8 #include <jpeglib.h>
9 #include "transupp.h" /* Support routines for jpegtran */
10 #include "jpegtools.h"
11
12 #include "misc.h"
13
14 #include "readers.h"
15 #include "filter.h"
16 #include "genthumbnail.h"
17
18 /* ---------------------------------------------------------------------- */
19
20 static struct ida_image*
read_jpeg(char * filename)21 read_jpeg(char *filename)
22 {
23 struct ida_image *img;
24 FILE *fp;
25 unsigned int y;
26 void *data;
27
28 /* open file */
29 if (NULL == (fp = fopen(filename, "r"))) {
30 fprintf(stderr,"open %s: %s\n",filename,strerror(errno));
31 return NULL;
32 }
33
34 /* load image */
35 img = malloc(sizeof(*img));
36 memset(img,0,sizeof(*img));
37 data = jpeg_loader.init(fp,filename,0,&img->i,0);
38 if (NULL == data) {
39 fprintf(stderr,"loading %s [%s] FAILED\n",filename,jpeg_loader.name);
40 free(img);
41 return NULL;
42 }
43 ida_image_alloc(img);
44 for (y = 0; y < img->i.height; y++)
45 jpeg_loader.read(ida_image_scanline(img, y), y, data);
46 jpeg_loader.done(data);
47 return img;
48 }
49
50 /* ---------------------------------------------------------------------- */
51
52 static struct ida_image*
scale_thumbnail(struct ida_image * src,int max)53 scale_thumbnail(struct ida_image *src, int max)
54 {
55 struct op_resize_parm p;
56 struct ida_rect rect;
57 struct ida_image *dest;
58 void *data;
59 unsigned int y;
60 float xs,ys,scale;
61
62 xs = (float)max / src->i.width;
63 ys = (float)max / src->i.height;
64 scale = (xs < ys) ? xs : ys;
65
66 dest = malloc(sizeof(*dest));
67 memset(dest,0,sizeof(*dest));
68 memset(&rect,0,sizeof(rect));
69 memset(&p,0,sizeof(p));
70
71 p.width = src->i.width * scale;
72 p.height = src->i.height * scale;
73 p.dpi = src->i.dpi;
74 if (0 == p.width)
75 p.width = 1;
76 if (0 == p.height)
77 p.height = 1;
78
79 data = desc_resize.init(src,&rect,&dest->i,&p);
80 ida_image_alloc(dest);
81 for (y = 0; y < dest->i.height; y++)
82 desc_resize.work(src, &rect, ida_image_scanline(dest, y), y, data);
83 desc_resize.done(data);
84 return dest;
85 }
86
87 /* ---------------------------------------------------------------------- */
88
89 struct thc {
90 struct jpeg_compress_struct dst;
91 struct jpeg_error_mgr err;
92 unsigned char *out;
93 int osize;
94 };
95
thc_dest_init(struct jpeg_compress_struct * cinfo)96 static void thc_dest_init(struct jpeg_compress_struct *cinfo)
97 {
98 struct thc *h = container_of(cinfo, struct thc, dst);
99 cinfo->dest->next_output_byte = h->out;
100 cinfo->dest->free_in_buffer = h->osize;
101 }
102
thc_dest_flush(struct jpeg_compress_struct * cinfo)103 static boolean thc_dest_flush(struct jpeg_compress_struct *cinfo)
104 {
105 fprintf(stderr,"jpeg: panic: output buffer full\n");
106 exit(1);
107 }
108
thc_dest_term(struct jpeg_compress_struct * cinfo)109 static void thc_dest_term(struct jpeg_compress_struct *cinfo)
110 {
111 struct thc *h = container_of(cinfo, struct thc, dst);
112 h->osize -= cinfo->dest->free_in_buffer;
113 }
114
115 static struct jpeg_destination_mgr thumbnail_dst = {
116 .init_destination = thc_dest_init,
117 .empty_output_buffer = thc_dest_flush,
118 .term_destination = thc_dest_term,
119 };
120
121 static int
compress_thumbnail(struct ida_image * img,char * dest,int max)122 compress_thumbnail(struct ida_image *img, char *dest, int max)
123 {
124 struct thc thc;
125 unsigned int i;
126
127 memset(&thc,0,sizeof(thc));
128 thc.dst.err = jpeg_std_error(&thc.err);
129 jpeg_create_compress(&thc.dst);
130 thc.dst.dest = &thumbnail_dst;
131 thc.out = dest;
132 thc.osize = max;
133
134 thc.dst.image_width = img->i.width;
135 thc.dst.image_height = img->i.height;
136 thc.dst.input_components = 3;
137 thc.dst.in_color_space = JCS_RGB;
138 jpeg_set_defaults(&thc.dst);
139 jpeg_start_compress(&thc.dst, TRUE);
140
141 for (i = 0; i < img->i.height; i++)
142 jpeg_write_scanlines(&thc.dst, (void*)ida_image_scanline(img, i), 1);
143
144 jpeg_finish_compress(&(thc.dst));
145 jpeg_destroy_compress(&(thc.dst));
146
147 return thc.osize;
148 }
149
150 /* ---------------------------------------------------------------------- */
151
create_thumbnail(char * filename,unsigned char * dest,int max)152 int create_thumbnail(char *filename, unsigned char *dest, int max)
153 {
154 struct ida_image *img,*thumb;
155 int size;
156
157 //fprintf(stderr,"%s: read ",filename);
158 img = read_jpeg(filename);
159 if (!img) {
160 fprintf(stderr,"FAILED\n");
161 return -1;
162 }
163
164 //fprintf(stderr,"scale ");
165 thumb = scale_thumbnail(img,160);
166 if (!thumb) {
167 ida_image_free(img);
168 free(img);
169 fprintf(stderr,"FAILED\n");
170 return -1;
171 }
172
173 //fprintf(stderr,"compress ");
174 size = compress_thumbnail(thumb,dest,max);
175
176 /* cleanup */
177 ida_image_free(img);
178 free(img);
179 ida_image_free(thumb);
180 free(thumb);
181 return size;
182 }
183
184 /* ---------------------------------------------------------------------- */
185
186 #if 0
187
188 #define THUMB_MAX 65536
189
190 static int handle_image(char *filename)
191 {
192 char *dest;
193 int size;
194
195 dest = malloc(THUMB_MAX);
196 size = create_thumbnail(filename,dest,THUMB_MAX);
197
198 fprintf(stderr,"transform ");
199 jpeg_transform_inplace(filename, JXFORM_NONE, NULL,
200 dest, size, JFLAG_UPDATE_THUMBNAIL);
201
202 fprintf(stderr,"done\n");
203 return 0;
204 }
205
206 int main(int argc, char *argv[])
207 {
208 int i;
209
210 for (i = 1; i < argc; i++)
211 handle_image(argv[i]);
212 return 0;
213 }
214
215 #endif
216
217