source: titan/minidlna-1.0.22/image_utils.c @ 13567

Last change on this file since 13567 was 13567, checked in by obi, 11 years ago

[titan] add minidlna-1.0.22 first step

File size: 19.5 KB
Line 
1/* MiniDLNA media server
2 * Copyright (C) 2009  Justin Maggard
3 *
4 * This file is part of MiniDLNA.
5 *
6 * MiniDLNA is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * MiniDLNA is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with MiniDLNA. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/* These functions are mostly based on code from other projects.
20 * There are function to effiently resize a JPEG image, and some utility functions.
21 * They are here to allow loading and saving JPEG data directly to or from memory with libjpeg.
22 * The standard functions only allow you to read from or write to a file.
23 *
24 * The reading code comes from the JpgAlleg library, at http://wiki.allegro.cc/index.php?title=Libjpeg
25 * The writing code was posted on a Google group from openjpeg, at http://groups.google.com/group/openjpeg/browse_thread/thread/331e6cf60f70797f
26 * The resize functions come from the resize_image project, at http://www.golac.fr/Image-Resizer
27 */
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <unistd.h>
33#include <sys/types.h>
34#include <setjmp.h>
35#include <jpeglib.h>
36#include <endian.h>
37
38#include "upnpreplyparse.h"
39#include "image_utils.h"
40#include "log.h"
41
42#if __BYTE_ORDER == __LITTLE_ENDIAN
43# define SWAP16(w) ( (((w) >> 8) & 0x00ff) | (((w) << 8) & 0xff00) )
44#else
45# define SWAP16(w) (w)
46#endif
47
48#define JPEG_QUALITY  96
49
50#define COL(red, green, blue) (((red) << 24) | ((green) << 16) | ((blue) << 8) | 0xFF)
51#define COL_FULL(red, green, blue, alpha) (((red) << 24) | ((green) << 16) | ((blue) << 8) | (alpha))
52#define COL_RED(col)   (col >> 24)
53#define COL_GREEN(col) ((col >> 16) & 0xFF)
54#define COL_BLUE(col)  ((col >> 8) & 0xFF)
55#define COL_ALPHA(col) (col & 0xFF)
56#define BLACK  0x000000FF
57
58
59struct my_dst_mgr {
60        struct jpeg_destination_mgr jdst;
61        JOCTET *buf;
62        JOCTET *off;
63        size_t sz;
64        size_t used;
65};
66
67/* Destination manager to store data in a buffer */
68static void
69my_dst_mgr_init(j_compress_ptr cinfo)
70{
71        struct my_dst_mgr *dst = (void *)cinfo->dest;
72
73        dst->used = 0;
74        dst->sz = cinfo->image_width
75                  * cinfo->image_height
76                  * cinfo->input_components;
77        dst->buf = malloc(dst->sz * sizeof *dst->buf);
78        dst->off = dst->buf;
79        dst->jdst.next_output_byte = dst->off;
80        dst->jdst.free_in_buffer = dst->sz;
81
82        return;
83
84}
85
86static boolean
87my_dst_mgr_empty(j_compress_ptr cinfo)
88{
89        struct my_dst_mgr *dst = (void *)cinfo->dest;
90
91        dst->sz *= 2;
92        dst->used = dst->off - dst->buf;
93        dst->buf = realloc(dst->buf, dst->sz * sizeof *dst->buf);
94        dst->off = dst->buf + dst->used;
95        dst->jdst.next_output_byte = dst->off;
96        dst->jdst.free_in_buffer = dst->sz - dst->used;
97
98        return TRUE;
99
100}
101
102static void
103my_dst_mgr_term(j_compress_ptr cinfo)
104{
105        struct my_dst_mgr *dst = (void *)cinfo->dest;
106
107        dst->used += dst->sz - dst->jdst.free_in_buffer;
108        dst->off = dst->buf + dst->used;
109
110        return;
111
112}
113
114static void
115jpeg_memory_dest(j_compress_ptr cinfo, struct my_dst_mgr *dst)
116{
117        dst->jdst.init_destination = my_dst_mgr_init;
118        dst->jdst.empty_output_buffer = my_dst_mgr_empty;
119        dst->jdst.term_destination = my_dst_mgr_term;
120        cinfo->dest = (void *)dst;
121
122        return;
123
124}
125
126/* Source manager to read data from a buffer */
127struct
128my_src_mgr
129{
130        struct jpeg_source_mgr pub;
131        JOCTET eoi_buffer[2];
132};
133
134static void
135init_source(j_decompress_ptr cinfo)
136{
137        return;
138}
139
140static int
141fill_input_buffer(j_decompress_ptr cinfo)
142{
143        struct my_src_mgr *src = (void *)cinfo->src;
144
145        /* Create a fake EOI marker */
146        src->eoi_buffer[0] = (JOCTET) 0xFF;
147        src->eoi_buffer[1] = (JOCTET) JPEG_EOI;
148        src->pub.next_input_byte = src->eoi_buffer;
149        src->pub.bytes_in_buffer = 2;
150
151        return TRUE;
152}
153
154static void
155skip_input_data(j_decompress_ptr cinfo, long num_bytes)
156{
157        struct my_src_mgr *src = (void *)cinfo->src;
158        if (num_bytes > 0)
159        {
160                while (num_bytes > (long)src->pub.bytes_in_buffer)
161                {
162                        num_bytes -= (long)src->pub.bytes_in_buffer;
163                        fill_input_buffer(cinfo);
164                }
165        }
166        src->pub.next_input_byte += num_bytes;
167        src->pub.bytes_in_buffer -= num_bytes;
168}
169
170static void
171term_source(j_decompress_ptr cinfo)
172{
173        return;
174}
175
176void
177jpeg_memory_src(j_decompress_ptr cinfo, const unsigned char * buffer, size_t bufsize)
178{
179        struct my_src_mgr *src;
180
181        if (! cinfo->src)
182        {
183                cinfo->src = (*cinfo->mem->alloc_small)((void *)cinfo, JPOOL_PERMANENT, sizeof(struct my_src_mgr));;
184        }
185        src = (void *)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        src->pub.next_input_byte = buffer;
192        src->pub.bytes_in_buffer = bufsize;
193}
194
195jmp_buf setjmp_buffer;
196/* Don't exit on error like libjpeg likes to do */
197static void
198libjpeg_error_handler(j_common_ptr cinfo)
199{
200        cinfo->err->output_message(cinfo);
201        longjmp(setjmp_buffer, 1);
202        return;
203}
204
205void
206image_free(image_s *pimage)
207{
208        free(pimage->buf);
209        free(pimage);
210}
211
212pix
213get_pix(image_s *pimage, int32_t x, int32_t y)
214{
215        if((x >= 0) && (y >= 0) && (x < pimage->width) && (y < pimage->height))
216        {
217                return(pimage->buf[(y * pimage->width) + x]);
218        }
219        else
220        {
221                pix vpix = BLACK;
222                return(vpix);
223        }
224}
225
226void
227put_pix_alpha_replace(image_s *pimage, int32_t x, int32_t y, pix col)
228{
229        if((x >= 0) && (y >= 0) && (x < pimage->width) && (y < pimage->height))
230                pimage->buf[(y * pimage->width) + x] = col;
231}
232
233int
234image_get_jpeg_resolution(const char * path, int * width, int * height)
235{
236        FILE *img;
237        unsigned char buf[8];
238        u_int16_t offset, h, w;
239        int ret = 1;
240        long size;
241       
242
243        img = fopen(path, "r");
244        if( !img )
245                return(-1);
246
247        fseek(img, 0, SEEK_END);
248        size = ftell(img);
249        rewind(img);
250
251        fread(&buf, 2, 1, img);
252        if( (buf[0] != 0xFF) || (buf[1] != 0xD8) )
253        {
254                fclose(img);
255                return(-1);
256        }
257        memset(&buf, 0, sizeof(buf));
258
259        while( ftell(img) < size )
260        {
261                while( buf[0] != 0xFF && !feof(img) )
262                        fread(&buf, 1, 1, img);
263
264                while( buf[0] == 0xFF && !feof(img) )
265                        fread(&buf, 1, 1, img);
266
267                if( (buf[0] >= 0xc0) && (buf[0] <= 0xc3) )
268                {
269                        fread(&buf, 7, 1, img);
270                        *width = 0;
271                        *height = 0;
272                        memcpy(&h, buf+3, 2);
273                        *height = SWAP16(h);
274                        memcpy(&w, buf+5, 2);
275                        *width = SWAP16(w);
276                        ret = 0;
277                        break;
278                }
279                else
280                {
281                        offset = 0;
282                        fread(&buf, 2, 1, img);
283                        memcpy(&offset, buf, 2);
284                        offset = SWAP16(offset) - 2;
285                        if( fseek(img, offset, SEEK_CUR) == -1 )
286                                break;
287                }
288        }
289        fclose(img);
290        return ret;
291}
292
293int
294image_get_jpeg_date_xmp(const char * path, char ** date)
295{
296        FILE *img;
297        unsigned char buf[8];
298        char *data = NULL, *newdata;
299        u_int16_t offset;
300        struct NameValueParserData xml;
301        char * exif;
302        int ret = 1;
303
304        img = fopen(path, "r");
305        if( !img )
306                return(-1);
307
308        fread(&buf, 2, 1, img);
309        if( (buf[0] != 0xFF) || (buf[1] != 0xD8) )
310        {
311                fclose(img);
312                return(-1);
313        }
314        memset(&buf, 0, sizeof(buf));
315
316        while( !feof(img) )
317        {
318                while( buf[0] != 0xFF && !feof(img) )
319                        fread(&buf, 1, 1, img);
320
321                while( buf[0] == 0xFF && !feof(img) )
322                        fread(&buf, 1, 1, img);
323
324                if( feof(img) )
325                        break;
326
327                if( buf[0] == 0xE1 ) // APP1 marker
328                {
329                        offset = 0;
330                        fread(&buf, 2, 1, img);
331                        memcpy(&offset, buf, 2);
332                        offset = SWAP16(offset) - 2;
333
334                        if( offset < 30 )
335                        {
336                                fseek(img, offset, SEEK_CUR);
337                                continue;
338                        }
339
340                        newdata = realloc(data, 30);
341                        if( !newdata )
342                                break;
343                        data = newdata;
344
345                        fread(data, 29, 1, img);
346                        offset -= 29;
347                        if( strcmp(data, "http://ns.adobe.com/xap/1.0/") != 0 )
348                        {
349                                fseek(img, offset, SEEK_CUR);
350                                continue;
351                        }
352
353                        newdata = realloc(data, offset+1);
354                        if( !newdata )
355                                break;
356                        data = newdata;
357                        fread(data, offset, 1, img);
358
359                        ParseNameValue(data, offset, &xml);
360                        exif = GetValueFromNameValueList(&xml, "DateTimeOriginal");
361                        if( !exif )
362                        {
363                                ClearNameValueList(&xml);
364                                break;
365                        }
366                        *date = realloc(*date, strlen(exif)+1);
367                        strcpy(*date, exif);
368                        ClearNameValueList(&xml);
369
370                        ret = 0;
371                        break;
372                }
373                else
374                {
375                        offset = 0;
376                        fread(&buf, 2, 1, img);
377                        memcpy(&offset, buf, 2);
378                        offset = SWAP16(offset) - 2;
379                        fseek(img, offset, SEEK_CUR);
380                }
381        }
382        fclose(img);
383        if( data )
384                free(data);
385        return ret;
386}
387
388image_s *
389image_new(int32_t width, int32_t height)
390{
391        image_s *vimage;
392
393        if((vimage = (image_s *)malloc(sizeof(image_s))) == NULL)
394        {
395                DPRINTF(E_WARN, L_METADATA, "malloc failed\n");
396                return NULL;
397        }
398        vimage->width = width; vimage->height = height;
399
400        if((vimage->buf = (pix *)malloc(width * height * sizeof(pix))) == NULL)
401        {
402                DPRINTF(E_WARN, L_METADATA, "malloc failed\n");
403                free(vimage);
404                return NULL;
405        }
406        return(vimage);
407}
408
409image_s *
410image_new_from_jpeg(const char * path, int is_file, const char * buf, int size, int scale)
411{
412        image_s *vimage;
413        FILE  *file = NULL;
414        struct jpeg_decompress_struct cinfo;
415        unsigned char *line[16], *ptr;
416        int x, y, i, w, h, ofs;
417        int maxbuf;
418        struct jpeg_error_mgr pub;
419
420
421        cinfo.err = jpeg_std_error(&pub);
422        pub.error_exit = libjpeg_error_handler;
423        jpeg_create_decompress(&cinfo);
424        if( is_file )
425        {
426                if( (file = fopen(path, "r")) == NULL )
427                {
428                        return NULL;
429                }
430                jpeg_stdio_src(&cinfo, file);
431        }
432        else
433        {
434                jpeg_memory_src(&cinfo, (const unsigned char *)buf, size);
435        }
436        if( setjmp(setjmp_buffer) )
437        {
438                jpeg_destroy_decompress(&cinfo);
439                if( is_file && file )
440                        fclose(file);
441                return NULL;
442        }
443        jpeg_read_header(&cinfo, TRUE);
444        cinfo.scale_denom = scale;
445        cinfo.do_fancy_upsampling = FALSE;
446        cinfo.do_block_smoothing = FALSE;
447        jpeg_start_decompress(&cinfo);
448        w = cinfo.output_width;
449        h = cinfo.output_height;
450        vimage = image_new(w, h);
451        if(!vimage)
452        {
453                jpeg_destroy_decompress(&cinfo);
454                if( is_file )
455                        fclose(file);
456                return NULL;
457        }
458
459        if( setjmp(setjmp_buffer) )
460        {
461                jpeg_destroy_decompress(&cinfo);
462                if( is_file && file )
463                        fclose(file);
464                if( vimage )
465                {
466                        if( vimage->buf )
467                                free(vimage->buf);
468                        free(vimage);
469                }
470                return NULL;
471        }
472
473        if(cinfo.rec_outbuf_height > 16)
474        {
475                DPRINTF(E_WARN, L_METADATA, "ERROR image_from_jpeg : (image_from_jpeg.c) JPEG uses line buffers > 16. Cannot load.\n");
476                image_free(vimage);
477                if( is_file )
478                        fclose(file);
479                return NULL;
480        }
481        maxbuf = vimage->width * vimage->height;
482        if(cinfo.output_components == 3)
483        {
484                ofs = 0;
485                if((ptr = (unsigned char *)malloc(w * 3 * cinfo.rec_outbuf_height + 16)) == NULL)
486                {
487                        DPRINTF(E_WARN, L_METADATA, "malloc failed\n");
488                        image_free(vimage);
489                        if( is_file )
490                                fclose(file);
491                        return NULL;
492                }
493
494                for(y = 0; y < h; y += cinfo.rec_outbuf_height)
495                {
496                        for(i = 0; i < cinfo.rec_outbuf_height; i++)
497                        {
498                                line[i] = ptr + (w * 3 * i);
499                        }
500                        jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
501                        for(x = 0; x < w * cinfo.rec_outbuf_height; x++)
502                        {
503                                if( ofs < maxbuf )
504                                {
505                                        vimage->buf[ofs] = COL(ptr[x + x + x], ptr[x + x + x + 1], ptr[x + x + x + 2]);
506                                        ofs++;
507                                }
508                        }
509                }
510                free(ptr);
511        }
512        else if(cinfo.output_components == 1)
513        {
514                ofs = 0;
515                for(i = 0; i < cinfo.rec_outbuf_height; i++)
516                {
517                        if((line[i] = (unsigned char *)malloc(w)) == NULL)
518                        {
519                                int t = 0;
520
521                                for(t = 0; t < i; t++) free(line[t]);
522                                jpeg_destroy_decompress(&cinfo);
523                                image_free(vimage);
524                                if( is_file )
525                                        fclose(file);
526                                return NULL;
527                        }
528                }
529                for(y = 0; y < h; y += cinfo.rec_outbuf_height)
530                {
531                        jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
532                        for(i = 0; i < cinfo.rec_outbuf_height; i++)
533                        {
534                                for(x = 0; x < w; x++)
535                                {
536                                        vimage->buf[ofs++] = COL(line[i][x], line[i][x], line[i][x]);
537                                }
538                        }
539                }
540                for(i = 0; i < cinfo.rec_outbuf_height; i++)
541                {
542                         free(line[i]);
543                }
544        }
545        jpeg_finish_decompress(&cinfo);
546        jpeg_destroy_decompress(&cinfo);
547        if( is_file )
548                fclose(file);
549
550        return vimage;
551}
552
553void
554image_upsize(image_s * pdest, image_s * psrc, int32_t width, int32_t height)
555{
556        int32_t vx, vy;
557#if !defined __i386__ && !defined __x86_64__
558        int32_t rx, ry;
559        pix vcol;
560
561        if((pdest == NULL) || (psrc == NULL))
562                return;
563
564        for(vy = 0; vy < height; vy++)
565        {
566                for(vx = 0; vx < width; vx++)
567                {
568                        rx = ((vx * psrc->width) / width);
569                        ry = ((vy * psrc->height) / height);
570                        vcol = get_pix(psrc, rx, ry);
571#else
572        pix   vcol,vcol1,vcol2,vcol3,vcol4;
573        float rx,ry;
574        float width_scale, height_scale;
575        float x_dist, y_dist;
576
577        width_scale  = (float)psrc->width  / (float)width;
578        height_scale = (float)psrc->height / (float)height;
579
580        for(vy = 0;vy < height; vy++)
581        {
582                for(vx = 0;vx < width; vx++)
583                {
584                        rx = vx * width_scale;
585                        ry = vy * height_scale;
586                        vcol1 = get_pix(psrc, (int32_t)rx, (int32_t)ry);
587                        vcol2 = get_pix(psrc, ((int32_t)rx)+1, (int32_t)ry);
588                        vcol3 = get_pix(psrc, (int32_t)rx, ((int32_t)ry)+1);
589                        vcol4 = get_pix(psrc, ((int32_t)rx)+1, ((int32_t)ry)+1);
590
591                        x_dist = rx - ((float)((int32_t)rx));
592                        y_dist = ry - ((float)((int32_t)ry));
593                        vcol = COL_FULL( (u_int8_t)((COL_RED(vcol1)*(1.0-x_dist)
594                                          + COL_RED(vcol2)*(x_dist))*(1.0-y_dist)
595                                          + (COL_RED(vcol3)*(1.0-x_dist)
596                                          + COL_RED(vcol4)*(x_dist))*(y_dist)),
597                                         (u_int8_t)((COL_GREEN(vcol1)*(1.0-x_dist)
598                                          + COL_GREEN(vcol2)*(x_dist))*(1.0-y_dist)
599                                          + (COL_GREEN(vcol3)*(1.0-x_dist)
600                                          + COL_GREEN(vcol4)*(x_dist))*(y_dist)),
601                                         (u_int8_t)((COL_BLUE(vcol1)*(1.0-x_dist)
602                                          + COL_BLUE(vcol2)*(x_dist))*(1.0-y_dist)
603                                          + (COL_BLUE(vcol3)*(1.0-x_dist)
604                                          + COL_BLUE(vcol4)*(x_dist))*(y_dist)),
605                                         (u_int8_t)((COL_ALPHA(vcol1)*(1.0-x_dist)
606                                          + COL_ALPHA(vcol2)*(x_dist))*(1.0-y_dist)
607                                          + (COL_ALPHA(vcol3)*(1.0-x_dist)
608                                          + COL_ALPHA(vcol4)*(x_dist))*(y_dist))
609                                       );
610#endif
611                        put_pix_alpha_replace(pdest, vx, vy, vcol);
612                }
613        }
614}
615
616void
617image_downsize(image_s * pdest, image_s * psrc, int32_t width, int32_t height)
618{
619        int32_t vx, vy;
620        pix vcol;
621        int32_t i, j;
622#if !defined __i386__ && !defined __x86_64__
623        int32_t rx, ry, rx_next, ry_next;
624        int red, green, blue, alpha;
625        int factor;
626
627        if((pdest == NULL) || (psrc == NULL))
628                return;
629
630        for(vy = 0; vy < height; vy++)
631        {
632                for(vx = 0; vx < width; vx++)
633                {
634
635                        rx = ((vx * psrc->width) / width);
636                        ry = ((vy * psrc->height) / height);
637
638                        red = green = blue = alpha = 0;
639
640                        rx_next = rx + (psrc->width / width);
641                        ry_next = ry + (psrc->width / width);
642                        factor = 0;
643
644                        for( j = rx; j < rx_next; j++)
645                        {
646                                for( i = ry; i < ry_next; i++)
647                                {
648                                        factor += 1;
649                                        vcol = get_pix(psrc, j, i);
650
651                                        red   += COL_RED(vcol);
652                                        green += COL_GREEN(vcol);
653                                        blue  += COL_BLUE(vcol);
654                                        alpha += COL_ALPHA(vcol);
655                                }
656                        }
657
658                        red   /= factor;
659                        green /= factor;
660                        blue  /= factor;
661                        alpha /= factor;
662
663                        /* on sature les valeurs */
664                        red   = (red   > 255) ? 255 : ((red   < 0) ? 0 : red  );
665                        green = (green > 255) ? 255 : ((green < 0) ? 0 : green);
666                        blue  = (blue  > 255) ? 255 : ((blue  < 0) ? 0 : blue );
667                        alpha = (alpha > 255) ? 255 : ((alpha < 0) ? 0 : alpha);
668#else
669        float rx,ry;
670        float width_scale, height_scale;
671        float red, green, blue, alpha;
672        int32_t half_square_width, half_square_height;
673        float round_width, round_height;
674
675        if( (pdest == NULL) || (psrc == NULL) )
676                return;
677
678        width_scale  = (float)psrc->width  / (float)width;
679        height_scale = (float)psrc->height / (float)height;
680
681        half_square_width  = (int32_t)(width_scale  / 2.0);
682        half_square_height = (int32_t)(height_scale / 2.0);
683        round_width  = (width_scale  / 2.0) - (float)half_square_width;
684        round_height = (height_scale / 2.0) - (float)half_square_height;
685        if(round_width  > 0.0)
686                half_square_width++;
687        else
688                round_width = 1.0;
689        if(round_height > 0.0)
690                half_square_height++;
691        else
692                round_height = 1.0;
693
694        for(vy = 0;vy < height; vy++) 
695        {
696                for(vx = 0;vx < width; vx++)
697                {
698                        rx = vx * width_scale;
699                        ry = vy * height_scale;
700                        vcol = get_pix(psrc, (int32_t)rx, (int32_t)ry);
701
702                        red = green = blue = alpha = 0.0;
703
704                        for(j=0;j<half_square_height<<1;j++)
705                        {
706                                for(i=0;i<half_square_width<<1;i++)
707                                {
708                                        vcol = get_pix(psrc, ((int32_t)rx)-half_square_width+i,
709                                                             ((int32_t)ry)-half_square_height+j);
710         
711                                        if(((j == 0) || (j == (half_square_height<<1)-1)) &&
712                                           ((i == 0) || (i == (half_square_width<<1)-1)))
713                                        {
714                                                red   += round_width*round_height*(float)COL_RED  (vcol);
715                                                green += round_width*round_height*(float)COL_GREEN(vcol);
716                                                blue  += round_width*round_height*(float)COL_BLUE (vcol);
717                                                alpha += round_width*round_height*(float)COL_ALPHA(vcol);
718                                        }
719                                        else if((j == 0) || (j == (half_square_height<<1)-1))
720                                        {
721                                                red   += round_height*(float)COL_RED  (vcol);
722                                                green += round_height*(float)COL_GREEN(vcol);
723                                                blue  += round_height*(float)COL_BLUE (vcol);
724                                                alpha += round_height*(float)COL_ALPHA(vcol);
725                                        }
726                                        else if((i == 0) || (i == (half_square_width<<1)-1))
727                                        {
728                                                red   += round_width*(float)COL_RED  (vcol);
729                                                green += round_width*(float)COL_GREEN(vcol);
730                                                blue  += round_width*(float)COL_BLUE (vcol);
731                                                alpha += round_width*(float)COL_ALPHA(vcol);
732                                        }
733                                        else
734                                        {
735                                                red   += (float)COL_RED  (vcol);
736                                                green += (float)COL_GREEN(vcol);
737                                                blue  += (float)COL_BLUE (vcol);
738                                                alpha += (float)COL_ALPHA(vcol);
739                                        }
740                                }
741                        }
742     
743                        red   /= width_scale*height_scale;
744                        green /= width_scale*height_scale;
745                        blue  /= width_scale*height_scale;
746                        alpha /= width_scale*height_scale;
747     
748                        /* on sature les valeurs */
749                        red   = (red   > 255.0)? 255.0 : ((red   < 0.0)? 0.0:red  );
750                        green = (green > 255.0)? 255.0 : ((green < 0.0)? 0.0:green);
751                        blue  = (blue  > 255.0)? 255.0 : ((blue  < 0.0)? 0.0:blue );
752                        alpha = (alpha > 255.0)? 255.0 : ((alpha < 0.0)? 0.0:alpha);
753#endif
754                        put_pix_alpha_replace(pdest, vx, vy,
755                                              COL_FULL((u_int8_t)red, (u_int8_t)green, (u_int8_t)blue, (u_int8_t)alpha));
756                }
757        }
758}
759
760image_s *
761image_resize(image_s * src_image, int32_t width, int32_t height)
762{
763        image_s * dst_image;
764
765        dst_image = image_new(width, height);
766        if( !dst_image )
767                return NULL;
768        if( (src_image->width < width) || (src_image->height < height) )
769                image_upsize(dst_image, src_image, width, height);
770        else
771                image_downsize(dst_image, src_image, width, height);
772
773        return dst_image;
774}
775
776
777unsigned char *
778image_save_to_jpeg_buf(image_s * pimage, int * size)
779{
780        struct jpeg_compress_struct cinfo;
781        struct jpeg_error_mgr jerr;
782        JSAMPROW row_pointer[1];
783        int row_stride;
784        char *data;
785        int i, x;
786        struct my_dst_mgr dst;
787
788        cinfo.err = jpeg_std_error(&jerr);
789        jpeg_create_compress(&cinfo);
790        jpeg_memory_dest(&cinfo, &dst);
791        cinfo.image_width = pimage->width;
792        cinfo.image_height = pimage->height;
793        cinfo.input_components = 3;
794        cinfo.in_color_space = JCS_RGB;
795        jpeg_set_defaults(&cinfo);
796        jpeg_set_quality(&cinfo, JPEG_QUALITY, TRUE);
797        jpeg_start_compress(&cinfo, TRUE);
798        row_stride = cinfo.image_width * 3;
799        if((data = malloc(row_stride)) == NULL)
800        {
801                DPRINTF(E_WARN, L_METADATA, "malloc failed\n");
802                return NULL;
803        }
804        i = 0;
805        while(cinfo.next_scanline < cinfo.image_height)
806        {
807                for(x = 0; x < pimage->width; x++)
808                {
809                        data[x + x + x]   = COL_RED(pimage->buf[i]);
810                        data[x + x + x + 1] = COL_GREEN(pimage->buf[i]);
811                        data[x + x + x + 2] = COL_BLUE(pimage->buf[i]);
812                        i++;
813                }
814                row_pointer[0] = (unsigned char *)data;
815                jpeg_write_scanlines(&cinfo, row_pointer, 1);
816        }
817        jpeg_finish_compress(&cinfo);
818        *size = dst.used;
819        free(data);
820        jpeg_destroy_compress(&cinfo);
821
822        return dst.buf;
823}
824
825int
826image_save_to_jpeg_file(image_s * pimage, const char * path)
827{
828        int nwritten, size = 0;
829        unsigned char * buf;
830        FILE * dst_file;
831
832        buf = image_save_to_jpeg_buf(pimage, &size);
833        if( !buf )
834                return -1;
835        dst_file = fopen(path, "w");
836        if( !dst_file )
837        {
838                free(buf);
839                return -1;
840        }
841        nwritten = fwrite(buf, 1, size, dst_file);
842        fclose(dst_file);
843        free(buf);
844
845        return (nwritten==size ? 0 : 1);
846}
Note: See TracBrowser for help on using the repository browser.