mirror of
https://github.com/unidoc/unipdf.git
synced 2025-04-24 13:48:49 +08:00
238 lines
44 KiB
Go
238 lines
44 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 (_a "bytes";_ed "crypto/md5";_bg "errors";_eea "fmt";_e "github.com/unidoc/unipdf/v3/common";_eb "github.com/unidoc/unipdf/v3/contentstream";_fg "github.com/unidoc/unipdf/v3/core";_b "github.com/unidoc/unipdf/v3/extractor";_da "github.com/unidoc/unipdf/v3/internal/imageutil";
|
|
_de "github.com/unidoc/unipdf/v3/internal/textencoding";_c "github.com/unidoc/unipdf/v3/model";_g "github.com/unidoc/unitype";_d "golang.org/x/image/draw";_fc "math";_ee "strings";);
|
|
|
|
// 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 _gbf (_ebeb *_fg .PdfObjectStream ,_geb []rune ,_gdb []_g .GlyphIndex )error {_ebeb ,_cff :=_fg .GetStream (_ebeb );if !_cff {_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 _bg .New ("\u0066\u006f\u006e\u0074fi\u006c\u0065\u0032\u0020\u006e\u006f\u0074\u0020\u0066\u006f\u0075\u006e\u0064");};_gbeb ,_gegd :=_fg .DecodeStream (_ebeb );if _gegd !=nil {_e .Log .Debug ("\u0044\u0065c\u006f\u0064\u0065 \u0065\u0072\u0072\u006f\u0072\u003a\u0020\u0025\u0076",_gegd );
|
|
return _gegd ;};_dbgc ,_gegd :=_g .Parse (_a .NewReader (_gbeb ));if _gegd !=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 (_ebeb .Stream ));
|
|
return _gegd ;};_bec :=_gdb ;if len (_geb )> 0{_aaf :=_dbgc .LookupRunes (_geb );_bec =append (_bec ,_aaf ...);};_dbgc ,_gegd =_dbgc .SubsetKeepIndices (_bec );if _gegd !=nil {_e .Log .Debug ("\u0045R\u0052\u004f\u0052\u0020s\u0075\u0062\u0073\u0065\u0074t\u0069n\u0067 \u0066\u006f\u006e\u0074\u003a\u0020\u0025v",_gegd );
|
|
return _gegd ;};var _bbe _a .Buffer ;_gegd =_dbgc .Write (&_bbe );if _gegd !=nil {_e .Log .Debug ("\u0045\u0052\u0052\u004fR \u0057\u0072\u0069\u0074\u0069\u006e\u0067\u0020\u0066\u006f\u006e\u0074\u003a\u0020%\u0076",_gegd );return _gegd ;};if _bbe .Len ()> len (_gbeb ){_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 ;};_fcd ,_gegd :=_fg .MakeStream (_bbe .Bytes (),_fg .NewFlateEncoder ());if _gegd !=nil {_e .Log .Debug ("\u0045\u0052\u0052\u004fR \u0057\u0072\u0069\u0074\u0069\u006e\u0067\u0020\u0066\u006f\u006e\u0074\u003a\u0020%\u0076",_gegd );return _gegd ;
|
|
};*_ebeb =*_fcd ;_ebeb .Set ("\u004ce\u006e\u0067\u0074\u0068\u0031",_fg .MakeInteger (int64 (_bbe .Len ())));return nil ;};
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
func (_ad *Chain )Optimize (objects []_fg .PdfObject )(_cc []_fg .PdfObject ,_gc error ){_adb :=objects ;for _ ,_ab :=range _ad ._db {_fcf ,_cg :=_ab .Optimize (_adb );if _cg !=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",_cg );
|
|
continue ;};_adb =_fcf ;};return _adb ,nil ;};
|
|
|
|
// CombineDuplicateStreams combines duplicated streams by its data hash.
|
|
// It implements interface model.Optimizer.
|
|
type CombineDuplicateStreams struct{};
|
|
|
|
// CombineIdenticalIndirectObjects combines identical indirect objects.
|
|
// It implements interface model.Optimizer.
|
|
type CombineIdenticalIndirectObjects struct{};
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
func (_gb *CleanContentstream )Optimize (objects []_fg .PdfObject )(_gcg []_fg .PdfObject ,_gd error ){_ebb :=map[*_fg .PdfObjectStream ]struct{}{};var _eeb []*_fg .PdfObjectStream ;_gg :=func (_fff *_fg .PdfObjectStream ){if _ ,_ea :=_ebb [_fff ];!_ea {_ebb [_fff ]=struct{}{};
|
|
_eeb =append (_eeb ,_fff );};};_gga :=map[_fg .PdfObject ]bool {};_ag :=map[_fg .PdfObject ]bool {};for _ ,_ae :=range objects {switch _fa :=_ae .(type ){case *_fg .PdfIndirectObject :switch _adf :=_fa .PdfObject .(type ){case *_fg .PdfObjectDictionary :if _eec ,_ffc :=_fg .GetName (_adf .Get ("\u0054\u0079\u0070\u0065"));
|
|
!_ffc ||_eec .String ()!="\u0050\u0061\u0067\u0065"{continue ;};if _ccf ,_ebe :=_fg .GetStream (_adf .Get ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073"));_ebe {_gg (_ccf );}else if _adfc ,_dbaf :=_fg .GetArray (_adf .Get ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073"));
|
|
_dbaf {var _gcc []*_fg .PdfObjectStream ;for _ ,_edg :=range _adfc .Elements (){if _geg ,_ccg :=_fg .GetStream (_edg );_ccg {_gcc =append (_gcc ,_geg );};};if len (_gcc )> 0{var _dcg _a .Buffer ;for _ ,_fd :=range _gcc {if _bee ,_gad :=_fg .DecodeStream (_fd );
|
|
_gad ==nil {_dcg .Write (_bee );};_gga [_fd ]=true ;};_bga ,_gcgg :=_fg .MakeStream (_dcg .Bytes (),_fg .NewFlateEncoder ());if _gcgg !=nil {return nil ,_gcgg ;};_ag [_bga ]=true ;_adf .Set ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073",_bga );_gg (_bga );
|
|
};};};case *_fg .PdfObjectStream :if _eed ,_bcc :=_fg .GetName (_fa .Get ("\u0054\u0079\u0070\u0065"));!_bcc ||_eed .String ()!="\u0058O\u0062\u006a\u0065\u0063\u0074"{continue ;};if _gab ,_gcd :=_fg .GetName (_fa .Get ("\u0053u\u0062\u0074\u0079\u0070\u0065"));
|
|
!_gcd ||_gab .String ()!="\u0046\u006f\u0072\u006d"{continue ;};_gg (_fa );};};for _ ,_ce :=range _eeb {_gd =_cf (_ce );if _gd !=nil {return nil ,_gd ;};};_gcg =nil ;for _ ,_gfe :=range objects {if _gga [_gfe ]{continue ;};_gcg =append (_gcg ,_gfe );};
|
|
for _dbf :=range _ag {_gcg =append (_gcg ,_dbf );};return _gcg ,nil ;};
|
|
|
|
// 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 (_egab *ObjectStreams )Optimize (objects []_fg .PdfObject )(_gbcb []_fg .PdfObject ,_caf error ){_ffcb :=&_fg .PdfObjectStreams {};_bdeca :=make ([]_fg .PdfObject ,0,len (objects ));for _ ,_abgd :=range objects {if _ccee ,_ggfd :=_abgd .(*_fg .PdfIndirectObject );
|
|
_ggfd &&_ccee .GenerationNumber ==0{_ffcb .Append (_abgd );}else {_bdeca =append (_bdeca ,_abgd );};};if _ffcb .Len ()==0{return _bdeca ,nil ;};_gbcb =make ([]_fg .PdfObject ,0,len (_bdeca )+_ffcb .Len ()+1);if _ffcb .Len ()> 1{_gbcb =append (_gbcb ,_ffcb );
|
|
};_gbcb =append (_gbcb ,_ffcb .Elements ()...);_gbcb =append (_gbcb ,_bdeca ...);return _gbcb ,nil ;};type imageInfo struct{BitsPerComponent int ;ColorComponents int ;Width int ;Height int ;Stream *_fg .PdfObjectStream ;PPI float64 ;};
|
|
|
|
// CompressStreams compresses uncompressed streams.
|
|
// It implements interface model.Optimizer.
|
|
type CompressStreams struct{};
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
func (_bgdd *CompressStreams )Optimize (objects []_fg .PdfObject )(_bac []_fg .PdfObject ,_fef error ){_bac =make ([]_fg .PdfObject ,len (objects ));copy (_bac ,objects );for _ ,_fcde :=range objects {_gbc ,_ageb :=_fg .GetStream (_fcde );if !_ageb {continue ;
|
|
};if _aab :=_gbc .Get ("\u0046\u0069\u006c\u0074\u0065\u0072");_aab !=nil {if _ ,_dfcd :=_fg .GetName (_aab );_dfcd {continue ;};if _bgbb ,_edfa :=_fg .GetArray (_aab );_edfa &&_bgbb .Len ()> 0{continue ;};};_eaeb :=_fg .NewFlateEncoder ();var _fac []byte ;
|
|
_fac ,_fef =_eaeb .EncodeBytes (_gbc .Stream );if _fef !=nil {return _bac ,_fef ;};_cbag :=_eaeb .MakeStreamDict ();if len (_fac )+len (_cbag .WriteString ())< len (_gbc .Stream ){_gbc .Stream =_fac ;_gbc .PdfObjectDictionary .Merge (_cbag );_gbc .PdfObjectDictionary .Set ("\u004c\u0065\u006e\u0067\u0074\u0068",_fg .MakeInteger (int64 (len (_gbc .Stream ))));
|
|
};};return _bac ,nil ;};
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
func (_eee *CombineDuplicateDirectObjects )Optimize (objects []_fg .PdfObject )(_afd []_fg .PdfObject ,_bcf error ){_dfbb (objects );_aeg :=make (map[string ][]*_fg .PdfObjectDictionary );var _fgcc func (_cabc *_fg .PdfObjectDictionary );_fgcc =func (_ggf *_fg .PdfObjectDictionary ){for _ ,_cee :=range _ggf .Keys (){_ebcd :=_ggf .Get (_cee );
|
|
if _cedc ,_aca :=_ebcd .(*_fg .PdfObjectDictionary );_aca {if _gfad :=_cedc .Keys ();len (_gfad )==0{continue ;};_dbc :=_ed .New ();_dbc .Write ([]byte (_cedc .WriteString ()));_egb :=string (_dbc .Sum (nil ));_aeg [_egb ]=append (_aeg [_egb ],_cedc );
|
|
_fgcc (_cedc );};};};for _ ,_fbf :=range objects {_gaf ,_geed :=_fbf .(*_fg .PdfIndirectObject );if !_geed {continue ;};if _fab ,_dffg :=_gaf .PdfObject .(*_fg .PdfObjectDictionary );_dffg {_fgcc (_fab );};};_adfe :=make ([]_fg .PdfObject ,0,len (_aeg ));
|
|
_dag :=make (map[_fg .PdfObject ]_fg .PdfObject );for _ ,_gaee :=range _aeg {if len (_gaee )< 2{continue ;};_eag :=_fg .MakeDict ();_eag .Merge (_gaee [0]);_fee :=_fg .MakeIndirectObject (_eag );_adfe =append (_adfe ,_fee );for _cbgb :=0;_cbgb < len (_gaee );
|
|
_cbgb ++{_aafc :=_gaee [_cbgb ];_dag [_aafc ]=_fee ;};};_afd =make ([]_fg .PdfObject ,len (objects ));copy (_afd ,objects );_afd =append (_adfe ,_afd ...);_afg (_afd ,_dag );return _afd ,nil ;};type imageModifications struct{Scale float64 ;Encoding _fg .StreamEncoder ;
|
|
};func _afg (_ebaff []_fg .PdfObject ,_dea map[_fg .PdfObject ]_fg .PdfObject ){if len (_dea )==0{return ;};for _gaff ,_dec :=range _ebaff {if _bfc ,_aadg :=_dea [_dec ];_aadg {_ebaff [_gaff ]=_bfc ;continue ;};_dea [_dec ]=_dec ;switch _ffce :=_dec .(type ){case *_fg .PdfObjectArray :_aeb :=make ([]_fg .PdfObject ,_ffce .Len ());
|
|
copy (_aeb ,_ffce .Elements ());_afg (_aeb ,_dea );for _ggee ,_gedc :=range _aeb {_ffce .Set (_ggee ,_gedc );};case *_fg .PdfObjectStreams :_afg (_ffce .Elements (),_dea );case *_fg .PdfObjectStream :_gbfga :=[]_fg .PdfObject {_ffce .PdfObjectDictionary };
|
|
_afg (_gbfga ,_dea );_ffce .PdfObjectDictionary =_gbfga [0].(*_fg .PdfObjectDictionary );case *_fg .PdfObjectDictionary :_dega :=_ffce .Keys ();_gaca :=make ([]_fg .PdfObject ,len (_dega ));for _gfcf ,_gfefg :=range _dega {_gaca [_gfcf ]=_ffce .Get (_gfefg );
|
|
};_afg (_gaca ,_dea );for _addd ,_cae :=range _dega {_ffce .Set (_cae ,_gaca [_addd ]);};case *_fg .PdfIndirectObject :_bgf :=[]_fg .PdfObject {_ffce .PdfObject };_afg (_bgf ,_dea );_ffce .PdfObject =_bgf [0];};};};
|
|
|
|
// Chain allows to use sequence of optimizers.
|
|
// It implements interface model.Optimizer.
|
|
type Chain struct{_db []_c .Optimizer };func _cf (_ge *_fg .PdfObjectStream )error {_cfd ,_aa :=_fg .DecodeStream (_ge );if _aa !=nil {return _aa ;};_be :=_eb .NewContentStreamParser (string (_cfd ));_cd ,_aa :=_be .Parse ();if _aa !=nil {return _aa ;};
|
|
_cd =_bc (_cd );_dee :=_cd .Bytes ();if len (_dee )>=len (_cfd ){return nil ;};_ga ,_aa :=_fg .MakeStream (_cd .Bytes (),_fg .NewFlateEncoder ());if _aa !=nil {return _aa ;};_ge .Stream =_ga .Stream ;_ge .Merge (_ga .PdfObjectDictionary );return nil ;};
|
|
|
|
|
|
// Optimize implements Optimizer interface.
|
|
func (_efc *CleanUnusedResources )Optimize (objects []_fg .PdfObject )(_egfd []_fg .PdfObject ,_cbb error ){_acd ,_cbb :=_ddg (objects );if _cbb !=nil {return nil ,_cbb ;};_abb :=[]_fg .PdfObject {};for _ ,_cge :=range objects {_ ,_bead :=_acd [_cge ];
|
|
if _bead {continue ;};_abb =append (_abb ,_cge );};return _abb ,nil ;};
|
|
|
|
// CleanUnusedResources represents an optimizer used to clean unused resources.
|
|
type CleanUnusedResources struct{};
|
|
|
|
// CombineDuplicateDirectObjects combines duplicated direct objects by its data hash.
|
|
// It implements interface model.Optimizer.
|
|
type CombineDuplicateDirectObjects struct{};func _fcdd (_dedbf *_fg .PdfObjectDictionary )[]string {_debf :=[]string {};for _ ,_cdeb :=range _dedbf .Keys (){_debf =append (_debf ,_cdeb .String ());};return _debf ;};func _cdg (_bge _fg .PdfObject )[]content {if _bge ==nil {return nil ;
|
|
};_cca ,_bef :=_fg .GetArray (_bge );if !_bef {_e .Log .Debug ("\u0041\u006e\u006e\u006fts\u0020\u006e\u006f\u0074\u0020\u0061\u006e\u0020\u0061\u0072\u0072\u0061\u0079");return nil ;};var _eedd []content ;for _ ,_eba :=range _cca .Elements (){_efd ,_aga :=_fg .GetDict (_eba );
|
|
if !_aga {_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 ;};_gae ,_aga :=_fg .GetDict (_efd .Get ("\u0041\u0050"));
|
|
if !_aga {_e .Log .Debug ("\u004e\u006f\u0020\u0041P \u0065\u006e\u0074\u0072\u0079\u0020\u002d\u0020\u0073\u006b\u0069\u0070\u0070\u0069n\u0067");continue ;};_deea :=_fg .TraceToDirectObject (_gae .Get ("\u004e"));if _deea ==nil {_e .Log .Debug ("N\u006f\u0020\u004e\u0020en\u0074r\u0079\u0020\u002d\u0020\u0073k\u0069\u0070\u0070\u0069\u006e\u0067");
|
|
continue ;};var _dgbe *_fg .PdfObjectStream ;switch _fgf :=_deea .(type ){case *_fg .PdfObjectDictionary :_aea ,_ec :=_fg .GetName (_efd .Get ("\u0041\u0053"));if !_ec {_e .Log .Debug ("\u004e\u006f\u0020\u0041S \u0065\u006e\u0074\u0072\u0079\u0020\u002d\u0020\u0073\u006b\u0069\u0070\u0070\u0069n\u0067");
|
|
continue ;};_dgbe ,_ec =_fg .GetStream (_fgf .Get (*_aea ));if !_ec {_e .Log .Debug ("\u0046o\u0072\u006d\u0020\u006eo\u0074\u0020\u0066\u006f\u0075n\u0064 \u002d \u0073\u006b\u0069\u0070\u0070\u0069\u006eg");continue ;};case *_fg .PdfObjectStream :_dgbe =_fgf ;
|
|
};if _dgbe ==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 ;};_gec ,_aaef :=_c .NewXObjectFormFromStream (_dgbe );
|
|
if _aaef !=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",_aaef );continue ;};_gbfg ,_aaef :=_gec .GetContentStream ();
|
|
if _aaef !=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",_aaef );continue ;};_eedd =append (_eedd ,content {_ege :string (_gbfg ),_feg :_gec .Resources });
|
|
};return _eedd ;};type objectStructure struct{_fdab *_fg .PdfObjectDictionary ;_bcca *_fg .PdfObjectDictionary ;_faea []*_fg .PdfIndirectObject ;};
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
func (_eebg *CleanFonts )Optimize (objects []_fg .PdfObject )(_ac []_fg .PdfObject ,_ead error ){var _bag map[*_fg .PdfObjectStream ]struct{};if _eebg .Subset {var _aae error ;_bag ,_aae =_beb (objects );if _aae !=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",_aae );
|
|
return nil ,_aae ;};};for _ ,_bgc :=range objects {_dgb ,_dcca :=_fg .GetStream (_bgc );if !_dcca {continue ;};if _ ,_fec :=_bag [_dgb ];_fec {continue ;};_beg ,_fdb :=_fg .NewEncoderFromStream (_dgb );if _fdb !=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",_fdb );
|
|
continue ;};_fgc ,_fdb :=_beg .DecodeStream (_dgb );if _fdb !=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",_fdb );
|
|
continue ;};if len (_fgc )< 4{continue ;};_eaf :=string (_fgc [:4]);if _eaf =="\u004f\u0054\u0054\u004f"{continue ;};if _eaf !="\u0000\u0001\u0000\u0000"&&_eaf !="\u0074\u0072\u0075\u0065"{continue ;};_egc ,_fdb :=_g .Parse (_a .NewReader (_fgc ));if _fdb !=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",_fdb );
|
|
continue ;};_fdb =_egc .Optimize ();if _fdb !=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",_fdb );continue ;};var _gdbf _a .Buffer ;
|
|
_fdb =_egc .Write (&_gdbf );if _fdb !=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",_fdb );
|
|
continue ;};if _gdbf .Len ()> len (_fgc ){_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 ;};_aac ,_fdb :=_fg .MakeStream (_gdbf .Bytes (),_fg .NewFlateEncoder ());if _fdb !=nil {continue ;};*_dgb =*_aac ;_dgb .Set ("\u004ce\u006e\u0067\u0074\u0068\u0031",_fg .MakeInteger (int64 (_gdbf .Len ())));};return objects ,nil ;};func _gdaf (_bgb string ,_cfee []string )bool {for _ ,_gdbb :=range _cfee {if _bgb ==_gdbb {return true ;
|
|
};};return false ;};
|
|
|
|
// 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 ;
|
|
CleanUnusedResources bool ;};
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
func (_fcbe *ImagePPI )Optimize (objects []_fg .PdfObject )(_afdf []_fg .PdfObject ,_bgcb error ){if _fcbe .ImageUpperPPI <=0{return objects ,nil ;};_bccf :=_cdb (objects );if len (_bccf )==0{return objects ,nil ;};_eaff :=make (map[_fg .PdfObject ]struct{});
|
|
for _ ,_ddc :=range _bccf {_aaa :=_ddc .Stream .PdfObjectDictionary .Get ("\u0053\u004d\u0061s\u006b");_eaff [_aaa ]=struct{}{};};_bed :=make (map[*_fg .PdfObjectStream ]*imageInfo );for _ ,_edcgb :=range _bccf {_bed [_edcgb .Stream ]=_edcgb ;};var _adfefc *_fg .PdfObjectDictionary ;
|
|
for _ ,_eca :=range objects {if _cfge ,_fdff :=_fg .GetDict (_eca );_adfefc ==nil &&_fdff {if _cfbeb ,_fecb :=_fg .GetName (_cfge .Get ("\u0054\u0079\u0070\u0065"));_fecb &&*_cfbeb =="\u0043a\u0074\u0061\u006c\u006f\u0067"{_adfefc =_cfge ;};};};if _adfefc ==nil {return objects ,nil ;
|
|
};_degd ,_gfefc :=_fg .GetDict (_adfefc .Get ("\u0050\u0061\u0067e\u0073"));if !_gfefc {return objects ,nil ;};_cedf ,_cffd :=_fg .GetArray (_degd .Get ("\u004b\u0069\u0064\u0073"));if !_cffd {return objects ,nil ;};for _ ,_aega :=range _cedf .Elements (){_adc :=make (map[string ]*imageInfo );
|
|
_abgb ,_fda :=_fg .GetDict (_aega );if !_fda {continue ;};_dda ,_ :=_bbdg (_abgb .Get ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073"));if len (_dda )==0{continue ;};_agf ,_dege :=_fg .GetDict (_abgb .Get ("\u0052e\u0073\u006f\u0075\u0072\u0063\u0065s"));
|
|
if !_dege {continue ;};_egd ,_eacb :=_c .NewPdfPageResourcesFromDict (_agf );if _eacb !=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",_eacb );
|
|
continue ;};_fdfa ,_begf :=_fg .GetDict (_agf .Get ("\u0058O\u0062\u006a\u0065\u0063\u0074"));if !_begf {continue ;};_gff :=_fdfa .Keys ();for _ ,_cbf :=range _gff {if _bebc ,_dbbb :=_fg .GetStream (_fdfa .Get (_cbf ));_dbbb {if _acde ,_ddcg :=_bed [_bebc ];
|
|
_ddcg {_adc [string (_cbf )]=_acde ;};};};_ddf :=_eb .NewContentStreamParser (_dda );_gebb ,_eacb :=_ddf .Parse ();if _eacb !=nil {_e .Log .Debug ("\u0045\u0052\u0052\u004f\u0052\u003a\u0020\u0025\u002b\u0076",_eacb );continue ;};_fdbg :=_eb .NewContentStreamProcessor (*_gebb );
|
|
_fdbg .AddHandler (_eb .HandlerConditionEnumAllOperands ,"",func (_fcfb *_eb .ContentStreamOperation ,_gfd _eb .GraphicsState ,_abab *_c .PdfPageResources )error {switch _fcfb .Operand {case "\u0044\u006f":if len (_fcfb .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 ;};_fcbg ,_cffa :=_fg .GetName (_fcfb .Params [0]);if !_cffa {_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 _bce ,_ebee :=_adc [string (*_fcbg )];_ebee {_fcfg :=_gfd .CTM .ScalingFactorX ();_gddf :=_gfd .CTM .ScalingFactorY ();_fcc ,_ddaa :=_fcfg /72.0,_gddf /72.0;_daa ,_ebafg :=float64 (_bce .Width )/_fcc ,float64 (_bce .Height )/_ddaa ;if _fcc ==0||_ddaa ==0{_daa =72.0;
|
|
_ebafg =72.0;};_bce .PPI =_fc .Max (_bce .PPI ,_daa );_bce .PPI =_fc .Max (_bce .PPI ,_ebafg );};};return nil ;});_eacb =_fdbg .Process (_egd );if _eacb !=nil {_e .Log .Debug ("E\u0052\u0052\u004f\u0052 p\u0072o\u0063\u0065\u0073\u0073\u0069n\u0067\u003a\u0020\u0025\u002b\u0076",_eacb );
|
|
continue ;};};for _ ,_cdea :=range _bccf {if _ ,_dcda :=_eaff [_cdea .Stream ];_dcda {continue ;};if _cdea .PPI <=_fcbe .ImageUpperPPI {continue ;};_defdd ,_bcg :=_c .NewXObjectImageFromStream (_cdea .Stream );if _bcg !=nil {_e .Log .Debug ("\u0045\u0052\u0052\u004f\u0052\u003a\u0020\u0025\u002b\u0076",_bcg );
|
|
continue ;};var _fbfa imageModifications ;_fbfa .Scale =_fcbe .ImageUpperPPI /_cdea .PPI ;if _cdea .BitsPerComponent ==1&&_cdea .ColorComponents ==1{_cgdg :=_fc .Round (_cdea .PPI /_fcbe .ImageUpperPPI );_dfce :=_da .NextPowerOf2 (uint (_cgdg ));if _da .InDelta (float64 (_dfce ),1/_fbfa .Scale ,0.3){_fbfa .Scale =float64 (1)/float64 (_dfce );
|
|
};if _ ,_cbff :=_defdd .Filter .(*_fg .JBIG2Encoder );!_cbff {_fbfa .Encoding =_fg .NewJBIG2Encoder ();};};if _bcg =_ceea (_defdd ,_fbfa );_bcg !=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",_bcg );
|
|
continue ;};_fbfa .Encoding =nil ;if _gcb ,_bbg :=_fg .GetStream (_cdea .Stream .PdfObjectDictionary .Get ("\u0053\u004d\u0061s\u006b"));_bbg {_cgab ,_bcdd :=_c .NewXObjectImageFromStream (_gcb );if _bcdd !=nil {_e .Log .Debug ("\u0045\u0052\u0052\u004f\u0052\u003a\u0020\u0025\u002b\u0076",_bcdd );
|
|
continue ;};if _bcdd =_ceea (_cgab ,_fbfa );_bcdd !=nil {_e .Log .Debug ("\u0045\u0052\u0052\u004f\u0052\u003a\u0020\u0025\u002b\u0076",_bcdd );continue ;};};};return objects ,nil ;};
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
func (_eacc *CombineDuplicateStreams )Optimize (objects []_fg .PdfObject )(_aacf []_fg .PdfObject ,_cfg error ){_faf :=make (map[_fg .PdfObject ]_fg .PdfObject );_aedd :=make (map[_fg .PdfObject ]struct{});_fdcb :=make (map[string ][]*_fg .PdfObjectStream );
|
|
for _ ,_ebfb :=range objects {if _dfc ,_ffdf :=_ebfb .(*_fg .PdfObjectStream );_ffdf {_bae :=_ed .New ();_bae .Write (_dfc .Stream );_bae .Write ([]byte (_dfc .PdfObjectDictionary .WriteString ()));_ffff :=string (_bae .Sum (nil ));_fdcb [_ffff ]=append (_fdcb [_ffff ],_dfc );
|
|
};};for _ ,_edaf :=range _fdcb {if len (_edaf )< 2{continue ;};_agaa :=_edaf [0];for _bgbe :=1;_bgbe < len (_edaf );_bgbe ++{_ecg :=_edaf [_bgbe ];_faf [_ecg ]=_agaa ;_aedd [_ecg ]=struct{}{};};};_aacf =make ([]_fg .PdfObject ,0,len (objects )-len (_aedd ));
|
|
for _ ,_eae :=range objects {if _ ,_bcde :=_aedd [_eae ];_bcde {continue ;};_aacf =append (_aacf ,_eae );};_afg (_aacf ,_faf );return _aacf ,nil ;};func _bbdg (_cdd _fg .PdfObject )(_daba string ,_eecfd []_fg .PdfObject ){var _dfbc _a .Buffer ;switch _fffg :=_cdd .(type ){case *_fg .PdfIndirectObject :_eecfd =append (_eecfd ,_fffg );
|
|
_cdd =_fffg .PdfObject ;};switch _agac :=_cdd .(type ){case *_fg .PdfObjectStream :if _dabd ,_bcfd :=_fg .DecodeStream (_agac );_bcfd ==nil {_dfbc .Write (_dabd );_eecfd =append (_eecfd ,_agac );};case *_fg .PdfObjectArray :for _ ,_ggg :=range _agac .Elements (){switch _geae :=_ggg .(type ){case *_fg .PdfObjectStream :if _ebeea ,_fefe :=_fg .DecodeStream (_geae );
|
|
_fefe ==nil {_dfbc .Write (_ebeea );_eecfd =append (_eecfd ,_geae );};};};};return _dfbc .String (),_eecfd ;};func _efdf (_gefg []_fg .PdfObject )objectStructure {_bdcc :=objectStructure {};_dfac :=false ;for _ ,_aafcc :=range _gefg {switch _efdd :=_aafcc .(type ){case *_fg .PdfIndirectObject :_fade ,_gdgf :=_fg .GetDict (_efdd );
|
|
if !_gdgf {continue ;};_cbbf ,_gdgf :=_fg .GetName (_fade .Get ("\u0054\u0079\u0070\u0065"));if !_gdgf {continue ;};switch _cbbf .String (){case "\u0043a\u0074\u0061\u006c\u006f\u0067":_bdcc ._fdab =_fade ;_dfac =true ;};};if _dfac {break ;};};if !_dfac {return _bdcc ;
|
|
};_gefa ,_dcbc :=_fg .GetDict (_bdcc ._fdab .Get ("\u0050\u0061\u0067e\u0073"));if !_dcbc {return _bdcc ;};_bdcc ._bcca =_gefa ;_cfde ,_dcbc :=_fg .GetArray (_gefa .Get ("\u004b\u0069\u0064\u0073"));if !_dcbc {return _bdcc ;};for _ ,_gabdg :=range _cfde .Elements (){_cfgd ,_cbc :=_fg .GetIndirect (_gabdg );
|
|
if !_cbc {break ;};_bdcc ._faea =append (_bdcc ._faea ,_cfgd );};return _bdcc ;};func _ebaf (_dedb []*_fg .PdfIndirectObject )map[string ][]string {_afa :=map[string ][]string {};for _ ,_ffd :=range _dedb {_ced ,_cedg :=_fg .GetDict (_ffd .PdfObject );
|
|
if !_cedg {continue ;};_afag :=_ced .Get ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073");_gce :=_fg .TraceToDirectObject (_afag );_ccdg :="";if _dff ,_cde :=_gce .(*_fg .PdfObjectArray );_cde {var _gdd []string ;for _ ,_bgd :=range _dff .Elements (){_ace ,_bfb :=_fdbc (_bgd );
|
|
if _bfb !=nil {continue ;};_gdd =append (_gdd ,_ace );};_ccdg =_ee .Join (_gdd ,"\u0020");};if _bde ,_fdd :=_gce .(*_fg .PdfObjectStream );_fdd {_dced ,_add :=_fg .DecodeStream (_bde );if _add !=nil {continue ;};_ccdg =string (_dced );};_edd :=_eb .NewContentStreamParser (_ccdg );
|
|
_fbg ,_gfa :=_edd .Parse ();if _gfa !=nil {continue ;};for _ ,_dcee :=range *_fbg {_fga :=_dcee .Operand ;_bbeb :=_dcee .Params ;switch _fga {case "\u0044\u006f":_agc :=_bbeb [0].String ();if _ ,_aed :=_afa ["\u0058O\u0062\u006a\u0065\u0063\u0074"];!_aed {_afa ["\u0058O\u0062\u006a\u0065\u0063\u0074"]=[]string {_agc };
|
|
}else {_afa ["\u0058O\u0062\u006a\u0065\u0063\u0074"]=append (_afa ["\u0058O\u0062\u006a\u0065\u0063\u0074"],_agc );};case "\u0054\u0066":_bdb :=_bbeb [0].String ();if _ ,_gabd :=_afa ["\u0046\u006f\u006e\u0074"];!_gabd {_afa ["\u0046\u006f\u006e\u0074"]=[]string {_bdb };
|
|
}else {_afa ["\u0046\u006f\u006e\u0074"]=append (_afa ["\u0046\u006f\u006e\u0074"],_bdb );};case "\u0067\u0073":_abg :=_bbeb [0].String ();if _ ,_dgbeg :=_afa ["\u0045x\u0074\u0047\u0053\u0074\u0061\u0074e"];!_dgbeg {_afa ["\u0045x\u0074\u0047\u0053\u0074\u0061\u0074e"]=[]string {_abg };
|
|
}else {_afa ["\u0045x\u0074\u0047\u0053\u0074\u0061\u0074e"]=append (_afa ["\u0045x\u0074\u0047\u0053\u0074\u0061\u0074e"],_abg );};};};};return _afa ;};func _fdbc (_ggd _fg .PdfObject )(string ,error ){_fffa :=_fg .TraceToDirectObject (_ggd );switch _gee :=_fffa .(type ){case *_fg .PdfObjectString :return _gee .Str (),nil ;
|
|
case *_fg .PdfObjectStream :_ebcf ,_bfa :=_fg .DecodeStream (_gee );if _bfa !=nil {return "",_bfa ;};return string (_ebcf ),nil ;};return "",_eea .Errorf ("\u0069\u006e\u0076\u0061\u006ci\u0064\u0020\u0063\u006f\u006e\u0074\u0065\u006e\u0074\u0020\u0073\u0074\u0072e\u0061\u006d\u0020\u006f\u0062\u006a\u0065\u0063\u0074\u0020\u0068\u006f\u006c\u0064\u0065\u0072\u0020\u0028\u0025\u0054\u0029",_fffa );
|
|
};
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
func (_eadb *Image )Optimize (objects []_fg .PdfObject )(_gdf []_fg .PdfObject ,_edac error ){if _eadb .ImageQuality <=0{return objects ,nil ;};_gge :=_cdb (objects );if len (_gge )==0{return objects ,nil ;};_dfa :=make (map[_fg .PdfObject ]_fg .PdfObject );
|
|
_fgff :=make (map[_fg .PdfObject ]struct{});for _ ,_eafd :=range _gge {_gfb :=_eafd .Stream .Get ("\u0053\u004d\u0061s\u006b");_fgff [_gfb ]=struct{}{};};for _fece ,_afb :=range _gge {_fad :=_afb .Stream ;if _ ,_agd :=_fgff [_fad ];_agd {continue ;};_bfg ,_bbed :=_c .NewXObjectImageFromStream (_fad );
|
|
if _bbed !=nil {_e .Log .Debug ("\u0045\u0052\u0052\u004f\u0052\u003a\u0020\u0025\u002b\u0076",_bbed );continue ;};switch _bfg .Filter .(type ){case *_fg .JBIG2Encoder :continue ;case *_fg .CCITTFaxEncoder :continue ;};_cac ,_bbed :=_bfg .ToImage ();if _bbed !=nil {_e .Log .Debug ("\u0045\u0052\u0052\u004f\u0052\u003a\u0020\u0025\u002b\u0076",_bbed );
|
|
continue ;};_faeb :=_fg .NewDCTEncoder ();_faeb .ColorComponents =_cac .ColorComponents ;_faeb .Quality =_eadb .ImageQuality ;_faeb .BitsPerComponent =_afb .BitsPerComponent ;_faeb .Width =_afb .Width ;_faeb .Height =_afb .Height ;_eaa ,_bbed :=_faeb .EncodeBytes (_cac .Data );
|
|
if _bbed !=nil {_e .Log .Debug ("\u0045\u0052\u0052\u004f\u0052\u003a\u0020\u0025\u002b\u0076",_bbed );continue ;};var _ebba _fg .StreamEncoder ;_ebba =_faeb ;{_baaf :=_fg .NewFlateEncoder ();_bbfb :=_fg .NewMultiEncoder ();_bbfb .AddEncoder (_baaf );_bbfb .AddEncoder (_faeb );
|
|
_gfg ,_fadb :=_bbfb .EncodeBytes (_cac .Data );if _fadb !=nil {_e .Log .Debug ("\u0045\u0052\u0052\u004f\u0052\u003a\u0020\u0025\u002b\u0076",_fadb );continue ;};if len (_gfg )< len (_eaa ){_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 (_eaa ),len (_gfg ),len (_fad .Stream ));
|
|
_eaa =_gfg ;_ebba =_bbfb ;};};_ffb :=len (_fad .Stream );if _ffb < len (_eaa ){continue ;};_ccga :=&_fg .PdfObjectStream {Stream :_eaa };_ccga .PdfObjectReference =_fad .PdfObjectReference ;_ccga .PdfObjectDictionary =_fg .MakeDict ();_ccga .Merge (_fad .PdfObjectDictionary );
|
|
_ccga .Merge (_ebba .MakeStreamDict ());_ccga .Set ("\u004c\u0065\u006e\u0067\u0074\u0068",_fg .MakeInteger (int64 (len (_eaa ))));_dfa [_fad ]=_ccga ;_gge [_fece ].Stream =_ccga ;};_gdf =make ([]_fg .PdfObject ,len (objects ));copy (_gdf ,objects );_afg (_gdf ,_dfa );
|
|
return _gdf ,nil ;};func _beb (_af []_fg .PdfObject )(_bf map[*_fg .PdfObjectStream ]struct{},_eg error ){_bf =map[*_fg .PdfObjectStream ]struct{}{};_dce :=map[*_c .PdfFont ]struct{}{};_gbg :=_efdf (_af );for _ ,_df :=range _gbg ._faea {_eef ,_dbg :=_fg .GetDict (_df .PdfObject );
|
|
if !_dbg {continue ;};_eeab ,_dbg :=_fg .GetDict (_eef .Get ("\u0052e\u0073\u006f\u0075\u0072\u0063\u0065s"));if !_dbg {continue ;};_ada ,_ :=_bbdg (_eef .Get ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073"));_ca ,_fe :=_c .NewPdfPageResourcesFromDict (_eeab );
|
|
if _fe !=nil {return nil ,_fe ;};_edf :=[]content {{_ege :_ada ,_feg :_ca }};_cgc :=_cdg (_eef .Get ("\u0041\u006e\u006e\u006f\u0074\u0073"));if _cgc !=nil {_edf =append (_edf ,_cgc ...);};for _ ,_cab :=range _edf {_ggc ,_ged :=_b .NewFromContents (_cab ._ege ,_cab ._feg );
|
|
if _ged !=nil {return nil ,_ged ;};_gac ,_ ,_ ,_ged :=_ggc .ExtractPageText ();if _ged !=nil {return nil ,_ged ;};for _ ,_fea :=range _gac .Marks ().Elements (){if _fea .Font ==nil {continue ;};if _ ,_cbg :=_dce [_fea .Font ];!_cbg {_dce [_fea .Font ]=struct{}{};
|
|
};};};};_aad :=map[*_fg .PdfObjectStream ][]*_c .PdfFont {};for _dfb :=range _dce {_egf :=_dfb .FontDescriptor ();if _egf ==nil ||_egf .FontFile2 ==nil {continue ;};_def ,_dd :=_fg .GetStream (_egf .FontFile2 );if !_dd {continue ;};_aad [_def ]=append (_aad [_def ],_dfb );
|
|
};for _cgcb :=range _aad {var _cce []rune ;var _ccd []_g .GlyphIndex ;for _ ,_dcef :=range _aad [_cgcb ]{switch _fdc :=_dcef .Encoder ().(type ){case *_de .IdentityEncoder :_dcb :=_fdc .RegisteredRunes ();_gbe :=make ([]_g .GlyphIndex ,len (_dcb ));for _gda ,_dfd :=range _dcb {_gbe [_gda ]=_g .GlyphIndex (_dfd );
|
|
};_ccd =append (_ccd ,_gbe ...);case *_de .TrueTypeFontEncoder :_ebc :=_fdc .RegisteredRunes ();_cce =append (_cce ,_ebc ...);case _de .SimpleEncoder :_dbe :=_fdc .Charcodes ();for _ ,_bb :=range _dbe {_ef ,_dcc :=_fdc .CharcodeToRune (_bb );if !_dcc {_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",_bb );
|
|
continue ;};_cce =append (_cce ,_ef );};};};_eg =_gbf (_cgcb ,_cce ,_ccd );if _eg !=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",_eg );
|
|
return nil ,_eg ;};_bf [_cgcb ]=struct{}{};};return _bf ,nil ;};func _dfbb (_cdab []_fg .PdfObject ){for _efg ,_gddg :=range _cdab {switch _gcga :=_gddg .(type ){case *_fg .PdfIndirectObject :_gcga .ObjectNumber =int64 (_efg +1);_gcga .GenerationNumber =0;
|
|
case *_fg .PdfObjectStream :_gcga .ObjectNumber =int64 (_efg +1);_gcga .GenerationNumber =0;case *_fg .PdfObjectStreams :_gcga .ObjectNumber =int64 (_efg +1);_gcga .GenerationNumber =0;};};};
|
|
|
|
// GetOptimizers gets the list of optimizers in chain `c`.
|
|
func (_dc *Chain )GetOptimizers ()[]_c .Optimizer {return _dc ._db };
|
|
|
|
// Append appends optimizers to the chain.
|
|
func (_fcb *Chain )Append (optimizers ..._c .Optimizer ){_fcb ._db =append (_fcb ._db ,optimizers ...)};
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
func (_bcba *CombineIdenticalIndirectObjects )Optimize (objects []_fg .PdfObject )(_aba []_fg .PdfObject ,_cgea error ){_dfbb (objects );_aec :=make (map[_fg .PdfObject ]_fg .PdfObject );_dab :=make (map[_fg .PdfObject ]struct{});_agcc :=make (map[string ][]*_fg .PdfIndirectObject );
|
|
for _ ,_edcg :=range objects {_cgg ,_ebd :=_edcg .(*_fg .PdfIndirectObject );if !_ebd {continue ;};if _cfdd ,_eaga :=_cgg .PdfObject .(*_fg .PdfObjectDictionary );_eaga {if _afdd ,_edad :=_cfdd .Get ("\u0054\u0079\u0070\u0065").(*_fg .PdfObjectName );_edad &&*_afdd =="\u0050\u0061\u0067\u0065"{continue ;
|
|
};if _fbc :=_cfdd .Keys ();len (_fbc )==0{continue ;};_ffa :=_ed .New ();_ffa .Write ([]byte (_cfdd .WriteString ()));_ccgf :=string (_ffa .Sum (nil ));_agcc [_ccgf ]=append (_agcc [_ccgf ],_cgg );};};for _ ,_cbgf :=range _agcc {if len (_cbgf )< 2{continue ;
|
|
};_feb :=_cbgf [0];for _cfc :=1;_cfc < len (_cbgf );_cfc ++{_fffc :=_cbgf [_cfc ];_aec [_fffc ]=_feb ;_dab [_fffc ]=struct{}{};};};_aba =make ([]_fg .PdfObject ,0,len (objects )-len (_dab ));for _ ,_ccfa :=range objects {if _ ,_adfef :=_dab [_ccfa ];_adfef {continue ;
|
|
};_aba =append (_aba ,_ccfa );};_afg (_aba ,_aec );return _aba ,nil ;};
|
|
|
|
// 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 ;};type content struct{_ege string ;_feg *_c .PdfPageResources ;};func _ddg (_aee []_fg .PdfObject )(map[_fg .PdfObject ]struct{},error ){_gbgb :=_efdf (_aee );_efdg :=_gbgb ._faea ;_cbd :=make (map[_fg .PdfObject ]struct{});_ggb :=_ebaf (_efdg );
|
|
for _ ,_ffca :=range _efdg {_cfb ,_cdc :=_fg .GetDict (_ffca .PdfObject );if !_cdc {continue ;};_deb ,_cdc :=_fg .GetDict (_cfb .Get ("\u0052e\u0073\u006f\u0075\u0072\u0063\u0065s"));if !_cdc {continue ;};_cgf :=_ggb ["\u0058O\u0062\u006a\u0065\u0063\u0074"];
|
|
_eebc ,_cdc :=_fg .GetDict (_deb .Get ("\u0058O\u0062\u006a\u0065\u0063\u0074"));if _cdc {_dcgd :=_fcdd (_eebc );for _ ,_gfeb :=range _dcgd {if _gdaf (_gfeb ,_cgf ){continue ;};_egg :=*_fg .MakeName (_gfeb );_edb :=_eebc .Get (_egg );_cbd [_edb ]=struct{}{};
|
|
_eebc .Remove (_egg );_abbg :=_edef (_edb ,_cbd );if _abbg !=nil {_e .Log .Debug ("\u0066\u0061\u0069\u006ce\u0064\u0020\u0074\u006f\u0020\u0074\u0072\u0061\u0076\u0065r\u0073e\u0020\u006f\u0062\u006a\u0065\u0063\u0074 \u0025\u0076",_edb );};};};_cec ,_cdc :=_fg .GetDict (_deb .Get ("\u0046\u006f\u006e\u0074"));
|
|
_ede :=_ggb ["\u0046\u006f\u006e\u0074"];if _cdc {_bcb :=_fcdd (_cec );for _ ,_dbb :=range _bcb {if _gdaf (_dbb ,_ede ){continue ;};_gdg :=*_fg .MakeName (_dbb );_ded :=_cec .Get (_gdg );_cbd [_ded ]=struct{}{};_cec .Remove (_gdg );_dgf :=_edef (_ded ,_cbd );
|
|
if _dgf !=nil {_e .Log .Debug ("\u0046\u0061i\u006c\u0065\u0064\u0020\u0074\u006f\u0020\u0074\u0072\u0061\u0076\u0065\u0072\u0073\u0065\u0020\u006f\u0062\u006a\u0065\u0063\u0074 %\u0076\u000a",_ded );};};};_fbe ,_cdc :=_fg .GetDict (_deb .Get ("\u0045x\u0074\u0047\u0053\u0074\u0061\u0074e"));
|
|
if _cdc {_bcbb :=_fcdd (_fbe );_fgd :=_ggb ["\u0045x\u0074\u0047\u0053\u0074\u0061\u0074e"];for _ ,_dcge :=range _bcbb {if _gdaf (_dcge ,_fgd ){continue ;};_eecf :=*_fg .MakeName (_dcge );_cfe :=_fbe .Get (_eecf );_cbd [_cfe ]=struct{}{};_fbe .Remove (_eecf );
|
|
_beab :=_edef (_cfe ,_cbd );if _beab !=nil {_e .Log .Debug ("\u0066\u0061i\u006c\u0065\u0064\u0020\u0074\u006f\u0020\u0074\u0072\u0061\u0076\u0065\u0072\u0073\u0065\u0020\u006f\u0062\u006a\u0065\u0063\u0074 %\u0076\u000a",_cfe );};};};};return _cbd ,nil ;
|
|
};func _aeea (_defd *_c .Image ,_cffb float64 )(*_c .Image ,error ){_egfdd ,_ggad :=_defd .ToGoImage ();if _ggad !=nil {return nil ,_ggad ;};var _dgg _da .Image ;_gbde ,_ebcg :=_egfdd .(*_da .Monochrome );if _ebcg {if _ggad =_gbde .ResolveDecode ();_ggad !=nil {return nil ,_ggad ;
|
|
};_dgg ,_ggad =_gbde .Scale (_cffb );if _ggad !=nil {return nil ,_ggad ;};}else {_ece :=int (_fc .RoundToEven (float64 (_defd .Width )*_cffb ));_faed :=int (_fc .RoundToEven (float64 (_defd .Height )*_cffb ));_dgg ,_ggad =_da .NewImage (_ece ,_faed ,int (_defd .BitsPerComponent ),_defd .ColorComponents ,nil ,nil ,nil );
|
|
if _ggad !=nil {return nil ,_ggad ;};_d .CatmullRom .Scale (_dgg ,_dgg .Bounds (),_egfdd ,_egfdd .Bounds (),_d .Over ,&_d .Options {});};_babe :=_dgg .Base ();_ceg :=&_c .Image {Width :int64 (_babe .Width ),Height :int64 (_babe .Height ),BitsPerComponent :int64 (_babe .BitsPerComponent ),ColorComponents :_babe .ColorComponents ,Data :_babe .Data };
|
|
_ceg .SetDecode (_babe .Decode );_ceg .SetAlpha (_babe .Alpha );return _ceg ,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 ;};func _cdb (_egeb []_fg .PdfObject )[]*imageInfo {_ebfd :=_fg .PdfObjectName ("\u0053u\u0062\u0074\u0079\u0070\u0065");_aeae :=make (map[*_fg .PdfObjectStream ]struct{});var _acbc []*imageInfo ;for _ ,_gbcd :=range _egeb {_cfbe ,_face :=_fg .GetStream (_gbcd );
|
|
if !_face {continue ;};if _ ,_cfcc :=_aeae [_cfbe ];_cfcc {continue ;};_aeae [_cfbe ]=struct{}{};_daeg :=_cfbe .PdfObjectDictionary .Get (_ebfd );_fgge ,_face :=_fg .GetName (_daeg );if !_face ||string (*_fgge )!="\u0049\u006d\u0061g\u0065"{continue ;};
|
|
_cdae :=&imageInfo {Stream :_cfbe ,BitsPerComponent :8};if _ccb ,_ggdc :=_fg .GetIntVal (_cfbe .Get ("\u0042\u0069t\u0073\u0050\u0065r\u0043\u006f\u006d\u0070\u006f\u006e\u0065\u006e\u0074"));_ggdc {_cdae .BitsPerComponent =_ccb ;};if _fggf ,_faeg :=_fg .GetIntVal (_cfbe .Get ("\u0057\u0069\u0064t\u0068"));
|
|
_faeg {_cdae .Width =_fggf ;};if _baa ,_dbea :=_fg .GetIntVal (_cfbe .Get ("\u0048\u0065\u0069\u0067\u0068\u0074"));_dbea {_cdae .Height =_baa ;};_bab ,_cfae :=_c .NewPdfColorspaceFromPdfObject (_cfbe .Get ("\u0043\u006f\u006c\u006f\u0072\u0053\u0070\u0061\u0063\u0065"));
|
|
if _cfae !=nil {_e .Log .Debug ("\u0045R\u0052\u004f\u0052\u003a\u0020\u0025v",_cfae );continue ;};if _bab ==nil {_efdgb ,_dcgc :=_fg .GetName (_cfbe .Get ("\u0046\u0069\u006c\u0074\u0065\u0072"));if _dcgc {switch _efdgb .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":_bab =_c .NewPdfColorspaceDeviceGray ();
|
|
_cdae .BitsPerComponent =1;};};};switch _ecf :=_bab .(type ){case *_c .PdfColorspaceDeviceRGB :_cdae .ColorComponents =3;case *_c .PdfColorspaceDeviceGray :_cdae .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",_ecf );
|
|
continue ;};_acbc =append (_acbc ,_cdae );};return _acbc ;};
|
|
|
|
// ObjectStreams groups PDF objects to object streams.
|
|
// It implements interface model.Optimizer.
|
|
type ObjectStreams struct{};func _edef (_beada _fg .PdfObject ,_gfc map[_fg .PdfObject ]struct{})error {if _acf ,_agag :=_beada .(*_fg .PdfIndirectObject );_agag {_gfc [_beada ]=struct{}{};_cea :=_edef (_acf .PdfObject ,_gfc );if _cea !=nil {return _cea ;
|
|
};return nil ;};if _eac ,_dedg :=_beada .(*_fg .PdfObjectStream );_dedg {_gfc [_eac ]=struct{}{};_cffe :=_edef (_eac .PdfObjectDictionary ,_gfc );if _cffe !=nil {return _cffe ;};return nil ;};if _cgce ,_cdac :=_beada .(*_fg .PdfObjectDictionary );_cdac {for _ ,_acb :=range _cgce .Keys (){_edc :=_cgce .Get (_acb );
|
|
_ =_edc ;if _cfa ,_cced :=_edc .(*_fg .PdfObjectReference );_cced {_edc =_cfa .Resolve ();_cgce .Set (_acb ,_edc );};if _acb !="\u0050\u0061\u0072\u0065\u006e\u0074"{if _fdfe :=_edef (_edc ,_gfc );_fdfe !=nil {return _fdfe ;};};};return nil ;};if _gfef ,_fbee :=_beada .(*_fg .PdfObjectArray );
|
|
_fbee {if _gfef ==nil {return _bg .New ("\u0061\u0072\u0072a\u0079\u0020\u0069\u0073\u0020\u006e\u0069\u006c");};for _fgg ,_dccaf :=range _gfef .Elements (){if _bff ,_acgg :=_dccaf .(*_fg .PdfObjectReference );_acgg {_dccaf =_bff .Resolve ();_gfef .Set (_fgg ,_dccaf );
|
|
};if _cabab :=_edef (_dccaf ,_gfc );_cabab !=nil {return _cabab ;};};return nil ;};return nil ;};func _ceea (_dbef *_c .XObjectImage ,_aef imageModifications )error {_gbca ,_aafg :=_dbef .ToImage ();if _aafg !=nil {return _aafg ;};if _aef .Scale !=0{_gbca ,_aafg =_aeea (_gbca ,_aef .Scale );
|
|
if _aafg !=nil {return _aafg ;};};if _aef .Encoding !=nil {_dbef .Filter =_aef .Encoding ;};_dbef .Decode =nil ;switch _dceb :=_dbef .Filter .(type ){case *_fg .FlateEncoder :if _dceb .Predictor !=1&&_dceb .Predictor !=11{_dceb .Predictor =1;};};if _aafg =_dbef .SetImage (_gbca ,nil );
|
|
_aafg !=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",_aafg );return _aafg ;};_dbef .ToPdfObject ();return nil ;};func _bc (_ff *_eb .ContentStreamOperations )*_eb .ContentStreamOperations {if _ff ==nil {return nil ;
|
|
};_gf :=_eb .ContentStreamOperations {};for _ ,_bcd :=range *_ff {switch _bcd .Operand {case "\u0042\u0044\u0043","\u0042\u004d\u0043","\u0045\u004d\u0043":continue ;case "\u0054\u006d":if len (_bcd .Params )==6{if _deg ,_eda :=_fg .GetNumbersAsFloat (_bcd .Params );
|
|
_eda ==nil {if _deg [0]==1&&_deg [1]==0&&_deg [2]==0&&_deg [3]==1{_bcd =&_eb .ContentStreamOperation {Params :[]_fg .PdfObject {_bcd .Params [4],_bcd .Params [5]},Operand :"\u0054\u0064"};};};};};_gf =append (_gf ,_bcd );};return &_gf ;};
|
|
|
|
// New creates a optimizers chain from options.
|
|
func New (options Options )*Chain {_cccg :=new (Chain );if options .CleanFonts ||options .SubsetFonts {_cccg .Append (&CleanFonts {Subset :options .SubsetFonts });};if options .CleanContentstream {_cccg .Append (new (CleanContentstream ));};if options .ImageUpperPPI > 0{_eab :=new (ImagePPI );
|
|
_eab .ImageUpperPPI =options .ImageUpperPPI ;_cccg .Append (_eab );};if options .ImageQuality > 0{_ebg :=new (Image );_ebg .ImageQuality =options .ImageQuality ;_cccg .Append (_ebg );};if options .CombineDuplicateDirectObjects {_cccg .Append (new (CombineDuplicateDirectObjects ));
|
|
};if options .CombineDuplicateStreams {_cccg .Append (new (CombineDuplicateStreams ));};if options .CombineIdenticalIndirectObjects {_cccg .Append (new (CombineIdenticalIndirectObjects ));};if options .UseObjectStreams {_cccg .Append (new (ObjectStreams ));
|
|
};if options .CompressStreams {_cccg .Append (new (CompressStreams ));};if options .CleanUnusedResources {_cccg .Append (new (CleanUnusedResources ));};return _cccg ;}; |