2020-08-27 21:45:09 +00:00
|
|
|
//
|
|
|
|
// Copyright 2020 FoxyUtils ehf. All rights reserved.
|
|
|
|
//
|
|
|
|
// This is a commercial product and requires a license to operate.
|
|
|
|
// A trial license can be obtained at https://unidoc.io
|
|
|
|
//
|
|
|
|
// DO NOT EDIT: generated by unitwist Go source code obfuscator.
|
|
|
|
//
|
|
|
|
// Use of this source code is governed by the UniDoc End User License Agreement
|
|
|
|
// terms that can be accessed at https://unidoc.io/eula/
|
|
|
|
|
2023-02-07 17:17:49 +00:00
|
|
|
package optimize ;import (_cb "bytes";_f "crypto/md5";_ee "errors";_e "github.com/unidoc/unipdf/v3/common";_af "github.com/unidoc/unipdf/v3/contentstream";_cf "github.com/unidoc/unipdf/v3/core";_c "github.com/unidoc/unipdf/v3/extractor";_a "github.com/unidoc/unipdf/v3/internal/imageutil";
|
|
|
|
_gdf "github.com/unidoc/unipdf/v3/internal/textencoding";_fg "github.com/unidoc/unipdf/v3/model";_eb "github.com/unidoc/unitype";_b "golang.org/x/image/draw";_gd "math";);type imageInfo struct{BitsPerComponent int ;ColorComponents int ;Width int ;Height int ;
|
|
|
|
Stream *_cf .PdfObjectStream ;PPI float64 ;};
|
|
|
|
|
|
|
|
// CombineIdenticalIndirectObjects combines identical indirect objects.
|
|
|
|
// It implements interface model.Optimizer.
|
|
|
|
type CombineIdenticalIndirectObjects struct{};
|
|
|
|
|
|
|
|
// ObjectStreams groups PDF objects to object streams.
|
|
|
|
// It implements interface model.Optimizer.
|
|
|
|
type ObjectStreams struct{};
|
2022-09-10 15:35:04 +00:00
|
|
|
|
2022-10-27 19:04:58 +00:00
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
2023-02-07 17:17:49 +00:00
|
|
|
func (_ede *ObjectStreams )Optimize (objects []_cf .PdfObject )(_ggdf []_cf .PdfObject ,_dfb error ){_fdc :=&_cf .PdfObjectStreams {};_geeae :=make ([]_cf .PdfObject ,0,len (objects ));for _ ,_bgfg :=range objects {if _cdeg ,_cdf :=_bgfg .(*_cf .PdfIndirectObject );
|
|
|
|
_cdf &&_cdeg .GenerationNumber ==0{_fdc .Append (_bgfg );}else {_geeae =append (_geeae ,_bgfg );};};if _fdc .Len ()==0{return _geeae ,nil ;};_ggdf =make ([]_cf .PdfObject ,0,len (_geeae )+_fdc .Len ()+1);if _fdc .Len ()> 1{_ggdf =append (_ggdf ,_fdc );
|
|
|
|
};_ggdf =append (_ggdf ,_fdc .Elements ()...);_ggdf =append (_ggdf ,_geeae ...);return _ggdf ,nil ;};type content struct{_fcc string ;_gga *_fg .PdfPageResources ;};
|
2022-09-10 15:35:04 +00:00
|
|
|
|
2023-02-07 17:17:49 +00:00
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
|
|
func (_cgb *CombineDuplicateDirectObjects )Optimize (objects []_cf .PdfObject )(_fda []_cf .PdfObject ,_efc error ){_fedf (objects );_gec :=make (map[string ][]*_cf .PdfObjectDictionary );var _ece func (_df *_cf .PdfObjectDictionary );_ece =func (_def *_cf .PdfObjectDictionary ){for _ ,_bgd :=range _def .Keys (){_gced :=_def .Get (_bgd );
|
|
|
|
if _agd ,_ddga :=_gced .(*_cf .PdfObjectDictionary );_ddga {_fed :=_f .New ();_fed .Write ([]byte (_agd .WriteString ()));_ead :=string (_fed .Sum (nil ));_gec [_ead ]=append (_gec [_ead ],_agd );_ece (_agd );};};};for _ ,_efee :=range objects {_cda ,_agf :=_efee .(*_cf .PdfIndirectObject );
|
|
|
|
if !_agf {continue ;};if _ccb ,_feb :=_cda .PdfObject .(*_cf .PdfObjectDictionary );_feb {_ece (_ccb );};};_cgbb :=make ([]_cf .PdfObject ,0,len (_gec ));_ebb :=make (map[_cf .PdfObject ]_cf .PdfObject );for _ ,_daae :=range _gec {if len (_daae )< 2{continue ;
|
|
|
|
};_ccd :=_cf .MakeDict ();_ccd .Merge (_daae [0]);_gbfd :=_cf .MakeIndirectObject (_ccd );_cgbb =append (_cgbb ,_gbfd );for _ffb :=0;_ffb < len (_daae );_ffb ++{_dafab :=_daae [_ffb ];_ebb [_dafab ]=_gbfd ;};};_fda =make ([]_cf .PdfObject ,len (objects ));
|
|
|
|
copy (_fda ,objects );_fda =append (_cgbb ,_fda ...);_cfdf (_fda ,_ebb );return _fda ,nil ;};
|
|
|
|
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
|
|
func (_abe *Image )Optimize (objects []_cf .PdfObject )(_gebc []_cf .PdfObject ,_bfcg error ){if _abe .ImageQuality <=0{return objects ,nil ;};_cdca :=_ffe (objects );if len (_cdca )==0{return objects ,nil ;};_egb :=make (map[_cf .PdfObject ]_cf .PdfObject );
|
|
|
|
_dag :=make (map[_cf .PdfObject ]struct{});for _ ,_bfed :=range _cdca {_dgbg :=_bfed .Stream .Get ("\u0053\u004d\u0061s\u006b");_dag [_dgbg ]=struct{}{};};for _bfgg ,_bfbb :=range _cdca {_ebcc :=_bfbb .Stream ;if _ ,_cbc :=_dag [_ebcc ];_cbc {continue ;
|
|
|
|
};_fdd ,_cgd :=_fg .NewXObjectImageFromStream (_ebcc );if _cgd !=nil {_e .Log .Debug ("\u0045\u0052\u0052\u004f\u0052\u003a\u0020\u0025\u002b\u0076",_cgd );continue ;};switch _fdd .Filter .(type ){case *_cf .JBIG2Encoder :continue ;case *_cf .CCITTFaxEncoder :continue ;
|
|
|
|
};_abeg ,_cgd :=_fdd .ToImage ();if _cgd !=nil {_e .Log .Debug ("\u0045\u0052\u0052\u004f\u0052\u003a\u0020\u0025\u002b\u0076",_cgd );continue ;};_gda :=_cf .NewDCTEncoder ();_gda .ColorComponents =_abeg .ColorComponents ;_gda .Quality =_abe .ImageQuality ;
|
|
|
|
_gda .BitsPerComponent =_bfbb .BitsPerComponent ;_gda .Width =_bfbb .Width ;_gda .Height =_bfbb .Height ;_gdgf ,_cgd :=_gda .EncodeBytes (_abeg .Data );if _cgd !=nil {_e .Log .Debug ("\u0045\u0052\u0052\u004f\u0052\u003a\u0020\u0025\u002b\u0076",_cgd );
|
|
|
|
continue ;};var _cdcb _cf .StreamEncoder ;_cdcb =_gda ;{_cffb :=_cf .NewFlateEncoder ();_defa :=_cf .NewMultiEncoder ();_defa .AddEncoder (_cffb );_defa .AddEncoder (_gda );_bcg ,_fgd :=_defa .EncodeBytes (_abeg .Data );if _fgd !=nil {_e .Log .Debug ("\u0045\u0052\u0052\u004f\u0052\u003a\u0020\u0025\u002b\u0076",_fgd );
|
|
|
|
continue ;};if len (_bcg )< len (_gdgf ){_e .Log .Trace ("\u004d\u0075\u006c\u0074\u0069\u0020\u0065\u006e\u0063\u0020\u0069\u006d\u0070\u0072\u006f\u0076\u0065\u0073\u003a\u0020\u0025\u0064\u0020\u0074o\u0020\u0025\u0064\u0020\u0028o\u0072\u0069g\u0020\u0025\u0064\u0029",len (_gdgf ),len (_bcg ),len (_ebcc .Stream ));
|
|
|
|
_gdgf =_bcg ;_cdcb =_defa ;};};_defb :=len (_ebcc .Stream );if _defb < len (_gdgf ){continue ;};_fcf :=&_cf .PdfObjectStream {Stream :_gdgf };_fcf .PdfObjectReference =_ebcc .PdfObjectReference ;_fcf .PdfObjectDictionary =_cf .MakeDict ();_fcf .Merge (_ebcc .PdfObjectDictionary );
|
|
|
|
_fcf .Merge (_cdcb .MakeStreamDict ());_fcf .Set ("\u004c\u0065\u006e\u0067\u0074\u0068",_cf .MakeInteger (int64 (len (_gdgf ))));_egb [_ebcc ]=_fcf ;_cdca [_bfgg ].Stream =_fcf ;};_gebc =make ([]_cf .PdfObject ,len (objects ));copy (_gebc ,objects );_cfdf (_gebc ,_egb );
|
|
|
|
return _gebc ,nil ;};
|
|
|
|
|
|
|
|
// New creates a optimizers chain from options.
|
|
|
|
func New (options Options )*Chain {_bfa :=new (Chain );if options .CleanFonts ||options .SubsetFonts {_bfa .Append (&CleanFonts {Subset :options .SubsetFonts });};if options .CleanContentstream {_bfa .Append (new (CleanContentstream ));};if options .ImageUpperPPI > 0{_bbd :=new (ImagePPI );
|
|
|
|
_bbd .ImageUpperPPI =options .ImageUpperPPI ;_bfa .Append (_bbd );};if options .ImageQuality > 0{_gcdd :=new (Image );_gcdd .ImageQuality =options .ImageQuality ;_bfa .Append (_gcdd );};if options .CombineDuplicateDirectObjects {_bfa .Append (new (CombineDuplicateDirectObjects ));
|
|
|
|
};if options .CombineDuplicateStreams {_bfa .Append (new (CombineDuplicateStreams ));};if options .CombineIdenticalIndirectObjects {_bfa .Append (new (CombineIdenticalIndirectObjects ));};if options .UseObjectStreams {_bfa .Append (new (ObjectStreams ));
|
|
|
|
};if options .CompressStreams {_bfa .Append (new (CompressStreams ));};return _bfa ;};
|
|
|
|
|
|
|
|
// CompressStreams compresses uncompressed streams.
|
|
|
|
// It implements interface model.Optimizer.
|
|
|
|
type CompressStreams struct{};
|
2022-09-10 15:35:04 +00:00
|
|
|
|
2023-01-08 22:34:27 +00:00
|
|
|
// CleanFonts cleans up embedded fonts, reducing font sizes.
|
|
|
|
type CleanFonts struct{
|
|
|
|
|
|
|
|
// Subset embedded fonts if encountered (if true).
|
|
|
|
// Otherwise attempts to reduce the font program.
|
2023-02-07 17:17:49 +00:00
|
|
|
Subset bool ;};type imageModifications struct{Scale float64 ;Encoding _cf .StreamEncoder ;};func _cde (_cea *_cf .PdfObjectStream ,_bd []rune ,_bbeb []_eb .GlyphIndex )error {_cea ,_ac :=_cf .GetStream (_cea );if !_ac {_e .Log .Debug ("\u0045\u006d\u0062\u0065\u0064\u0064\u0065\u0064\u0020\u0066\u006f\u006e\u0074\u0020\u006f\u0062\u006a\u0065c\u0074\u0020\u006e\u006f\u0074\u0020\u0066o\u0075\u006e\u0064\u0020\u002d\u002d\u0020\u0041\u0042\u004f\u0052T\u0020\u0073\u0075\u0062\u0073\u0065\u0074\u0074\u0069\u006e\u0067");
|
|
|
|
return _ee .New ("\u0066\u006f\u006e\u0074fi\u006c\u0065\u0032\u0020\u006e\u006f\u0074\u0020\u0066\u006f\u0075\u006e\u0064");};_dde ,_egc :=_cf .DecodeStream (_cea );if _egc !=nil {_e .Log .Debug ("\u0044\u0065c\u006f\u0064\u0065 \u0065\u0072\u0072\u006f\u0072\u003a\u0020\u0025\u0076",_egc );
|
|
|
|
return _egc ;};_dad ,_egc :=_eb .Parse (_cb .NewReader (_dde ));if _egc !=nil {_e .Log .Debug ("\u0045\u0072\u0072\u006f\u0072\u0020\u0070\u0061\u0072\u0073\u0069n\u0067\u0020\u0025\u0064\u0020\u0062\u0079\u0074\u0065\u0020f\u006f\u006e\u0074",len (_cea .Stream ));
|
|
|
|
return _egc ;};_fbe :=_bbeb ;if len (_bd )> 0{_fac :=_dad .LookupRunes (_bd );_fbe =append (_fbe ,_fac ...);};_dad ,_egc =_dad .SubsetKeepIndices (_fbe );if _egc !=nil {_e .Log .Debug ("\u0045R\u0052\u004f\u0052\u0020s\u0075\u0062\u0073\u0065\u0074t\u0069n\u0067 \u0066\u006f\u006e\u0074\u003a\u0020\u0025v",_egc );
|
|
|
|
return _egc ;};var _bdb _cb .Buffer ;_egc =_dad .Write (&_bdb );if _egc !=nil {_e .Log .Debug ("\u0045\u0052\u0052\u004fR \u0057\u0072\u0069\u0074\u0069\u006e\u0067\u0020\u0066\u006f\u006e\u0074\u003a\u0020%\u0076",_egc );return _egc ;};if _bdb .Len ()> len (_dde ){_e .Log .Debug ("\u0052\u0065-\u0077\u0072\u0069\u0074\u0074\u0065\u006e\u0020\u0066\u006f\u006e\u0074\u0020\u0069\u0073\u0020\u006c\u0061\u0072\u0067\u0065\u0072\u0020\u0074\u0068\u0061\u006e\u0020\u006f\u0072\u0069\u0067\u0069\u006e\u0061\u006c\u0020\u002d\u0020\u0073\u006b\u0069\u0070");
|
|
|
|
return nil ;};_fbg ,_egc :=_cf .MakeStream (_bdb .Bytes (),_cf .NewFlateEncoder ());if _egc !=nil {_e .Log .Debug ("\u0045\u0052\u0052\u004fR \u0057\u0072\u0069\u0074\u0069\u006e\u0067\u0020\u0066\u006f\u006e\u0074\u003a\u0020%\u0076",_egc );return _egc ;
|
|
|
|
};*_cea =*_fbg ;_cea .Set ("\u004ce\u006e\u0067\u0074\u0068\u0031",_cf .MakeInteger (int64 (_bdb .Len ())));return nil ;};func _bgdc (_dfea []_cf .PdfObject )objectStructure {_eee :=objectStructure {};_fgdc :=false ;for _ ,_aabb :=range _dfea {switch _bgfb :=_aabb .(type ){case *_cf .PdfIndirectObject :_dafb ,_gfd :=_cf .GetDict (_bgfb );
|
|
|
|
if !_gfd {continue ;};_cee ,_gfd :=_cf .GetName (_dafb .Get ("\u0054\u0079\u0070\u0065"));if !_gfd {continue ;};switch _cee .String (){case "\u0043a\u0074\u0061\u006c\u006f\u0067":_eee ._dfg =_dafb ;_fgdc =true ;};};if _fgdc {break ;};};if !_fgdc {return _eee ;
|
|
|
|
};_bcbd ,_eaa :=_cf .GetDict (_eee ._dfg .Get ("\u0050\u0061\u0067e\u0073"));if !_eaa {return _eee ;};_eee ._dge =_bcbd ;_cfed ,_eaa :=_cf .GetArray (_bcbd .Get ("\u004b\u0069\u0064\u0073"));if !_eaa {return _eee ;};for _ ,_age :=range _cfed .Elements (){_cce ,_accc :=_cf .GetIndirect (_age );
|
|
|
|
if !_accc {break ;};_eee ._efb =append (_eee ._efb ,_cce );};return _eee ;};
|
2022-09-10 15:35:04 +00:00
|
|
|
|
2022-09-23 18:05:51 +00:00
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
2023-02-07 17:17:49 +00:00
|
|
|
func (_bfcd *CombineIdenticalIndirectObjects )Optimize (objects []_cf .PdfObject )(_ebg []_cf .PdfObject ,_aeb error ){_fedf (objects );_bgc :=make (map[_cf .PdfObject ]_cf .PdfObject );_cdag :=make (map[_cf .PdfObject ]struct{});_eagg :=make (map[string ][]*_cf .PdfIndirectObject );
|
|
|
|
for _ ,_geea :=range objects {_ebbd ,_bea :=_geea .(*_cf .PdfIndirectObject );if !_bea {continue ;};if _gad ,_dae :=_ebbd .PdfObject .(*_cf .PdfObjectDictionary );_dae {if _cbg ,_dfe :=_gad .Get ("\u0054\u0079\u0070\u0065").(*_cf .PdfObjectName );_dfe &&*_cbg =="\u0050\u0061\u0067\u0065"{continue ;
|
|
|
|
};_bge :=_f .New ();_bge .Write ([]byte (_gad .WriteString ()));_gde :=string (_bge .Sum (nil ));_eagg [_gde ]=append (_eagg [_gde ],_ebbd );};};for _ ,_afa :=range _eagg {if len (_afa )< 2{continue ;};_bda :=_afa [0];for _eacg :=1;_eacg < len (_afa );
|
|
|
|
_eacg ++{_edga :=_afa [_eacg ];_bgc [_edga ]=_bda ;_cdag [_edga ]=struct{}{};};};_ebg =make ([]_cf .PdfObject ,0,len (objects )-len (_cdag ));for _ ,_cafe :=range objects {if _ ,_gegg :=_cdag [_cafe ];_gegg {continue ;};_ebg =append (_ebg ,_cafe );};_cfdf (_ebg ,_bgc );
|
|
|
|
return _ebg ,nil ;};
|
2022-09-10 15:35:04 +00:00
|
|
|
|
2023-02-07 17:17:49 +00:00
|
|
|
// Chain allows to use sequence of optimizers.
|
|
|
|
// It implements interface model.Optimizer.
|
|
|
|
type Chain struct{_eef []_fg .Optimizer };type objectStructure struct{_dfg *_cf .PdfObjectDictionary ;_dge *_cf .PdfObjectDictionary ;_efb []*_cf .PdfIndirectObject ;};
|
2022-07-13 21:28:43 +00:00
|
|
|
|
2023-02-07 17:17:49 +00:00
|
|
|
// Image optimizes images by rewrite images into JPEG format with quality equals to ImageQuality.
|
|
|
|
// TODO(a5i): Add support for inline images.
|
|
|
|
// It implements interface model.Optimizer.
|
|
|
|
type Image struct{ImageQuality int ;};func _fdf (_dabe *_fg .Image ,_dgbf float64 )(*_fg .Image ,error ){_gffb ,_cffg :=_dabe .ToGoImage ();if _cffg !=nil {return nil ,_cffg ;};var _fgda _a .Image ;_dafe ,_ceac :=_gffb .(*_a .Monochrome );if _ceac {if _cffg =_dafe .ResolveDecode ();
|
|
|
|
_cffg !=nil {return nil ,_cffg ;};_fgda ,_cffg =_dafe .Scale (_dgbf );if _cffg !=nil {return nil ,_cffg ;};}else {_gggf :=int (_gd .RoundToEven (float64 (_dabe .Width )*_dgbf ));_beg :=int (_gd .RoundToEven (float64 (_dabe .Height )*_dgbf ));_fgda ,_cffg =_a .NewImage (_gggf ,_beg ,int (_dabe .BitsPerComponent ),_dabe .ColorComponents ,nil ,nil ,nil );
|
|
|
|
if _cffg !=nil {return nil ,_cffg ;};_b .CatmullRom .Scale (_fgda ,_fgda .Bounds (),_gffb ,_gffb .Bounds (),_b .Over ,&_b .Options {});};_dadd :=_fgda .Base ();_ddd :=&_fg .Image {Width :int64 (_dadd .Width ),Height :int64 (_dadd .Height ),BitsPerComponent :int64 (_dadd .BitsPerComponent ),ColorComponents :_dadd .ColorComponents ,Data :_dadd .Data };
|
|
|
|
_ddd .SetDecode (_dadd .Decode );_ddd .SetAlpha (_dadd .Alpha );return _ddd ,nil ;};func _gg (_ggf *_cf .PdfObjectStream )error {_be ,_db :=_cf .DecodeStream (_ggf );if _db !=nil {return _db ;};_ea :=_af .NewContentStreamParser (string (_be ));_bfd ,_db :=_ea .Parse ();
|
|
|
|
if _db !=nil {return _db ;};_bfd =_gf (_bfd );_daa :=_bfd .Bytes ();if len (_daa )>=len (_be ){return nil ;};_ada ,_db :=_cf .MakeStream (_bfd .Bytes (),_cf .NewFlateEncoder ());if _db !=nil {return _db ;};_ggf .Stream =_ada .Stream ;_ggf .Merge (_ada .PdfObjectDictionary );
|
|
|
|
return nil ;};func _fbff (_ggd *_fg .XObjectImage ,_gfce imageModifications )error {_cad ,_bfdf :=_ggd .ToImage ();if _bfdf !=nil {return _bfdf ;};if _gfce .Scale !=0{_cad ,_bfdf =_fdf (_cad ,_gfce .Scale );if _bfdf !=nil {return _bfdf ;};};if _gfce .Encoding !=nil {_ggd .Filter =_gfce .Encoding ;
|
|
|
|
};_ggd .Decode =nil ;switch _cca :=_ggd .Filter .(type ){case *_cf .FlateEncoder :if _cca .Predictor !=1&&_cca .Predictor !=11{_cca .Predictor =1;};};if _bfdf =_ggd .SetImage (_cad ,nil );_bfdf !=nil {_e .Log .Debug ("\u0045\u0072\u0072or\u0020\u0073\u0065\u0074\u0074\u0069\u006e\u0067\u0020\u0069\u006d\u0061\u0067\u0065\u003a\u0020\u0025\u0076",_bfdf );
|
|
|
|
return _bfdf ;};_ggd .ToPdfObject ();return nil ;};
|
2022-09-23 18:05:51 +00:00
|
|
|
|
2023-02-07 17:17:49 +00:00
|
|
|
// Append appends optimizers to the chain.
|
|
|
|
func (_cc *Chain )Append (optimizers ..._fg .Optimizer ){_cc ._eef =append (_cc ._eef ,optimizers ...)};
|
2023-01-08 22:34:27 +00:00
|
|
|
|
2023-02-07 17:17:49 +00:00
|
|
|
// Options describes PDF optimization parameters.
|
|
|
|
type Options struct{CombineDuplicateStreams bool ;CombineDuplicateDirectObjects bool ;ImageUpperPPI float64 ;ImageQuality int ;UseObjectStreams bool ;CombineIdenticalIndirectObjects bool ;CompressStreams bool ;CleanFonts bool ;SubsetFonts bool ;CleanContentstream bool ;
|
|
|
|
};func _dagb (_afd _cf .PdfObject )(_afe string ,_eabb []_cf .PdfObject ){var _eaaf _cb .Buffer ;switch _cgdd :=_afd .(type ){case *_cf .PdfIndirectObject :_eabb =append (_eabb ,_cgdd );_afd =_cgdd .PdfObject ;};switch _gded :=_afd .(type ){case *_cf .PdfObjectStream :if _ace ,_dgaf :=_cf .DecodeStream (_gded );
|
|
|
|
_dgaf ==nil {_eaaf .Write (_ace );_eabb =append (_eabb ,_gded );};case *_cf .PdfObjectArray :for _ ,_acafd :=range _gded .Elements (){switch _ecg :=_acafd .(type ){case *_cf .PdfObjectStream :if _ccdf ,_dcfb :=_cf .DecodeStream (_ecg );_dcfb ==nil {_eaaf .Write (_ccdf );
|
|
|
|
_eabb =append (_eabb ,_ecg );};};};};return _eaaf .String (),_eabb ;};func _ddf (_fa []_cf .PdfObject )(_cg map[*_cf .PdfObjectStream ]struct{},_deb error ){_cg =map[*_cf .PdfObjectStream ]struct{}{};_dbc :=map[*_fg .PdfFont ]struct{}{};_cfd :=_bgdc (_fa );
|
|
|
|
for _ ,_dg :=range _cfd ._efb {_cag ,_gdgc :=_cf .GetDict (_dg .PdfObject );if !_gdgc {continue ;};_ff ,_gdgc :=_cf .GetDict (_cag .Get ("\u0052e\u0073\u006f\u0075\u0072\u0063\u0065s"));if !_gdgc {continue ;};_ae ,_ :=_dagb (_cag .Get ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073"));
|
|
|
|
_fgb ,_gcge :=_fg .NewPdfPageResourcesFromDict (_ff );if _gcge !=nil {return nil ,_gcge ;};_fbd :=[]content {{_fcc :_ae ,_gga :_fgb }};_bec :=_dgg (_cag .Get ("\u0041\u006e\u006e\u006f\u0074\u0073"));if _bec !=nil {_fbd =append (_fbd ,_bec ...);};for _ ,_fga :=range _fbd {_ffg ,_ggg :=_c .NewFromContents (_fga ._fcc ,_fga ._gga );
|
|
|
|
if _ggg !=nil {return nil ,_ggg ;};_bg ,_ ,_ ,_ggg :=_ffg .ExtractPageText ();if _ggg !=nil {return nil ,_ggg ;};for _ ,_fgc :=range _bg .Marks ().Elements (){if _fgc .Font ==nil {continue ;};if _ ,_faa :=_dbc [_fgc .Font ];!_faa {_dbc [_fgc .Font ]=struct{}{};
|
|
|
|
};};};};_aafb :=map[*_cf .PdfObjectStream ][]*_fg .PdfFont {};for _geb :=range _dbc {_bb :=_geb .FontDescriptor ();if _bb ==nil ||_bb .FontFile2 ==nil {continue ;};_ebaa ,_ebf :=_cf .GetStream (_bb .FontFile2 );if !_ebf {continue ;};_aafb [_ebaa ]=append (_aafb [_ebaa ],_geb );
|
|
|
|
};for _dab :=range _aafb {var _egg []rune ;var _gfc []_eb .GlyphIndex ;for _ ,_fef :=range _aafb [_dab ]{switch _ceb :=_fef .Encoder ().(type ){case *_gdf .IdentityEncoder :_dbb :=_ceb .RegisteredRunes ();_gfcf :=make ([]_eb .GlyphIndex ,len (_dbb ));for _cfc ,_bbe :=range _dbb {_gfcf [_cfc ]=_eb .GlyphIndex (_bbe );
|
|
|
|
};_gfc =append (_gfc ,_gfcf ...);case *_gdf .TrueTypeFontEncoder :_babf :=_ceb .RegisteredRunes ();_egg =append (_egg ,_babf ...);case _gdf .SimpleEncoder :_gfb :=_ceb .Charcodes ();for _ ,_cdc :=range _gfb {_fae ,_cfb :=_ceb .CharcodeToRune (_cdc );if !_cfb {_e .Log .Debug ("\u0043\u0068a\u0072\u0063\u006f\u0064\u0065\u003c\u002d\u003e\u0072\u0075\u006e\u0065\u0020\u006e\u006f\u0074\u0020\u0066\u006f\u0075\u006e\u0064: \u0025\u0064",_cdc );
|
|
|
|
continue ;};_egg =append (_egg ,_fae );};};};_deb =_cde (_dab ,_egg ,_gfc );if _deb !=nil {_e .Log .Debug ("\u0045\u0052\u0052\u004f\u0052\u0020\u0073\u0075\u0062\u0073\u0065\u0074\u0074\u0069\u006eg\u0020f\u006f\u006e\u0074\u0020\u0073\u0074\u0072\u0065\u0061\u006d\u003a\u0020\u0025\u0076",_deb );
|
|
|
|
return nil ,_deb ;};_cg [_dab ]=struct{}{};};return _cg ,nil ;};
|
2022-12-15 21:59:56 +00:00
|
|
|
|
|
|
|
// ImagePPI optimizes images by scaling images such that the PPI (pixels per inch) is never higher than ImageUpperPPI.
|
|
|
|
// TODO(a5i): Add support for inline images.
|
|
|
|
// It implements interface model.Optimizer.
|
2023-02-07 17:17:49 +00:00
|
|
|
type ImagePPI struct{ImageUpperPPI float64 ;};
|
2022-10-27 19:04:58 +00:00
|
|
|
|
2023-02-07 17:17:49 +00:00
|
|
|
// CombineDuplicateDirectObjects combines duplicated direct objects by its data hash.
|
2023-01-08 22:34:27 +00:00
|
|
|
// It implements interface model.Optimizer.
|
2023-02-07 17:17:49 +00:00
|
|
|
type CombineDuplicateDirectObjects struct{};func _fedf (_bdf []_cf .PdfObject ){for _bfea ,_gac :=range _bdf {switch _cagd :=_gac .(type ){case *_cf .PdfIndirectObject :_cagd .ObjectNumber =int64 (_bfea +1);_cagd .GenerationNumber =0;case *_cf .PdfObjectStream :_cagd .ObjectNumber =int64 (_bfea +1);
|
|
|
|
_cagd .GenerationNumber =0;case *_cf .PdfObjectStreams :_cagd .ObjectNumber =int64 (_bfea +1);_cagd .GenerationNumber =0;};};};func _cfdf (_abcc []_cf .PdfObject ,_gfe map[_cf .PdfObject ]_cf .PdfObject ){if len (_gfe )==0{return ;};for _bbb ,_defd :=range _abcc {if _gbc ,_cbe :=_gfe [_defd ];
|
|
|
|
_cbe {_abcc [_bbb ]=_gbc ;continue ;};_gfe [_defd ]=_defd ;switch _cab :=_defd .(type ){case *_cf .PdfObjectArray :_aag :=make ([]_cf .PdfObject ,_cab .Len ());copy (_aag ,_cab .Elements ());_cfdf (_aag ,_gfe );for _efec ,_ebcf :=range _aag {_cab .Set (_efec ,_ebcf );
|
|
|
|
};case *_cf .PdfObjectStreams :_cfdf (_cab .Elements (),_gfe );case *_cf .PdfObjectStream :_cfe :=[]_cf .PdfObject {_cab .PdfObjectDictionary };_cfdf (_cfe ,_gfe );_cab .PdfObjectDictionary =_cfe [0].(*_cf .PdfObjectDictionary );case *_cf .PdfObjectDictionary :_bbef :=_cab .Keys ();
|
|
|
|
_acfg :=make ([]_cf .PdfObject ,len (_bbef ));for _gcddg ,_bcbf :=range _bbef {_acfg [_gcddg ]=_cab .Get (_bcbf );};_cfdf (_acfg ,_gfe );for _bae ,_ffaa :=range _bbef {_cab .Set (_ffaa ,_acfg [_bae ]);};case *_cf .PdfIndirectObject :_gdfe :=[]_cf .PdfObject {_cab .PdfObject };
|
|
|
|
_cfdf (_gdfe ,_gfe );_cab .PdfObject =_gdfe [0];};};};func _ffe (_dgb []_cf .PdfObject )[]*imageInfo {_fgbg :=_cf .PdfObjectName ("\u0053u\u0062\u0074\u0079\u0070\u0065");_eec :=make (map[*_cf .PdfObjectStream ]struct{});var _feg []*imageInfo ;for _ ,_aeba :=range _dgb {_efca ,_fcd :=_cf .GetStream (_aeba );
|
|
|
|
if !_fcd {continue ;};if _ ,_dgc :=_eec [_efca ];_dgc {continue ;};_eec [_efca ]=struct{}{};_bca :=_efca .PdfObjectDictionary .Get (_fgbg );_cdd ,_fcd :=_cf .GetName (_bca );if !_fcd ||string (*_cdd )!="\u0049\u006d\u0061g\u0065"{continue ;};_gbb :=&imageInfo {Stream :_efca ,BitsPerComponent :8};
|
|
|
|
if _eced ,_dfc :=_cf .GetIntVal (_efca .Get ("\u0042\u0069t\u0073\u0050\u0065r\u0043\u006f\u006d\u0070\u006f\u006e\u0065\u006e\u0074"));_dfc {_gbb .BitsPerComponent =_eced ;};if _fce ,_cdg :=_cf .GetIntVal (_efca .Get ("\u0057\u0069\u0064t\u0068"));_cdg {_gbb .Width =_fce ;
|
|
|
|
};if _efa ,_bgeg :=_cf .GetIntVal (_efca .Get ("\u0048\u0065\u0069\u0067\u0068\u0074"));_bgeg {_gbb .Height =_efa ;};_egfb ,_ccbe :=_fg .NewPdfColorspaceFromPdfObject (_efca .Get ("\u0043\u006f\u006c\u006f\u0072\u0053\u0070\u0061\u0063\u0065"));if _ccbe !=nil {_e .Log .Debug ("\u0045R\u0052\u004f\u0052\u003a\u0020\u0025v",_ccbe );
|
|
|
|
continue ;};if _egfb ==nil {_edb ,_eeg :=_cf .GetName (_efca .Get ("\u0046\u0069\u006c\u0074\u0065\u0072"));if _eeg {switch _edb .String (){case "\u0043\u0043\u0049\u0054\u0054\u0046\u0061\u0078\u0044e\u0063\u006f\u0064\u0065","J\u0042\u0049\u0047\u0032\u0044\u0065\u0063\u006f\u0064\u0065":_egfb =_fg .NewPdfColorspaceDeviceGray ();
|
|
|
|
_gbb .BitsPerComponent =1;};};};switch _fcdc :=_egfb .(type ){case *_fg .PdfColorspaceDeviceRGB :_gbb .ColorComponents =3;case *_fg .PdfColorspaceDeviceGray :_gbb .ColorComponents =1;default:_e .Log .Debug ("\u004f\u0070\u0074\u0069\u006d\u0069\u007aa\u0074\u0069\u006fn\u0020\u0069\u0073 \u006e\u006ft\u0020\u0073\u0075\u0070\u0070\u006fr\u0074ed\u0020\u0066\u006f\u0072\u0020\u0063\u006f\u006c\u006f\u0072\u0020\u0073\u0070\u0061\u0063\u0065\u0020\u0025\u0054\u0020\u002d\u0020\u0073\u006b\u0069\u0070",_fcdc );
|
|
|
|
continue ;};_feg =append (_feg ,_gbb );};return _feg ;};
|
2022-02-05 21:34:53 +00:00
|
|
|
|
2022-12-15 21:59:56 +00:00
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
2023-02-07 17:17:49 +00:00
|
|
|
func (_cbd *CombineDuplicateStreams )Optimize (objects []_cf .PdfObject )(_ebdd []_cf .PdfObject ,_bdbb error ){_fcb :=make (map[_cf .PdfObject ]_cf .PdfObject );_efd :=make (map[_cf .PdfObject ]struct{});_bcf :=make (map[string ][]*_cf .PdfObjectStream );
|
|
|
|
for _ ,_acc :=range objects {if _adgc ,_baf :=_acc .(*_cf .PdfObjectStream );_baf {_cfda :=_f .New ();_cfda .Write (_adgc .Stream );_cfda .Write ([]byte (_adgc .PdfObjectDictionary .WriteString ()));_dbg :=string (_cfda .Sum (nil ));_bcf [_dbg ]=append (_bcf [_dbg ],_adgc );
|
|
|
|
};};for _ ,_ffa :=range _bcf {if len (_ffa )< 2{continue ;};_bcb :=_ffa [0];for _egf :=1;_egf < len (_ffa );_egf ++{_ccf :=_ffa [_egf ];_fcb [_ccf ]=_bcb ;_efd [_ccf ]=struct{}{};};};_ebdd =make ([]_cf .PdfObject ,0,len (objects )-len (_efd ));for _ ,_ccc :=range objects {if _ ,_gff :=_efd [_ccc ];
|
|
|
|
_gff {continue ;};_ebdd =append (_ebdd ,_ccc );};_cfdf (_ebdd ,_fcb );return _ebdd ,nil ;};
|
2022-09-23 18:05:51 +00:00
|
|
|
|
2022-12-15 21:59:56 +00:00
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
2023-02-07 17:17:49 +00:00
|
|
|
func (_aba *CleanFonts )Optimize (objects []_cf .PdfObject )(_ag []_cf .PdfObject ,_fee error ){var _aca map[*_cf .PdfObjectStream ]struct{};if _aba .Subset {var _dea error ;_aca ,_dea =_ddf (objects );if _dea !=nil {_e .Log .Debug ("\u0045\u0052\u0052\u004fR\u003a\u0020\u0046\u0061\u0069\u006c\u0065\u0064\u0020\u0073u\u0062s\u0065\u0074\u0074\u0069\u006e\u0067\u003a \u0025\u0076",_dea );
|
|
|
|
return nil ,_dea ;};};for _ ,_cfbb :=range objects {_aab ,_eca :=_cf .GetStream (_cfbb );if !_eca {continue ;};if _ ,_caf :=_aca [_aab ];_caf {continue ;};_fgg ,_ceba :=_cf .NewEncoderFromStream (_aab );if _ceba !=nil {_e .Log .Debug ("\u0045\u0052RO\u0052\u0020\u0067e\u0074\u0074\u0069\u006eg e\u006eco\u0064\u0065\u0072\u003a\u0020\u0025\u0076 -\u0020\u0069\u0067\u006e\u006f\u0072\u0069n\u0067",_ceba );
|
|
|
|
continue ;};_fgf ,_ceba :=_fgg .DecodeStream (_aab );if _ceba !=nil {_e .Log .Debug ("\u0044\u0065\u0063\u006f\u0064\u0069\u006e\u0067\u0020\u0065r\u0072\u006f\u0072\u0020\u003a\u0020\u0025v\u0020\u002d\u0020\u0069\u0067\u006e\u006f\u0072\u0069\u006e\u0067",_ceba );
|
|
|
|
continue ;};if len (_fgf )< 4{continue ;};_dba :=string (_fgf [:4]);if _dba =="\u004f\u0054\u0054\u004f"{continue ;};if _dba !="\u0000\u0001\u0000\u0000"&&_dba !="\u0074\u0072\u0075\u0065"{continue ;};_dc ,_ceba :=_eb .Parse (_cb .NewReader (_fgf ));if _ceba !=nil {_e .Log .Debug ("\u0045\u0052\u0052\u004f\u0052\u0020P\u0061\u0072\u0073\u0069\u006e\u0067\u0020\u0066\u006f\u006e\u0074\u003a\u0020%\u0076\u0020\u002d\u0020\u0069\u0067\u006eo\u0072\u0069\u006e\u0067",_ceba );
|
|
|
|
continue ;};_ceba =_dc .Optimize ();if _ceba !=nil {_e .Log .Debug ("\u0045\u0052RO\u0052\u0020\u004fp\u0074\u0069\u006d\u0069zin\u0067 f\u006f\u006e\u0074\u003a\u0020\u0025\u0076 -\u0020\u0073\u006b\u0069\u0070\u0070\u0069n\u0067",_ceba );continue ;};
|
|
|
|
var _abbf _cb .Buffer ;_ceba =_dc .Write (&_abbf );if _ceba !=nil {_e .Log .Debug ("\u0045\u0052\u0052\u004f\u0052\u0020W\u0072\u0069\u0074\u0069\u006e\u0067\u0020\u0066\u006f\u006e\u0074\u003a\u0020%\u0076\u0020\u002d\u0020\u0069\u0067\u006eo\u0072\u0069\u006e\u0067",_ceba );
|
|
|
|
continue ;};if _abbf .Len ()> len (_fgf ){_e .Log .Debug ("\u0052\u0065-\u0077\u0072\u0069\u0074\u0074\u0065\u006e\u0020\u0066\u006f\u006e\u0074\u0020\u0069\u0073\u0020\u006c\u0061\u0072\u0067\u0065\u0072\u0020\u0074\u0068\u0061\u006e\u0020\u006f\u0072\u0069\u0067\u0069\u006e\u0061\u006c\u0020\u002d\u0020\u0073\u006b\u0069\u0070");
|
|
|
|
continue ;};_abc ,_ceba :=_cf .MakeStream (_abbf .Bytes (),_cf .NewFlateEncoder ());if _ceba !=nil {continue ;};*_aab =*_abc ;_aab .Set ("\u004ce\u006e\u0067\u0074\u0068\u0031",_cf .MakeInteger (int64 (_abbf .Len ())));};return objects ,nil ;};
|
2022-12-15 21:59:56 +00:00
|
|
|
|
2023-02-07 17:17:49 +00:00
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
|
|
func (_dce *ImagePPI )Optimize (objects []_cf .PdfObject )(_ddaa []_cf .PdfObject ,_fff error ){if _dce .ImageUpperPPI <=0{return objects ,nil ;};_bbec :=_ffe (objects );if len (_bbec )==0{return objects ,nil ;};_bfdb :=make (map[_cf .PdfObject ]struct{});
|
|
|
|
for _ ,_eadc :=range _bbec {_faed :=_eadc .Stream .PdfObjectDictionary .Get ("\u0053\u004d\u0061s\u006b");_bfdb [_faed ]=struct{}{};};_cbff :=make (map[*_cf .PdfObjectStream ]*imageInfo );for _ ,_cbcd :=range _bbec {_cbff [_cbcd .Stream ]=_cbcd ;};var _gab *_cf .PdfObjectDictionary ;
|
|
|
|
for _ ,_caa :=range objects {if _ddb ,_gddc :=_cf .GetDict (_caa );_gab ==nil &&_gddc {if _bdee ,_egfg :=_cf .GetName (_ddb .Get ("\u0054\u0079\u0070\u0065"));_egfg &&*_bdee =="\u0043a\u0074\u0061\u006c\u006f\u0067"{_gab =_ddb ;};};};if _gab ==nil {return objects ,nil ;
|
|
|
|
};_agag ,_caag :=_cf .GetDict (_gab .Get ("\u0050\u0061\u0067e\u0073"));if !_caag {return objects ,nil ;};_bbee ,_afge :=_cf .GetArray (_agag .Get ("\u004b\u0069\u0064\u0073"));if !_afge {return objects ,nil ;};for _ ,_aed :=range _bbee .Elements (){_abca :=make (map[string ]*imageInfo );
|
|
|
|
_eed ,_fge :=_cf .GetDict (_aed );if !_fge {continue ;};_bgf ,_ :=_dagb (_eed .Get ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073"));if len (_bgf )==0{continue ;};_baba ,_bdc :=_cf .GetDict (_eed .Get ("\u0052e\u0073\u006f\u0075\u0072\u0063\u0065s"));
|
|
|
|
if !_bdc {continue ;};_abab ,_ffgb :=_fg .NewPdfPageResourcesFromDict (_baba );if _ffgb !=nil {_e .Log .Debug ("\u0045\u0052\u0052\u004f\u0052\u0020\u0070\u0061\u0072\u0073\u0069\u006e\u0067\u0020\u0072\u0065\u0073\u006f\u0075\u0072\u0063\u0065\u0073\u0020-\u0020\u0069\u0067\u006e\u006fr\u0069\u006eg\u003a\u0020\u0025\u0076",_ffgb );
|
|
|
|
continue ;};_dbgf ,_aegag :=_cf .GetDict (_baba .Get ("\u0058O\u0062\u006a\u0065\u0063\u0074"));if !_aegag {continue ;};_eaba :=_dbgf .Keys ();for _ ,_cac :=range _eaba {if _bbc ,_ega :=_cf .GetStream (_dbgf .Get (_cac ));_ega {if _bbg ,_afb :=_cbff [_bbc ];
|
|
|
|
_afb {_abca [string (_cac )]=_bbg ;};};};_fea :=_af .NewContentStreamParser (_bgf );_dcab ,_ffgb :=_fea .Parse ();if _ffgb !=nil {_e .Log .Debug ("\u0045\u0052\u0052\u004f\u0052\u003a\u0020\u0025\u002b\u0076",_ffgb );continue ;};_ddc :=_af .NewContentStreamProcessor (*_dcab );
|
|
|
|
_ddc .AddHandler (_af .HandlerConditionEnumAllOperands ,"",func (_dac *_af .ContentStreamOperation ,_dgd _af .GraphicsState ,_abfc *_fg .PdfPageResources )error {switch _dac .Operand {case "\u0044\u006f":if len (_dac .Params )!=1{_e .Log .Debug ("E\u0052\u0052\u004f\u0052\u003a\u0020\u0049\u0067\u006e\u006f\u0072\u0069\u006e\u0067\u0020\u0044\u006f\u0020w\u0069\u0074\u0068\u0020\u006c\u0065\u006e\u0028\u0070\u0061ra\u006d\u0073\u0029 \u0021=\u0020\u0031");
|
|
|
|
return nil ;};_bba ,_ebccc :=_cf .GetName (_dac .Params [0]);if !_ebccc {_e .Log .Debug ("\u0045\u0052\u0052O\u0052\u003a\u0020\u0049\u0067\u006e\u006f\u0072\u0069\u006e\u0067\u0020\u0044\u006f\u0020\u0077\u0069\u0074\u0068\u0020\u006e\u006f\u006e\u0020\u004e\u0061\u006d\u0065\u0020p\u0061\u0072\u0061\u006d\u0065\u0074\u0065\u0072");
|
|
|
|
return nil ;};if _eea ,_dcf :=_abca [string (*_bba )];_dcf {_cbcf :=_dgd .CTM .ScalingFactorX ();_cffbb :=_dgd .CTM .ScalingFactorY ();_fegg ,_aaed :=_cbcf /72.0,_cffbb /72.0;_egca ,_aad :=float64 (_eea .Width )/_fegg ,float64 (_eea .Height )/_aaed ;if _fegg ==0||_aaed ==0{_egca =72.0;
|
|
|
|
_aad =72.0;};_eea .PPI =_gd .Max (_eea .PPI ,_egca );_eea .PPI =_gd .Max (_eea .PPI ,_aad );};};return nil ;});_ffgb =_ddc .Process (_abab );if _ffgb !=nil {_e .Log .Debug ("E\u0052\u0052\u004f\u0052 p\u0072o\u0063\u0065\u0073\u0073\u0069n\u0067\u003a\u0020\u0025\u002b\u0076",_ffgb );
|
|
|
|
continue ;};};for _ ,_ged :=range _bbec {if _ ,_bfgf :=_bfdb [_ged .Stream ];_bfgf {continue ;};if _ged .PPI <=_dce .ImageUpperPPI {continue ;};_fggb ,_ffagg :=_fg .NewXObjectImageFromStream (_ged .Stream );if _ffagg !=nil {_e .Log .Debug ("\u0045\u0052\u0052\u004f\u0052\u003a\u0020\u0025\u002b\u0076",_ffagg );
|
|
|
|
continue ;};var _fad imageModifications ;_fad .Scale =_dce .ImageUpperPPI /_ged .PPI ;if _ged .BitsPerComponent ==1&&_ged .ColorComponents ==1{_dcc :=_gd .Round (_ged .PPI /_dce .ImageUpperPPI );_fggbf :=_a .NextPowerOf2 (uint (_dcc ));if _a .InDelta (float64 (_fggbf ),1/_fad .Scale ,0.3){_fad .Scale =float64 (1)/float64 (_fggbf );
|
|
|
|
};if _ ,_gddb :=_fggb .Filter .(*_cf .JBIG2Encoder );!_gddb {_fad .Encoding =_cf .NewJBIG2Encoder ();};};if _ffagg =_fbff (_fggb ,_fad );_ffagg !=nil {_e .Log .Debug ("\u0045\u0072\u0072\u006f\u0072 \u0073\u0063\u0061\u006c\u0065\u0020\u0069\u006d\u0061\u0067\u0065\u0020\u006be\u0065\u0070\u0020\u006f\u0072\u0069\u0067\u0069\u006e\u0061\u006c\u0020\u0069\u006d\u0061\u0067\u0065\u003a\u0020\u0025\u0073",_ffagg );
|
|
|
|
continue ;};_fad .Encoding =nil ;if _agaa ,_bdcb :=_cf .GetStream (_ged .Stream .PdfObjectDictionary .Get ("\u0053\u004d\u0061s\u006b"));_bdcb {_dcg ,_bgb :=_fg .NewXObjectImageFromStream (_agaa );if _bgb !=nil {_e .Log .Debug ("\u0045\u0052\u0052\u004f\u0052\u003a\u0020\u0025\u002b\u0076",_bgb );
|
|
|
|
continue ;};if _bgb =_fbff (_dcg ,_fad );_bgb !=nil {_e .Log .Debug ("\u0045\u0052\u0052\u004f\u0052\u003a\u0020\u0025\u002b\u0076",_bgb );continue ;};};};return objects ,nil ;};
|
2022-12-15 21:59:56 +00:00
|
|
|
|
2023-02-07 17:17:49 +00:00
|
|
|
// CleanContentstream cleans up redundant operands in content streams, including Page and XObject Form
|
|
|
|
// contents. This process includes:
|
|
|
|
// 1. Marked content operators are removed.
|
|
|
|
// 2. Some operands are simplified (shorter form).
|
|
|
|
// TODO: Add more reduction methods and improving the methods for identifying unnecessary operands.
|
|
|
|
type CleanContentstream struct{};
|
2022-07-13 21:28:43 +00:00
|
|
|
|
2023-02-07 17:17:49 +00:00
|
|
|
// CombineDuplicateStreams combines duplicated streams by its data hash.
|
2023-01-08 22:34:27 +00:00
|
|
|
// It implements interface model.Optimizer.
|
2023-02-07 17:17:49 +00:00
|
|
|
type CombineDuplicateStreams struct{};func _gf (_de *_af .ContentStreamOperations )*_af .ContentStreamOperations {if _de ==nil {return nil ;};_ab :=_af .ContentStreamOperations {};for _ ,_cd :=range *_de {switch _cd .Operand {case "\u0042\u0044\u0043","\u0042\u004d\u0043","\u0045\u004d\u0043":continue ;
|
|
|
|
case "\u0054\u006d":if len (_cd .Params )==6{if _gbd ,_da :=_cf .GetNumbersAsFloat (_cd .Params );_da ==nil {if _gbd [0]==1&&_gbd [1]==0&&_gbd [2]==0&&_gbd [3]==1{_cd =&_af .ContentStreamOperation {Params :[]_cf .PdfObject {_cd .Params [4],_cd .Params [5]},Operand :"\u0054\u0064"};
|
|
|
|
};};};};_ab =append (_ab ,_cd );};return &_ab ;};
|
2021-04-23 20:28:14 +00:00
|
|
|
|
2022-10-27 19:04:58 +00:00
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
2023-02-07 17:17:49 +00:00
|
|
|
func (_ge *CleanContentstream )Optimize (objects []_cf .PdfObject )(_abb []_cf .PdfObject ,_abf error ){_fd :=map[*_cf .PdfObjectStream ]struct{}{};var _cfa []*_cf .PdfObjectStream ;_fe :=func (_gc *_cf .PdfObjectStream ){if _ ,_eag :=_fd [_gc ];!_eag {_fd [_gc ]=struct{}{};
|
|
|
|
_cfa =append (_cfa ,_gc );};};_gbf :=map[_cf .PdfObject ]bool {};_eac :=map[_cf .PdfObject ]bool {};for _ ,_ddg :=range objects {switch _bc :=_ddg .(type ){case *_cf .PdfIndirectObject :switch _ba :=_bc .PdfObject .(type ){case *_cf .PdfObjectDictionary :if _adg ,_bfb :=_cf .GetName (_ba .Get ("\u0054\u0079\u0070\u0065"));
|
|
|
|
!_bfb ||_adg .String ()!="\u0050\u0061\u0067\u0065"{continue ;};if _bag ,_ded :=_cf .GetStream (_ba .Get ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073"));_ded {_fe (_bag );}else if _ef ,_gee :=_cf .GetArray (_ba .Get ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073"));
|
|
|
|
_gee {var _bab []*_cf .PdfObjectStream ;for _ ,_bac :=range _ef .Elements (){if _aa ,_ec :=_cf .GetStream (_bac );_ec {_bab =append (_bab ,_aa );};};if len (_bab )> 0{var _geg _cb .Buffer ;for _ ,_beb :=range _bab {if _ce ,_bfc :=_cf .DecodeStream (_beb );
|
|
|
|
_bfc ==nil {_geg .Write (_ce );};_gbf [_beb ]=true ;};_fba ,_cff :=_cf .MakeStream (_geg .Bytes (),_cf .NewFlateEncoder ());if _cff !=nil {return nil ,_cff ;};_eac [_fba ]=true ;_ba .Set ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073",_fba );_fe (_fba );
|
|
|
|
};};};case *_cf .PdfObjectStream :if _efg ,_ggb :=_cf .GetName (_bc .Get ("\u0054\u0079\u0070\u0065"));!_ggb ||_efg .String ()!="\u0058O\u0062\u006a\u0065\u0063\u0074"{continue ;};if _adgf ,_eba :=_cf .GetName (_bc .Get ("\u0053u\u0062\u0074\u0079\u0070\u0065"));
|
|
|
|
!_eba ||_adgf .String ()!="\u0046\u006f\u0072\u006d"{continue ;};_fe (_bc );};};for _ ,_eg :=range _cfa {_abf =_gg (_eg );if _abf !=nil {return nil ,_abf ;};};_abb =nil ;for _ ,_ecd :=range objects {if _gbf [_ecd ]{continue ;};_abb =append (_abb ,_ecd );
|
|
|
|
};for _gdg :=range _eac {_abb =append (_abb ,_gdg );};return _abb ,nil ;};func _dgg (_bebd _cf .PdfObject )[]content {if _bebd ==nil {return nil ;};_eff ,_fbf :=_cf .GetArray (_bebd );if !_fbf {_e .Log .Debug ("\u0041\u006e\u006e\u006fts\u0020\u006e\u006f\u0074\u0020\u0061\u006e\u0020\u0061\u0072\u0072\u0061\u0079");
|
|
|
|
return nil ;};var _bebe []content ;for _ ,_aeg :=range _eff .Elements (){_geec ,_fca :=_cf .GetDict (_aeg );if !_fca {_e .Log .Debug ("I\u0067\u006e\u006f\u0072\u0069\u006eg\u0020\u006e\u006f\u006e\u002d\u0064i\u0063\u0074\u0020\u0065\u006c\u0065\u006de\u006e\u0074\u0020\u0069\u006e\u0020\u0041\u006e\u006e\u006ft\u0073");
|
|
|
|
continue ;};_acaf ,_fca :=_cf .GetDict (_geec .Get ("\u0041\u0050"));if !_fca {_e .Log .Debug ("\u004e\u006f\u0020\u0041P \u0065\u006e\u0074\u0072\u0079\u0020\u002d\u0020\u0073\u006b\u0069\u0070\u0070\u0069n\u0067");continue ;};_bdbf :=_cf .TraceToDirectObject (_acaf .Get ("\u004e"));
|
|
|
|
if _bdbf ==nil {_e .Log .Debug ("N\u006f\u0020\u004e\u0020en\u0074r\u0079\u0020\u002d\u0020\u0073k\u0069\u0070\u0070\u0069\u006e\u0067");continue ;};var _fcaf *_cf .PdfObjectStream ;switch _afgf :=_bdbf .(type ){case *_cf .PdfObjectDictionary :_fbaa ,_bde :=_cf .GetName (_geec .Get ("\u0041\u0053"));
|
|
|
|
if !_bde {_e .Log .Debug ("\u004e\u006f\u0020\u0041S \u0065\u006e\u0074\u0072\u0079\u0020\u002d\u0020\u0073\u006b\u0069\u0070\u0070\u0069n\u0067");continue ;};_fcaf ,_bde =_cf .GetStream (_afgf .Get (*_fbaa ));if !_bde {_e .Log .Debug ("\u0046o\u0072\u006d\u0020\u006eo\u0074\u0020\u0066\u006f\u0075n\u0064 \u002d \u0073\u006b\u0069\u0070\u0070\u0069\u006eg");
|
|
|
|
continue ;};case *_cf .PdfObjectStream :_fcaf =_afgf ;};if _fcaf ==nil {_e .Log .Debug ("\u0046\u006f\u0072m\u0020\u006e\u006f\u0074 \u0066\u006f\u0075\u006e\u0064\u0020\u0028n\u0069\u006c\u0029\u0020\u002d\u0020\u0073\u006b\u0069\u0070\u0070\u0069\u006e\u0067");
|
|
|
|
continue ;};_eab ,_fbae :=_fg .NewXObjectFormFromStream (_fcaf );if _fbae !=nil {_e .Log .Debug ("\u0045\u0072\u0072\u006f\u0072\u0020l\u006f\u0061\u0064\u0069\u006e\u0067\u0020\u0066\u006f\u0072\u006d\u003a\u0020%\u0076\u0020\u002d\u0020\u0069\u0067\u006eo\u0072\u0069\u006e\u0067",_fbae );
|
|
|
|
continue ;};_faaf ,_fbae :=_eab .GetContentStream ();if _fbae !=nil {_e .Log .Debug ("E\u0072\u0072\u006f\u0072\u0020\u0064e\u0063\u006f\u0064\u0069\u006e\u0067\u0020\u0063\u006fn\u0074\u0065\u006et\u0073:\u0020\u0025\u0076",_fbae );continue ;};_bebe =append (_bebe ,content {_fcc :string (_faaf ),_gga :_eab .Resources });
|
|
|
|
};return _bebe ;};
|
2022-06-06 22:48:24 +00:00
|
|
|
|
2023-02-07 17:17:49 +00:00
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
|
|
func (_bef *CompressStreams )Optimize (objects []_cf .PdfObject )(_fbfc []_cf .PdfObject ,_bcd error ){_fbfc =make ([]_cf .PdfObject ,len (objects ));copy (_fbfc ,objects );for _ ,_aega :=range objects {_edd ,_gfcc :=_cf .GetStream (_aega );if !_gfcc {continue ;
|
|
|
|
};if _ffgc :=_edd .Get ("\u0046\u0069\u006c\u0074\u0065\u0072");_ffgc !=nil {if _ ,_edac :=_cf .GetName (_ffgc );_edac {continue ;};if _ceg ,_gcd :=_cf .GetArray (_ffgc );_gcd &&_ceg .Len ()> 0{continue ;};};_aga :=_cf .NewFlateEncoder ();var _bfg []byte ;
|
|
|
|
_bfg ,_bcd =_aga .EncodeBytes (_edd .Stream );if _bcd !=nil {return _fbfc ,_bcd ;};_dadg :=_aga .MakeStreamDict ();if len (_bfg )+len (_dadg .WriteString ())< len (_edd .Stream ){_edd .Stream =_bfg ;_edd .PdfObjectDictionary .Merge (_dadg );_edd .PdfObjectDictionary .Set ("\u004c\u0065\u006e\u0067\u0074\u0068",_cf .MakeInteger (int64 (len (_edd .Stream ))));
|
|
|
|
};};return _fbfc ,nil ;};
|
2022-09-23 18:05:51 +00:00
|
|
|
|
2022-10-27 19:04:58 +00:00
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
2023-02-07 17:17:49 +00:00
|
|
|
func (_fb *Chain )Optimize (objects []_cf .PdfObject )(_gb []_cf .PdfObject ,_cba error ){_ca :=objects ;for _ ,_bf :=range _fb ._eef {_ad ,_d :=_bf .Optimize (_ca );if _d !=nil {_e .Log .Debug ("\u0045\u0052\u0052OR\u0020\u004f\u0070\u0074\u0069\u006d\u0069\u007a\u0061\u0074\u0069\u006f\u006e\u003a\u0020\u0025\u002b\u0076",_d );
|
|
|
|
continue ;};_ca =_ad ;};return _ca ,nil ;};
|