2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program 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.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
19 * Parts of this code taken from Guido Vollbeding <http://sylvana.net/jpegcrop/exif_orientation.html>
23 #include "lib/libexif/libexif.h"
24 #include "windowing/WindowingFactory.h"
25 #include "settings/AdvancedSettings.h"
26 #include "filesystem/File.h"
27 #include "utils/log.h"
30 #include "utils/StringUtils.h"
33 #define EXIF_TAG_ORIENTATION 0x0112
37 struct jpeg_error_mgr pub; // "public" fields
38 jmp_buf setjmp_buffer; // for return to caller
41 #if JPEG_LIB_VERSION < 80
43 /*Versions of libjpeg prior to 8.0 did not have a pre-made mechanism for
44 decoding directly from memory. Here we backport the functions from v8.
45 When using v8 or higher, the built-in functions are used instead.
46 Original formatting left intact for the most part for easy comparison. */
48 static void x_init_mem_source (j_decompress_ptr cinfo)
50 /* no work necessary here */
53 void x_term_source (j_decompress_ptr cinfo)
55 /* no work necessary here */
58 static boolean x_fill_mem_input_buffer (j_decompress_ptr cinfo)
60 static JOCTET mybuffer[4];
62 /* The whole JPEG data is expected to reside in the supplied memory
63 * buffer, so any request for more data beyond the given buffer size
64 * is treated as an error.
66 /* Insert a fake EOI marker */
67 mybuffer[0] = (JOCTET) 0xFF;
68 mybuffer[1] = (JOCTET) JPEG_EOI;
70 cinfo->src->next_input_byte = mybuffer;
71 cinfo->src->bytes_in_buffer = 2;
76 static void x_skip_input_data (j_decompress_ptr cinfo, long num_bytes)
78 struct jpeg_source_mgr * src = cinfo->src;
80 /* Just a dumb implementation for now. Could use fseek() except
81 * it doesn't work on pipes. Not clear that being smart is worth
82 * any trouble anyway --- large skips are infrequent.
85 while (num_bytes > (long) src->bytes_in_buffer) {
86 num_bytes -= (long) src->bytes_in_buffer;
87 (void) (*src->fill_input_buffer) (cinfo);
88 /* note we assume that fill_input_buffer will never return FALSE,
89 * so suspension need not be handled.
92 src->next_input_byte += (size_t) num_bytes;
93 src->bytes_in_buffer -= (size_t) num_bytes;
97 static void x_mem_src (j_decompress_ptr cinfo, unsigned char * inbuffer, unsigned long insize)
99 struct jpeg_source_mgr * src;
101 if (inbuffer == NULL || insize == 0) /* Treat empty input as fatal error */
103 (cinfo)->err->msg_code = 0;
104 (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo));
107 /* The source object is made permanent so that a series of JPEG images
108 * can be read from the same buffer by calling jpeg_mem_src only before
111 if (cinfo->src == NULL) { /* first time for this JPEG object? */
112 cinfo->src = (struct jpeg_source_mgr *)
113 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
114 sizeof(struct jpeg_source_mgr));
118 src->init_source = x_init_mem_source;
119 src->fill_input_buffer = x_fill_mem_input_buffer;
120 src->skip_input_data = x_skip_input_data;
121 src->resync_to_restart = jpeg_resync_to_restart; /* use default method */
122 src->term_source = x_term_source;
123 src->bytes_in_buffer = (size_t) insize;
124 src->next_input_byte = (JOCTET *) inbuffer;
127 #define OUTPUT_BUF_SIZE 4096
129 struct jpeg_destination_mgr pub; /* public fields */
131 unsigned char ** outbuffer; /* target buffer */
132 unsigned long * outsize;
133 unsigned char * newbuffer; /* newly allocated buffer */
134 JOCTET * buffer; /* start of buffer */
136 } x_mem_destination_mgr;
138 typedef x_mem_destination_mgr * x_mem_dest_ptr;
140 static void x_init_mem_destination (j_compress_ptr cinfo)
142 /* no work necessary here */
145 static boolean x_empty_mem_output_buffer (j_compress_ptr cinfo)
149 x_mem_dest_ptr dest = (x_mem_dest_ptr) cinfo->dest;
151 /* Try to allocate new buffer with double size */
152 nextsize = dest->bufsize * 2;
153 nextbuffer = (JOCTET*) malloc(nextsize);
155 if (nextbuffer == NULL)
157 (cinfo)->err->msg_code = 0;
158 (cinfo)->err->msg_parm.i[0] = 10;
159 (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo));
162 memcpy(nextbuffer, dest->buffer, dest->bufsize);
164 if (dest->newbuffer != NULL)
165 free(dest->newbuffer);
167 dest->newbuffer = nextbuffer;
169 dest->pub.next_output_byte = nextbuffer + dest->bufsize;
170 dest->pub.free_in_buffer = dest->bufsize;
172 dest->buffer = nextbuffer;
173 dest->bufsize = nextsize;
178 static void x_term_mem_destination (j_compress_ptr cinfo)
180 x_mem_dest_ptr dest = (x_mem_dest_ptr) cinfo->dest;
182 *dest->outbuffer = dest->buffer;
183 *dest->outsize = dest->bufsize - dest->pub.free_in_buffer;
186 static void x_jpeg_mem_dest (j_compress_ptr cinfo,
187 unsigned char ** outbuffer, unsigned long * outsize)
191 if (outbuffer == NULL || outsize == NULL) /* sanity check */
193 (cinfo)->err->msg_code = 0;
194 (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo));
197 /* The destination object is made permanent so that multiple JPEG images
198 * can be written to the same buffer without re-executing jpeg_mem_dest.
200 if (cinfo->dest == NULL) { /* first time for this JPEG object? */
201 cinfo->dest = (struct jpeg_destination_mgr *)
202 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
203 sizeof(x_mem_destination_mgr));
206 dest = (x_mem_dest_ptr) cinfo->dest;
207 dest->pub.init_destination = x_init_mem_destination;
208 dest->pub.empty_output_buffer = x_empty_mem_output_buffer;
209 dest->pub.term_destination = x_term_mem_destination;
210 dest->outbuffer = outbuffer;
211 dest->outsize = outsize;
212 dest->newbuffer = NULL;
214 if (*outbuffer == NULL || *outsize == 0) {
215 /* Allocate initial buffer */
216 dest->newbuffer = *outbuffer = (unsigned char*)malloc(OUTPUT_BUF_SIZE);
217 if (dest->newbuffer == NULL)
219 (cinfo)->err->msg_code = 0;
220 (cinfo)->err->msg_parm.i[0] = 10;
221 (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo));
223 *outsize = OUTPUT_BUF_SIZE;
226 dest->pub.next_output_byte = dest->buffer = *outbuffer;
227 dest->pub.free_in_buffer = dest->bufsize = *outsize;
239 memset(&m_cinfo, 0, sizeof(m_cinfo));
240 m_thumbnailbuffer = NULL;
248 void CJpegIO::Close()
253 ReleaseThumbnailBuffer();
256 bool CJpegIO::Open(const CStdString &texturePath, unsigned int minx, unsigned int miny, bool read)
260 m_texturePath = texturePath;
263 if (file.Open(m_texturePath.c_str(), READ_TRUNCATED))
266 GetLength() will typically return values that fall into three cases:
267 1. The real filesize. This is the typical case.
268 2. Zero. This is the case for some http:// streams for example.
269 3. Some value smaller than the real filesize. This is the case for an expanding file.
271 In order to handle all three cases, we read the file in chunks, relying on Read()
272 returning 0 at EOF. To minimize (re)allocation of the buffer, the chunksize in
273 cases 1 and 3 is set to one byte larger** than the value returned by GetLength().
274 The chunksize in case 2 is set to the larger of 64k and GetChunkSize().
276 We fill the buffer entirely before reallocation. Thus, reallocation never occurs in case 1
277 as the buffer is larger than the file, so we hit EOF before we hit the end of buffer.
279 To minimize reallocation, we double the chunksize each time up to a maxchunksize of 2MB.
281 unsigned int filesize = (unsigned int)file.GetLength();
282 unsigned int chunksize = filesize ? (filesize + 1) : std::max(65536U, (unsigned int)file.GetChunkSize());
283 unsigned int maxchunksize = 2048*1024U; /* max 2MB chunksize */
285 unsigned int total_read = 0, free_space = 0;
290 m_inputBuffSize += chunksize;
291 unsigned char* new_buf = (unsigned char *)realloc(m_inputBuff, m_inputBuffSize);
294 CLog::Log(LOGERROR, "%s unable to allocate buffer of size %u", __FUNCTION__, m_inputBuffSize);
299 m_inputBuff = new_buf;
301 free_space = chunksize;
302 chunksize = std::min(chunksize*2, maxchunksize);
304 unsigned int read = file.Read(m_inputBuff + total_read, free_space);
310 m_inputBuffSize = total_read;
313 if (m_inputBuffSize == 0)
322 if (Read(m_inputBuff, m_inputBuffSize, minx, miny))
327 bool CJpegIO::Read(unsigned char* buffer, unsigned int bufSize, unsigned int minx, unsigned int miny)
329 struct my_error_mgr jerr;
330 m_cinfo.err = jpeg_std_error(&jerr.pub);
331 jerr.pub.error_exit = jpeg_error_exit;
333 if (buffer == NULL || !bufSize )
336 jpeg_create_decompress(&m_cinfo);
337 #if JPEG_LIB_VERSION < 80
338 x_mem_src(&m_cinfo, buffer, bufSize);
340 jpeg_mem_src(&m_cinfo, buffer, bufSize);
343 if (setjmp(jerr.setjmp_buffer))
345 jpeg_destroy_decompress(&m_cinfo);
350 jpeg_save_markers (&m_cinfo, JPEG_APP0 + 1, 0xFFFF);
351 jpeg_read_header(&m_cinfo, true);
353 /* libjpeg can scale the image for us if it is too big. It must be in the format
354 num/denom, where (for our purposes) that is [1-8]/8 where 8/8 is the unscaled image.
355 The only way to know how big a resulting image will be is to try a ratio and
356 test its resulting size.
357 If the res is greater than the one desired, use that one since there's no need
358 to decode a bigger one just to squish it back down. If the res is greater than
359 the gpu can hold, use the previous one.*/
360 if (minx == 0 || miny == 0)
362 miny = g_advancedSettings.m_imageRes;
363 if (g_advancedSettings.m_fanartRes > g_advancedSettings.m_imageRes)
364 { // a separate fanart resolution is specified - check if the image is exactly equal to this res
365 if (m_cinfo.image_width == (unsigned int)g_advancedSettings.m_fanartRes * 16/9 &&
366 m_cinfo.image_height == (unsigned int)g_advancedSettings.m_fanartRes)
367 { // special case for fanart res
368 miny = g_advancedSettings.m_fanartRes;
374 m_cinfo.scale_denom = 8;
375 m_cinfo.out_color_space = JCS_RGB;
376 unsigned int maxtexsize = g_Windowing.GetMaxTextureSize();
377 for (unsigned int scale = 1; scale <= 8; scale++)
379 m_cinfo.scale_num = scale;
380 jpeg_calc_output_dimensions(&m_cinfo);
381 if ((m_cinfo.output_width > maxtexsize) || (m_cinfo.output_height > maxtexsize))
386 if (m_cinfo.output_width >= minx && m_cinfo.output_height >= miny)
389 jpeg_calc_output_dimensions(&m_cinfo);
390 m_width = m_cinfo.output_width;
391 m_height = m_cinfo.output_height;
393 if (m_cinfo.marker_list)
394 m_orientation = GetExifOrientation(m_cinfo.marker_list->data, m_cinfo.marker_list->data_length);
399 bool CJpegIO::Decode(const unsigned char *pixels, unsigned int pitch, unsigned int format)
401 unsigned char *dst = (unsigned char*)pixels;
403 struct my_error_mgr jerr;
404 m_cinfo.err = jpeg_std_error(&jerr.pub);
405 jerr.pub.error_exit = jpeg_error_exit;
407 if (setjmp(jerr.setjmp_buffer))
409 jpeg_destroy_decompress(&m_cinfo);
414 jpeg_start_decompress(&m_cinfo);
416 if (format == XB_FMT_RGB8)
418 while (m_cinfo.output_scanline < m_height)
420 jpeg_read_scanlines(&m_cinfo, &dst, 1);
424 else if (format == XB_FMT_A8R8G8B8)
426 unsigned char* row = new unsigned char[m_width * 3];
427 while (m_cinfo.output_scanline < m_height)
429 jpeg_read_scanlines(&m_cinfo, &row, 1);
430 unsigned char *src2 = row;
431 unsigned char *dst2 = dst;
432 for (unsigned int x = 0; x < m_width; x++, src2 += 3)
445 CLog::Log(LOGWARNING, "JpegIO: Incorrect output format specified");
446 jpeg_destroy_decompress(&m_cinfo);
449 jpeg_finish_decompress(&m_cinfo);
451 jpeg_destroy_decompress(&m_cinfo);
455 bool CJpegIO::CreateThumbnail(const CStdString& sourceFile, const CStdString& destFile, int minx, int miny, bool rotateExif)
457 //Copy sourceFile to buffer, pass to CreateThumbnailFromMemory for decode+re-encode
458 if (!Open(sourceFile, minx, miny, false))
461 return CreateThumbnailFromMemory(m_inputBuff, m_inputBuffSize, destFile, minx, miny);
464 bool CJpegIO::CreateThumbnailFromMemory(unsigned char* buffer, unsigned int bufSize, const CStdString& destFile, unsigned int minx, unsigned int miny)
466 //Decode a jpeg residing in buffer, pass to CreateThumbnailFromSurface for re-encode
467 unsigned int pitch = 0;
468 unsigned char *sourceBuf = NULL;
470 if (!Read(buffer, bufSize, minx, miny))
473 sourceBuf = new unsigned char [Height() * pitch];
475 if (!Decode(sourceBuf,pitch,XB_FMT_RGB8))
480 if (!CreateThumbnailFromSurface(sourceBuf, Width(), Height() , XB_FMT_RGB8, pitch, destFile))
489 bool CJpegIO::CreateThumbnailFromSurface(unsigned char* buffer, unsigned int width, unsigned int height, unsigned int format, unsigned int pitch, const CStdString& destFile)
491 //Encode raw data from buffer, save to destFile
492 struct jpeg_compress_struct cinfo;
493 struct my_error_mgr jerr;
494 JSAMPROW row_pointer[1];
495 long unsigned int outBufSize = width * height;
496 unsigned char* result;
497 unsigned char* src = buffer;
498 unsigned char* rgbbuf;
502 CLog::Log(LOGERROR, "JpegIO::CreateThumbnailFromSurface no buffer");
506 result = (unsigned char*) malloc(outBufSize); //Initial buffer. Grows as-needed.
509 CLog::Log(LOGERROR, "JpegIO::CreateThumbnailFromSurface error allocating memory for image buffer");
513 if(format == XB_FMT_RGB8)
517 else if(format == XB_FMT_A8R8G8B8)
519 // create a copy for bgra -> rgb.
520 rgbbuf = new unsigned char [(width * height * 3)];
521 unsigned char* dst = rgbbuf;
522 for (unsigned int y = 0; y < height; y++)
524 unsigned char* dst2 = dst;
525 unsigned char* src2 = src;
526 for (unsigned int x = 0; x < width; x++, src2 += 4)
538 CLog::Log(LOGWARNING, "JpegIO::CreateThumbnailFromSurface Unsupported format");
543 cinfo.err = jpeg_std_error(&jerr.pub);
544 jerr.pub.error_exit = jpeg_error_exit;
545 jpeg_create_compress(&cinfo);
547 if (setjmp(jerr.setjmp_buffer))
549 jpeg_destroy_compress(&cinfo);
551 if(format != XB_FMT_RGB8)
557 #if JPEG_LIB_VERSION < 80
558 x_jpeg_mem_dest(&cinfo, &result, &outBufSize);
560 jpeg_mem_dest(&cinfo, &result, &outBufSize);
562 cinfo.image_width = width;
563 cinfo.image_height = height;
564 cinfo.input_components = 3;
565 cinfo.in_color_space = JCS_RGB;
566 jpeg_set_defaults(&cinfo);
567 jpeg_set_quality(&cinfo, 90, TRUE);
568 jpeg_start_compress(&cinfo, TRUE);
570 while (cinfo.next_scanline < cinfo.image_height)
572 row_pointer[0] = &rgbbuf[cinfo.next_scanline * width * 3];
573 jpeg_write_scanlines(&cinfo, row_pointer, 1);
576 jpeg_finish_compress(&cinfo);
577 jpeg_destroy_compress(&cinfo);
579 if(format != XB_FMT_RGB8)
583 if (file.OpenForWrite(destFile, true))
585 file.Write(result, outBufSize);
594 // override libjpeg's error function to avoid an exit() call
595 void CJpegIO::jpeg_error_exit(j_common_ptr cinfo)
597 CStdString msg = StringUtils::Format("Error %i: %s",cinfo->err->msg_code, cinfo->err->jpeg_message_table[cinfo->err->msg_code]);
598 CLog::Log(LOGWARNING, "JpegIO: %s", msg.c_str());
600 my_error_mgr *myerr = (my_error_mgr*)cinfo->err;
601 longjmp(myerr->setjmp_buffer, 1);
604 unsigned int CJpegIO::GetExifOrientation(unsigned char* exif_data, unsigned int exif_data_size)
606 unsigned int offset = 0;
607 unsigned int numberOfTags = 0;
608 unsigned int tagNumber = 0;
609 bool isMotorola = false;
610 unsigned const char ExifHeader[] = "Exif\0\0";
611 unsigned int orientation = 0;
613 // read exif head, check for "Exif"
614 // next we want to read to current offset + length
615 // check if buffer is big enough
616 if (exif_data_size && memcmp(exif_data, ExifHeader, 6) == 0)
626 // Discover byte order
627 if (exif_data[0] == 'I' && exif_data[1] == 'I')
629 else if (exif_data[0] == 'M' && exif_data[1] == 'M')
637 if (exif_data[2] != 0 || exif_data[3] != 0x2A)
642 if (exif_data[3] != 0 || exif_data[2] != 0x2A)
646 // Get first IFD offset (offset to IFD0)
649 if (exif_data[4] != 0 || exif_data[5] != 0)
651 offset = exif_data[6];
653 offset += exif_data[7];
657 if (exif_data[7] != 0 || exif_data[6] != 0)
659 offset = exif_data[5];
661 offset += exif_data[4];
664 if (offset > exif_data_size - 2)
665 return 0; // check end of data segment
667 // Get the number of directory entries contained in this IFD
670 numberOfTags = exif_data[offset];
672 numberOfTags += exif_data[offset+1];
676 numberOfTags = exif_data[offset+1];
678 numberOfTags += exif_data[offset];
681 if (numberOfTags == 0)
685 // Search for Orientation Tag in IFD0 - hey almost there! :D
686 while(1)//hopefully this jpeg has correct exif data...
688 if (offset > exif_data_size - 12)
689 return 0; // check end of data segment
694 tagNumber = exif_data[offset];
696 tagNumber += exif_data[offset+1];
700 tagNumber = exif_data[offset+1];
702 tagNumber += exif_data[offset];
705 if (tagNumber == EXIF_TAG_ORIENTATION)
706 break; //found orientation tag
708 if ( --numberOfTags == 0)
709 return 0;//no orientation found
710 offset += 12;//jump to next tag
713 // Get the Orientation value
716 if (exif_data[offset+8] != 0)
718 orientation = exif_data[offset+9];
722 if (exif_data[offset+9] != 0)
724 orientation = exif_data[offset+8];
729 return orientation;//done
732 bool CJpegIO::LoadImageFromMemory(unsigned char* buffer, unsigned int bufSize, unsigned int width, unsigned int height)
734 return Read(buffer, bufSize, width, height);
737 bool CJpegIO::CreateThumbnailFromSurface(unsigned char* bufferin, unsigned int width, unsigned int height, unsigned int format, unsigned int pitch, const CStdString& destFile,
738 unsigned char* &bufferout, unsigned int &bufferoutSize)
740 //Encode raw data from buffer, save to destbuffer
741 struct jpeg_compress_struct cinfo;
742 struct my_error_mgr jerr;
743 JSAMPROW row_pointer[1];
744 long unsigned int outBufSize = width * height;
745 unsigned char* src = bufferin;
746 unsigned char* rgbbuf;
750 CLog::Log(LOGERROR, "JpegIO::CreateThumbnailFromSurface no buffer");
754 m_thumbnailbuffer = (unsigned char*) malloc(outBufSize); //Initial buffer. Grows as-needed.
755 if (m_thumbnailbuffer == NULL)
757 CLog::Log(LOGERROR, "JpegIO::CreateThumbnailFromSurface error allocating memory for image buffer");
761 if(format == XB_FMT_RGB8)
765 else if(format == XB_FMT_A8R8G8B8)
767 // create a copy for bgra -> rgb.
768 rgbbuf = new unsigned char [(width * height * 3)];
769 unsigned char* dst = rgbbuf;
770 for (unsigned int y = 0; y < height; y++)
773 unsigned char* dst2 = dst;
774 unsigned char* src2 = src;
775 for (unsigned int x = 0; x < width; x++, src2 += 4)
787 CLog::Log(LOGWARNING, "JpegIO::CreateThumbnailFromSurface Unsupported format");
788 free(m_thumbnailbuffer);
792 cinfo.err = jpeg_std_error(&jerr.pub);
793 jerr.pub.error_exit = jpeg_error_exit;
794 jpeg_create_compress(&cinfo);
796 if (setjmp(jerr.setjmp_buffer))
798 jpeg_destroy_compress(&cinfo);
799 free(m_thumbnailbuffer);
800 if(format != XB_FMT_RGB8)
806 #if JPEG_LIB_VERSION < 80
807 x_jpeg_mem_dest(&cinfo, &m_thumbnailbuffer, &outBufSize);
809 jpeg_mem_dest(&cinfo, &m_thumbnailbuffer, &outBufSize);
811 cinfo.image_width = width;
812 cinfo.image_height = height;
813 cinfo.input_components = 3;
814 cinfo.in_color_space = JCS_RGB;
815 jpeg_set_defaults(&cinfo);
816 jpeg_set_quality(&cinfo, 90, TRUE);
817 jpeg_start_compress(&cinfo, TRUE);
819 while (cinfo.next_scanline < cinfo.image_height)
821 row_pointer[0] = &rgbbuf[cinfo.next_scanline * width * 3];
822 jpeg_write_scanlines(&cinfo, row_pointer, 1);
825 jpeg_finish_compress(&cinfo);
826 jpeg_destroy_compress(&cinfo);
828 if(format != XB_FMT_RGB8)
831 bufferout = m_thumbnailbuffer;
832 bufferoutSize = outBufSize;
837 void CJpegIO::ReleaseThumbnailBuffer()
839 if(m_thumbnailbuffer != NULL)
841 free(m_thumbnailbuffer);
842 m_thumbnailbuffer = NULL;