1 {
2 Vampyre Imaging Library
3 by Marek Mauder
4 http://imaginglib.sourceforge.net
6 The contents of this file are used with permission, subject to the Mozilla
7 Public License Version 1.1 (the "License"); you may not use this file except
8 in compliance with the License. You may obtain a copy of the License at
9 http://www.mozilla.org/MPL/MPL-1.1.html
11 Software distributed under the License is distributed on an "AS IS" basis,
12 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
13 the specific language governing rights and limitations under the License.
15 Alternatively, the contents of this file may be used under the terms of the
16 GNU Lesser General Public License (the "LGPL License"), in which case the
17 provisions of the LGPL License are applicable instead of those above.
18 If you wish to allow use of your version of this file only under the terms
19 of the LGPL License and not to allow others to use your version of this file
20 under the MPL, indicate your decision by deleting the provisions above and
21 replace them with the notice and other provisions required by the LGPL
22 License. If you do not delete the provisions above, a recipient may use
23 your version of this file under either the MPL or the LGPL License.
25 For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html
26 }
28 { This unit contains image format loader/saver for Jpeg images.}
31 {$I ImagingOptions.inc}
33 { You can choose which Pascal JpegLib implementation will be used.
34 IMJPEGLIB is version bundled with Imaging which works with all supported
35 compilers and platforms.
36 PASJPEG is original JpegLib translation or version modified for FPC
37 (and shipped with it). You can use PASJPEG if this version is already
38 linked with another part of your program and you don't want to have
39 two quite large almost the same libraries linked to your exe.
40 This is the case with Lazarus applications for example.}
42 {$DEFINE IMJPEGLIB}
43 { $DEFINE PASJPEG}
45 { Automatically use FPC's PasJpeg when compiling with Lazarus. But not when
46 WINDOWS is defined. See http://galfar.vevb.net/imaging/smf/index.php/topic,90.0.html.
47 Fixed in FPC revision 13963: http://bugs.freepascal.org/view.php?id=14928 }
48 {$IF Defined(LCL) and not Defined(WINDOWS)}
49 {$UNDEF IMJPEGLIB}
50 {$DEFINE PASJPEG}
51 {$IFEND}
53 { We usually want to skip the rest of the corrupted file when loading JEPG files
54 instead of getting exception. JpegLib's error handler can only be
55 exited using setjmp/longjmp ("non-local goto") functions to get error
56 recovery when loading corrupted JPEG files. This is implemented in assembler
57 and currently available only for 32bit Delphi targets and FPC.}
58 {$DEFINE ErrorJmpRecovery}
59 {$IF Defined(DCC) and not Defined(CPUX86)}
60 {$UNDEF ErrorJmpRecovery}
61 {$IFEND}
63 interface
65 uses
67 {$IF Defined(IMJPEGLIB)}
70 {$ELSEIF Defined(PASJPEG)}
73 {$IFEND}
74 ImagingUtility;
76 {$IF Defined(FPC) and Defined(PASJPEG)}
77 { When using FPC's pasjpeg in FPC the channel order is BGR instead of RGB}
78 {$DEFINE RGBSWAPPED}
79 {$IFEND}
81 type
82 { Class for loading/saving Jpeg images. Supports load/save of
83 8 bit grayscale and 24 bit RGB images. Jpegs can be saved with optional
84 progressive encoding.
85 Based on IJG's JpegLib so doesn't support alpha channels and lossless
86 coding.}
88 private
90 protected
101 public
104 published
105 { Controls Jpeg save compression quality. It is number in range 1..100.
106 1 means small/ugly file, 100 means large/nice file. Accessible trough
107 ImagingJpegQuality option.}
109 { If True Jpeg images are saved in progressive format. Accessible trough
110 ImagingJpegProgressive option.}
114 implementation
116 const
123 const
124 { Jpeg file identifiers.}
128 resourcestring
131 type
154 var
158 { Intenal unit jpeglib support functions }
160 {$IFDEF ErrorJmpRecovery}
161 {$IFDEF DCC}
162 type
164 EBX,
165 ESI,
166 EDI,
167 ESP,
168 EBP,
173 { JmpLib SetJmp/LongJmp Library
174 (C)Copyright 2003, 2004 Will DeWitt Jr. <edge@boink.net> }
176 asm
177 { -> EAX jmpb }
178 { <- EAX Result }
180 // Save task state
189 @@1:
190 end;
193 asm
194 { -> EAX jmpb }
195 { EDX retval }
196 { <- EAX Result }
200 // Restore task state
211 @@1:
212 end;
213 {$ENDIF}
215 type
222 {$ENDIF}
227 var
229 begin
230 // Create the message and raise exception
232 // Warning: you can get "Invalid argument index in format" exception when
233 // using FPC (see http://bugs.freepascal.org/view.php?id=21229).
234 // Fixed in FPC 2.7.1
235 {$IF Defined(FPC) and (FPC_FULLVERSION <= 20701)}
237 {$ELSE}
239 {$IFEND}
242 begin
243 {$IFDEF ErrorJmpRecovery}
244 // Only recovers on loads and when header is sucessfully loaded
245 // (error occurs when reading scanlines)
248 begin
249 // Non-local jump to error handler in TJpegFileFormat.LoadData
251 end
252 else
253 RaiseError;
254 {$ELSE}
255 RaiseError;
256 {$ENDIF}
260 begin
264 begin
266 Exit;
274 begin
279 var
282 begin
287 begin
299 var
301 begin
304 begin
306 begin
311 //Inc(LongInt(Src.Pub.next_input_byte), num_bytes);
317 var
319 begin
321 // Move stream position back just after EOI marker so that more that one
322 // JPEG images can be loaded from one stream
327 TImagingHandle);
328 var
330 begin
332 begin
351 var
353 begin
360 var
362 begin
371 var
374 begin
382 TImagingHandle);
383 var
385 begin
399 begin
400 // Set standard error handlers and then override some
407 begin
415 begin
423 begin
428 else
436 { TJpegFileFormat class implementation }
439 begin
453 begin
454 // Check if option values are valid
461 var
469 {$IFDEF ErrorJmpRecovery}
471 {$ENDIF}
474 var
477 begin
478 // Density unit: 0 - undef, 1 - inch, 2 - cm
481 begin
491 begin
492 // Copy IO functions to global var used in JpegLib callbacks
498 try
501 {$IFDEF ErrorJmpRecovery}
505 begin
507 Exit;
509 {$ENDIF}
516 else
517 Exit;
527 // If Jpeg's colorspace is RGB and not YCbCr we need to swap
528 // R and B to get Imaging's native order
530 {$IFDEF RGBSWAPPED}
531 // Force R-B swap for FPC's PasJpeg
533 {$ENDIF}
535 {$IFDEF ErrorJmpRecovery}
537 {$ENDIF}
540 begin
543 begin
546 begin
555 begin
557 // Translate from CMYK to RGB
559 begin
567 // Store supported metadata
568 LoadMetaData;
573 finally
580 var
587 {$IFDEF RGBSWAPPED}
590 {$ENDIF}
593 var
595 begin
597 begin
604 begin
606 // Copy IO functions to global var used in JpegLib callbacks
609 // Makes image to save compatible with Jpeg saving capabilities
612 try
622 begin
625 end
626 else
627 begin
635 {$IFDEF RGBSWAPPED}
637 {$ENDIF}
639 // Save supported metadata
640 SaveMetaData;
644 begin
645 {$IFDEF RGBSWAPPED}
647 begin
651 begin
656 {$ELSE}
658 {$ENDIF}
666 finally
670 {$IFDEF RGBSWAPPED}
672 {$ENDIF}
678 begin
681 else
686 var
689 begin
693 begin
703 begin
707 initialization
710 {
711 File Notes:
713 -- TODOS ----------------------------------------------------
714 - nothing now
716 -- 0.77.1 ---------------------------------------------------
717 - Able to read corrupted JPEG files - loads partial image
718 and skips the corrupted parts (FPC and x86 Delphi).
719 - Fixed reading of physical resolution metadata, could cause
720 "divided by zero" later on for some files.
722 -- 0.26.5 Changes/Bug Fixes ---------------------------------
723 - Fixed loading of some JPEGs with certain APPN markers (bug in JpegLib).
724 - Fixed swapped Red-Blue order when loading Jpegs with
725 jc.d.jpeg_color_space = JCS_RGB.
726 - Added loading and saving of physical pixel size metadata.
728 -- 0.26.3 Changes/Bug Fixes ---------------------------------
729 - Changed the Jpeg error manager, messages were not properly formated.
731 -- 0.26.1 Changes/Bug Fixes ---------------------------------
732 - Fixed wrong color space setting in InitCompressor.
733 - Fixed problem with progressive Jpegs in FPC (modified JpegLib,
734 can't use FPC's PasJpeg in Windows).
736 -- 0.25.0 Changes/Bug Fixes ---------------------------------
737 - FPC's PasJpeg wasn't really used in last version, fixed.
739 -- 0.24.1 Changes/Bug Fixes ---------------------------------
740 - Fixed loading of CMYK jpeg images. Could cause heap corruption
741 and loaded image looked wrong.
743 -- 0.23 Changes/Bug Fixes -----------------------------------
744 - Removed JFIF/EXIF detection from TestFormat. Found JPEGs
745 with different headers (Lavc) which weren't recognized.
747 -- 0.21 Changes/Bug Fixes -----------------------------------
748 - MakeCompatible method moved to base class, put ConvertToSupported here.
749 GetSupportedFormats removed, it is now set in constructor.
750 - Made public properties for options registered to SetOption/GetOption
751 functions.
752 - Changed extensions to filename masks.
753 - Changed SaveData, LoadData, and MakeCompatible methods according
754 to changes in base class in Imaging unit.
755 - Changes in TestFormat, now reads JFIF and EXIF signatures too.
757 -- 0.19 Changes/Bug Fixes -----------------------------------
758 - input position is now set correctly to the end of the image
759 after loading is done. Loading of sequence of JPEG files stored in
760 single stream works now
761 - when loading and saving images in FPC with PASJPEG read and
762 blue channels are swapped to have the same chanel order as IMJPEGLIB
763 - you can now choose between IMJPEGLIB and PASJPEG implementations
765 -- 0.17 Changes/Bug Fixes -----------------------------------
766 - added SetJpegIO method which is used by JNG image format
767 }