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