unipdf/model/optimize/optimize.go

99 lines
34 KiB
Go
Raw Normal View History

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/
2021-01-26 01:31:56 +00:00
package optimize ;import (_f "bytes";_e "crypto/md5";_bf "errors";_c "fmt";_ee "github.com/unidoc/unipdf/v3/common";_fb "github.com/unidoc/unipdf/v3/contentstream";_ge "github.com/unidoc/unipdf/v3/core";_bc "github.com/unidoc/unipdf/v3/extractor";_ec "github.com/unidoc/unipdf/v3/internal/textencoding";_a "github.com/unidoc/unipdf/v3/model";_cf "github.com/unidoc/unitype";_gb "golang.org/x/image/draw";_b "image";_gc "math";);
2020-08-27 21:45:09 +00:00
2021-01-07 14:20:10 +00:00
// CleanFonts cleans up embedded fonts, reducing font sizes.
type CleanFonts struct{
2020-08-27 21:45:09 +00:00
2021-01-07 14:20:10 +00:00
// Subset embedded fonts if encountered (if true).
// Otherwise attempts to reduce the font program.
Subset bool ;};
2020-08-27 21:45:09 +00:00
2021-01-26 01:31: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.
type ImagePPI struct{ImageUpperPPI float64 ;};func _dc (_ea *_ge .PdfObjectStream )error {_ba ,_fbab :=_ge .DecodeStream (_ea );if _fbab !=nil {return _fbab ;};_fa :=_fb .NewContentStreamParser (string (_ba ));_dd ,_fbab :=_fa .Parse ();if _fbab !=nil {return _fbab ;};_dd =_fg (_dd );_ac :=_dd .Bytes ();if len (_ac )>=len (_ba ){return nil ;};_bfa ,_fbab :=_ge .MakeStream (_dd .Bytes (),_ge .NewFlateEncoder ());if _fbab !=nil {return _fbab ;};_ea .Stream =_bfa .Stream ;_ea .Merge (_bfa .PdfObjectDictionary );return nil ;};
// 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 _cce (_bacc *_ge .PdfObjectStream ,_bgca float64 )error {_fggg ,_bggb :=_a .NewXObjectImageFromStream (_bacc );if _bggb !=nil {return _bggb ;};_dfgg ,_bggb :=_fggg .ToImage ();if _bggb !=nil {return _bggb ;};_ecfg ,_bggb :=_dfgg .ToGoImage ();if _bggb !=nil {return _bggb ;};_aed :=int (_gc .RoundToEven (float64 (_dfgg .Width )*_bgca ));_dfeg :=int (_gc .RoundToEven (float64 (_dfgg .Height )*_bgca ));_dfga :=_b .Rect (0,0,_aed ,_dfeg );var _agag _gb .Image ;var _afdc func (_b .Image )(*_a .Image ,error );switch _fggg .ColorSpace .String (){case "\u0044e\u0076\u0069\u0063\u0065\u0052\u0047B":_agag =_b .NewRGBA (_dfga );_afdc =_a .ImageHandling .NewImageFromGoImage ;case "\u0044\u0065\u0076\u0069\u0063\u0065\u0047\u0072\u0061\u0079":_agag =_b .NewGray (_dfga );_afdc =_a .ImageHandling .NewGrayImageFromGoImage ;default:return _c .Errorf ("\u006f\u0070\u0074\u0069\u006d\u0069\u007a\u0061t\u0069\u006f\u006e i\u0073\u0020\u006e\u006f\u0074\u0020s\u0075\u0070\u0070\u006f\u0072\u0074\u0065\u0064\u0020\u0066\u006f\u0072\u0020\u0063\u006fl\u006f\u0072\u0020\u0073\u0070\u0061\u0063\u0065 \u0025\u0073",_fggg .ColorSpace .String ());};_gb .CatmullRom .Scale (_agag ,_agag .Bounds (),_ecfg ,_ecfg .Bounds (),_gb .Over ,&_gb .Options {});if _dfgg ,_bggb =_afdc (_agag );_bggb !=nil {return _bggb ;};_afc :=_ge .MakeDict ();_afc .Set ("\u0051u\u0061\u006c\u0069\u0074\u0079",_ge .MakeInteger (100));_afc .Set ("\u0050r\u0065\u0064\u0069\u0063\u0074\u006fr",_ge .MakeInteger (1));_fggg .Filter .UpdateParams (_afc );if _bggb =_fggg .SetImage (_dfgg ,nil );_bggb !=nil {return _bggb ;};_fggg .ToPdfObject ();return nil ;};func _fg (_fba *_fb .ContentStreamOperations )*_fb .ContentStreamOperations {if _fba ==nil {return nil ;};_fd :=_fb .ContentStreamOperations {};for _ ,_ce :=range *_fba {switch _ce .Operand {case "\u0042\u0044\u0043","\u0042\u004d\u0043","\u0045\u004d\u0043":continue ;case "\u0054\u006d":if len (_ce .Params )==6{if _gcb ,_ceg :=_ge .GetNumbersAsFloat (_ce .Params );_ceg ==nil {if _gcb [0]==1&&_gcb [1]==0&&_gcb [2]==0&&_gcb [3]==1{_ce =&_fb .ContentStreamOperation {Params :[]_ge .PdfObject {_ce .Params [4],_ce .Params [5]},Operand :"\u0054\u0064"};};};};};_fd =append (_fd ,_ce );};return &_fd ;};func _baa (_acf *_ge .PdfObjectStream ,_be []rune ,_ad []_cf .GlyphIndex )error {_acf ,_ace :=_ge .GetStream (_acf );if !_ace {_ee .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 _bf .New ("\u0066\u006f\u006e\u0074fi\u006c\u0065\u0032\u0020\u006e\u006f\u0074\u0020\u0066\u006f\u0075\u006e\u0064");};_edd ,_aa :=_ge .DecodeStream (_acf );if _aa !=nil {_ee .Log .Debug ("\u0044\u0065c\u006f\u0064\u0065 \u0065\u0072\u0072\u006f\u0072\u003a\u0020\u0025\u0076",_aa );return _aa ;};_bef ,_aa :=_cf .Parse (_f .NewReader (_edd ));if _aa !=nil {_ee .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 (_acf .Stream ));return _aa ;};_dce :=_ad ;if len (_be )> 0{_cba :=_bef .LookupRunes (_be );_dce =append (_dce ,_cba ...);};_bef ,_aa =_bef .SubsetKeepIndices (_dce );if _aa !=nil {_ee .Log .Debug ("\u0045R\u0052\u004f\u0052\u0020s\u0075\u0062\u0073\u0065\u0074t\u0069n\u0067 \u0066\u006f\u006e\u0074\u003a\u0020\u0025v",_aa );return _aa ;};var _edf _f .Buffer ;_aa =_bef .Write (&_edf );if _aa !=nil {_ee .Log .Debug ("\u0045\u0052\u0052\u004fR \u0057\u0072\u0069\u0074\u0069\u006e\u0067\u0020\u0066\u006f\u006e\u0074\u003a\u0020%\u0076",_aa );return _aa ;};if _edf .Len ()> len (_edd ){_ee .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\
// CompressStreams compresses uncompressed streams.
// It implements interface model.Optimizer.
type CompressStreams struct{};
2020-09-28 23:18:17 +00:00
// Optimize optimizes PDF objects to decrease PDF size.
2021-01-26 01:31:56 +00:00
func (_bgea *ObjectStreams )Optimize (objects []_ge .PdfObject )(_gbbdf []_ge .PdfObject ,_cedg error ){_egcf :=&_ge .PdfObjectStreams {};_cceg :=make ([]_ge .PdfObject ,0,len (objects ));for _ ,_aeeg :=range objects {if _eefb ,_ddgf :=_aeeg .(*_ge .PdfIndirectObject );_ddgf &&_eefb .GenerationNumber ==0{_egcf .Append (_aeeg );}else {_cceg =append (_cceg ,_aeeg );};};if _egcf .Len ()==0{return _cceg ,nil ;};_gbbdf =make ([]_ge .PdfObject ,0,len (_cceg )+_egcf .Len ()+1);if _egcf .Len ()> 1{_gbbdf =append (_gbbdf ,_egcf );};_gbbdf =append (_gbbdf ,_egcf .Elements ()...);_gbbdf =append (_gbbdf ,_cceg ...);return _gbbdf ,nil ;};
2020-08-27 21:45:09 +00:00
2020-10-19 10:58:10 +00:00
// Optimize optimizes PDF objects to decrease PDF size.
2021-01-26 01:31:56 +00:00
func (_bggg *CompressStreams )Optimize (objects []_ge .PdfObject )(_dde []_ge .PdfObject ,_bbg error ){_dde =make ([]_ge .PdfObject ,len (objects ));copy (_dde ,objects );for _ ,_cdcc :=range objects {_gag ,_ddef :=_ge .GetStream (_cdcc );if !_ddef {continue ;};if _ggg :=_gag .Get ("\u0046\u0069\u006c\u0074\u0065\u0072");_ggg !=nil {if _ ,_dba :=_ge .GetName (_ggg );_dba {continue ;};if _eda ,_dae :=_ge .GetArray (_ggg );_dae &&_eda .Len ()> 0{continue ;};};_eeg :=_ge .NewFlateEncoder ();var _dec []byte ;_dec ,_bbg =_eeg .EncodeBytes (_gag .Stream );if _bbg !=nil {return _dde ,_bbg ;};_agg :=_eeg .MakeStreamDict ();if len (_dec )+len (_agg .WriteString ())< len (_gag .Stream ){_gag .Stream =_dec ;_gag .PdfObjectDictionary .Merge (_agg );_gag .PdfObjectDictionary .Set ("\u004c\u0065\u006e\u0067\u0074\u0068",_ge .MakeInteger (int64 (len (_gag .Stream ))));};};return _dde ,nil ;};
2020-08-27 21:45:09 +00:00
2020-11-11 18:48:37 +00:00
// Optimize optimizes PDF objects to decrease PDF size.
2021-01-26 01:31:56 +00:00
func (_cfaf *CombineDuplicateStreams )Optimize (objects []_ge .PdfObject )(_gff []_ge .PdfObject ,_bfc error ){_abe :=make (map[_ge .PdfObject ]_ge .PdfObject );_gcbd :=make (map[_ge .PdfObject ]struct{});_cgd :=make (map[string ][]*_ge .PdfObjectStream );for _ ,_add :=range objects {if _cbf ,_dfg :=_add .(*_ge .PdfObjectStream );_dfg {_ebgf :=_e .New ();_ebgf .Write (_cbf .Stream );_adg :=string (_ebgf .Sum (nil ));_cgd [_adg ]=append (_cgd [_adg ],_cbf );};};for _ ,_age :=range _cgd {if len (_age )< 2{continue ;};_cff :=_age [0];for _bcb :=1;_bcb < len (_age );_bcb ++{_effb :=_age [_bcb ];_abe [_effb ]=_cff ;_gcbd [_effb ]=struct{}{};};};_gff =make ([]_ge .PdfObject ,0,len (objects )-len (_gcbd ));for _ ,_ebbf :=range objects {if _ ,_bff :=_gcbd [_ebbf ];_bff {continue ;};_gff =append (_gff ,_ebbf );};_cbebd (_gff ,_abe );return _gff ,nil ;};type imageInfo struct{ColorSpace _ge .PdfObjectName ;BitsPerComponent int ;ColorComponents int ;Width int ;Height int ;Stream *_ge .PdfObjectStream ;PPI float64 ;};
2020-09-28 23:18:17 +00:00
2021-01-07 14:20:10 +00:00
// Optimize optimizes PDF objects to decrease PDF size.
2021-01-26 01:31:56 +00:00
func (_ccb *CleanFonts )Optimize (objects []_ge .PdfObject )(_bab []_ge .PdfObject ,_edfg error ){var _ceb map[*_ge .PdfObjectStream ]struct{};if _ccb .Subset {var _aecc error ;_ceb ,_aecc =_gbb (objects );if _aecc !=nil {return nil ,_aecc ;};};for _ ,_dgc :=range objects {_gbbd ,_fdc :=_ge .GetStream (_dgc );if !_fdc {continue ;};if _ ,_fbae :=_ceb [_gbbd ];_fbae {continue ;};_bdb ,_dad :=_ge .NewEncoderFromStream (_gbbd );if _dad !=nil {_ee .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",_dad );continue ;};_fded ,_dad :=_bdb .DecodeStream (_gbbd );if _dad !=nil {_ee .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",_dad );continue ;};if len (_fded )< 4{continue ;};_cbc :=string (_fded [:4]);if _cbc =="\u004f\u0054\u0054\u004f"{continue ;};if _cbc !="\u0000\u0001\u0000\u0000"&&_cbc !="\u0074\u0072\u0075\u0065"{continue ;};_abf ,_dad :=_cf .Parse (_f .NewReader (_fded ));if _dad !=nil {_ee .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",_dad );continue ;};_dad =_abf .Optimize ();if _dad !=nil {continue ;};var _bga _f .Buffer ;_dad =_abf .Write (&_bga );if _dad !=nil {_ee .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",_dad );continue ;};if _bga .Len ()> len (_fded ){_ee .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 ;};_afb ,_dad :=_ge .MakeStream (_bga .Bytes (),_ge .NewFlateEncoder ());if _dad !=nil {continue ;};*_gbbd =*_afb ;_gbbd .Set ("\u004ce\u006e\u0067\u0074\u0068\u0031",_ge .MakeInteger (int64 (_bga .Len ())));};return objects ,nil ;};func _efceb (_eagd []_ge .PdfObject )objectStructure {_bfef :=objectStructure {};_fffg :=false ;for _ ,_ebgg :=range _eagd {switch _acb :=_ebgg .(type ){case *_ge .PdfIndirectObject :_eaaa ,_aegg :=_ge .GetDict (_acb );if !_aegg {continue ;};_afcd ,_aegg :=_ge .GetName (_eaaa .Get ("\u0054\u0079\u0070\u0065"));if !_aegg {continue ;};switch _afcd .String (){case "\u0043a\u0074\u0061\u006c\u006f\u0067":_bfef ._abgg =_eaaa ;_fffg =true ;};};if _fffg {break ;};};if !_fffg {return _bfef ;};_eegd ,_eccg :=_ge .GetDict (_bfef ._abgg .Get ("\u0050\u0061\u0067e\u0073"));if !_eccg {return _bfef ;};_bfef ._eae =_eegd ;_eabg ,_eccg :=_ge .GetArray (_eegd .Get ("\u004b\u0069\u0064\u0073"));if !_eccg {return _bfef ;};for _ ,_cbec :=range _eabg .Elements (){_cegc ,_efbg :=_ge .GetIndirect (_cbec );if !_efbg {break ;};_bfef ._dfed =append (_bfef ._dfed ,_cegc );};return _bfef ;};
2020-12-06 13:03:03 +00:00
2021-01-26 01:31:56 +00:00
// CombineDuplicateStreams combines duplicated streams by its data hash.
// It implements interface model.Optimizer.
type CombineDuplicateStreams struct{};
2020-09-28 23:18:17 +00:00
2021-01-07 14:20:10 +00:00
// Chain allows to use sequence of optimizers.
2020-12-06 13:03:03 +00:00
// It implements interface model.Optimizer.
2021-01-26 01:31:56 +00:00
type Chain struct{_ef []_a .Optimizer };func _bafg (_abg []_ge .PdfObject ){for _bbgg ,_febd :=range _abg {switch _efce :=_febd .(type ){case *_ge .PdfIndirectObject :_efce .ObjectNumber =int64 (_bbgg +1);_efce .GenerationNumber =0;case *_ge .PdfObjectStream :_efce .ObjectNumber =int64 (_bbgg +1);_efce .GenerationNumber =0;case *_ge .PdfObjectStreams :_efce .ObjectNumber =int64 (_bbgg +1);_efce .GenerationNumber =0;};};};func _gbb (_gbcd []_ge .PdfObject )(_cfc map[*_ge .PdfObjectStream ]struct{},_gde error ){_cfc =map[*_ge .PdfObjectStream ]struct{}{};_edb :=map[*_a .PdfFont ]struct{}{};_ff :=_efceb (_gbcd );for _ ,_ga :=range _ff ._dfed {_afd ,_fde :=_ge .GetDict (_ga .PdfObject );if !_fde {continue ;};_gcd ,_fde :=_ge .GetDict (_afd .Get ("\u0052e\u0073\u006f\u0075\u0072\u0063\u0065s"));if !_fde {continue ;};_ebb ,_ :=_eggd (_afd .Get ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073"));_bda ,_eg :=_a .NewPdfPageResourcesFromDict (_gcd );if _eg !=nil {return nil ,_eg ;};_cfcc :=[]content {{_ddf :_ebb ,_fgg :_bda }};_fdef :=_fda (_afd .Get ("\u0041\u006e\u006e\u006f\u0074\u0073"));if _fdef !=nil {_cfcc =append (_cfcc ,_fdef ...);};for _ ,_cb :=range _cfcc {_bde ,_ddg :=_bc .NewFromContents (_cb ._ddf ,_cb ._fgg );if _ddg !=nil {return nil ,_ddg ;};_eaag ,_ ,_ ,_ddg :=_bde .ExtractPageText ();if _ddg !=nil {return nil ,_ddg ;};for _ ,_cc :=range _eaag .Marks ().Elements (){if _cc .Font ==nil {continue ;};if _ ,_eff :=_edb [_cc .Font ];!_eff {_edb [_cc .Font ]=struct{}{};};};};};_cfb :=map[*_ge .PdfObjectStream ][]*_a .PdfFont {};for _ecf :=range _edb {_edg :=_ecf .FontDescriptor ();if _edg ==nil ||_edg .FontFile2 ==nil {continue ;};_fgb ,_ffg :=_ge .GetStream (_edg .FontFile2 );if !_ffg {continue ;};_cfb [_fgb ]=append (_cfb [_fgb ],_ecf );};for _dcg :=range _cfb {var _cg []rune ;var _aga []_cf .GlyphIndex ;for _ ,_gcec :=range _cfb [_dcg ]{switch _bfb :=_gcec .Encoder ().(type ){case *_ec .IdentityEncoder :_bfd :=_bfb .RegisteredRunes ();_efaf :=make ([]_cf .GlyphIndex ,len (_bfd ));for _dfa ,_dfc :=range _bfd {_efaf [_dfa ]=_cf .GlyphIndex (_dfc );};_aga =append (_aga ,_efaf ...);case *_ec .TrueTypeFontEncoder :_efc :=_bfb .RegisteredRunes ();_cg =append (_cg ,_efc ...);case _ec .SimpleEncoder :_db :=_bfb .Charcodes ();for _ ,_aeg :=range _db {_cbe ,_dbd :=_bfb .CharcodeToRune (_aeg );if !_dbd {_ee .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",_aeg );continue ;};_cg =append (_cg ,_cbe );};};};_gde =_baa (_dcg ,_cg ,_aga );if _gde !=nil {_ee .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",_gde );return nil ,_gde ;};_cfc [_dcg ]=struct{}{};};return _cfc ,nil ;};
2020-12-06 13:03:03 +00:00
2021-01-26 01:31:56 +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 ;};
2020-09-21 01:20:10 +00:00
2020-11-11 18:48:37 +00:00
// CombineDuplicateDirectObjects combines duplicated direct objects by its data hash.
2020-09-21 01:20:10 +00:00
// It implements interface model.Optimizer.
2020-11-11 18:48:37 +00:00
type CombineDuplicateDirectObjects struct{};
2020-09-14 09:32:45 +00:00
2021-01-26 01:31:56 +00:00
// ObjectStreams groups PDF objects to object streams.
// It implements interface model.Optimizer.
type ObjectStreams struct{};
2021-01-07 14:20:10 +00:00
2021-01-26 01:31:56 +00:00
// New creates a optimizers chain from options.
func New (options Options )*Chain {_bba :=new (Chain );if options .CleanFonts ||options .SubsetFonts {_bba .Append (&CleanFonts {Subset :options .SubsetFonts });};if options .CleanContentstream {_bba .Append (new (CleanContentstream ));};if options .ImageUpperPPI > 0{_cea :=new (ImagePPI );_cea .ImageUpperPPI =options .ImageUpperPPI ;_bba .Append (_cea );};if options .ImageQuality > 0{_egca :=new (Image );_egca .ImageQuality =options .ImageQuality ;_bba .Append (_egca );};if options .CombineDuplicateDirectObjects {_bba .Append (new (CombineDuplicateDirectObjects ));};if options .CombineDuplicateStreams {_bba .Append (new (CombineDuplicateStreams ));};if options .CombineIdenticalIndirectObjects {_bba .Append (new (CombineIdenticalIndirectObjects ));};if options .UseObjectStreams {_bba .Append (new (ObjectStreams ));};if options .CompressStreams {_bba .Append (new (CompressStreams ));};return _bba ;};
// CombineIdenticalIndirectObjects combines identical indirect objects.
2020-12-06 13:03:03 +00:00
// It implements interface model.Optimizer.
2021-01-26 01:31:56 +00:00
type CombineIdenticalIndirectObjects struct{};
2020-11-23 22:15:56 +00:00
2020-12-06 13:03:03 +00:00
// Optimize optimizes PDF objects to decrease PDF size.
2021-01-26 01:31:56 +00:00
func (_faef *Image )Optimize (objects []_ge .PdfObject )(_cee []_ge .PdfObject ,_bec error ){if _faef .ImageQuality <=0{return objects ,nil ;};_dag :=_gggd (objects );if len (_dag )==0{return objects ,nil ;};_cfde :=make (map[_ge .PdfObject ]_ge .PdfObject );_edab :=make (map[_ge .PdfObject ]struct{});for _ ,_dfde :=range _dag {_abfa :=_dfde .Stream .PdfObjectDictionary .Get (_ge .PdfObjectName ("\u0053\u004d\u0061s\u006b"));_edab [_abfa ]=struct{}{};};for _bfcf ,_adb :=range _dag {_fgf :=_adb .Stream ;if _ ,_ffca :=_edab [_fgf ];_ffca {continue ;};_bgaa ,_gagd :=_ge .NewEncoderFromStream (_fgf );if _gagd !=nil {_ee .Log .Warning ("\u0045\u0072\u0072\u006f\u0072 \u0067\u0065\u0074\u0020\u0065\u006e\u0063\u006f\u0064\u0065\u0072\u0020\u0066o\u0072\u0020\u0074\u0068\u0065\u0020\u0069\u006d\u0061\u0067\u0065\u0020\u0073\u0074\u0072\u0065\u0061\u006d\u0020\u0025\u0073");continue ;};_beg ,_gagd :=_bgaa .DecodeStream (_fgf );if _gagd !=nil {_ee .Log .Warning ("\u0045\u0072\u0072\u006f\u0072\u0020\u0064\u0065\u0063\u006f\u0064\u0065\u0020\u0074\u0068e\u0020i\u006d\u0061\u0067\u0065\u0020\u0073\u0074\u0072\u0065\u0061\u006d\u0020\u0025\u0073");continue ;};_ggdc :=_ge .NewDCTEncoder ();_ggdc .ColorComponents =_adb .ColorComponents ;_ggdc .Quality =_faef .ImageQuality ;_ggdc .BitsPerComponent =_adb .BitsPerComponent ;_ggdc .Width =_adb .Width ;_ggdc .Height =_adb .Height ;_bbe ,_gagd :=_ggdc .EncodeBytes (_beg );if _gagd !=nil {_ee .Log .Debug ("\u0045R\u0052\u004f\u0052\u003a\u0020\u0025v",_gagd );return nil ,_gagd ;};var _bge _ge .StreamEncoder ;_bge =_ggdc ;{_cag :=_ge .NewFlateEncoder ();_bffd :=_ge .NewMultiEncoder ();_bffd .AddEncoder (_cag );_bffd .AddEncoder (_ggdc );_ccfc ,_cdf :=_bffd .EncodeBytes (_beg );if _cdf !=nil {return nil ,_cdf ;};if len (_ccfc )< len (_bbe ){_ee .Log .Debug ("\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 (_bbe ),len (_ccfc ),len (_fgf .Stream ));_bbe =_ccfc ;_bge =_bffd ;};};_dffc :=len (_fgf .Stream );if _dffc < len (_bbe ){continue ;};_adgd :=&_ge .PdfObjectStream {Stream :_bbe };_adgd .PdfObjectReference =_fgf .PdfObjectReference ;_adgd .PdfObjectDictionary =_ge .MakeDict ();_adgd .Merge (_fgf .PdfObjectDictionary );_adgd .Merge (_bge .MakeStreamDict ());_adgd .Set ("\u004c\u0065\u006e\u0067\u0074\u0068",_ge .MakeInteger (int64 (len (_bbe ))));_cfde [_fgf ]=_adgd ;_dag [_bfcf ].Stream =_adgd ;};_cee =make ([]_ge .PdfObject ,len (objects ));copy (_cee ,objects );_cbebd (_cee ,_cfde );return _cee ,nil ;};
2020-12-06 13:03:03 +00:00
2021-01-07 14:20:10 +00:00
// Optimize optimizes PDF objects to decrease PDF size.
2021-01-26 01:31:56 +00:00
func (_fcg *CombineIdenticalIndirectObjects )Optimize (objects []_ge .PdfObject )(_cefe []_ge .PdfObject ,_eaf error ){_bafg (objects );_gcf :=make (map[_ge .PdfObject ]_ge .PdfObject );_bgc :=make (map[_ge .PdfObject ]struct{});_gcff :=make (map[string ][]*_ge .PdfIndirectObject );for _ ,_bca :=range objects {_cdc ,_fgga :=_bca .(*_ge .PdfIndirectObject );if !_fgga {continue ;};if _edc ,_ecc :=_cdc .PdfObject .(*_ge .PdfObjectDictionary );_ecc {if _faed ,_bfaf :=_edc .Get ("\u0054\u0079\u0070\u0065").(*_ge .PdfObjectName );_bfaf &&*_faed =="\u0050\u0061\u0067\u0065"{continue ;};_dff :=_e .New ();_dff .Write ([]byte (_edc .WriteString ()));_bdgf :=string (_dff .Sum (nil ));_gcff [_bdgf ]=append (_gcff [_bdgf ],_cdc );};};for _ ,_egb :=range _gcff {if len (_egb )< 2{continue ;};_gcg :=_egb [0];for _bdga :=1;_bdga < len (_egb );_bdga ++{_fbd :=_egb [_bdga ];_gcf [_fbd ]=_gcg ;_bgc [_fbd ]=struct{}{};};};_cefe =make ([]_ge .PdfObject ,0,len (objects )-len (_bgc ));for _ ,_gdeg :=range objects {if _ ,_dfgd :=_bgc [_gdeg ];_dfgd {continue ;};_cefe =append (_cefe ,_gdeg );};_cbebd (_cefe ,_gcf );return _cefe ,nil ;};
2021-01-07 14:20:10 +00:00
2021-01-26 01:31:56 +00:00
// Optimize optimizes PDF objects to decrease PDF size.
func (_bg *Chain )Optimize (objects []_ge .PdfObject )(_ged []_ge .PdfObject ,_af error ){_ged =objects ;for _ ,_d :=range _bg ._ef {_ged ,_af =_d .Optimize (_ged );if _af !=nil {return _ged ,_af ;};};return _ged ,nil ;};func _cbebd (_gdge []_ge .PdfObject ,_eab map[_ge .PdfObject ]_ge .PdfObject ){if len (_eab )==0{return ;};for _bccf ,_dgb :=range _gdge {if _dbg ,_adbd :=_eab [_dgb ];_adbd {_gdge [_bccf ]=_dbg ;continue ;};_eab [_dgb ]=_dgb ;switch _affb :=_dgb .(type ){case *_ge .PdfObjectArray :_eafb :=make ([]_ge .PdfObject ,_affb .Len ());copy (_eafb ,_affb .Elements ());_cbebd (_eafb ,_eab );for _abb ,_ccgc :=range _eafb {_affb .Set (_abb ,_ccgc );};case *_ge .PdfObjectStreams :_cbebd (_affb .Elements (),_eab );case *_ge .PdfObjectStream :_eag :=[]_ge .PdfObject {_affb .PdfObjectDictionary };_cbebd (_eag ,_eab );_affb .PdfObjectDictionary =_eag [0].(*_ge .PdfObjectDictionary );case *_ge .PdfObjectDictionary :_abdc :=_affb .Keys ();_ceba :=make ([]_ge .PdfObject ,len (_abdc ));for _ffe ,_gbe :=range _abdc {_ceba [_ffe ]=_affb .Get (_gbe );};_cbebd (_ceba ,_eab );for _dbac ,_gge :=range _abdc {_affb .Set (_gge ,_ceba [_dbac ]);};case *_ge .PdfIndirectObject :_cedgf :=[]_ge .PdfObject {_affb .PdfObject };_cbebd (_cedgf ,_eab );_affb .PdfObject =_cedgf [0];};};};
// Optimize optimizes PDF objects to decrease PDF size.
func (_afe *CombineDuplicateDirectObjects )Optimize (objects []_ge .PdfObject )(_gedd []_ge .PdfObject ,_aca error ){_bafg (objects );_fag :=make (map[string ][]*_ge .PdfObjectDictionary );var _bae func (_fgc *_ge .PdfObjectDictionary );_bae =func (_ccg *_ge .PdfObjectDictionary ){for _ ,_afda :=range _ccg .Keys (){_ebg :=_ccg .Get (_afda );if _bdbb ,_afbd :=_ebg .(*_ge .PdfObjectDictionary );_afbd {_gbbg :=_e .New ();_gbbg .Write ([]byte (_bdbb .WriteString ()));_ebba :=string (_gbbg .Sum (nil ));_fag [_ebba ]=append (_fag [_ebba ],_bdbb );_bae (_bdbb );};};};for _ ,_gbbb :=range objects {_fdgg ,_gcad :=_gbbb .(*_ge .PdfIndirectObject );if !_gcad {continue ;};if _daa ,_ade :=_fdgg .PdfObject .(*_ge .PdfObjectDictionary );_ade {_bae (_daa );};};_cd :=make ([]_ge .PdfObject ,0,len (_fag ));_eee :=make (map[_ge .PdfObject ]_ge .PdfObject );for _ ,_gf :=range _fag {if len (_gf )< 2{continue ;};_fff :=_ge .MakeDict ();_fff .Merge (_gf [0]);_egg :=_ge .MakeIndirectObject (_fff );_cd =append (_cd ,_egg );for _cgc :=0;_cgc < len (_gf );_cgc ++{_aba :=_gf [_cgc ];_eee [_aba ]=_egg ;};};_gedd =make ([]_ge .PdfObject ,len (objects ));copy (_gedd ,objects );_gedd =append (_cd ,_gedd ...);_cbebd (_gedd ,_eee );return _gedd ,nil ;};type content struct{_ddf string ;_fgg *_a .PdfPageResources ;};func _fda (_bbf _ge .PdfObject )[]content {if _bbf ==nil {return nil ;};_ccf ,_aaa :=_ge .GetArray (_bbf );if !_aaa {_ee .Log .Debug ("\u0041\u006e\u006e\u006fts\u0020\u006e\u006f\u0074\u0020\u0061\u006e\u0020\u0061\u0072\u0072\u0061\u0079");return nil ;};var _fea []content ;for _ ,_ecg :=range _ccf .Elements (){_gef ,_fgd :=_ge .GetDict (_ecg );if !_fgd {_ee .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 ;};_edfa ,_fgd :=_ge .GetDict (_gef .Get ("\u0041\u0050"));if !_fgd {_ee .Log .Debug ("\u004e\u006f\u0020\u0041P \u0065\u006e\u0074\u0072\u0079\u0020\u002d\u0020\u0073\u006b\u0069\u0070\u0070\u0069n\u0067");continue ;};_gg :=_ge .TraceToDirectObject (_edfa .Get ("\u004e"));if _gg ==nil {_ee .Log .Debug ("N\u006f\u0020\u004e\u0020en\u0074r\u0079\u0020\u002d\u0020\u0073k\u0069\u0070\u0070\u0069\u006e\u0067");continue ;};var _bgg *_ge .PdfObjectStream ;switch _fae :=_gg .(type ){case *_ge .PdfObjectDictionary :_fgge ,_afa :=_ge .GetName (_gef .Get ("\u0041\u0053"));if !_afa {_ee .Log .Debug ("\u004e\u006f\u0020\u0041S \u0065\u006e\u0074\u0072\u0079\u0020\u002d\u0020\u0073\u006b\u0069\u0070\u0070\u0069n\u0067");continue ;};_bgg ,_afa =_ge .GetStream (_fae .Get (*_fgge ));if !_afa {_ee .Log .Debug ("\u0046o\u0072\u006d\u0020\u006eo\u0074\u0020\u0066\u006f\u0075n\u0064 \u002d \u0073\u006b\u0069\u0070\u0070\u0069\u006eg");continue ;};case *_ge .PdfObjectStream :_bgg =_fae ;};if _bgg ==nil {_ee .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 ;};_gca ,_feg :=_a .NewXObjectFormFromStream (_bgg );if _feg !=nil {_ee .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",_feg );continue ;};_bdg ,_feg :=_gca .GetContentStream ();if _feg !=nil {_ee .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",_feg );continue ;};_fea =append (_fea ,content {_ddf :string (_bdg ),_fgg :_gca .Resources });};return _fea ;};type objectStructure struct{_abgg *_ge .PdfObjectDictionary ;_eae *_ge .PdfObjectDictionary ;_dfed []*_ge .PdfIndirectObject ;};
2020-12-06 13:03:03 +00:00
2021-01-07 14:20:10 +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.
2021-01-26 01:31:56 +00:00
type CleanContentstream struct{};
2020-10-05 19:28:24 +00:00
2020-11-11 18:48:37 +00:00
// Optimize optimizes PDF objects to decrease PDF size.
2021-01-26 01:31:56 +00:00
func (_def *ImagePPI )Optimize (objects []_ge .PdfObject )(_ebbe []_ge .PdfObject ,_afaf error ){if _def .ImageUpperPPI <=0{return objects ,nil ;};_cbd :=_gggd (objects );if len (_cbd )==0{return objects ,nil ;};_abfac :=make (map[_ge .PdfObject ]struct{});for _ ,_bgd :=range _cbd {_gdc :=_bgd .Stream .PdfObjectDictionary .Get (_ge .PdfObjectName ("\u0053\u004d\u0061s\u006b"));_abfac [_gdc ]=struct{}{};};_dgd :=make (map[*_ge .PdfObjectStream ]*imageInfo );for _ ,_acd :=range _cbd {_dgd [_acd .Stream ]=_acd ;};var _cffa *_ge .PdfObjectDictionary ;for _ ,_dffd :=range objects {if _bfce ,_bgbc :=_ge .GetDict (_dffd );_cffa ==nil &&_bgbc {if _fbdb ,_babc :=_ge .GetName (_bfce .Get (_ge .PdfObjectName ("\u0054\u0079\u0070\u0065")));_babc &&*_fbdb =="\u0043a\u0074\u0061\u006c\u006f\u0067"{_cffa =_bfce ;};};};if _cffa ==nil {return objects ,nil ;};_faefg ,_edbe :=_ge .GetDict (_cffa .Get (_ge .PdfObjectName ("\u0050\u0061\u0067e\u0073")));if !_edbe {return objects ,nil ;};_caeg ,_fdag :=_ge .GetArray (_faefg .Get (_ge .PdfObjectName ("\u004b\u0069\u0064\u0073")));if !_fdag {return objects ,nil ;};_fdaa :=make (map[string ]*imageInfo );for _ ,_dcd :=range _caeg .Elements (){_afef ,_dgcd :=_ge .GetDict (_dcd );if !_dgcd {continue ;};_cfae ,_ced :=_ge .GetArray (_afef .Get ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073"));if !_ced {continue ;};_fbf ,_fgbe :=_ge .GetDict (_afef .Get ("\u0052e\u0073\u006f\u0075\u0072\u0063\u0065s"));if !_fgbe {continue ;};_dafb ,_fcf :=_ge .GetDict (_fbf .Get ("\u0058O\u0062\u006a\u0065\u0063\u0074"));if !_fcf {continue ;};_facf :=_dafb .Keys ();for _ ,_bbeb :=range _facf {if _fga ,_aff :=_ge .GetStream (_dafb .Get (_bbeb ));_aff {if _defg ,_eba :=_dgd [_fga ];_eba {_fdaa [string (_bbeb )]=_defg ;};};};for _ ,_gefg :=range _cfae .Elements (){if _cab ,_cbca :=_ge .GetStream (_gefg );_cbca {_ddc ,_egcg :=_ge .NewEncoderFromStream (_cab );if _egcg !=nil {return nil ,_egcg ;};_cfe ,_egcg :=_ddc .DecodeStream (_cab );if _egcg !=nil {return nil ,_egcg ;};_aeccf :=_fb .NewContentStreamParser (string (_cfe ));_cbda ,_egcg :=_aeccf .Parse ();if _egcg !=nil {return nil ,_egcg ;};_dge ,_cega :=1.0,1.0;for _ ,_fege :=range *_cbda {if _fege .Operand =="\u0051"{_dge ,_cega =1.0,1.0;};if _fege .Operand =="\u0063\u006d"&&len (_fege .Params )==6{if _cbg ,_fad :=_ge .GetFloatVal (_fege .Params [0]);_fad {_dge =_dge *_cbg ;};if _feb ,_beff :=_ge .GetFloatVal (_fege .Params [3]);_beff {_cega =_cega *_feb ;};if _gee ,_bbef :=_ge .GetIntVal (_fege .Params [0]);_bbef {_dge =_dge *float64 (_gee );};if _cfg ,_bgdg :=_ge .GetIntVal (_fege .Params [3]);_bgdg {_cega =_cega *float64 (_cfg );};};if _fege .Operand =="\u0044\u006f"&&len (_fege .Params )==1{_fdd ,_fcd :=_ge .GetName (_fege .Params [0]);if !_fcd {continue ;};if _gaf ,_cbeb :=_fdaa [string (*_fdd )];_cbeb {_gdbb ,_fgba :=_dge /72.0,_cega /72.0;_abdf ,_bcbd :=float64 (_gaf .Width )/_gdbb ,float64 (_gaf .Height )/_fgba ;if _gdbb ==0||_fgba ==0{_abdf =72.0;_bcbd =72.0;};_gaf .PPI =_gc .Max (_gaf .PPI ,_abdf );_gaf .PPI =_gc .Max (_gaf .PPI ,_bcbd );};};};};};};for _ ,_aaf :=range _cbd {if _ ,_efae :=_abfac [_aaf .Stream ];_efae {continue ;};if _aaf .PPI <=_def .ImageUpperPPI {continue ;};_aee :=_def .ImageUpperPPI /_aaf .PPI ;if _fdeff :=_cce (_aaf .Stream ,_aee );_fdeff !=nil {_ee .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",_fdeff );}else {if _afed ,_fbdf :=_ge .GetStream (_aaf .Stream .PdfObjectDictionary .Get (_ge .PdfObjectName ("\u0053\u004d\u0061s\u006b")));_fbdf {if _bbc :=_cce (_afed ,_aee );_bbc !=nil {return nil ,_bbc ;};};};};return objects ,nil ;};func _gggd (_eac []_ge .PdfObject )[]*imageInfo {_egc :=_ge .PdfObjectName ("\u0053u\u0062\u0074\u0079\u0070\u0065");_daeb :=make (map[*_ge .PdfObjectStream ]struct{});var _geaf error ;var _bccc []*imageInfo ;for _ ,_cafa :=range _eac {_fbc ,_ecfd :=_ge .GetStream (_cafa );if !_ecfd {continue ;};if _ ,_df
// Append appends optimizers to the chain.
func (_ab *Chain )Append (optimizers ..._a .Optimizer ){_ab ._ef =append (_ab ._ef ,optimizers ...)};func _eggd (_cge _ge .PdfObject )(_eddb string ,_afbb []_ge .PdfObject ){var _fcdd _f .Buffer ;switch _fca :=_cge .(type ){case *_ge .PdfIndirectObject :_afbb =append (_afbb ,_fca );_cge =_fca .PdfObject ;};switch _bdba :=_cge .(type ){case *_ge .PdfObjectStream :if _fec ,_efg :=_ge .DecodeStream (_bdba );_efg ==nil {_fcdd .Write (_fec );_afbb =append (_afbb ,_bdba );};case *_ge .PdfObjectArray :for _ ,_cgef :=range _bdba .Elements (){switch _bad :=_cgef .(type ){case *_ge .PdfObjectStream :if _cegag ,_acdf :=_ge .DecodeStream (_bad );_acdf ==nil {_fcdd .Write (_cegag );_afbb =append (_afbb ,_bad );};};};};return _fcdd .String (),_afbb ;};
2020-11-11 18:48:37 +00:00
2021-01-07 14:20:10 +00:00
// Optimize optimizes PDF objects to decrease PDF size.
2021-01-26 01:31:56 +00:00
func (_eaa *CleanContentstream )Optimize (objects []_ge .PdfObject )(_fe []_ge .PdfObject ,_gea error ){_dg :=map[*_ge .PdfObjectStream ]struct{}{};var _ae []*_ge .PdfObjectStream ;_gd :=func (_fac *_ge .PdfObjectStream ){if _ ,_bcf :=_dg [_fac ];!_bcf {_dg [_fac ]=struct{}{};_ae =append (_ae ,_fac );};};for _ ,_aec :=range objects {switch _da :=_aec .(type ){case *_ge .PdfIndirectObject :switch _bd :=_da .PdfObject .(type ){case *_ge .PdfObjectDictionary :if _eef ,_eaaf :=_ge .GetName (_bd .Get ("\u0054\u0079\u0070\u0065"));!_eaaf ||_eef .String ()!="\u0050\u0061\u0067\u0065"{continue ;};if _ed ,_eaab :=_ge .GetStream (_bd .Get ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073"));_eaab {_gd (_ed );}else if _eb ,_fge :=_ge .GetArray (_bd .Get ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073"));_fge {for _ ,_efa :=range _eb .Elements (){if _de ,_baf :=_ge .GetStream (_efa );_baf {_gd (_de );};};};};case *_ge .PdfObjectStream :if _cae ,_cfa :=_ge .GetName (_da .Get ("\u0054\u0079\u0070\u0065"));!_cfa ||_cae .String ()!="\u0058O\u0062\u006a\u0065\u0063\u0074"{continue ;};if _cec ,_gdb :=_ge .GetName (_da .Get ("\u0053u\u0062\u0074\u0079\u0070\u0065"));!_gdb ||_cec .String ()!="\u0046\u006f\u0072\u006d"{continue ;};_gd (_da );};};for _ ,_cegd :=range _ae {_gea =_dc (_cegd );if _gea !=nil {return nil ,_gea ;};};return objects ,nil ;};