diff --git a/packages/fcl-image/src/fpreadjpeg.pas b/packages/fcl-image/src/fpreadjpeg.pas
index e32cf68db2..847492d7ee 100644
--- a/packages/fcl-image/src/fpreadjpeg.pas
+++ b/packages/fcl-image/src/fpreadjpeg.pas
@@ -79,6 +79,7 @@ type
     FProgressiveEncoding: boolean;
     FError: jpeg_error_mgr;
     FProgressMgr: TFPJPEGProgressManager;
+    FExtensions: jpeg_extensions;
     FInfo: jpeg_decompress_struct;
     FScale: TJPEGScale;
     FPerformance: TJPEGReadPerformance;
@@ -87,6 +88,10 @@ type
     procedure SetPerformance(const AValue: TJPEGReadPerformance);
     procedure SetSmoothing(const AValue: boolean);
   protected
+    function CMYKToRGB(const C, M, Y, K: Byte): TFPColor; virtual;
+    procedure ReadExtAPPn(Marker: int; var Header: array of JOCTET; HeaderLen: uint;
+      var Remaining: INT32; ReadData: jpeg_ext_appn_readdata); virtual;
+
     procedure ReadHeader(Str: TStream; Img: TFPCustomImage); virtual;
     procedure ReadPixels(Str: TStream; Img: TFPCustomImage); virtual;
     procedure InternalRead(Str: TStream; Img: TFPCustomImage); override;
@@ -202,6 +207,14 @@ begin
   // ToDo
 end;
 
+procedure ReadExtAPPnCallback(cinfo : j_decompress_ptr; marker : int; var header : array of JOCTET; headerlen : uint;
+  var remaining : int32; readdata: jpeg_ext_appn_readdata);
+begin
+  if (cinfo=nil) or (cinfo^.client_data=nil) then exit;
+
+  TFPReaderJPEG(cinfo^.client_data).ReadExtAPPn(marker, header, headerlen, remaining, readdata);
+end;
+
 { TFPReaderJPEG }
 
 procedure TFPReaderJPEG.SetSmoothing(const AValue: boolean);
@@ -210,6 +223,11 @@ begin
   FSmoothing:=AValue;
 end;
 
+procedure TFPReaderJPEG.ReadExtAPPn(Marker: int; var Header: array of JOCTET; HeaderLen: uint; var Remaining: INT32; ReadData: jpeg_ext_appn_readdata);
+begin
+  // override to read extended APPn data
+end;
+
 procedure TFPReaderJPEG.SetPerformance(const AValue: TJPEGReadPerformance);
 begin
   if FPerformance=AValue then exit;
@@ -347,21 +365,6 @@ var
     Img.Colors[P.x, P.y] := C;
   end;
 
-  function CorrectCMYK(const C: TFPColor): TFPColor;
-  var
-    MinColor: word;
-  begin
-    // accuracy not 100%
-    if C.red<C.green then MinColor:=C.red
-    else MinColor:= C.green;
-    if C.blue<MinColor then MinColor:= C.blue;
-    if MinColor+ C.alpha>$FF then MinColor:=$FF-C.alpha;
-    Result.red:=(C.red-MinColor) shl 8;
-    Result.green:=(C.green-MinColor) shl 8;
-    Result.blue:=(C.blue-MinColor) shl 8;
-    Result.alpha:=alphaOpaque;
-  end;
-
   procedure OutputScanLines();
   var
     x: integer;
@@ -428,12 +431,7 @@ var
         end;
       JCS_CMYK, JCS_YCCK:
         for x:=0 to FInfo.output_width-1 do
-        begin
-          //SetPixel(x, y, CorrectCMYK(TFPColor.New(SampRow^[x*4+0], SampRow^[x*4+1], SampRow^[x*4+2], SampRow^[x*4+3])));
-
-          cmyk :=TStdCMYK.New(SampRow^[x*4+0], SampRow^[x*4+1], SampRow^[x*4+2], SampRow^[x*4+3]);
-          SetPixel(x, y, cmyk.ToExpandedPixel.ToFPColor(false));
-        end;
+          SetPixel(x, y, CMYKToRGB(SampRow^[x*4+0], SampRow^[x*4+1], SampRow^[x*4+2], SampRow^[x*4+3]));
       else
         for x:=0 to FInfo.output_width-1 do begin
           Color.Red:=SampRow^[x*3+0] shl 8;
@@ -593,6 +591,11 @@ begin
         MemStream.Position:=0;
         jpeg_stdio_src(@FInfo, @MemStream);
 
+        FInfo.extensions := @FExtensions;
+        FExtensions.read_ext_appn := @ReadExtAPPnCallback;
+
+        FInfo.client_data := Self;
+
         ReadHeader(MemStream, Img);
         ReadPixels(MemStream, Img);
       finally
@@ -646,6 +649,14 @@ begin
   inherited Create;
 end;
 
+function TFPReaderJPEG.CMYKToRGB(const C, M, Y, K: Byte): TFPColor;
+begin
+  Result.Red := ((C*K) div 255) shl 8;
+  Result.Green := ((M*K) div 255) shl 8;
+  Result.Blue := ((Y*K) div 255) shl 8;
+  Result.Alpha := alphaOpaque;
+end;
+
 destructor TFPReaderJPEG.Destroy;
 begin
   inherited Destroy;
diff --git a/packages/pasjpeg/src/jdmarker.pas b/packages/pasjpeg/src/jdmarker.pas
index 8b61aaa523..dd7eac1442 100644
--- a/packages/pasjpeg/src/jdmarker.pas
+++ b/packages/pasjpeg/src/jdmarker.pas
@@ -17,6 +17,7 @@ Unit JdMarker;
 interface
 
 {$I jconfig.inc}
+{$modeswitch nestedprocvars}
 
 {$IFDEF FPC_DOTTEDUNITS}
 uses
@@ -1665,13 +1666,13 @@ begin
 end;
 
 {LOCAL}
-function examine_app1 (cinfo : j_decompress_ptr;
+procedure examine_app1 (cinfo : j_decompress_ptr;
                         var header : array of JOCTET;
                         headerlen : uint;
                         var remaining : INT32;
                         datasrc : jpeg_source_mgr_ptr;
                         var next_input_byte : JOCTETptr;
-                        var bytes_in_buffer : size_t): Boolean;
+                        var bytes_in_buffer : size_t);
 
 { Read Exif marker.
   headerlen is # of bytes at header[], remaining is length of rest of marker header.
@@ -1790,7 +1791,7 @@ begin
 
     // read data
     if not Read16(numRecords) then
-      Exit(False);
+      Exit;
 
     for i:=1 to numRecords do
     begin
@@ -1820,6 +1821,12 @@ begin
         my_marker_ptr(cinfo^.marker)^.handle_exif_tag(cinfo, ifdRec, BigEndian, data, EXIF_TAGPARENT_PRIMARY);
       end;
     end;
+  end else
+  if Assigned(cinfo.extensions) and Assigned(cinfo.extensions^.read_ext_appn) and (headerlen>0) then
+  begin
+    BigEndian := False;
+    Offset := APP1_HEADER_LEN;
+    cinfo.extensions^.read_ext_appn(cinfo, M_APP1, header, headerlen, remaining, Read);
   end;
 end;
 
diff --git a/packages/pasjpeg/src/jpeglib.pas b/packages/pasjpeg/src/jpeglib.pas
index 15b6819826..57f96e4fa0 100644
--- a/packages/pasjpeg/src/jpeglib.pas
+++ b/packages/pasjpeg/src/jpeglib.pas
@@ -12,6 +12,7 @@ Unit JPEGLib;
 interface
 
 {$I jconfig.inc}
+{$modeswitch nestedprocvars}
 
 { First we include the configuration files that record how this
   installation of the JPEG library is set up.  jconfig.h can be
@@ -719,6 +720,15 @@ type
     new_color_map : procedure(cinfo : j_decompress_ptr);
   end;
 
+{ JPEG extensions }
+  jpeg_ext_appn_readdata = function (const Buffer: Pointer; numtoread: uint): Boolean is nested;
+  jpeg_extensions_ptr = ^jpeg_extensions;
+  jpeg_extensions = record
+    // read extended (unknown) APPn data
+    read_ext_appn : procedure(cinfo : j_decompress_ptr; marker : int; var header : array of JOCTET; headerlen : uint;
+      var remaining : int32; readdata: jpeg_ext_appn_readdata);
+  end;
+
   {int8array = Array[0..8-1] of int;}
   int8array = Array[0..8-1] of longint; { for TP FormatStr }
   TFormatCallback = procedure  (cinfo : j_common_ptr; var buffer : shortstring);
@@ -1280,6 +1290,7 @@ type
     upsample : jpeg_upsampler_ptr;
     cconvert : jpeg_color_deconverter_ptr;
     cquantize : jpeg_color_quantizer_ptr;
+    extensions : jpeg_extensions_ptr;
   end;
 
 { Decompression startup: read start of JPEG datastream to see what's there