style cleanup: follow style guide for formatting of if/for/while loops, and else...
[blender.git] / source / blender / imbuf / intern / jpeg.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/imbuf/intern/jpeg.c
29  *  \ingroup imbuf
30  */
31
32
33
34 /* This little block needed for linking to Blender... */
35 #include <stdio.h>
36 #include <setjmp.h>
37
38 #include "MEM_guardedalloc.h"
39
40 #include "BLI_blenlib.h"
41
42 #include "imbuf.h"
43 #include "IMB_imbuf_types.h"
44 #include "IMB_imbuf.h"
45 #include "IMB_metadata.h"
46 #include "IMB_filetype.h"
47 #include "jpeglib.h" 
48 #include "jerror.h"
49
50 #define IS_jpg(x)               (x->ftype & JPG)
51 #define IS_stdjpg(x)    ((x->ftype & JPG_MSK) == JPG_STD)
52 #define IS_vidjpg(x)    ((x->ftype & JPG_MSK) == JPG_VID)
53 #define IS_jstjpg(x)    ((x->ftype & JPG_MSK) == JPG_JST)
54 #define IS_maxjpg(x)    ((x->ftype & JPG_MSK) == JPG_MAX)
55
56 /* the types are from the jpeg lib */
57 static void jpeg_error (j_common_ptr cinfo);
58 static void init_source(j_decompress_ptr cinfo);
59 static boolean fill_input_buffer(j_decompress_ptr cinfo);
60 static void skip_input_data(j_decompress_ptr cinfo, long num_bytes);
61 static void term_source(j_decompress_ptr cinfo);
62 static void memory_source(j_decompress_ptr cinfo, unsigned char *buffer, size_t size);
63 static boolean handle_app1 (j_decompress_ptr cinfo);
64 static ImBuf * ibJpegImageFromCinfo(struct jpeg_decompress_struct * cinfo, int flags);
65
66
67 /*
68  * In principle there are 4 jpeg formats.
69  *
70  * 1. jpeg - standard printing, u & v at quarter of resulution
71  * 2. jvid - standaard video, u & v half resolution, frame not interlaced
72  *
73  * type 3 is unsupported as of jul 05 2000 Frank.
74  *
75  * 3. jstr - as 2, but written in 2 separate fields
76  *
77  * 4. jmax - no scaling in the components
78  */
79
80 static int jpeg_default_quality;
81 static int ibuf_ftype;
82
83 int imb_is_a_jpeg(unsigned char *mem)
84 {
85         if ((mem[0]== 0xFF) && (mem[1] == 0xD8))return 1;
86         return 0;
87 }
88
89 //----------------------------------------------------------
90 //      JPG ERROR HANDLING
91 //----------------------------------------------------------
92
93 typedef struct my_error_mgr {
94         struct jpeg_error_mgr pub;      /* "public" fields */
95
96         jmp_buf setjmp_buffer;  /* for return to caller */
97 } my_error_mgr;
98
99 typedef my_error_mgr * my_error_ptr;
100
101 static void jpeg_error (j_common_ptr cinfo)
102 {
103         my_error_ptr err = (my_error_ptr)cinfo->err;
104
105         /* Always display the message */
106         (*cinfo->err->output_message) (cinfo);
107
108         /* Let the memory manager delete any temp files before we die */
109         jpeg_destroy(cinfo);
110
111         /* return control to the setjmp point */
112         longjmp(err->setjmp_buffer, 1);
113 }
114
115 //----------------------------------------------------------
116 //      INPUT HANDLER FROM MEMORY
117 //----------------------------------------------------------
118
119 typedef struct {
120         unsigned char   *buffer;
121         int             filled;
122 } buffer_struct;
123
124 typedef struct {
125         struct jpeg_source_mgr pub;     /* public fields */
126
127         unsigned char   *buffer;
128         int                             size;
129         JOCTET                  terminal[2];
130 } my_source_mgr;
131
132 typedef my_source_mgr * my_src_ptr;
133
134 static void init_source(j_decompress_ptr cinfo)
135 {
136         (void)cinfo; /* unused */
137 }
138
139
140 static boolean fill_input_buffer(j_decompress_ptr cinfo)
141 {
142         my_src_ptr src = (my_src_ptr) cinfo->src;
143
144         /* Since we have given all we have got already
145          * we simply fake an end of file
146          */
147
148         src->pub.next_input_byte = src->terminal;
149         src->pub.bytes_in_buffer = 2;
150         src->terminal[0] = (JOCTET) 0xFF;
151         src->terminal[1] = (JOCTET) JPEG_EOI;
152
153         return TRUE;
154 }
155
156
157 static void skip_input_data(j_decompress_ptr cinfo, long num_bytes)
158 {
159         my_src_ptr src = (my_src_ptr) cinfo->src;
160
161         if (num_bytes > 0) {
162                 // prevent skipping over file end
163                 size_t skip_size = (size_t)num_bytes <= src->pub.bytes_in_buffer ? num_bytes : src->pub.bytes_in_buffer;
164
165                 src->pub.next_input_byte = src->pub.next_input_byte + skip_size;
166                 src->pub.bytes_in_buffer = src->pub.bytes_in_buffer - skip_size;
167         }
168 }
169
170
171 static void term_source(j_decompress_ptr cinfo)
172 {
173         (void)cinfo; /* unused */
174 }
175
176 static void memory_source(j_decompress_ptr cinfo, unsigned char *buffer, size_t size)
177 {
178         my_src_ptr src;
179
180         if (cinfo->src == NULL) { /* first time for this JPEG object? */
181                 cinfo->src = (struct jpeg_source_mgr *)(*cinfo->mem->alloc_small)
182                         ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(my_source_mgr));
183         }
184
185         src = (my_src_ptr) cinfo->src;
186         src->pub.init_source            = init_source;
187         src->pub.fill_input_buffer      = fill_input_buffer;
188         src->pub.skip_input_data        = skip_input_data;
189         src->pub.resync_to_restart      = jpeg_resync_to_restart;
190         src->pub.term_source            = term_source;
191
192         src->pub.bytes_in_buffer        = size;
193         src->pub.next_input_byte        = buffer;
194
195         src->buffer = buffer;
196         src->size = size;
197 }
198
199
200 #define MAKESTMT(stuff)         do { stuff } while (0)
201
202 #define INPUT_VARS(cinfo)  \
203         struct jpeg_source_mgr * datasrc = (cinfo)->src;  \
204         const JOCTET * next_input_byte = datasrc->next_input_byte;  \
205         size_t bytes_in_buffer = datasrc->bytes_in_buffer
206
207 /* Unload the local copies --- do this only at a restart boundary */
208 #define INPUT_SYNC(cinfo)  \
209         ( datasrc->next_input_byte = next_input_byte,  \
210           datasrc->bytes_in_buffer = bytes_in_buffer )
211
212 /* Reload the local copies --- seldom used except in MAKE_BYTE_AVAIL */
213 #define INPUT_RELOAD(cinfo)  \
214         ( next_input_byte = datasrc->next_input_byte,  \
215           bytes_in_buffer = datasrc->bytes_in_buffer )
216
217 /* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available.
218  * Note we do *not* do INPUT_SYNC before calling fill_input_buffer,
219  * but we must reload the local copies after a successful fill.
220  */
221 #define MAKE_BYTE_AVAIL(cinfo, action)                                        \
222         if (bytes_in_buffer == 0) {                                               \
223                 if (! (*datasrc->fill_input_buffer) (cinfo))                          \
224                         { action; }                                                       \
225                 INPUT_RELOAD(cinfo);  \
226         }
227
228
229 /* Read a byte into variable V.
230  * If must suspend, take the specified action (typically "return FALSE").
231  */
232 #define INPUT_BYTE(cinfo,V,action)  \
233         MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \
234                   bytes_in_buffer--; \
235                   V = GETJOCTET(*next_input_byte++); )
236
237 /* As above, but read two bytes interpreted as an unsigned 16-bit integer.
238  * V should be declared unsigned int or perhaps INT32.
239  */
240 #define INPUT_2BYTES(cinfo,V,action)  \
241         MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \
242                   bytes_in_buffer--; \
243                   V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \
244                   MAKE_BYTE_AVAIL(cinfo,action); \
245                   bytes_in_buffer--; \
246                   V += GETJOCTET(*next_input_byte++); )
247
248
249 static boolean
250 handle_app1 (j_decompress_ptr cinfo)
251 {
252         INT32 length; /* initialized by the macro */
253         INT32 i;
254         char neogeo[128];
255         
256         INPUT_VARS(cinfo);
257
258         INPUT_2BYTES(cinfo, length, return FALSE);
259         length -= 2;
260         
261         if (length < 16) {
262                 for (i = 0; i < length; i++) INPUT_BYTE(cinfo, neogeo[i], return FALSE);
263                 length = 0;
264                 if (strncmp(neogeo, "NeoGeo", 6) == 0) memcpy(&ibuf_ftype, neogeo + 6, 4);
265                 ibuf_ftype = BIG_LONG(ibuf_ftype);
266         }
267         INPUT_SYNC(cinfo);              /* do before skip_input_data */
268         if (length > 0) (*cinfo->src->skip_input_data) (cinfo, length);
269         return TRUE;
270 }
271
272
273 static ImBuf * ibJpegImageFromCinfo(struct jpeg_decompress_struct * cinfo, int flags)
274 {
275         JSAMPARRAY row_pointer;
276         JSAMPLE * buffer = NULL;
277         int row_stride;
278         int x, y, depth, r, g, b, k;
279         struct ImBuf * ibuf = NULL;
280         uchar * rect;
281         jpeg_saved_marker_ptr marker;
282         char *str, *key, *value;
283
284         /* install own app1 handler */
285         ibuf_ftype = 0;
286         jpeg_set_marker_processor(cinfo, 0xe1, handle_app1);
287         cinfo->dct_method = JDCT_FLOAT;
288         jpeg_save_markers(cinfo, JPEG_COM, 0xffff);
289
290         if (jpeg_read_header(cinfo, FALSE) == JPEG_HEADER_OK) {
291                 x = cinfo->image_width;
292                 y = cinfo->image_height;
293                 depth = cinfo->num_components;
294
295                 if (cinfo->jpeg_color_space == JCS_YCCK) cinfo->out_color_space = JCS_CMYK;
296
297                 jpeg_start_decompress(cinfo);
298
299                 if (ibuf_ftype == 0) {
300                         ibuf_ftype = JPG_STD;
301                         if (cinfo->max_v_samp_factor == 1) {
302                                 if (cinfo->max_h_samp_factor == 1) ibuf_ftype = JPG_MAX;
303                                 else ibuf_ftype = JPG_VID;
304                         }
305                 }
306
307                 if (flags & IB_test) {
308                         jpeg_abort_decompress(cinfo);
309                         ibuf = IMB_allocImBuf(x, y, 8 * depth, 0);
310                 }
311                 else if ((ibuf = IMB_allocImBuf(x, y, 8 * depth, IB_rect)) == NULL) {
312                         jpeg_abort_decompress(cinfo);
313                 }
314                 else {
315                         row_stride = cinfo->output_width * depth;
316
317                         row_pointer = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, row_stride, 1);
318                         
319                         for (y = ibuf->y - 1; y >= 0; y--) {
320                                 jpeg_read_scanlines(cinfo, row_pointer, 1);
321                                 rect = (uchar *) (ibuf->rect + y * ibuf->x);
322                                 buffer = row_pointer[0];
323                                 
324                                 switch(depth) {
325                                         case 1:
326                                                 for (x=ibuf->x; x >0; x--) {
327                                                         rect[3] = 255;
328                                                         rect[0] = rect[1] = rect[2] = *buffer++;
329                                                         rect += 4;
330                                                 }
331                                                 break;
332                                         case 3:
333                                                 for (x=ibuf->x; x >0; x--) {
334                                                         rect[3] = 255;
335                                                         rect[0] = *buffer++;
336                                                         rect[1] = *buffer++;
337                                                         rect[2] = *buffer++;
338                                                         rect += 4;
339                                                 }
340                                                 break;
341                                         case 4:
342                                                 for (x=ibuf->x; x >0; x--) {
343                                                         r = *buffer++;
344                                                         g = *buffer++;
345                                                         b = *buffer++;
346                                                         k = *buffer++;
347                                                         
348                                                         k = 255 - k;
349                                                         r -= k;
350                                                         if (r & 0xffffff00) {
351                                                                 if (r < 0) r = 0;
352                                                                 else r = 255;
353                                                         }
354                                                         g -= k;
355                                                         if (g & 0xffffff00) {
356                                                                 if (g < 0) g = 0;
357                                                                 else g = 255;
358                                                         }
359                                                         b -= k;
360                                                         if (b & 0xffffff00) {
361                                                                 if (b < 0) b = 0;
362                                                                 else b = 255;
363                                                         }
364                                                         
365                                                         rect[3] = 255 - k;
366                                                         rect[2] = b;
367                                                         rect[1] = g;
368                                                         rect[0] = r;
369                                                         rect += 4;
370                                                 }
371                                 }
372                         }
373
374                         marker= cinfo->marker_list;
375                         while (marker) {
376                                 if (marker->marker != JPEG_COM)
377                                         goto next_stamp_marker;
378
379                                 /*
380                                  * Because JPEG format don't support the
381                                  * pair "key/value" like PNG, we store the
382                                  * stampinfo in a single "encode" string:
383                                  *      "Blender:key:value"
384                                  *
385                                  * That is why we need split it to the
386                                  * common key/value here.
387                                  */
388                                 if (strncmp((char *) marker->data, "Blender", 7)) {
389                                         /*
390                                          * Maybe the file have text that
391                                          * we don't know "what it's", in that
392                                          * case we keep the text (with a
393                                          * key "None").
394                                          * This is only for don't "lose"
395                                          * the information when we write
396                                          * it back to disk.
397                                          */
398                                         IMB_metadata_add_field(ibuf, "None", (char *) marker->data);
399                                         ibuf->flags |= IB_metadata;
400                                         goto next_stamp_marker;
401                                 }
402
403                                 str = BLI_strdup ((char *) marker->data);
404                                 key = strchr (str, ':');
405                                 /*
406                                  * A little paranoid, but the file maybe
407                                  * is broken... and a "extra" check is better
408                                  * then segfault ;)
409                                  */
410                                 if (!key) {
411                                         MEM_freeN(str);
412                                         goto next_stamp_marker;
413                                 }
414
415                                 key++;
416                                 value = strchr (key, ':');
417                                 if (!value) {
418                                         MEM_freeN(str);
419                                         goto next_stamp_marker;
420                                 }
421
422                                 *value = '\0'; /* need finish the key string */
423                                 value++;
424                                 IMB_metadata_add_field(ibuf, key, value);
425                                 ibuf->flags |= IB_metadata;
426                                 MEM_freeN(str);
427 next_stamp_marker:
428                                 marker= marker->next;
429                         }
430
431                         jpeg_finish_decompress(cinfo);
432                 }
433                 
434                 jpeg_destroy((j_common_ptr) cinfo);
435                 if (ibuf) {
436                         ibuf->ftype = ibuf_ftype;
437                         ibuf->profile = IB_PROFILE_SRGB;
438                 }
439         }
440
441         return(ibuf);
442 }
443
444 ImBuf * imb_load_jpeg (unsigned char * buffer, size_t size, int flags)
445 {
446         struct jpeg_decompress_struct _cinfo, *cinfo = &_cinfo;
447         struct my_error_mgr jerr;
448         ImBuf * ibuf;
449
450         if (!imb_is_a_jpeg(buffer)) return NULL;
451         
452         cinfo->err = jpeg_std_error(&jerr.pub);
453         jerr.pub.error_exit = jpeg_error;
454
455         /* Establish the setjmp return context for my_error_exit to use. */
456         if (setjmp(jerr.setjmp_buffer)) {
457                 /* If we get here, the JPEG code has signaled an error.
458                  * We need to clean up the JPEG object, close the input file, and return.
459                  */
460                 jpeg_destroy_decompress(cinfo);
461                 return NULL;
462         }
463
464         jpeg_create_decompress(cinfo);
465         memory_source(cinfo, buffer, size);
466
467         ibuf = ibJpegImageFromCinfo(cinfo, flags);
468         
469         return(ibuf);
470 }
471
472
473 static void write_jpeg(struct jpeg_compress_struct * cinfo, struct ImBuf * ibuf)
474 {
475         JSAMPLE * buffer = NULL;
476         JSAMPROW row_pointer[1];
477         uchar * rect;
478         int x, y;
479         char neogeo[128];
480         ImMetaData *iptr;
481         char *text;
482
483         jpeg_start_compress(cinfo, TRUE);
484
485         strcpy(neogeo, "NeoGeo");
486         ibuf_ftype = BIG_LONG(ibuf->ftype);
487         
488         memcpy(neogeo + 6, &ibuf_ftype, 4);
489         jpeg_write_marker(cinfo, 0xe1, (JOCTET*) neogeo, 10);
490
491         if (ibuf->metadata) {
492                 /* key + max value + "Blender" */
493                 text= MEM_mallocN(530, "stamp info read");
494                 iptr= ibuf->metadata;
495                 while (iptr) {
496                         if (!strcmp (iptr->key, "None")) {
497                                 jpeg_write_marker(cinfo, JPEG_COM, (JOCTET *) iptr->value, strlen (iptr->value) + 1);
498                                 goto next_stamp_info;
499                         }
500
501                         /*
502                          * The JPEG format don't support a pair "key/value"
503                          * like PNG, so we "encode" the stamp in a
504                          * single string:
505                          *      "Blender:key:value"
506                          *
507                          * The first "Blender" is a simple identify to help
508                          * in the read process.
509                          */
510                         sprintf (text, "Blender:%s:%s", iptr->key, iptr->value);
511                         jpeg_write_marker(cinfo, JPEG_COM, (JOCTET *) text, strlen (text)+1);
512 next_stamp_info:
513                         iptr = iptr->next;
514                 }
515                 MEM_freeN(text);
516         }
517
518         row_pointer[0] =
519                 MEM_mallocN(sizeof(JSAMPLE) *
520                                          cinfo->input_components *
521                                          cinfo->image_width, "jpeg row_pointer");
522
523         for (y = ibuf->y - 1; y >= 0; y--) {
524                 rect = (uchar *) (ibuf->rect + y * ibuf->x);
525                 buffer = row_pointer[0];
526
527                 switch(cinfo->in_color_space) {
528                         case JCS_RGB:
529                                 for (x = 0; x < ibuf->x; x++) {
530                                         *buffer++ = rect[0];
531                                         *buffer++ = rect[1];
532                                         *buffer++ = rect[2];
533                                         rect += 4;
534                                 }
535                                 break;
536                         case JCS_GRAYSCALE:
537                                 for (x = 0; x < ibuf->x; x++) {
538                                         *buffer++ = rect[0];
539                                         rect += 4;
540                                 }
541                                 break;
542                         case JCS_UNKNOWN:
543                                 memcpy(buffer, rect, 4 * ibuf->x);
544                                 break;
545                                 /* default was missing... intentional ? */
546                         default:
547                                 ; /* do nothing */
548                 }
549
550                 jpeg_write_scanlines(cinfo, row_pointer, 1);
551         }
552
553         jpeg_finish_compress(cinfo);
554         MEM_freeN(row_pointer[0]);
555 }
556
557
558 static int init_jpeg(FILE * outfile, struct jpeg_compress_struct * cinfo, struct ImBuf *ibuf)
559 {
560         int quality;
561
562         quality = ibuf->ftype & 0xff;
563         if (quality <= 0) quality = jpeg_default_quality;
564         if (quality > 100) quality = 100;
565
566         jpeg_create_compress(cinfo);
567         jpeg_stdio_dest(cinfo, outfile);
568
569         cinfo->image_width = ibuf->x;
570         cinfo->image_height = ibuf->y;
571
572         cinfo->in_color_space = JCS_RGB;
573         if (ibuf->planes == 8) cinfo->in_color_space = JCS_GRAYSCALE;
574 #if 0
575         /* just write RGBA as RGB,
576          * unsupported feature only confuses other s/w */
577
578         if (ibuf->planes == 32) cinfo->in_color_space = JCS_UNKNOWN;
579 #endif
580         switch(cinfo->in_color_space) {
581                 case JCS_RGB:
582                         cinfo->input_components = 3;
583                         break;
584                 case JCS_GRAYSCALE:
585                         cinfo->input_components = 1;
586                         break;
587                 case JCS_UNKNOWN:
588                         cinfo->input_components = 4;
589                         break;
590                         /* default was missing... intentional ? */
591                 default:
592                         ; /* do nothing */
593         }
594         jpeg_set_defaults(cinfo);
595         
596         /* own settings */
597
598         cinfo->dct_method = JDCT_FLOAT;
599         jpeg_set_quality(cinfo, quality, TRUE);
600
601         return(0);
602 }
603
604
605 static int save_stdjpeg(const char *name, struct ImBuf *ibuf)
606 {
607         FILE * outfile;
608         struct jpeg_compress_struct _cinfo, *cinfo = &_cinfo;
609         struct my_error_mgr jerr;
610
611         if ((outfile = BLI_fopen(name, "wb")) == NULL) return 0;
612         jpeg_default_quality = 75;
613
614         cinfo->err = jpeg_std_error(&jerr.pub);
615         jerr.pub.error_exit = jpeg_error;
616
617         /* Establish the setjmp return context for jpeg_error to use. */
618         if (setjmp(jerr.setjmp_buffer)) {
619                 /* If we get here, the JPEG code has signaled an error.
620                  * We need to clean up the JPEG object, close the input file, and return.
621                  */
622                 jpeg_destroy_compress(cinfo);
623                 fclose(outfile);
624                 remove(name);
625                 return 0;
626         }
627
628         init_jpeg(outfile, cinfo, ibuf);
629
630         write_jpeg(cinfo, ibuf);
631
632         fclose(outfile);
633         jpeg_destroy_compress(cinfo);
634
635         return 1;
636 }
637
638
639 static int save_vidjpeg(const char *name, struct ImBuf *ibuf)
640 {
641         FILE * outfile;
642         struct jpeg_compress_struct _cinfo, *cinfo = &_cinfo;
643         struct my_error_mgr jerr;
644
645         if ((outfile = BLI_fopen(name, "wb")) == NULL) return 0;
646         jpeg_default_quality = 90;
647
648         cinfo->err = jpeg_std_error(&jerr.pub);
649         jerr.pub.error_exit = jpeg_error;
650
651         /* Establish the setjmp return context for jpeg_error to use. */
652         if (setjmp(jerr.setjmp_buffer)) {
653                 /* If we get here, the JPEG code has signaled an error.
654                  * We need to clean up the JPEG object, close the input file, and return.
655                  */
656                 jpeg_destroy_compress(cinfo);
657                 fclose(outfile);
658                 remove(name);
659                 return 0;
660         }
661
662         init_jpeg(outfile, cinfo, ibuf);
663
664         /* adjust scaling factors */
665         if (cinfo->in_color_space == JCS_RGB) {
666                 cinfo->comp_info[0].h_samp_factor = 2;
667                 cinfo->comp_info[0].v_samp_factor = 1;
668         }
669
670         write_jpeg(cinfo, ibuf);
671
672         fclose(outfile);
673         jpeg_destroy_compress(cinfo);
674
675         return 1;
676 }
677
678 static int save_jstjpeg(const char *name, struct ImBuf *ibuf)
679 {
680         char fieldname[1024];
681         struct ImBuf * tbuf;
682         int oldy, returnval;
683
684         tbuf = IMB_allocImBuf(ibuf->x, ibuf->y / 2, 24, IB_rect);
685         tbuf->ftype = ibuf->ftype;
686         tbuf->flags = ibuf->flags;
687         
688         oldy = ibuf->y;
689         ibuf->x *= 2;
690         ibuf->y /= 2;
691
692         IMB_rectcpy(tbuf, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y);
693         sprintf(fieldname, "%s.jf0", name);
694
695         returnval = save_vidjpeg(fieldname, tbuf);
696         if (returnval == 1) {
697                 IMB_rectcpy(tbuf, ibuf, 0, 0, tbuf->x, 0, ibuf->x, ibuf->y);
698                 sprintf(fieldname, "%s.jf1", name);
699                 returnval = save_vidjpeg(fieldname, tbuf);
700         }
701
702         ibuf->y = oldy;
703         ibuf->x /= 2;
704         IMB_freeImBuf(tbuf);
705
706         return returnval;
707 }
708
709 static int save_maxjpeg(const char *name, struct ImBuf *ibuf)
710 {
711         FILE * outfile;
712         struct jpeg_compress_struct _cinfo, *cinfo = &_cinfo;
713         struct my_error_mgr jerr;
714
715         if ((outfile = BLI_fopen(name, "wb")) == NULL) return 0;
716         jpeg_default_quality = 100;
717
718         cinfo->err = jpeg_std_error(&jerr.pub);
719         jerr.pub.error_exit = jpeg_error;
720
721         /* Establish the setjmp return context for jpeg_error to use. */
722         if (setjmp(jerr.setjmp_buffer)) {
723                 /* If we get here, the JPEG code has signaled an error.
724                  * We need to clean up the JPEG object, close the input file, and return.
725                  */
726                 jpeg_destroy_compress(cinfo);
727                 fclose(outfile);
728                 remove(name);
729                 return 0;
730         }
731
732         init_jpeg(outfile, cinfo, ibuf);
733
734         /* adjust scaling factors */
735         if (cinfo->in_color_space == JCS_RGB) {
736                 cinfo->comp_info[0].h_samp_factor = 1;
737                 cinfo->comp_info[0].v_samp_factor = 1;
738         }
739
740         write_jpeg(cinfo, ibuf);
741
742         fclose(outfile);
743         jpeg_destroy_compress(cinfo);
744
745         return 1;
746 }
747
748 int imb_savejpeg(struct ImBuf *ibuf, const char *name, int flags)
749 {
750         
751         ibuf->flags = flags;
752         if (IS_stdjpg(ibuf)) return save_stdjpeg(name, ibuf);
753         if (IS_jstjpg(ibuf)) return save_jstjpeg(name, ibuf);
754         if (IS_maxjpg(ibuf)) return save_maxjpeg(name, ibuf);
755         return save_vidjpeg(name, ibuf);
756 }
757