mirror of
https://github.com/unidoc/unipdf.git
synced 2025-05-04 22:17:22 +08:00
239 lines
43 KiB
Go
239 lines
43 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 (_b "bytes";_d "crypto/md5";_dc "errors";_fb "fmt";_fe "github.com/unidoc/unipdf/v3/common";_a "github.com/unidoc/unipdf/v3/contentstream";_bg "github.com/unidoc/unipdf/v3/core";_g "github.com/unidoc/unipdf/v3/extractor";_fg "github.com/unidoc/unipdf/v3/internal/imageutil";
|
|
_faa "github.com/unidoc/unipdf/v3/internal/textencoding";_ge "github.com/unidoc/unipdf/v3/model";_dd "github.com/unidoc/unitype";_fa "golang.org/x/image/draw";_e "math";_ec "strings";);type content struct{_dca string ;_cgga *_ge .PdfPageResources ;};
|
|
|
|
// Append appends optimizers to the chain.
|
|
func (_dg *Chain )Append (optimizers ..._ge .Optimizer ){_dg ._gc =append (_dg ._gc ,optimizers ...)};
|
|
|
|
// 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 ;};
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
func (_dbd *CombineDuplicateStreams )Optimize (objects []_bg .PdfObject )(_ebea []_bg .PdfObject ,_bgda error ){_fbfc :=make (map[_bg .PdfObject ]_bg .PdfObject );_gcbb :=make (map[_bg .PdfObject ]struct{});_geda :=make (map[string ][]*_bg .PdfObjectStream );
|
|
for _ ,_fcf :=range objects {if _ffe ,_ffg :=_fcf .(*_bg .PdfObjectStream );_ffg {_gdda :=_d .New ();_gdda .Write (_ffe .Stream );_gdda .Write ([]byte (_ffe .PdfObjectDictionary .WriteString ()));_dgd :=string (_gdda .Sum (nil ));_geda [_dgd ]=append (_geda [_dgd ],_ffe );
|
|
};};for _ ,_ceb :=range _geda {if len (_ceb )< 2{continue ;};_gbca :=_ceb [0];for _cdab :=1;_cdab < len (_ceb );_cdab ++{_bgg :=_ceb [_cdab ];_fbfc [_bgg ]=_gbca ;_gcbb [_bgg ]=struct{}{};};};_ebea =make ([]_bg .PdfObject ,0,len (objects )-len (_gcbb ));
|
|
for _ ,_cebc :=range objects {if _ ,_cegd :=_gcbb [_cebc ];_cegd {continue ;};_ebea =append (_ebea ,_cebc );};_bbce (_ebea ,_fbfc );return _ebea ,nil ;};func _cc (_ddb *_a .ContentStreamOperations )*_a .ContentStreamOperations {if _ddb ==nil {return nil ;
|
|
};_ba :=_a .ContentStreamOperations {};for _ ,_af :=range *_ddb {switch _af .Operand {case "\u0042\u0044\u0043","\u0042\u004d\u0043","\u0045\u004d\u0043":continue ;case "\u0054\u006d":if len (_af .Params )==6{if _gd ,_ab :=_bg .GetNumbersAsFloat (_af .Params );
|
|
_ab ==nil {if _gd [0]==1&&_gd [1]==0&&_gd [2]==0&&_gd [3]==1{_af =&_a .ContentStreamOperation {Params :[]_bg .PdfObject {_af .Params [4],_af .Params [5]},Operand :"\u0054\u0064"};};};};};_ba =append (_ba ,_af );};return &_ba ;};func _eefa (_gcf _bg .PdfObject ,_cab map[_bg .PdfObject ]struct{})error {if _eged ,_dgef :=_gcf .(*_bg .PdfIndirectObject );
|
|
_dgef {_cab [_gcf ]=struct{}{};_ggc :=_eefa (_eged .PdfObject ,_cab );if _ggc !=nil {return _ggc ;};return nil ;};if _ccab ,_edf :=_gcf .(*_bg .PdfObjectStream );_edf {_cab [_ccab ]=struct{}{};_afc :=_eefa (_ccab .PdfObjectDictionary ,_cab );if _afc !=nil {return _afc ;
|
|
};return nil ;};if _gfa ,_gecg :=_gcf .(*_bg .PdfObjectDictionary );_gecg {for _ ,_fege :=range _gfa .Keys (){_ccg :=_gfa .Get (_fege );_ =_ccg ;if _adgd ,_dfb :=_ccg .(*_bg .PdfObjectReference );_dfb {_ccg =_adgd .Resolve ();_gfa .Set (_fege ,_ccg );};
|
|
if _fege !="\u0050\u0061\u0072\u0065\u006e\u0074"{if _bfgg :=_eefa (_ccg ,_cab );_bfgg !=nil {return _bfgg ;};};};return nil ;};if _ggce ,_dbaf :=_gcf .(*_bg .PdfObjectArray );_dbaf {if _ggce ==nil {return _dc .New ("\u0061\u0072\u0072a\u0079\u0020\u0069\u0073\u0020\u006e\u0069\u006c");
|
|
};for _cbeg ,_bbc :=range _ggce .Elements (){if _fdf ,_gab :=_bbc .(*_bg .PdfObjectReference );_gab {_bbc =_fdf .Resolve ();_ggce .Set (_cbeg ,_bbc );};if _gced :=_eefa (_bbc ,_cab );_gced !=nil {return _gced ;};};return nil ;};return nil ;};func _gag (_dge []_bg .PdfObject )(map[_bg .PdfObject ]struct{},error ){_eefc :=_ded (_dge );
|
|
_aed :=_eefc ._feag ;_ega :=make (map[_bg .PdfObject ]struct{});_bff :=_ffae (_aed );for _ ,_gee :=range _aed {_bbee ,_gbg :=_bg .GetDict (_gee .PdfObject );if !_gbg {continue ;};_fgff ,_gbg :=_bg .GetDict (_bbee .Get ("\u0052e\u0073\u006f\u0075\u0072\u0063\u0065s"));
|
|
if !_gbg {continue ;};_ebe :=_bff ["\u0058O\u0062\u006a\u0065\u0063\u0074"];_gae ,_gbg :=_bg .GetDict (_fgff .Get ("\u0058O\u0062\u006a\u0065\u0063\u0074"));if _gbg {_ffb :=_cda (_gae );for _ ,_cba :=range _ffb {if _bgcb (_cba ,_ebe ){continue ;};_gbdf :=*_bg .MakeName (_cba );
|
|
_aae :=_gae .Get (_gbdf );_ega [_aae ]=struct{}{};_gae .Remove (_gbdf );_gdd :=_eefa (_aae ,_ega );if _gdd !=nil {_fe .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",_aae );
|
|
};};};_cbdb ,_gbg :=_bg .GetDict (_fgff .Get ("\u0046\u006f\u006e\u0074"));_dda :=_bff ["\u0046\u006f\u006e\u0074"];if _gbg {_bab :=_cda (_cbdb );for _ ,_cbe :=range _bab {if _bgcb (_cbe ,_dda ){continue ;};_caad :=*_bg .MakeName (_cbe );_acaa :=_cbdb .Get (_caad );
|
|
_ega [_acaa ]=struct{}{};_cbdb .Remove (_caad );_gfe :=_eefa (_acaa ,_ega );if _gfe !=nil {_fe .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",_acaa );
|
|
};};};_fggf ,_gbg :=_bg .GetDict (_fgff .Get ("\u0045x\u0074\u0047\u0053\u0074\u0061\u0074e"));if _gbg {_ecg :=_cda (_fggf );_cbea :=_bff ["\u0045x\u0074\u0047\u0053\u0074\u0061\u0074e"];for _ ,_dcgf :=range _ecg {if _bgcb (_dcgf ,_cbea ){continue ;};_ebd :=*_bg .MakeName (_dcgf );
|
|
_efa :=_fggf .Get (_ebd );_ega [_efa ]=struct{}{};_fggf .Remove (_ebd );_acaf :=_eefa (_efa ,_ega );if _acaf !=nil {_fe .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",_efa );
|
|
};};};};return _ega ,nil ;};
|
|
|
|
// 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 ;};type imageModifications struct{Scale float64 ;Encoding _bg .StreamEncoder ;};
|
|
|
|
// Optimize implements Optimizer interface.
|
|
func (_bag *CleanUnusedResources )Optimize (objects []_bg .PdfObject )(_agcd []_bg .PdfObject ,_dab error ){_acg ,_dab :=_gag (objects );if _dab !=nil {return nil ,_dab ;};_aeg :=[]_bg .PdfObject {};for _ ,_daa :=range objects {_ ,_bef :=_acg [_daa ];if _bef {continue ;
|
|
};_aeg =append (_aeg ,_daa );};return _aeg ,nil ;};func _bggd (_bbd []_bg .PdfObject ){for _egba ,_befe :=range _bbd {switch _dee :=_befe .(type ){case *_bg .PdfIndirectObject :_dee .ObjectNumber =int64 (_egba +1);_dee .GenerationNumber =0;case *_bg .PdfObjectStream :_dee .ObjectNumber =int64 (_egba +1);
|
|
_dee .GenerationNumber =0;case *_bg .PdfObjectStreams :_dee .ObjectNumber =int64 (_egba +1);_dee .GenerationNumber =0;};};};
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
func (_gg *Chain )Optimize (objects []_bg .PdfObject )(_fbg []_bg .PdfObject ,_gf error ){_gcb :=objects ;for _ ,_fbb :=range _gg ._gc {_c ,_dde :=_fbb .Optimize (_gcb );if _dde !=nil {_fe .Log .Debug ("\u0045\u0052\u0052OR\u0020\u004f\u0070\u0074\u0069\u006d\u0069\u007a\u0061\u0074\u0069\u006f\u006e\u003a\u0020\u0025\u002b\u0076",_dde );
|
|
continue ;};_gcb =_c ;};return _gcb ,nil ;};
|
|
|
|
// CleanUnusedResources represents an optimizer used to clean unused resources.
|
|
type CleanUnusedResources struct{};
|
|
|
|
// CombineIdenticalIndirectObjects combines identical indirect objects.
|
|
// It implements interface model.Optimizer.
|
|
type CombineIdenticalIndirectObjects struct{};func _fee (_dafe _bg .PdfObject )(string ,error ){_cce :=_bg .TraceToDirectObject (_dafe );switch _ddf :=_cce .(type ){case *_bg .PdfObjectString :return _ddf .Str (),nil ;case *_bg .PdfObjectStream :_fef ,_agcc :=_bg .DecodeStream (_ddf );
|
|
if _agcc !=nil {return "",_agcc ;};return string (_fef ),nil ;};return "",_fb .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",_cce );
|
|
};func _cgg (_ggg *_bg .PdfObjectStream ,_ddd []rune ,_abb []_dd .GlyphIndex )error {_ggg ,_dcgg :=_bg .GetStream (_ggg );if !_dcgg {_fe .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 _dc .New ("\u0066\u006f\u006e\u0074fi\u006c\u0065\u0032\u0020\u006e\u006f\u0074\u0020\u0066\u006f\u0075\u006e\u0064");};_beg ,_ebb :=_bg .DecodeStream (_ggg );if _ebb !=nil {_fe .Log .Debug ("\u0044\u0065c\u006f\u0064\u0065 \u0065\u0072\u0072\u006f\u0072\u003a\u0020\u0025\u0076",_ebb );
|
|
return _ebb ;};_acd ,_ebb :=_dd .Parse (_b .NewReader (_beg ));if _ebb !=nil {_fe .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 (_ggg .Stream ));
|
|
return _ebb ;};_gga :=_abb ;if len (_ddd )> 0{_fde :=_acd .LookupRunes (_ddd );_gga =append (_gga ,_fde ...);};_acd ,_ebb =_acd .SubsetKeepIndices (_gga );if _ebb !=nil {_fe .Log .Debug ("\u0045R\u0052\u004f\u0052\u0020s\u0075\u0062\u0073\u0065\u0074t\u0069n\u0067 \u0066\u006f\u006e\u0074\u003a\u0020\u0025v",_ebb );
|
|
return _ebb ;};var _dcd _b .Buffer ;_ebb =_acd .Write (&_dcd );if _ebb !=nil {_fe .Log .Debug ("\u0045\u0052\u0052\u004fR \u0057\u0072\u0069\u0074\u0069\u006e\u0067\u0020\u0066\u006f\u006e\u0074\u003a\u0020%\u0076",_ebb );return _ebb ;};if _dcd .Len ()> len (_beg ){_fe .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 ;};_gda ,_ebb :=_bg .MakeStream (_dcd .Bytes (),_bg .NewFlateEncoder ());if _ebb !=nil {_fe .Log .Debug ("\u0045\u0052\u0052\u004fR \u0057\u0072\u0069\u0074\u0069\u006e\u0067\u0020\u0066\u006f\u006e\u0074\u003a\u0020%\u0076",_ebb );return _ebb ;
|
|
};*_ggg =*_gda ;_ggg .Set ("\u004ce\u006e\u0067\u0074\u0068\u0031",_bg .MakeInteger (int64 (_dcd .Len ())));return nil ;};
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
func (_cfd *Image )Optimize (objects []_bg .PdfObject )(_dad []_bg .PdfObject ,_dccf error ){if _cfd .ImageQuality <=0{return objects ,nil ;};_dfbc :=_dfa (objects );if len (_dfbc )==0{return objects ,nil ;};_fgd :=make (map[_bg .PdfObject ]_bg .PdfObject );
|
|
_edfd :=make (map[_bg .PdfObject ]struct{});for _ ,_bcce :=range _dfbc {_bddfgf :=_bcce .Stream .Get ("\u0053\u004d\u0061s\u006b");_edfd [_bddfgf ]=struct{}{};};for _cfg ,_gabe :=range _dfbc {_fcbc :=_gabe .Stream ;if _ ,_ead :=_edfd [_fcbc ];_ead {continue ;
|
|
};_ceef ,_dcdb :=_ge .NewXObjectImageFromStream (_fcbc );if _dcdb !=nil {_fe .Log .Debug ("\u0045\u0052\u0052\u004f\u0052\u003a\u0020\u0025\u002b\u0076",_dcdb );continue ;};switch _ceef .Filter .(type ){case *_bg .JBIG2Encoder :continue ;case *_bg .CCITTFaxEncoder :continue ;
|
|
};_cgee ,_dcdb :=_ceef .ToImage ();if _dcdb !=nil {_fe .Log .Debug ("\u0045\u0052\u0052\u004f\u0052\u003a\u0020\u0025\u002b\u0076",_dcdb );continue ;};_dacc :=_bg .NewDCTEncoder ();_dacc .ColorComponents =_cgee .ColorComponents ;_dacc .Quality =_cfd .ImageQuality ;
|
|
_dacc .BitsPerComponent =_gabe .BitsPerComponent ;_dacc .Width =_gabe .Width ;_dacc .Height =_gabe .Height ;_bcgg ,_dcdb :=_dacc .EncodeBytes (_cgee .Data );if _dcdb !=nil {_fe .Log .Debug ("\u0045\u0052\u0052\u004f\u0052\u003a\u0020\u0025\u002b\u0076",_dcdb );
|
|
continue ;};var _dbcb _bg .StreamEncoder ;_dbcb =_dacc ;{_gdaf :=_bg .NewFlateEncoder ();_aecd :=_bg .NewMultiEncoder ();_aecd .AddEncoder (_gdaf );_aecd .AddEncoder (_dacc );_edfad ,_dgbd :=_aecd .EncodeBytes (_cgee .Data );if _dgbd !=nil {_fe .Log .Debug ("\u0045\u0052\u0052\u004f\u0052\u003a\u0020\u0025\u002b\u0076",_dgbd );
|
|
continue ;};if len (_edfad )< len (_bcgg ){_fe .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 (_bcgg ),len (_edfad ),len (_fcbc .Stream ));
|
|
_bcgg =_edfad ;_dbcb =_aecd ;};};_cgce :=len (_fcbc .Stream );if _cgce < len (_bcgg ){continue ;};_gaag :=&_bg .PdfObjectStream {Stream :_bcgg };_gaag .PdfObjectReference =_fcbc .PdfObjectReference ;_gaag .PdfObjectDictionary =_bg .MakeDict ();_gaag .Merge (_fcbc .PdfObjectDictionary );
|
|
_gaag .Merge (_dbcb .MakeStreamDict ());_gaag .Set ("\u004c\u0065\u006e\u0067\u0074\u0068",_bg .MakeInteger (int64 (len (_bcgg ))));_fgd [_fcbc ]=_gaag ;_dfbc [_cfg ].Stream =_gaag ;};_dad =make ([]_bg .PdfObject ,len (objects ));copy (_dad ,objects );
|
|
_bbce (_dad ,_fgd );return _dad ,nil ;};func _dfa (_baa []_bg .PdfObject )[]*imageInfo {_def :=_bg .PdfObjectName ("\u0053u\u0062\u0074\u0079\u0070\u0065");_efab :=make (map[*_bg .PdfObjectStream ]struct{});var _bdc []*imageInfo ;for _ ,_bcc :=range _baa {_fdde ,_gaf :=_bg .GetStream (_bcc );
|
|
if !_gaf {continue ;};if _ ,_aacc :=_efab [_fdde ];_aacc {continue ;};_efab [_fdde ]=struct{}{};_agfb :=_fdde .PdfObjectDictionary .Get (_def );_efbb ,_gaf :=_bg .GetName (_agfb );if !_gaf ||string (*_efbb )!="\u0049\u006d\u0061g\u0065"{continue ;};_add :=&imageInfo {Stream :_fdde ,BitsPerComponent :8};
|
|
if _agcg ,_dag :=_bg .GetIntVal (_fdde .Get ("\u0042\u0069t\u0073\u0050\u0065r\u0043\u006f\u006d\u0070\u006f\u006e\u0065\u006e\u0074"));_dag {_add .BitsPerComponent =_agcg ;};if _egde ,_afbe :=_bg .GetIntVal (_fdde .Get ("\u0057\u0069\u0064t\u0068"));_afbe {_add .Width =_egde ;
|
|
};if _bcga ,_feec :=_bg .GetIntVal (_fdde .Get ("\u0048\u0065\u0069\u0067\u0068\u0074"));_feec {_add .Height =_bcga ;};_dfe ,_gcbf :=_ge .NewPdfColorspaceFromPdfObject (_fdde .Get ("\u0043\u006f\u006c\u006f\u0072\u0053\u0070\u0061\u0063\u0065"));if _gcbf !=nil {_fe .Log .Debug ("\u0045R\u0052\u004f\u0052\u003a\u0020\u0025v",_gcbf );
|
|
continue ;};if _dfe ==nil {_gcea ,_dgac :=_bg .GetName (_fdde .Get ("\u0046\u0069\u006c\u0074\u0065\u0072"));if _dgac {switch _gcea .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":_dfe =_ge .NewPdfColorspaceDeviceGray ();
|
|
_add .BitsPerComponent =1;};};};switch _efg :=_dfe .(type ){case *_ge .PdfColorspaceDeviceRGB :_add .ColorComponents =3;case *_ge .PdfColorspaceDeviceGray :_add .ColorComponents =1;default:_fe .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",_efg );
|
|
continue ;};_bdc =append (_bdc ,_add );};return _bdc ;};
|
|
|
|
// 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 (_ca *CleanFonts )Optimize (objects []_bg .PdfObject )(_aga []_bg .PdfObject ,_dbaa error ){var _ege map[*_bg .PdfObjectStream ]struct{};if _ca .Subset {var _affb error ;_ege ,_affb =_gec (objects );if _affb !=nil {_fe .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",_affb );
|
|
return nil ,_affb ;};};for _ ,_gcd :=range objects {_fed ,_bbae :=_bg .GetStream (_gcd );if !_bbae {continue ;};if _ ,_efef :=_ege [_fed ];_efef {continue ;};_fda ,_bca :=_bg .NewEncoderFromStream (_fed );if _bca !=nil {_fe .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",_bca );
|
|
continue ;};_edb ,_bca :=_fda .DecodeStream (_fed );if _bca !=nil {_fe .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",_bca );
|
|
continue ;};if len (_edb )< 4{continue ;};_bcg :=string (_edb [:4]);if _bcg =="\u004f\u0054\u0054\u004f"{continue ;};if _bcg !="\u0000\u0001\u0000\u0000"&&_bcg !="\u0074\u0072\u0075\u0065"{continue ;};_ceg ,_bca :=_dd .Parse (_b .NewReader (_edb ));if _bca !=nil {_fe .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",_bca );
|
|
continue ;};_bca =_ceg .Optimize ();if _bca !=nil {_fe .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",_bca );continue ;};var _ggd _b .Buffer ;
|
|
_bca =_ceg .Write (&_ggd );if _bca !=nil {_fe .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",_bca );
|
|
continue ;};if _ggd .Len ()> len (_edb ){_fe .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 ;};_afeb ,_bca :=_bg .MakeStream (_ggd .Bytes (),_bg .NewFlateEncoder ());if _bca !=nil {continue ;};*_fed =*_afeb ;_fed .Set ("\u004ce\u006e\u0067\u0074\u0068\u0031",_bg .MakeInteger (int64 (_ggd .Len ())));};return objects ,nil ;};
|
|
|
|
// GetOptimizers gets the list of optimizers in chain `c`.
|
|
func (_fgf *Chain )GetOptimizers ()[]_ge .Optimizer {return _fgf ._gc };func _gbaag (_egdef _bg .PdfObject )(_bdee string ,_ebfd []_bg .PdfObject ){var _ccec _b .Buffer ;switch _gbga :=_egdef .(type ){case *_bg .PdfIndirectObject :_ebfd =append (_ebfd ,_gbga );
|
|
_egdef =_gbga .PdfObject ;};switch _baee :=_egdef .(type ){case *_bg .PdfObjectStream :if _fdeg ,_bdf :=_bg .DecodeStream (_baee );_bdf ==nil {_ccec .Write (_fdeg );_ebfd =append (_ebfd ,_baee );};case *_bg .PdfObjectArray :for _ ,_agg :=range _baee .Elements (){switch _dgda :=_agg .(type ){case *_bg .PdfObjectStream :if _cea ,_bfef :=_bg .DecodeStream (_dgda );
|
|
_bfef ==nil {_ccec .Write (_cea );_ebfd =append (_ebfd ,_dgda );};};};};return _ccec .String (),_ebfd ;};func _bbce (_eaa []_bg .PdfObject ,_cabf map[_bg .PdfObject ]_bg .PdfObject ){if len (_cabf )==0{return ;};for _dbca ,_ebbb :=range _eaa {if _ggga ,_gcdg :=_cabf [_ebbb ];
|
|
_gcdg {_eaa [_dbca ]=_ggga ;continue ;};_cabf [_ebbb ]=_ebbb ;switch _aebe :=_ebbb .(type ){case *_bg .PdfObjectArray :_eeg :=make ([]_bg .PdfObject ,_aebe .Len ());copy (_eeg ,_aebe .Elements ());_bbce (_eeg ,_cabf );for _fegef ,_acdb :=range _eeg {_aebe .Set (_fegef ,_acdb );
|
|
};case *_bg .PdfObjectStreams :_bbce (_aebe .Elements (),_cabf );case *_bg .PdfObjectStream :_geg :=[]_bg .PdfObject {_aebe .PdfObjectDictionary };_bbce (_geg ,_cabf );_aebe .PdfObjectDictionary =_geg [0].(*_bg .PdfObjectDictionary );case *_bg .PdfObjectDictionary :_bcceb :=_aebe .Keys ();
|
|
_cae :=make ([]_bg .PdfObject ,len (_bcceb ));for _fbae ,_ggccb :=range _bcceb {_cae [_fbae ]=_aebe .Get (_ggccb );};_bbce (_cae ,_cabf );for _egbeb ,_bbg :=range _bcceb {_aebe .Set (_bbg ,_cae [_egbeb ]);};case *_bg .PdfIndirectObject :_fgdg :=[]_bg .PdfObject {_aebe .PdfObject };
|
|
_bbce (_fgdg ,_cabf );_aebe .PdfObject =_fgdg [0];};};};
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
func (_adce *ObjectStreams )Optimize (objects []_bg .PdfObject )(_abba []_bg .PdfObject ,_babg error ){_cfgc :=&_bg .PdfObjectStreams {};_agab :=make ([]_bg .PdfObject ,0,len (objects ));for _ ,_fdgd :=range objects {if _efbd ,_abag :=_fdgd .(*_bg .PdfIndirectObject );
|
|
_abag &&_efbd .GenerationNumber ==0{_cfgc .Append (_fdgd );}else {_agab =append (_agab ,_fdgd );};};if _cfgc .Len ()==0{return _agab ,nil ;};_abba =make ([]_bg .PdfObject ,0,len (_agab )+_cfgc .Len ()+1);if _cfgc .Len ()> 1{_abba =append (_abba ,_cfgc );
|
|
};_abba =append (_abba ,_cfgc .Elements ()...);_abba =append (_abba ,_agab ...);return _abba ,nil ;};
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
func (_bga *CombineIdenticalIndirectObjects )Optimize (objects []_bg .PdfObject )(_gbdb []_bg .PdfObject ,_ddae error ){_bggd (objects );_ebf :=make (map[_bg .PdfObject ]_bg .PdfObject );_bfa :=make (map[_bg .PdfObject ]struct{});_caac :=make (map[string ][]*_bg .PdfIndirectObject );
|
|
for _ ,_aab :=range objects {_fce ,_cef :=_aab .(*_bg .PdfIndirectObject );if !_cef {continue ;};if _gfea ,_aac :=_fce .PdfObject .(*_bg .PdfObjectDictionary );_aac {if _aegb ,_adb :=_gfea .Get ("\u0054\u0079\u0070\u0065").(*_bg .PdfObjectName );_adb &&*_aegb =="\u0050\u0061\u0067\u0065"{continue ;
|
|
};_ggea :=_d .New ();_ggea .Write ([]byte (_gfea .WriteString ()));_cgc :=string (_ggea .Sum (nil ));_caac [_cgc ]=append (_caac [_cgc ],_fce );};};for _ ,_bedc :=range _caac {if len (_bedc )< 2{continue ;};_gbce :=_bedc [0];for _dcf :=1;_dcf < len (_bedc );
|
|
_dcf ++{_bcd :=_bedc [_dcf ];_ebf [_bcd ]=_gbce ;_bfa [_bcd ]=struct{}{};};};_gbdb =make ([]_bg .PdfObject ,0,len (objects )-len (_bfa ));for _ ,_dfcf :=range objects {if _ ,_edac :=_bfa [_dfcf ];_edac {continue ;};_gbdb =append (_gbdb ,_dfcf );};_bbce (_gbdb ,_ebf );
|
|
return _gbdb ,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 ;};
|
|
|
|
// CompressStreams compresses uncompressed streams.
|
|
// It implements interface model.Optimizer.
|
|
type CompressStreams struct{};func _gec (_gbb []_bg .PdfObject )(_adc map[*_bg .PdfObjectStream ]struct{},_feg error ){_adc =map[*_bg .PdfObjectStream ]struct{}{};_gce :=map[*_ge .PdfFont ]struct{}{};_afe :=_ded (_gbb );for _ ,_agd :=range _afe ._feag {_dgb ,_cgd :=_bg .GetDict (_agd .PdfObject );
|
|
if !_cgd {continue ;};_gbf ,_cgd :=_bg .GetDict (_dgb .Get ("\u0052e\u0073\u006f\u0075\u0072\u0063\u0065s"));if !_cgd {continue ;};_bfb ,_ :=_gbaag (_dgb .Get ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073"));_fad ,_bde :=_ge .NewPdfPageResourcesFromDict (_gbf );
|
|
if _bde !=nil {return nil ,_bde ;};_adg :=[]content {{_dca :_bfb ,_cgga :_fad }};_ece :=_gbfe (_dgb .Get ("\u0041\u006e\u006e\u006f\u0074\u0073"));if _ece !=nil {_adg =append (_adg ,_ece ...);};for _ ,_fgb :=range _adg {_fbd ,_cgb :=_g .NewFromContents (_fgb ._dca ,_fgb ._cgga );
|
|
if _cgb !=nil {return nil ,_cgb ;};_bdd ,_ ,_ ,_cgb :=_fbd .ExtractPageText ();if _cgb !=nil {return nil ,_cgb ;};for _ ,_eed :=range _bdd .Marks ().Elements (){if _eed .Font ==nil {continue ;};if _ ,_ff :=_gce [_eed .Font ];!_ff {_gce [_eed .Font ]=struct{}{};
|
|
};};};};_efe :=map[*_bg .PdfObjectStream ][]*_ge .PdfFont {};for _dcg :=range _gce {_fga :=_dcg .FontDescriptor ();if _fga ==nil ||_fga .FontFile2 ==nil {continue ;};_eg ,_ada :=_bg .GetStream (_fga .FontFile2 );if !_ada {continue ;};_efe [_eg ]=append (_efe [_eg ],_dcg );
|
|
};for _bae :=range _efe {var _bddf []rune ;var _deb []_dd .GlyphIndex ;for _ ,_cbbd :=range _efe [_bae ]{switch _efb :=_cbbd .Encoder ().(type ){case *_faa .IdentityEncoder :_bge :=_efb .RegisteredRunes ();_egb :=make ([]_dd .GlyphIndex ,len (_bge ));for _daf ,_gaa :=range _bge {_egb [_daf ]=_dd .GlyphIndex (_gaa );
|
|
};_deb =append (_deb ,_egb ...);case *_faa .TrueTypeFontEncoder :_egc :=_efb .RegisteredRunes ();_bddf =append (_bddf ,_egc ...);case _faa .SimpleEncoder :_cee :=_efb .Charcodes ();for _ ,_fd :=range _cee {_ffa ,_fgg :=_efb .CharcodeToRune (_fd );if !_fgg {_fe .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",_fd );
|
|
continue ;};_bddf =append (_bddf ,_ffa );};};};_feg =_cgg (_bae ,_bddf ,_deb );if _feg !=nil {_fe .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",_feg );
|
|
return nil ,_feg ;};_adc [_bae ]=struct{}{};};return _adc ,nil ;};
|
|
|
|
// CombineDuplicateDirectObjects combines duplicated direct objects by its data hash.
|
|
// It implements interface model.Optimizer.
|
|
type CombineDuplicateDirectObjects struct{};func _ded (_cfba []_bg .PdfObject )objectStructure {_dff :=objectStructure {};_gdeg :=false ;for _ ,_ffag :=range _cfba {switch _fdbf :=_ffag .(type ){case *_bg .PdfIndirectObject :_gdb ,_gca :=_bg .GetDict (_fdbf );
|
|
if !_gca {continue ;};_dfdf ,_gca :=_bg .GetName (_gdb .Get ("\u0054\u0079\u0070\u0065"));if !_gca {continue ;};switch _dfdf .String (){case "\u0043a\u0074\u0061\u006c\u006f\u0067":_dff ._gaeb =_gdb ;_gdeg =true ;};};if _gdeg {break ;};};if !_gdeg {return _dff ;
|
|
};_ggeaa ,_abdg :=_bg .GetDict (_dff ._gaeb .Get ("\u0050\u0061\u0067e\u0073"));if !_abdg {return _dff ;};_dff ._bcee =_ggeaa ;_agbe ,_abdg :=_bg .GetArray (_ggeaa .Get ("\u004b\u0069\u0064\u0073"));if !_abdg {return _dff ;};for _ ,_cdge :=range _agbe .Elements (){_bcdg ,_agfa :=_bg .GetIndirect (_cdge );
|
|
if !_agfa {break ;};_dff ._feag =append (_dff ._feag ,_bcdg );};return _dff ;};func _cda (_gac *_bg .PdfObjectDictionary )[]string {_eca :=[]string {};for _ ,_egd :=range _gac .Keys (){_eca =append (_eca ,_egd .String ());};return _eca ;};func _ccd (_dddfb *_ge .XObjectImage ,_gbaa imageModifications )error {_aef ,_bdde :=_dddfb .ToImage ();
|
|
if _bdde !=nil {return _bdde ;};if _gbaa .Scale !=0{_aef ,_bdde =_dbae (_aef ,_gbaa .Scale );if _bdde !=nil {return _bdde ;};};if _gbaa .Encoding !=nil {_dddfb .Filter =_gbaa .Encoding ;};_dddfb .Decode =nil ;switch _ffbb :=_dddfb .Filter .(type ){case *_bg .FlateEncoder :if _ffbb .Predictor !=1&&_ffbb .Predictor !=11{_ffbb .Predictor =1;
|
|
};};if _bdde =_dddfb .SetImage (_aef ,nil );_bdde !=nil {_fe .Log .Debug ("\u0045\u0072\u0072or\u0020\u0073\u0065\u0074\u0074\u0069\u006e\u0067\u0020\u0069\u006d\u0061\u0067\u0065\u003a\u0020\u0025\u0076",_bdde );return _bdde ;};_dddfb .ToPdfObject ();
|
|
return nil ;};func _bgcb (_debe string ,_fea []string )bool {for _ ,_cde :=range _fea {if _debe ==_cde {return true ;};};return false ;};func _dbae (_cggd *_ge .Image ,_bagf float64 )(*_ge .Image ,error ){_fcc ,_baf :=_cggd .ToGoImage ();if _baf !=nil {return nil ,_baf ;
|
|
};var _caf _fg .Image ;_dfea ,_dfbf :=_fcc .(*_fg .Monochrome );if _dfbf {if _baf =_dfea .ResolveDecode ();_baf !=nil {return nil ,_baf ;};_caf ,_baf =_dfea .Scale (_bagf );if _baf !=nil {return nil ,_baf ;};}else {_cdg :=int (_e .RoundToEven (float64 (_cggd .Width )*_bagf ));
|
|
_fabe :=int (_e .RoundToEven (float64 (_cggd .Height )*_bagf ));_caf ,_baf =_fg .NewImage (_cdg ,_fabe ,int (_cggd .BitsPerComponent ),_cggd .ColorComponents ,nil ,nil ,nil );if _baf !=nil {return nil ,_baf ;};_fa .CatmullRom .Scale (_caf ,_caf .Bounds (),_fcc ,_fcc .Bounds (),_fa .Over ,&_fa .Options {});
|
|
};_fec :=_caf .Base ();_cebca :=&_ge .Image {Width :int64 (_fec .Width ),Height :int64 (_fec .Height ),BitsPerComponent :int64 (_fec .BitsPerComponent ),ColorComponents :_fec .ColorComponents ,Data :_fec .Data };_cebca .SetDecode (_fec .Decode );_cebca .SetAlpha (_fec .Alpha );
|
|
return _cebca ,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 ;};
|
|
|
|
// ObjectStreams groups PDF objects to object streams.
|
|
// It implements interface model.Optimizer.
|
|
type ObjectStreams struct{};
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
func (_fcfc *ImagePPI )Optimize (objects []_bg .PdfObject )(_bce []_bg .PdfObject ,_afbdb error ){if _fcfc .ImageUpperPPI <=0{return objects ,nil ;};_dagg :=_dfa (objects );if len (_dagg )==0{return objects ,nil ;};_dec :=make (map[_bg .PdfObject ]struct{});
|
|
for _ ,_eba :=range _dagg {_bgee :=_eba .Stream .PdfObjectDictionary .Get ("\u0053\u004d\u0061s\u006b");_dec [_bgee ]=struct{}{};};_decb :=make (map[*_bg .PdfObjectStream ]*imageInfo );for _ ,_fggd :=range _dagg {_decb [_fggd .Stream ]=_fggd ;};var _bcggg *_bg .PdfObjectDictionary ;
|
|
for _ ,_ecea :=range objects {if _adbg ,_efag :=_bg .GetDict (_ecea );_bcggg ==nil &&_efag {if _bfcg ,_cfac :=_bg .GetName (_adbg .Get ("\u0054\u0079\u0070\u0065"));_cfac &&*_bfcg =="\u0043a\u0074\u0061\u006c\u006f\u0067"{_bcggg =_adbg ;};};};if _bcggg ==nil {return objects ,nil ;
|
|
};_ccfd ,_fbgc :=_bg .GetDict (_bcggg .Get ("\u0050\u0061\u0067e\u0073"));if !_fbgc {return objects ,nil ;};_cafa ,_dgg :=_bg .GetArray (_ccfd .Get ("\u004b\u0069\u0064\u0073"));if !_dgg {return objects ,nil ;};for _ ,_gebe :=range _cafa .Elements (){_abbd :=make (map[string ]*imageInfo );
|
|
_afff ,_cgf :=_bg .GetDict (_gebe );if !_cgf {continue ;};_fdb ,_ :=_gbaag (_afff .Get ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073"));if len (_fdb )==0{continue ;};_gbcf ,_ggcc :=_bg .GetDict (_afff .Get ("\u0052e\u0073\u006f\u0075\u0072\u0063\u0065s"));
|
|
if !_ggcc {continue ;};_fbga ,_faf :=_ge .NewPdfPageResourcesFromDict (_gbcf );if _faf !=nil {_fe .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",_faf );
|
|
continue ;};_ffbbd ,_eff :=_bg .GetDict (_gbcf .Get ("\u0058O\u0062\u006a\u0065\u0063\u0074"));if !_eff {continue ;};_fba :=_ffbbd .Keys ();for _ ,_fbfg :=range _fba {if _ccdc ,_bfaf :=_bg .GetStream (_ffbbd .Get (_fbfg ));_bfaf {if _edaa ,_edfc :=_decb [_ccdc ];
|
|
_edfc {_abbd [string (_fbfg )]=_edaa ;};};};_agdf :=_a .NewContentStreamParser (_fdb );_fcd ,_faf :=_agdf .Parse ();if _faf !=nil {_fe .Log .Debug ("\u0045\u0052\u0052\u004f\u0052\u003a\u0020\u0025\u002b\u0076",_faf );continue ;};_acae :=_a .NewContentStreamProcessor (*_fcd );
|
|
_acae .AddHandler (_a .HandlerConditionEnumAllOperands ,"",func (_aebg *_a .ContentStreamOperation ,_geba _a .GraphicsState ,_bdb *_ge .PdfPageResources )error {switch _aebg .Operand {case "\u0044\u006f":if len (_aebg .Params )!=1{_fe .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 ;};_acc ,_dfbd :=_bg .GetName (_aebg .Params [0]);if !_dfbd {_fe .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 _dcdf ,_ddec :=_abbd [string (*_acc )];_ddec {_bbab :=_geba .CTM .ScalingFactorX ();_abbg :=_geba .CTM .ScalingFactorY ();_cceg ,_ecc :=_bbab /72.0,_abbg /72.0;_gdec ,_gecb :=float64 (_dcdf .Width )/_cceg ,float64 (_dcdf .Height )/_ecc ;
|
|
if _cceg ==0||_ecc ==0{_gdec =72.0;_gecb =72.0;};_dcdf .PPI =_e .Max (_dcdf .PPI ,_gdec );_dcdf .PPI =_e .Max (_dcdf .PPI ,_gecb );};};return nil ;});_faf =_acae .Process (_fbga );if _faf !=nil {_fe .Log .Debug ("E\u0052\u0052\u004f\u0052 p\u0072o\u0063\u0065\u0073\u0073\u0069n\u0067\u003a\u0020\u0025\u002b\u0076",_faf );
|
|
continue ;};};for _ ,_agb :=range _dagg {if _ ,_abe :=_dec [_agb .Stream ];_abe {continue ;};if _agb .PPI <=_fcfc .ImageUpperPPI {continue ;};_fegd ,_daca :=_ge .NewXObjectImageFromStream (_agb .Stream );if _daca !=nil {_fe .Log .Debug ("\u0045\u0052\u0052\u004f\u0052\u003a\u0020\u0025\u002b\u0076",_daca );
|
|
continue ;};var _bddea imageModifications ;_bddea .Scale =_fcfc .ImageUpperPPI /_agb .PPI ;if _agb .BitsPerComponent ==1&&_agb .ColorComponents ==1{_acb :=_e .Round (_agb .PPI /_fcfc .ImageUpperPPI );_ffad :=_fg .NextPowerOf2 (uint (_acb ));if _fg .InDelta (float64 (_ffad ),1/_bddea .Scale ,0.3){_bddea .Scale =float64 (1)/float64 (_ffad );
|
|
};if _ ,_fbab :=_fegd .Filter .(*_bg .JBIG2Encoder );!_fbab {_bddea .Encoding =_bg .NewJBIG2Encoder ();};};if _daca =_ccd (_fegd ,_bddea );_daca !=nil {_fe .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",_daca );
|
|
continue ;};_bddea .Encoding =nil ;if _dgbg ,_adag :=_bg .GetStream (_agb .Stream .PdfObjectDictionary .Get ("\u0053\u004d\u0061s\u006b"));_adag {_fabc ,_aegg :=_ge .NewXObjectImageFromStream (_dgbg );if _aegg !=nil {_fe .Log .Debug ("\u0045\u0052\u0052\u004f\u0052\u003a\u0020\u0025\u002b\u0076",_aegg );
|
|
continue ;};if _aegg =_ccd (_fabc ,_bddea );_aegg !=nil {_fe .Log .Debug ("\u0045\u0052\u0052\u004f\u0052\u003a\u0020\u0025\u002b\u0076",_aegg );continue ;};};};return objects ,nil ;};
|
|
|
|
// New creates a optimizers chain from options.
|
|
func New (options Options )*Chain {_aebb :=new (Chain );if options .CleanFonts ||options .SubsetFonts {_aebb .Append (&CleanFonts {Subset :options .SubsetFonts });};if options .CleanContentstream {_aebb .Append (new (CleanContentstream ));};if options .ImageUpperPPI > 0{_eag :=new (ImagePPI );
|
|
_eag .ImageUpperPPI =options .ImageUpperPPI ;_aebb .Append (_eag );};if options .ImageQuality > 0{_ffbbc :=new (Image );_ffbbc .ImageQuality =options .ImageQuality ;_aebb .Append (_ffbbc );};if options .CombineDuplicateDirectObjects {_aebb .Append (new (CombineDuplicateDirectObjects ));
|
|
};if options .CombineDuplicateStreams {_aebb .Append (new (CombineDuplicateStreams ));};if options .CombineIdenticalIndirectObjects {_aebb .Append (new (CombineIdenticalIndirectObjects ));};if options .UseObjectStreams {_aebb .Append (new (ObjectStreams ));
|
|
};if options .CompressStreams {_aebb .Append (new (CompressStreams ));};if options .CleanUnusedResources {_aebb .Append (new (CleanUnusedResources ));};return _aebb ;};func _gbfe (_aec _bg .PdfObject )[]content {if _aec ==nil {return nil ;};_caa ,_bda :=_bg .GetArray (_aec );
|
|
if !_bda {_fe .Log .Debug ("\u0041\u006e\u006e\u006fts\u0020\u006e\u006f\u0074\u0020\u0061\u006e\u0020\u0061\u0072\u0072\u0061\u0079");return nil ;};var _fab []content ;for _ ,_bfgc :=range _caa .Elements (){_faeb ,_afbf :=_bg .GetDict (_bfgc );if !_afbf {_fe .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 ;};_deg ,_afbf :=_bg .GetDict (_faeb .Get ("\u0041\u0050"));if !_afbf {_fe .Log .Debug ("\u004e\u006f\u0020\u0041P \u0065\u006e\u0074\u0072\u0079\u0020\u002d\u0020\u0073\u006b\u0069\u0070\u0070\u0069n\u0067");continue ;};_ddc :=_bg .TraceToDirectObject (_deg .Get ("\u004e"));
|
|
if _ddc ==nil {_fe .Log .Debug ("N\u006f\u0020\u004e\u0020en\u0074r\u0079\u0020\u002d\u0020\u0073k\u0069\u0070\u0070\u0069\u006e\u0067");continue ;};var _gbd *_bg .PdfObjectStream ;switch _eec :=_ddc .(type ){case *_bg .PdfObjectDictionary :_aa ,_bfe :=_bg .GetName (_faeb .Get ("\u0041\u0053"));
|
|
if !_bfe {_fe .Log .Debug ("\u004e\u006f\u0020\u0041S \u0065\u006e\u0074\u0072\u0079\u0020\u002d\u0020\u0073\u006b\u0069\u0070\u0070\u0069n\u0067");continue ;};_gbd ,_bfe =_bg .GetStream (_eec .Get (*_aa ));if !_bfe {_fe .Log .Debug ("\u0046o\u0072\u006d\u0020\u006eo\u0074\u0020\u0066\u006f\u0075n\u0064 \u002d \u0073\u006b\u0069\u0070\u0070\u0069\u006eg");
|
|
continue ;};case *_bg .PdfObjectStream :_gbd =_eec ;};if _gbd ==nil {_fe .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 ;};_fdd ,_dae :=_ge .NewXObjectFormFromStream (_gbd );if _dae !=nil {_fe .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",_dae );
|
|
continue ;};_agc ,_dae :=_fdd .GetContentStream ();if _dae !=nil {_fe .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",_dae );continue ;};_fab =append (_fab ,content {_dca :string (_agc ),_cgga :_fdd .Resources });
|
|
};return _fab ;};
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
func (_cbc *CompressStreams )Optimize (objects []_bg .PdfObject )(_ddbd []_bg .PdfObject ,_cfa error ){_ddbd =make ([]_bg .PdfObject ,len (objects ));copy (_ddbd ,objects );for _ ,_cbcg :=range objects {_fcgc ,_cced :=_bg .GetStream (_cbcg );if !_cced {continue ;
|
|
};if _fcfa :=_fcgc .Get ("\u0046\u0069\u006c\u0074\u0065\u0072");_fcfa !=nil {if _ ,_ffea :=_bg .GetName (_fcfa );_ffea {continue ;};if _cgeae ,_bec :=_bg .GetArray (_fcfa );_bec &&_cgeae .Len ()> 0{continue ;};};_cabc :=_bg .NewFlateEncoder ();var _bddfg []byte ;
|
|
_bddfg ,_cfa =_cabc .EncodeBytes (_fcgc .Stream );if _cfa !=nil {return _ddbd ,_cfa ;};_abd :=_cabc .MakeStreamDict ();if len (_bddfg )+len (_abd .WriteString ())< len (_fcgc .Stream ){_fcgc .Stream =_bddfg ;_fcgc .PdfObjectDictionary .Merge (_abd );_fcgc .PdfObjectDictionary .Set ("\u004c\u0065\u006e\u0067\u0074\u0068",_bg .MakeInteger (int64 (len (_fcgc .Stream ))));
|
|
};};return _ddbd ,nil ;};type imageInfo struct{BitsPerComponent int ;ColorComponents int ;Width int ;Height int ;Stream *_bg .PdfObjectStream ;PPI float64 ;};func _ffae (_bddg []*_bg .PdfIndirectObject )map[string ][]string {_egf :=map[string ][]string {};
|
|
for _ ,_fada :=range _bddg {_dfgc ,_gebb :=_bg .GetDict (_fada .PdfObject );if !_gebb {continue ;};_bgc :=_dfgc .Get ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073");_agcb :=_bg .TraceToDirectObject (_bgc );var _fbgb []string ;if _eeb ,_cca :=_agcb .(*_bg .PdfObjectArray );
|
|
_cca {for _ ,_afa :=range _eeb .Elements (){_gggc ,_eda :=_fee (_afa );if _eda !=nil {continue ;};_fbgb =append (_fbgb ,_gggc );};};_dfc :=_ec .Join (_fbgb ,"\u0020");_cggf :=_a .NewContentStreamParser (_dfc );_gebf ,_afda :=_cggf .Parse ();if _afda !=nil {continue ;
|
|
};for _ ,_dbcf :=range *_gebf {_bad :=_dbcf .Operand ;_dcbf :=_dbcf .Params ;switch _bad {case "\u0044\u006f":_afba :=_dcbf [0].String ();if _ ,_dcc :=_egf ["\u0058O\u0062\u006a\u0065\u0063\u0074"];!_dcc {_egf ["\u0058O\u0062\u006a\u0065\u0063\u0074"]=[]string {_afba };
|
|
}else {_egf ["\u0058O\u0062\u006a\u0065\u0063\u0074"]=append (_egf ["\u0058O\u0062\u006a\u0065\u0063\u0074"],_afba );};case "\u0054\u0066":_bfc :=_dcbf [0].String ();if _ ,_agf :=_egf ["\u0046\u006f\u006e\u0074"];!_agf {_egf ["\u0046\u006f\u006e\u0074"]=[]string {_bfc };
|
|
}else {_egf ["\u0046\u006f\u006e\u0074"]=append (_egf ["\u0046\u006f\u006e\u0074"],_bfc );};case "\u0067\u0073":_gcgc :=_dcbf [0].String ();if _ ,_beb :=_egf ["\u0045x\u0074\u0047\u0053\u0074\u0061\u0074e"];!_beb {_egf ["\u0045x\u0074\u0047\u0053\u0074\u0061\u0074e"]=[]string {_gcgc };
|
|
}else {_egf ["\u0045x\u0074\u0047\u0053\u0074\u0061\u0074e"]=append (_egf ["\u0045x\u0074\u0047\u0053\u0074\u0061\u0074e"],_gcgc );};};};};return _egf ;};
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
func (_bf *CleanContentstream )Optimize (objects []_bg .PdfObject )(_dga []_bg .PdfObject ,_dba error ){_bd :=map[*_bg .PdfObjectStream ]struct{}{};var _ad []*_bg .PdfObjectStream ;_ecf :=func (_da *_bg .PdfObjectStream ){if _ ,_dgf :=_bd [_da ];!_dgf {_bd [_da ]=struct{}{};
|
|
_ad =append (_ad ,_da );};};_dfg :=map[_bg .PdfObject ]bool {};_bc :=map[_bg .PdfObject ]bool {};for _ ,_gb :=range objects {switch _de :=_gb .(type ){case *_bg .PdfIndirectObject :switch _geb :=_de .PdfObject .(type ){case *_bg .PdfObjectDictionary :if _afb ,_ee :=_bg .GetName (_geb .Get ("\u0054\u0079\u0070\u0065"));
|
|
!_ee ||_afb .String ()!="\u0050\u0061\u0067\u0065"{continue ;};if _ed ,_cbb :=_bg .GetStream (_geb .Get ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073"));_cbb {_ecf (_ed );}else if _aba ,_cbd :=_bg .GetArray (_geb .Get ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073"));
|
|
_cbd {var _ag []*_bg .PdfObjectStream ;for _ ,_afd :=range _aba .Elements (){if _fag ,_ce :=_bg .GetStream (_afd );_ce {_ag =append (_ag ,_fag );};};if len (_ag )> 0{var _bb _b .Buffer ;for _ ,_ac :=range _ag {if _ade ,_gde :=_bg .DecodeStream (_ac );_gde ==nil {_bb .Write (_ade );
|
|
};_dfg [_ac ]=true ;};_gcg ,_cfb :=_bg .MakeStream (_bb .Bytes (),_bg .NewFlateEncoder ());if _cfb !=nil {return nil ,_cfb ;};_bc [_gcg ]=true ;_geb .Set ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073",_gcg );_ecf (_gcg );};};};case *_bg .PdfObjectStream :if _gdg ,_ddea :=_bg .GetName (_de .Get ("\u0054\u0079\u0070\u0065"));
|
|
!_ddea ||_gdg .String ()!="\u0058O\u0062\u006a\u0065\u0063\u0074"{continue ;};if _ged ,_aca :=_bg .GetName (_de .Get ("\u0053u\u0062\u0074\u0079\u0070\u0065"));!_aca ||_ged .String ()!="\u0046\u006f\u0072\u006d"{continue ;};_ecf (_de );};};for _ ,_bba :=range _ad {_dba =_gfc (_bba );
|
|
if _dba !=nil {return nil ,_dba ;};};_dga =nil ;for _ ,_cg :=range objects {if _dfg [_cg ]{continue ;};_dga =append (_dga ,_cg );};for _bdg :=range _bc {_dga =append (_dga ,_bdg );};return _dga ,nil ;};type objectStructure struct{_gaeb *_bg .PdfObjectDictionary ;
|
|
_bcee *_bg .PdfObjectDictionary ;_feag []*_bg .PdfIndirectObject ;};func _gfc (_ef *_bg .PdfObjectStream )error {_gcc ,_aff :=_bg .DecodeStream (_ef );if _aff !=nil {return _aff ;};_df :=_a .NewContentStreamParser (string (_gcc ));_ae ,_aff :=_df .Parse ();
|
|
if _aff !=nil {return _aff ;};_ae =_cc (_ae );_fbc :=_ae .Bytes ();if len (_fbc )>=len (_gcc ){return nil ;};_cb ,_aff :=_bg .MakeStream (_ae .Bytes (),_bg .NewFlateEncoder ());if _aff !=nil {return _aff ;};_ef .Stream =_cb .Stream ;_ef .Merge (_cb .PdfObjectDictionary );
|
|
return nil ;};
|
|
|
|
// Chain allows to use sequence of optimizers.
|
|
// It implements interface model.Optimizer.
|
|
type Chain struct{_gc []_ge .Optimizer };
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
func (_efaa *CombineDuplicateDirectObjects )Optimize (objects []_bg .PdfObject )(_cge []_bg .PdfObject ,_gge error ){_bggd (objects );_ebc :=make (map[string ][]*_bg .PdfObjectDictionary );var _efd func (_dddf *_bg .PdfObjectDictionary );_efd =func (_bed *_bg .PdfObjectDictionary ){for _ ,_cgea :=range _bed .Keys (){_ddab :=_bed .Get (_cgea );
|
|
if _gba ,_fagd :=_ddab .(*_bg .PdfObjectDictionary );_fagd {_gcfa :=_d .New ();_gcfa .Write ([]byte (_gba .WriteString ()));_aeb :=string (_gcfa .Sum (nil ));_ebc [_aeb ]=append (_ebc [_aeb ],_gba );_efd (_gba );};};};for _ ,_daeg :=range objects {_cac ,_dded :=_daeg .(*_bg .PdfIndirectObject );
|
|
if !_dded {continue ;};if _gfec ,_bbeed :=_cac .PdfObject .(*_bg .PdfObjectDictionary );_bbeed {_efd (_gfec );};};_egca :=make ([]_bg .PdfObject ,0,len (_ebc ));_aea :=make (map[_bg .PdfObject ]_bg .PdfObject );for _ ,_cbba :=range _ebc {if len (_cbba )< 2{continue ;
|
|
};_fdc :=_bg .MakeDict ();_fdc .Merge (_cbba [0]);_bgd :=_bg .MakeIndirectObject (_fdc );_egca =append (_egca ,_bgd );for _bebc :=0;_bebc < len (_cbba );_bebc ++{_gabg :=_cbba [_bebc ];_aea [_gabg ]=_bgd ;};};_cge =make ([]_bg .PdfObject ,len (objects ));
|
|
copy (_cge ,objects );_cge =append (_egca ,_cge ...);_bbce (_cge ,_aea );return _cge ,nil ;};
|
|
|
|
// CombineDuplicateStreams combines duplicated streams by its data hash.
|
|
// It implements interface model.Optimizer.
|
|
type CombineDuplicateStreams struct{}; |