mirror of
https://github.com/unidoc/unipdf.git
synced 2025-04-27 13:48:51 +08:00
206 lines
35 KiB
Go
206 lines
35 KiB
Go
//
|
|
// 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/
|
|
|
|
package optimize ;import (_af "bytes";_a "crypto/md5";_e "errors";_be "github.com/unidoc/unipdf/v3/common";_f "github.com/unidoc/unipdf/v3/contentstream";_dc "github.com/unidoc/unipdf/v3/core";_ac "github.com/unidoc/unipdf/v3/extractor";_gc "github.com/unidoc/unipdf/v3/internal/imageutil";
|
|
_g "github.com/unidoc/unipdf/v3/internal/textencoding";_c "github.com/unidoc/unipdf/v3/model";_gg "github.com/unidoc/unitype";_da "golang.org/x/image/draw";_b "math";);func _cb (_gcag *_dc .PdfObjectStream ,_gef []rune ,_gdg []_gg .GlyphIndex )error {_gcag ,_dcbf :=_dc .GetStream (_gcag );
|
|
if !_dcbf {_be .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 _e .New ("\u0066\u006f\u006e\u0074fi\u006c\u0065\u0032\u0020\u006e\u006f\u0074\u0020\u0066\u006f\u0075\u006e\u0064");};_cecd ,_dfcg :=_dc .DecodeStream (_gcag );if _dfcg !=nil {_be .Log .Debug ("\u0044\u0065c\u006f\u0064\u0065 \u0065\u0072\u0072\u006f\u0072\u003a\u0020\u0025\u0076",_dfcg );
|
|
return _dfcg ;};_dea ,_dfcg :=_gg .Parse (_af .NewReader (_cecd ));if _dfcg !=nil {_be .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 (_gcag .Stream ));
|
|
return _dfcg ;};_bdcf :=_gdg ;if len (_gef )> 0{_gdc :=_dea .LookupRunes (_gef );_bdcf =append (_bdcf ,_gdc ...);};_dea ,_dfcg =_dea .SubsetKeepIndices (_bdcf );if _dfcg !=nil {_be .Log .Debug ("\u0045R\u0052\u004f\u0052\u0020s\u0075\u0062\u0073\u0065\u0074t\u0069n\u0067 \u0066\u006f\u006e\u0074\u003a\u0020\u0025v",_dfcg );
|
|
return _dfcg ;};var _dgb _af .Buffer ;_dfcg =_dea .Write (&_dgb );if _dfcg !=nil {_be .Log .Debug ("\u0045\u0052\u0052\u004fR \u0057\u0072\u0069\u0074\u0069\u006e\u0067\u0020\u0066\u006f\u006e\u0074\u003a\u0020%\u0076",_dfcg );return _dfcg ;};if _dgb .Len ()> len (_cecd ){_be .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 ;};_fbf ,_dfcg :=_dc .MakeStream (_dgb .Bytes (),_dc .NewFlateEncoder ());if _dfcg !=nil {_be .Log .Debug ("\u0045\u0052\u0052\u004fR \u0057\u0072\u0069\u0074\u0069\u006e\u0067\u0020\u0066\u006f\u006e\u0074\u003a\u0020%\u0076",_dfcg );return _dfcg ;
|
|
};*_gcag =*_fbf ;_gcag .Set ("\u004ce\u006e\u0067\u0074\u0068\u0031",_dc .MakeInteger (int64 (_dgb .Len ())));return nil ;};
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
func (_gbc *CleanFonts )Optimize (objects []_dc .PdfObject )(_afb []_dc .PdfObject ,_cfa error ){var _bcd map[*_dc .PdfObjectStream ]struct{};if _gbc .Subset {var _gadf error ;_bcd ,_gadf =_bgad (objects );if _gadf !=nil {return nil ,_gadf ;};};for _ ,_ccg :=range objects {_efb ,_gfd :=_dc .GetStream (_ccg );
|
|
if !_gfd {continue ;};if _ ,_fef :=_bcd [_efb ];_fef {continue ;};_bcc ,_dcbe :=_dc .NewEncoderFromStream (_efb );if _dcbe !=nil {_be .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",_dcbe );
|
|
continue ;};_afbc ,_dcbe :=_bcc .DecodeStream (_efb );if _dcbe !=nil {_be .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",_dcbe );
|
|
continue ;};if len (_afbc )< 4{continue ;};_eeb :=string (_afbc [:4]);if _eeb =="\u004f\u0054\u0054\u004f"{continue ;};if _eeb !="\u0000\u0001\u0000\u0000"&&_eeb !="\u0074\u0072\u0075\u0065"{continue ;};_abd ,_dcbe :=_gg .Parse (_af .NewReader (_afbc ));
|
|
if _dcbe !=nil {_be .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",_dcbe );continue ;};_dcbe =_abd .Optimize ();
|
|
if _dcbe !=nil {continue ;};var _aacc _af .Buffer ;_dcbe =_abd .Write (&_aacc );if _dcbe !=nil {_be .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",_dcbe );
|
|
continue ;};if _aacc .Len ()> len (_afbc ){_be .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 ;};_efdc ,_dcbe :=_dc .MakeStream (_aacc .Bytes (),_dc .NewFlateEncoder ());if _dcbe !=nil {continue ;};*_efb =*_efdc ;_efb .Set ("\u004ce\u006e\u0067\u0074\u0068\u0031",_dc .MakeInteger (int64 (_aacc .Len ())));};return objects ,nil ;};func _fa (_fc *_f .ContentStreamOperations )*_f .ContentStreamOperations {if _fc ==nil {return nil ;
|
|
};_dfc :=_f .ContentStreamOperations {};for _ ,_fd :=range *_fc {switch _fd .Operand {case "\u0042\u0044\u0043","\u0042\u004d\u0043","\u0045\u004d\u0043":continue ;case "\u0054\u006d":if len (_fd .Params )==6{if _bd ,_ea :=_dc .GetNumbersAsFloat (_fd .Params );
|
|
_ea ==nil {if _bd [0]==1&&_bd [1]==0&&_bd [2]==0&&_bd [3]==1{_fd =&_f .ContentStreamOperation {Params :[]_dc .PdfObject {_fd .Params [4],_fd .Params [5]},Operand :"\u0054\u0064"};};};};};_dfc =append (_dfc ,_fd );};return &_dfc ;};
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
func (_bddg *ImagePPI )Optimize (objects []_dc .PdfObject )(_fcga []_dc .PdfObject ,_eeg error ){if _bddg .ImageUpperPPI <=0{return objects ,nil ;};_fgdd :=_ecc (objects );if len (_fgdd )==0{return objects ,nil ;};_afegb :=make (map[_dc .PdfObject ]struct{});
|
|
for _ ,_gefd :=range _fgdd {_egba :=_gefd .Stream .PdfObjectDictionary .Get (_dc .PdfObjectName ("\u0053\u004d\u0061s\u006b"));_afegb [_egba ]=struct{}{};};_eec :=make (map[*_dc .PdfObjectStream ]*imageInfo );for _ ,_dfde :=range _fgdd {_eec [_dfde .Stream ]=_dfde ;
|
|
};var _ebc *_dc .PdfObjectDictionary ;for _ ,_daff :=range objects {if _acg ,_dbd :=_dc .GetDict (_daff );_ebc ==nil &&_dbd {if _faac ,_dcgg :=_dc .GetName (_acg .Get (_dc .PdfObjectName ("\u0054\u0079\u0070\u0065")));_dcgg &&*_faac =="\u0043a\u0074\u0061\u006c\u006f\u0067"{_ebc =_acg ;
|
|
};};};if _ebc ==nil {return objects ,nil ;};_aega ,_cba :=_dc .GetDict (_ebc .Get (_dc .PdfObjectName ("\u0050\u0061\u0067e\u0073")));if !_cba {return objects ,nil ;};_abe ,_ebca :=_dc .GetArray (_aega .Get (_dc .PdfObjectName ("\u004b\u0069\u0064\u0073")));
|
|
if !_ebca {return objects ,nil ;};_bgfb :=make (map[string ]*imageInfo );for _ ,_gdb :=range _abe .Elements (){_ebb ,_dgbf :=_dc .GetDict (_gdb );if !_dgbf {continue ;};_bcf ,_gbdc :=_dc .GetArray (_ebb .Get ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073"));
|
|
if !_gbdc {continue ;};_gbgd ,_aecd :=_dc .GetDict (_ebb .Get ("\u0052e\u0073\u006f\u0075\u0072\u0063\u0065s"));if !_aecd {continue ;};_eecc ,_ffg :=_dc .GetDict (_gbgd .Get ("\u0058O\u0062\u006a\u0065\u0063\u0074"));if !_ffg {continue ;};_caf :=_eecc .Keys ();
|
|
for _ ,_fbdg :=range _caf {if _cdb ,_ddfa :=_dc .GetStream (_eecc .Get (_fbdg ));_ddfa {if _adg ,_fdag :=_eec [_cdb ];_fdag {_bgfb [string (_fbdg )]=_adg ;};};};for _ ,_efda :=range _bcf .Elements (){if _ged ,_bdf :=_dc .GetStream (_efda );_bdf {_ggdgg ,_dbcd :=_dc .NewEncoderFromStream (_ged );
|
|
if _dbcd !=nil {return nil ,_dbcd ;};_cgfc ,_dbcd :=_ggdgg .DecodeStream (_ged );if _dbcd !=nil {return nil ,_dbcd ;};_abc :=_f .NewContentStreamParser (string (_cgfc ));_bce ,_dbcd :=_abc .Parse ();if _dbcd !=nil {return nil ,_dbcd ;};_ecdg ,_geba :=1.0,1.0;
|
|
for _ ,_cfdd :=range *_bce {if _cfdd .Operand =="\u0051"{_ecdg ,_geba =1.0,1.0;};if _cfdd .Operand =="\u0063\u006d"&&len (_cfdd .Params )==6{if _bbd ,_ebec :=_dc .GetFloatVal (_cfdd .Params [0]);_ebec {_ecdg =_ecdg *_bbd ;};if _dgc ,_cag :=_dc .GetFloatVal (_cfdd .Params [3]);
|
|
_cag {_geba =_geba *_dgc ;};if _ebgd ,_cad :=_dc .GetIntVal (_cfdd .Params [0]);_cad {_ecdg =_ecdg *float64 (_ebgd );};if _cdeg ,_fcce :=_dc .GetIntVal (_cfdd .Params [3]);_fcce {_geba =_geba *float64 (_cdeg );};};if _cfdd .Operand =="\u0044\u006f"&&len (_cfdd .Params )==1{_adgg ,_dfdg :=_dc .GetName (_cfdd .Params [0]);
|
|
if !_dfdg {continue ;};if _acbd ,_bba :=_bgfb [string (*_adgg )];_bba {_fab ,_fdbg :=_ecdg /72.0,_geba /72.0;_gfee ,_ccgc :=float64 (_acbd .Width )/_fab ,float64 (_acbd .Height )/_fdbg ;if _fab ==0||_fdbg ==0{_gfee =72.0;_ccgc =72.0;};_acbd .PPI =_b .Max (_acbd .PPI ,_gfee );
|
|
_acbd .PPI =_b .Max (_acbd .PPI ,_ccgc );};};};};};};for _ ,_ggc :=range _fgdd {if _ ,_ccge :=_afegb [_ggc .Stream ];_ccge {continue ;};if _ggc .PPI <=_bddg .ImageUpperPPI {continue ;};_gea ,_bac :=_c .NewXObjectImageFromStream (_ggc .Stream );if _bac !=nil {return nil ,_bac ;
|
|
};var _acaa imageModifications ;_acaa .Scale =_bddg .ImageUpperPPI /_ggc .PPI ;if _ggc .BitsPerComponent ==1&&_ggc .ColorComponents ==1{_aggf :=_b .Round (_ggc .PPI /_bddg .ImageUpperPPI );_bffa :=_gc .NextPowerOf2 (uint (_aggf ));if _gc .InDelta (float64 (_bffa ),1/_acaa .Scale ,0.3){_acaa .Scale =float64 (1)/float64 (_bffa );
|
|
};if _ ,_gcac :=_gea .Filter .(*_dc .JBIG2Encoder );!_gcac {_acaa .Encoding =_dc .NewJBIG2Encoder ();};};if _bac =_dfdc (_gea ,_acaa );_bac !=nil {_be .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",_bac );
|
|
continue ;};_acaa .Encoding =nil ;if _ega ,_bgef :=_dc .GetStream (_ggc .Stream .PdfObjectDictionary .Get (_dc .PdfObjectName ("\u0053\u004d\u0061s\u006b")));_bgef {_bafga ,_cae :=_c .NewXObjectImageFromStream (_ega );if _cae !=nil {return nil ,_cae ;};
|
|
if _cae =_dfdc (_bafga ,_acaa );_cae !=nil {return nil ,_cae ;};};};return objects ,nil ;};
|
|
|
|
// 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 ;};type objectStructure struct{_ceea *_dc .PdfObjectDictionary ;_eaa *_dc .PdfObjectDictionary ;_cedg []*_dc .PdfIndirectObject ;};func _dbgb (_aeda _dc .PdfObject )(_fcbg string ,_gfgb []_dc .PdfObject ){var _fdagd _af .Buffer ;
|
|
switch _eeef :=_aeda .(type ){case *_dc .PdfIndirectObject :_gfgb =append (_gfgb ,_eeef );_aeda =_eeef .PdfObject ;};switch _gbce :=_aeda .(type ){case *_dc .PdfObjectStream :if _faef ,_ddd :=_dc .DecodeStream (_gbce );_ddd ==nil {_fdagd .Write (_faef );
|
|
_gfgb =append (_gfgb ,_gbce );};case *_dc .PdfObjectArray :for _ ,_gcad :=range _gbce .Elements (){switch _gbcd :=_gcad .(type ){case *_dc .PdfObjectStream :if _ggdb ,_dga :=_dc .DecodeStream (_gbcd );_dga ==nil {_fdagd .Write (_ggdb );_gfgb =append (_gfgb ,_gbcd );
|
|
};};};};return _fdagd .String (),_gfgb ;};
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
func (_face *CombineIdenticalIndirectObjects )Optimize (objects []_dc .PdfObject )(_age []_dc .PdfObject ,_ceed error ){_dcc (objects );_ggd :=make (map[_dc .PdfObject ]_dc .PdfObject );_bdb :=make (map[_dc .PdfObject ]struct{});_efad :=make (map[string ][]*_dc .PdfIndirectObject );
|
|
for _ ,_acc :=range objects {_bge ,_fff :=_acc .(*_dc .PdfIndirectObject );if !_fff {continue ;};if _acba ,_facd :=_bge .PdfObject .(*_dc .PdfObjectDictionary );_facd {if _ggg ,_bbcf :=_acba .Get ("\u0054\u0079\u0070\u0065").(*_dc .PdfObjectName );_bbcf &&*_ggg =="\u0050\u0061\u0067\u0065"{continue ;
|
|
};_gaa :=_a .New ();_gaa .Write ([]byte (_acba .WriteString ()));_cgc :=string (_gaa .Sum (nil ));_efad [_cgc ]=append (_efad [_cgc ],_bge );};};for _ ,_ddbae :=range _efad {if len (_ddbae )< 2{continue ;};_dcg :=_ddbae [0];for _afeg :=1;_afeg < len (_ddbae );
|
|
_afeg ++{_fad :=_ddbae [_afeg ];_ggd [_fad ]=_dcg ;_bdb [_fad ]=struct{}{};};};_age =make ([]_dc .PdfObject ,0,len (objects )-len (_bdb ));for _ ,_cfde :=range objects {if _ ,_bgga :=_bdb [_cfde ];_bgga {continue ;};_age =append (_age ,_cfde );};_fdf (_age ,_ggd );
|
|
return _age ,nil ;};
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
func (_efab *CompressStreams )Optimize (objects []_dc .PdfObject )(_fga []_dc .PdfObject ,_dbb error ){_fga =make ([]_dc .PdfObject ,len (objects ));copy (_fga ,objects );for _ ,_ebe :=range objects {_bbe ,_eag :=_dc .GetStream (_ebe );if !_eag {continue ;
|
|
};if _caa :=_bbe .Get ("\u0046\u0069\u006c\u0074\u0065\u0072");_caa !=nil {if _ ,_dfe :=_dc .GetName (_caa );_dfe {continue ;};if _gfe ,_gefe :=_dc .GetArray (_caa );_gefe &&_gfe .Len ()> 0{continue ;};};_aca :=_dc .NewFlateEncoder ();var _fda []byte ;
|
|
_fda ,_dbb =_aca .EncodeBytes (_bbe .Stream );if _dbb !=nil {return _fga ,_dbb ;};_gcba :=_aca .MakeStreamDict ();if len (_fda )+len (_gcba .WriteString ())< len (_bbe .Stream ){_bbe .Stream =_fda ;_bbe .PdfObjectDictionary .Merge (_gcba );_bbe .PdfObjectDictionary .Set ("\u004c\u0065\u006e\u0067\u0074\u0068",_dc .MakeInteger (int64 (len (_bbe .Stream ))));
|
|
};};return _fga ,nil ;};type content struct{_ca string ;_bcdc *_c .PdfPageResources ;};func _gcbd (_fbg *_c .Image ,_bab float64 )(*_c .Image ,error ){_bdbe ,_eda :=_fbg .ToGoImage ();if _eda !=nil {return nil ,_eda ;};var _bff _gc .Image ;_eabac ,_dfb :=_bdbe .(*_gc .Monochrome );
|
|
if _dfb {if _eda =_eabac .ResolveDecode ();_eda !=nil {return nil ,_eda ;};_bff ,_eda =_eabac .Scale (_bab );if _eda !=nil {return nil ,_eda ;};}else {_acd :=int (_b .RoundToEven (float64 (_fbg .Width )*_bab ));_bbge :=int (_b .RoundToEven (float64 (_fbg .Height )*_bab ));
|
|
_bff ,_eda =_gc .NewImage (_acd ,_bbge ,int (_fbg .BitsPerComponent ),_fbg .ColorComponents ,nil ,nil ,nil );if _eda !=nil {return nil ,_eda ;};_da .CatmullRom .Scale (_bff ,_bff .Bounds (),_bdbe ,_bdbe .Bounds (),_da .Over ,&_da .Options {});};_gbbb :=_bff .Base ();
|
|
_eca :=&_c .Image {Width :int64 (_gbbb .Width ),Height :int64 (_gbbb .Height ),BitsPerComponent :int64 (_gbbb .BitsPerComponent ),ColorComponents :_gbbb .ColorComponents ,Data :_gbbb .Data };_eca .SetDecode (_gbbb .Decode );_eca .SetAlpha (_gbbb .Alpha );
|
|
return _eca ,nil ;};
|
|
|
|
// Append appends optimizers to the chain.
|
|
func (_fb *Chain )Append (optimizers ..._c .Optimizer ){_fb ._gd =append (_fb ._gd ,optimizers ...)};
|
|
|
|
// 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 ;
|
|
};
|
|
|
|
// 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.
|
|
Subset bool ;};
|
|
|
|
// 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{};
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
func (_dff *CombineDuplicateStreams )Optimize (objects []_dc .PdfObject )(_facf []_dc .PdfObject ,_aaa error ){_aaf :=make (map[_dc .PdfObject ]_dc .PdfObject );_eb :=make (map[_dc .PdfObject ]struct{});_efaf :=make (map[string ][]*_dc .PdfObjectStream );
|
|
for _ ,_ced :=range objects {if _fag ,_gff :=_ced .(*_dc .PdfObjectStream );_gff {_gcb :=_a .New ();_gcb .Write (_fag .Stream );_aeb :=string (_gcb .Sum (nil ));_efaf [_aeb ]=append (_efaf [_aeb ],_fag );};};for _ ,_bcg :=range _efaf {if len (_bcg )< 2{continue ;
|
|
};_eadg :=_bcg [0];for _afa :=1;_afa < len (_bcg );_afa ++{_debg :=_bcg [_afa ];_aaf [_debg ]=_eadg ;_eb [_debg ]=struct{}{};};};_facf =make ([]_dc .PdfObject ,0,len (objects )-len (_eb ));for _ ,_aed :=range objects {if _ ,_gdgb :=_eb [_aed ];_gdgb {continue ;
|
|
};_facf =append (_facf ,_aed );};_fdf (_facf ,_aaf );return _facf ,nil ;};func _bfc (_edc _dc .PdfObject )[]content {if _edc ==nil {return nil ;};_acbg ,_fbb :=_dc .GetArray (_edc );if !_fbb {_be .Log .Debug ("\u0041\u006e\u006e\u006fts\u0020\u006e\u006f\u0074\u0020\u0061\u006e\u0020\u0061\u0072\u0072\u0061\u0079");
|
|
return nil ;};var _afe []content ;for _ ,_gbb :=range _acbg .Elements (){_eac ,_bdd :=_dc .GetDict (_gbb );if !_bdd {_be .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 ;};_ccbe ,_bdd :=_dc .GetDict (_eac .Get ("\u0041\u0050"));if !_bdd {_be .Log .Debug ("\u004e\u006f\u0020\u0041P \u0065\u006e\u0074\u0072\u0079\u0020\u002d\u0020\u0073\u006b\u0069\u0070\u0070\u0069n\u0067");continue ;};_dbe :=_dc .TraceToDirectObject (_ccbe .Get ("\u004e"));
|
|
if _dbe ==nil {_be .Log .Debug ("N\u006f\u0020\u004e\u0020en\u0074r\u0079\u0020\u002d\u0020\u0073k\u0069\u0070\u0070\u0069\u006e\u0067");continue ;};var _fbe *_dc .PdfObjectStream ;switch _cgd :=_dbe .(type ){case *_dc .PdfObjectDictionary :_ddba ,_bafa :=_dc .GetName (_eac .Get ("\u0041\u0053"));
|
|
if !_bafa {_be .Log .Debug ("\u004e\u006f\u0020\u0041S \u0065\u006e\u0074\u0072\u0079\u0020\u002d\u0020\u0073\u006b\u0069\u0070\u0070\u0069n\u0067");continue ;};_fbe ,_bafa =_dc .GetStream (_cgd .Get (*_ddba ));if !_bafa {_be .Log .Debug ("\u0046o\u0072\u006d\u0020\u006eo\u0074\u0020\u0066\u006f\u0075n\u0064 \u002d \u0073\u006b\u0069\u0070\u0070\u0069\u006eg");
|
|
continue ;};case *_dc .PdfObjectStream :_fbe =_cgd ;};if _fbe ==nil {_be .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 ;};_gfa ,_fcb :=_c .NewXObjectFormFromStream (_fbe );if _fcb !=nil {_be .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",_fcb );
|
|
continue ;};_fbeb ,_fcb :=_gfa .GetContentStream ();if _fcb !=nil {_be .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",_fcb );continue ;};_afe =append (_afe ,content {_ca :string (_fbeb ),_bcdc :_gfa .Resources });
|
|
};return _afe ;};type imageInfo struct{ColorSpace _dc .PdfObjectName ;BitsPerComponent int ;ColorComponents int ;Width int ;Height int ;Stream *_dc .PdfObjectStream ;PPI float64 ;};
|
|
|
|
// Chain allows to use sequence of optimizers.
|
|
// It implements interface model.Optimizer.
|
|
type Chain struct{_gd []_c .Optimizer };
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
func (_ba *Chain )Optimize (objects []_dc .PdfObject )(_eg []_dc .PdfObject ,_ae error ){_eg =objects ;for _ ,_gb :=range _ba ._gd {_eg ,_ae =_gb .Optimize (_eg );if _ae !=nil {return _eg ,_ae ;};};return _eg ,nil ;};
|
|
|
|
// CompressStreams compresses uncompressed streams.
|
|
// It implements interface model.Optimizer.
|
|
type CompressStreams struct{};func _ecc (_afcbb []_dc .PdfObject )[]*imageInfo {_fcg :=_dc .PdfObjectName ("\u0053u\u0062\u0074\u0079\u0070\u0065");_cbf :=make (map[*_dc .PdfObjectStream ]struct{});var _fgd error ;var _fcc []*imageInfo ;for _ ,_fffg :=range _afcbb {_bgcf ,_aeg :=_dc .GetStream (_fffg );
|
|
if !_aeg {continue ;};if _ ,_fcgf :=_cbf [_bgcf ];_fcgf {continue ;};_cbf [_bgcf ]=struct{}{};_dgbg :=_bgcf .PdfObjectDictionary .Get (_fcg );_eadga ,_aeg :=_dc .GetName (_dgbg );if !_aeg ||string (*_eadga )!="\u0049\u006d\u0061g\u0065"{continue ;};_afce :=&imageInfo {BitsPerComponent :8,Stream :_bgcf };
|
|
if _afce .ColorSpace ,_fgd =_c .DetermineColorspaceNameFromPdfObject (_bgcf .PdfObjectDictionary .Get ("\u0043\u006f\u006c\u006f\u0072\u0053\u0070\u0061\u0063\u0065"));_fgd !=nil {_be .Log .Error ("\u0045\u0072\u0072\u006f\u0072\u0020\u0064\u0065\u0074\u0065r\u006d\u0069\u006e\u0065\u0020\u0063\u006fl\u006f\u0072\u0020\u0073\u0070\u0061\u0063\u0065\u0020\u0025\u0073",_fgd );
|
|
continue ;};if _bgca ,_faa :=_dc .GetIntVal (_bgcf .PdfObjectDictionary .Get ("\u0042\u0069t\u0073\u0050\u0065r\u0043\u006f\u006d\u0070\u006f\u006e\u0065\u006e\u0074"));_faa {_afce .BitsPerComponent =_bgca ;};if _fdea ,_fdbb :=_dc .GetIntVal (_bgcf .PdfObjectDictionary .Get ("\u0057\u0069\u0064t\u0068"));
|
|
_fdbb {_afce .Width =_fdea ;};if _afde ,_ddaa :=_dc .GetIntVal (_bgcf .PdfObjectDictionary .Get ("\u0048\u0065\u0069\u0067\u0068\u0074"));_ddaa {_afce .Height =_afde ;};switch _afce .ColorSpace {case "\u0044e\u0076\u0069\u0063\u0065\u0052\u0047B":_afce .ColorComponents =3;
|
|
case "\u0044\u0065\u0076\u0069\u0063\u0065\u0047\u0072\u0061\u0079":_afce .ColorComponents =1;default:_be .Log .Warning ("\u004f\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",_afce .ColorSpace );
|
|
continue ;};_fcc =append (_fcc ,_afce );};return _fcc ;};
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
func (_cab *ObjectStreams )Optimize (objects []_dc .PdfObject )(_egfa []_dc .PdfObject ,_ffbg error ){_bffae :=&_dc .PdfObjectStreams {};_fdba :=make ([]_dc .PdfObject ,0,len (objects ));for _ ,_ddgc :=range objects {if _dfed ,_aaag :=_ddgc .(*_dc .PdfIndirectObject );
|
|
_aaag &&_dfed .GenerationNumber ==0{_bffae .Append (_ddgc );}else {_fdba =append (_fdba ,_ddgc );};};if _bffae .Len ()==0{return _fdba ,nil ;};_egfa =make ([]_dc .PdfObject ,0,len (_fdba )+_bffae .Len ()+1);if _bffae .Len ()> 1{_egfa =append (_egfa ,_bffae );
|
|
};_egfa =append (_egfa ,_bffae .Elements ()...);_egfa =append (_egfa ,_fdba ...);return _egfa ,nil ;};
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
func (_afc *CleanContentstream )Optimize (objects []_dc .PdfObject )(_bf []_dc .PdfObject ,_ed error ){_acf :=map[*_dc .PdfObjectStream ]struct{}{};var _ce []*_dc .PdfObjectStream ;_afcb :=func (_egb *_dc .PdfObjectStream ){if _ ,_ab :=_acf [_egb ];!_ab {_acf [_egb ]=struct{}{};
|
|
_ce =append (_ce ,_egb );};};for _ ,_db :=range objects {switch _acb :=_db .(type ){case *_dc .PdfIndirectObject :switch _ddb :=_acb .PdfObject .(type ){case *_dc .PdfObjectDictionary :if _cgg ,_bg :=_dc .GetName (_ddb .Get ("\u0054\u0079\u0070\u0065"));
|
|
!_bg ||_cgg .String ()!="\u0050\u0061\u0067\u0065"{continue ;};if _edd ,_efc :=_dc .GetStream (_ddb .Get ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073"));_efc {_afcb (_edd );}else if _ag ,_edg :=_dc .GetArray (_ddb .Get ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073"));
|
|
_edg {for _ ,_bbc :=range _ag .Elements (){if _bc ,_dbg :=_dc .GetStream (_bbc );_dbg {_afcb (_bc );};};};};case *_dc .PdfObjectStream :if _ddf ,_cd :=_dc .GetName (_acb .Get ("\u0054\u0079\u0070\u0065"));!_cd ||_ddf .String ()!="\u0058O\u0062\u006a\u0065\u0063\u0074"{continue ;
|
|
};if _gf ,_bgg :=_dc .GetName (_acb .Get ("\u0053u\u0062\u0074\u0079\u0070\u0065"));!_bgg ||_gf .String ()!="\u0046\u006f\u0072\u006d"{continue ;};_afcb (_acb );};};for _ ,_fac :=range _ce {_ed =_bdc (_fac );if _ed !=nil {return nil ,_ed ;};};return objects ,nil ;
|
|
};func _fee (_bdcb []_dc .PdfObject )objectStructure {_fdbgf :=objectStructure {};_dba :=false ;for _ ,_aea :=range _bdcb {switch _gfda :=_aea .(type ){case *_dc .PdfIndirectObject :_ecb ,_gcd :=_dc .GetDict (_gfda );if !_gcd {continue ;};_abb ,_gcd :=_dc .GetName (_ecb .Get ("\u0054\u0079\u0070\u0065"));
|
|
if !_gcd {continue ;};switch _abb .String (){case "\u0043a\u0074\u0061\u006c\u006f\u0067":_fdbgf ._ceea =_ecb ;_dba =true ;};};if _dba {break ;};};if !_dba {return _fdbgf ;};_facc ,_faee :=_dc .GetDict (_fdbgf ._ceea .Get ("\u0050\u0061\u0067e\u0073"));
|
|
if !_faee {return _fdbgf ;};_fdbgf ._eaa =_facc ;_cabg ,_faee :=_dc .GetArray (_facc .Get ("\u004b\u0069\u0064\u0073"));if !_faee {return _fdbgf ;};for _ ,_fdfe :=range _cabg .Elements (){_dcbd ,_abdg :=_dc .GetIndirect (_fdfe );if !_abdg {break ;};_fdbgf ._cedg =append (_fdbgf ._cedg ,_dcbd );
|
|
};return _fdbgf ;};func _dfdc (_dcff *_c .XObjectImage ,_gag imageModifications )error {_faca ,_fada :=_dcff .ToImage ();if _fada !=nil {return _fada ;};if _gag .Scale !=0{_faca ,_fada =_gcbd (_faca ,_gag .Scale );if _fada !=nil {return _fada ;};};if _gag .Encoding !=nil {_dcff .Filter =_gag .Encoding ;
|
|
};_gbd :=_dc .MakeDict ();_gbd .Set ("\u0051u\u0061\u006c\u0069\u0074\u0079",_dc .MakeInteger (100));_gbd .Set ("\u0050r\u0065\u0064\u0069\u0063\u0074\u006fr",_dc .MakeInteger (1));_dcff .Decode =nil ;if _fada =_dcff .SetImage (_faca ,nil );_fada !=nil {return _fada ;
|
|
};_dcff .ToPdfObject ();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 ;};
|
|
|
|
// 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{};
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
func (_dag *Image )Optimize (objects []_dc .PdfObject )(_agec []_dc .PdfObject ,_ceda error ){if _dag .ImageQuality <=0{return objects ,nil ;};_bgaa :=_ecc (objects );if len (_bgaa )==0{return objects ,nil ;};_ggdg :=make (map[_dc .PdfObject ]_dc .PdfObject );
|
|
_ffb :=make (map[_dc .PdfObject ]struct{});for _ ,_dffd :=range _bgaa {_eedc :=_dffd .Stream .PdfObjectDictionary .Get (_dc .PdfObjectName ("\u0053\u004d\u0061s\u006b"));_ffb [_eedc ]=struct{}{};};for _ebg ,_dbcf :=range _bgaa {_aafe :=_dbcf .Stream ;if _ ,_bea :=_ffb [_aafe ];
|
|
_bea {continue ;};_efcg ,_gba :=_dc .NewEncoderFromStream (_aafe );if _gba !=nil {_be .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 ;};_cedf ,_gba :=_efcg .DecodeStream (_aafe );if _gba !=nil {_be .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 ;};_gcf :=_dc .NewDCTEncoder ();_gcf .ColorComponents =_dbcf .ColorComponents ;_gcf .Quality =_dag .ImageQuality ;_gcf .BitsPerComponent =_dbcf .BitsPerComponent ;_gcf .Width =_dbcf .Width ;_gcf .Height =_dbcf .Height ;_bef ,_gba :=_gcf .EncodeBytes (_cedf );
|
|
if _gba !=nil {_be .Log .Debug ("\u0045R\u0052\u004f\u0052\u003a\u0020\u0025v",_gba );return nil ,_gba ;};var _ddg _dc .StreamEncoder ;_ddg =_gcf ;{_fdae :=_dc .NewFlateEncoder ();_cbb :=_dc .NewMultiEncoder ();_cbb .AddEncoder (_fdae );_cbb .AddEncoder (_gcf );
|
|
_dcd ,_fefc :=_cbb .EncodeBytes (_cedf );if _fefc !=nil {return nil ,_fefc ;};if len (_dcd )< len (_bef ){_be .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 (_bef ),len (_dcd ),len (_aafe .Stream ));
|
|
_bef =_dcd ;_ddg =_cbb ;};};_cge :=len (_aafe .Stream );if _cge < len (_bef ){continue ;};_fadc :=&_dc .PdfObjectStream {Stream :_bef };_fadc .PdfObjectReference =_aafe .PdfObjectReference ;_fadc .PdfObjectDictionary =_dc .MakeDict ();_fadc .Merge (_aafe .PdfObjectDictionary );
|
|
_fadc .Merge (_ddg .MakeStreamDict ());_fadc .Set ("\u004c\u0065\u006e\u0067\u0074\u0068",_dc .MakeInteger (int64 (len (_bef ))));_ggdg [_aafe ]=_fadc ;_bgaa [_ebg ].Stream =_fadc ;};_agec =make ([]_dc .PdfObject ,len (objects ));copy (_agec ,objects );
|
|
_fdf (_agec ,_ggdg );return _agec ,nil ;};func _bdc (_dd *_dc .PdfObjectStream )error {_afd ,_ff :=_dc .DecodeStream (_dd );if _ff !=nil {return _ff ;};_eab :=_f .NewContentStreamParser (string (_afd ));_baf ,_ff :=_eab .Parse ();if _ff !=nil {return _ff ;
|
|
};_baf =_fa (_baf );_cg :=_baf .Bytes ();if len (_cg )>=len (_afd ){return nil ;};_dca ,_ff :=_dc .MakeStream (_baf .Bytes (),_dc .NewFlateEncoder ());if _ff !=nil {return _ff ;};_dd .Stream =_dca .Stream ;_dd .Merge (_dca .PdfObjectDictionary );return nil ;
|
|
};func _fdf (_fgae []_dc .PdfObject ,_cbc map[_dc .PdfObject ]_dc .PdfObject ){if len (_cbc )==0{return ;};for _cea ,_eddd :=range _fgae {if _faaf ,_acbc :=_cbc [_eddd ];_acbc {_fgae [_cea ]=_faaf ;continue ;};_cbc [_eddd ]=_eddd ;switch _bcdg :=_eddd .(type ){case *_dc .PdfObjectArray :_aedb :=make ([]_dc .PdfObject ,_bcdg .Len ());
|
|
copy (_aedb ,_bcdg .Elements ());_fdf (_aedb ,_cbc );for _bbgf ,_bae :=range _aedb {_bcdg .Set (_bbgf ,_bae );};case *_dc .PdfObjectStreams :_fdf (_bcdg .Elements (),_cbc );case *_dc .PdfObjectStream :_bgd :=[]_dc .PdfObject {_bcdg .PdfObjectDictionary };
|
|
_fdf (_bgd ,_cbc );_bcdg .PdfObjectDictionary =_bgd [0].(*_dc .PdfObjectDictionary );case *_dc .PdfObjectDictionary :_gcae :=_bcdg .Keys ();_ecg :=make ([]_dc .PdfObject ,len (_gcae ));for _ffag ,_ded :=range _gcae {_ecg [_ffag ]=_bcdg .Get (_ded );};_fdf (_ecg ,_cbc );
|
|
for _dfbd ,_cdec :=range _gcae {_bcdg .Set (_cdec ,_ecg [_dfbd ]);};case *_dc .PdfIndirectObject :_ade :=[]_dc .PdfObject {_bcdg .PdfObject };_fdf (_ade ,_cbc );_bcdg .PdfObject =_ade [0];};};};type imageModifications struct{Scale float64 ;Encoding _dc .StreamEncoder ;
|
|
};func _bgad (_gbg []_dc .PdfObject )(_ec map[*_dc .PdfObjectStream ]struct{},_cc error ){_ec =map[*_dc .PdfObjectStream ]struct{}{};_fdb :=map[*_c .PdfFont ]struct{}{};_gdd :=_fee (_gbg );for _ ,_dcb :=range _gdd ._cedg {_gbf ,_ga :=_dc .GetDict (_dcb .PdfObject );
|
|
if !_ga {continue ;};_agb ,_ga :=_dc .GetDict (_gbf .Get ("\u0052e\u0073\u006f\u0075\u0072\u0063\u0065s"));if !_ga {continue ;};_cf ,_ :=_dbgb (_gbf .Get ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073"));_agg ,_aa :=_c .NewPdfPageResourcesFromDict (_agb );
|
|
if _aa !=nil {return nil ,_aa ;};_efe :=[]content {{_ca :_cf ,_bcdc :_agg }};_bgf :=_bfc (_gbf .Get ("\u0041\u006e\u006e\u006f\u0074\u0073"));if _bgf !=nil {_efe =append (_efe ,_bgf ...);};for _ ,_dfd :=range _efe {_gfg ,_aac :=_ac .NewFromContents (_dfd ._ca ,_dfd ._bcdc );
|
|
if _aac !=nil {return nil ,_aac ;};_cec ,_ ,_ ,_aac :=_gfg .ExtractPageText ();if _aac !=nil {return nil ,_aac ;};for _ ,_ee :=range _cec .Marks ().Elements (){if _ee .Font ==nil {continue ;};if _ ,_eaba :=_fdb [_ee .Font ];!_eaba {_fdb [_ee .Font ]=struct{}{};
|
|
};};};};_aggd :=map[*_dc .PdfObjectStream ][]*_c .PdfFont {};for _aec :=range _fdb {_dfg :=_aec .FontDescriptor ();if _dfg ==nil ||_dfg .FontFile2 ==nil {continue ;};_cde ,_bbf :=_dc .GetStream (_dfg .FontFile2 );if !_bbf {continue ;};_aggd [_cde ]=append (_aggd [_cde ],_aec );
|
|
};for _gca :=range _aggd {var _baa []rune ;var _faf []_gg .GlyphIndex ;for _ ,_deba :=range _aggd [_gca ]{switch _gab :=_deba .Encoder ().(type ){case *_g .IdentityEncoder :_fg :=_gab .RegisteredRunes ();_eed :=make ([]_gg .GlyphIndex ,len (_fg ));for _bca ,_gaf :=range _fg {_eed [_bca ]=_gg .GlyphIndex (_gaf );
|
|
};_faf =append (_faf ,_eed ...);case *_g .TrueTypeFontEncoder :_cca :=_gab .RegisteredRunes ();_baa =append (_baa ,_cca ...);case _g .SimpleEncoder :_cga :=_gab .Charcodes ();for _ ,_cdef :=range _cga {_daf ,_dg :=_gab .CharcodeToRune (_cdef );if !_dg {_be .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",_cdef );
|
|
continue ;};_baa =append (_baa ,_daf );};};};_cc =_cb (_gca ,_baa ,_faf );if _cc !=nil {_be .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",_cc );
|
|
return nil ,_cc ;};_ec [_gca ]=struct{}{};};return _ec ,nil ;};
|
|
|
|
// CombineDuplicateStreams combines duplicated streams by its data hash.
|
|
// It implements interface model.Optimizer.
|
|
type CombineDuplicateStreams struct{};
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
func (_cgf *CombineDuplicateDirectObjects )Optimize (objects []_dc .PdfObject )(_eee []_dc .PdfObject ,_cfd error ){_dcc (objects );_edgb :=make (map[string ][]*_dc .PdfObjectDictionary );var _bbg func (_gcc *_dc .PdfObjectDictionary );_bbg =func (_dcbee *_dc .PdfObjectDictionary ){for _ ,_bde :=range _dcbee .Keys (){_fec :=_dcbee .Get (_bde );
|
|
if _gfgg ,_fae :=_fec .(*_dc .PdfObjectDictionary );_fae {_egbb :=_a .New ();_egbb .Write ([]byte (_gfgg .WriteString ()));_gbgf :=string (_egbb .Sum (nil ));_edgb [_gbgf ]=append (_edgb [_gbgf ],_gfgg );_bbg (_gfgg );};};};for _ ,_gdgc :=range objects {_ead ,_gbfg :=_gdgc .(*_dc .PdfIndirectObject );
|
|
if !_gbfg {continue ;};if _efa ,_geb :=_ead .PdfObject .(*_dc .PdfObjectDictionary );_geb {_bbg (_efa );};};_fde :=make ([]_dc .PdfObject ,0,len (_edgb ));_cee :=make (map[_dc .PdfObject ]_dc .PdfObject );for _ ,_gbe :=range _edgb {if len (_gbe )< 2{continue ;
|
|
};_afbg :=_dc .MakeDict ();_afbg .Merge (_gbe [0]);_aaca :=_dc .MakeIndirectObject (_afbg );_fde =append (_fde ,_aaca );for _bcb :=0;_bcb < len (_gbe );_bcb ++{_debe :=_gbe [_bcb ];_cee [_debe ]=_aaca ;};};_eee =make ([]_dc .PdfObject ,len (objects ));
|
|
copy (_eee ,objects );_eee =append (_fde ,_eee ...);_fdf (_eee ,_cee );return _eee ,nil ;};
|
|
|
|
// New creates a optimizers chain from options.
|
|
func New (options Options )*Chain {_edga :=new (Chain );if options .CleanFonts ||options .SubsetFonts {_edga .Append (&CleanFonts {Subset :options .SubsetFonts });};if options .CleanContentstream {_edga .Append (new (CleanContentstream ));};if options .ImageUpperPPI > 0{_ceef :=new (ImagePPI );
|
|
_ceef .ImageUpperPPI =options .ImageUpperPPI ;_edga .Append (_ceef );};if options .ImageQuality > 0{_bee :=new (Image );_bee .ImageQuality =options .ImageQuality ;_edga .Append (_bee );};if options .CombineDuplicateDirectObjects {_edga .Append (new (CombineDuplicateDirectObjects ));
|
|
};if options .CombineDuplicateStreams {_edga .Append (new (CombineDuplicateStreams ));};if options .CombineIdenticalIndirectObjects {_edga .Append (new (CombineIdenticalIndirectObjects ));};if options .UseObjectStreams {_edga .Append (new (ObjectStreams ));
|
|
};if options .CompressStreams {_edga .Append (new (CompressStreams ));};return _edga ;};
|
|
|
|
// CombineDuplicateDirectObjects combines duplicated direct objects by its data hash.
|
|
// It implements interface model.Optimizer.
|
|
type CombineDuplicateDirectObjects struct{};func _dcc (_eeac []_dc .PdfObject ){for _gagd ,_gcg :=range _eeac {switch _egc :=_gcg .(type ){case *_dc .PdfIndirectObject :_egc .ObjectNumber =int64 (_gagd +1);_egc .GenerationNumber =0;case *_dc .PdfObjectStream :_egc .ObjectNumber =int64 (_gagd +1);
|
|
_egc .GenerationNumber =0;case *_dc .PdfObjectStreams :_egc .ObjectNumber =int64 (_gagd +1);_egc .GenerationNumber =0;};};}; |