2020-08-27 21:45:09 +00:00
|
|
|
//
|
|
|
|
// Copyright 2020 FoxyUtils ehf. All rights reserved.
|
|
|
|
//
|
|
|
|
// This is a commercial product and requires a license to operate.
|
|
|
|
// A trial license can be obtained at https://unidoc.io
|
|
|
|
//
|
|
|
|
// DO NOT EDIT: generated by unitwist Go source code obfuscator.
|
|
|
|
//
|
|
|
|
// Use of this source code is governed by the UniDoc End User License Agreement
|
|
|
|
// terms that can be accessed at https://unidoc.io/eula/
|
|
|
|
|
2020-09-21 01:20:10 +00:00
|
|
|
package optimize ;import (_cd "bytes";_d "crypto/md5";_bb "errors";_bf "fmt";_db "github.com/unidoc/unipdf/v3/common";_ca "github.com/unidoc/unipdf/v3/contentstream";_b "github.com/unidoc/unipdf/v3/core";_cf "github.com/unidoc/unipdf/v3/extractor";_bad "github.com/unidoc/unipdf/v3/internal/textencoding";_bd "github.com/unidoc/unipdf/v3/model";_dg "github.com/unidoc/unitype";_a "golang.org/x/image/draw";_f "image";_ba "math";);
|
2020-08-31 21:12:07 +00:00
|
|
|
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
2020-09-21 01:20:10 +00:00
|
|
|
func (_bbeb *ObjectStreams )Optimize (objects []_b .PdfObject )(_ffa []_b .PdfObject ,_cbd error ){_dgcc :=&_b .PdfObjectStreams {};_ddd :=make ([]_b .PdfObject ,0,len (objects ));for _ ,_gbdf :=range objects {if _acd ,_dfac :=_gbdf .(*_b .PdfIndirectObject );_dfac &&_acd .GenerationNumber ==0{_dgcc .Append (_gbdf );}else {_ddd =append (_ddd ,_gbdf );};};if _dgcc .Len ()==0{return _ddd ,nil ;};_ffa =make ([]_b .PdfObject ,0,len (_ddd )+_dgcc .Len ()+1);if _dgcc .Len ()> 1{_ffa =append (_ffa ,_dgcc );};_ffa =append (_ffa ,_dgcc .Elements ()...);_ffa =append (_ffa ,_ddd ...);return _ffa ,nil ;};
|
2020-08-27 21:45:09 +00:00
|
|
|
|
2020-09-07 00:23:12 +00:00
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
2020-09-21 01:20:10 +00:00
|
|
|
func (_bde *Chain )Optimize (objects []_b .PdfObject )(_cae []_b .PdfObject ,_dbc error ){_cae =objects ;for _ ,_cg :=range _bde ._fd {_cae ,_dbc =_cg .Optimize (_cae );if _dbc !=nil {return _cae ,_dbc ;};};return _cae ,nil ;};
|
2020-08-27 21:45:09 +00:00
|
|
|
|
2020-09-21 01:20:10 +00:00
|
|
|
// Append appends optimizers to the chain.
|
|
|
|
func (_aa *Chain )Append (optimizers ..._bd .Optimizer ){_aa ._fd =append (_aa ._fd ,optimizers ...)};type content struct{_dde string ;_ddec *_bd .PdfPageResources ;};
|
2020-08-27 21:45:09 +00:00
|
|
|
|
2020-09-21 01:20:10 +00:00
|
|
|
// CombineDuplicateDirectObjects combines duplicated direct objects by its data hash.
|
|
|
|
// It implements interface model.Optimizer.
|
|
|
|
type CombineDuplicateDirectObjects struct{};func _agg (_dda []_b .PdfObject )[]*imageInfo {_bfd :=_b .PdfObjectName ("\u0053u\u0062\u0074\u0079\u0070\u0065");_age :=make (map[*_b .PdfObjectStream ]struct{});var _dgbg error ;var _aac []*imageInfo ;for _ ,_fdec :=range _dda {_becf ,_fcf :=_b .GetStream (_fdec );if !_fcf {continue ;};if _ ,_dfg :=_age [_becf ];_dfg {continue ;};_age [_becf ]=struct{}{};_cabc :=_becf .PdfObjectDictionary .Get (_bfd );_agfa ,_fcf :=_b .GetName (_cabc );if !_fcf ||string (*_agfa )!="\u0049\u006d\u0061g\u0065"{continue ;};_ggd :=&imageInfo {BitsPerComponent :8,Stream :_becf };if _ggd .ColorSpace ,_dgbg =_bd .DetermineColorspaceNameFromPdfObject (_becf .PdfObjectDictionary .Get ("\u0043\u006f\u006c\u006f\u0072\u0053\u0070\u0061\u0063\u0065"));_dgbg !=nil {_db .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",_dgbg );continue ;};if _egc ,_edg :=_b .GetIntVal (_becf .PdfObjectDictionary .Get ("\u0042\u0069t\u0073\u0050\u0065r\u0043\u006f\u006d\u0070\u006f\u006e\u0065\u006e\u0074"));_edg {_ggd .BitsPerComponent =_egc ;};if _fdd ,_ceb :=_b .GetIntVal (_becf .PdfObjectDictionary .Get ("\u0057\u0069\u0064t\u0068"));_ceb {_ggd .Width =_fdd ;};if _cgg ,_eff :=_b .GetIntVal (_becf .PdfObjectDictionary .Get ("\u0048\u0065\u0069\u0067\u0068\u0074"));_eff {_ggd .Height =_cgg ;};switch _ggd .ColorSpace {case "\u0044e\u0076\u0069\u0063\u0065\u0052\u0047B":_ggd .ColorComponents =3;case "\u0044\u0065\u0076\u0069\u0063\u0065\u0047\u0072\u0061\u0079":_ggd .ColorComponents =1;default:_db .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",_ggd .ColorSpace );continue ;};_aac =append (_aac ,_ggd );};return _aac ;};func _ddafb (_fcgg _b .PdfObject )(_cafff string ,_efce []_b .PdfObject ){var _bfe _cd .Buffer ;switch _fece :=_fcgg .(type ){case *_b .PdfIndirectObject :_efce =append (_efce ,_fece );_fcgg =_fece .PdfObject ;};switch _dfba :=_fcgg .(type ){case *_b .PdfObjectStream :if _eccd ,_aged :=_b .DecodeStream (_dfba );_aged ==nil {_bfe .Write (_eccd );_efce =append (_efce ,_dfba );};case *_b .PdfObjectArray :for _ ,_accd :=range _dfba .Elements (){switch _agd :=_accd .(type ){case *_b .PdfObjectStream :if _adgge ,_ccda :=_b .DecodeStream (_agd );_ccda ==nil {_bfe .Write (_adgge );_efce =append (_efce ,_agd );};};};};return _bfe .String (),_efce ;};
|
2020-08-27 21:45:09 +00:00
|
|
|
|
2020-09-21 01:20:10 +00:00
|
|
|
// ImagePPI optimizes images by scaling images such that the PPI (pixels per inch) is never higher than ImageUpperPPI.
|
|
|
|
// TODO(a5i): Add support for inline images.
|
2020-08-31 21:12:07 +00:00
|
|
|
// It implements interface model.Optimizer.
|
2020-09-21 01:20:10 +00:00
|
|
|
type ImagePPI struct{ImageUpperPPI float64 ;};type objectStructure struct{_gfbb *_b .PdfObjectDictionary ;_bbff *_b .PdfObjectDictionary ;_fdeb []*_b .PdfIndirectObject ;};func _fgcd (_dcbd *_b .PdfObjectStream ,_aeb []rune ,_dgg []_dg .GlyphIndex )error {_dcbd ,_cdfe :=_b .GetStream (_dcbd );if !_cdfe {_db .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 _bb .New ("\u0066\u006f\u006e\u0074fi\u006c\u0065\u0032\u0020\u006e\u006f\u0074\u0020\u0066\u006f\u0075\u006e\u0064");};_dcf ,_bdeg :=_b .DecodeStream (_dcbd );if _bdeg !=nil {_db .Log .Debug ("\u0044\u0065c\u006f\u0064\u0065 \u0065\u0072\u0072\u006f\u0072\u003a\u0020\u0025\u0076",_bdeg );return _bdeg ;};_gdd ,_bdeg :=_dg .Parse (_cd .NewReader (_dcf ));if _bdeg !=nil {_db .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 (_dcbd .Stream ));return _bdeg ;};_adb :=_dgg ;if len (_aeb )> 0{_ab :=_gdd .LookupRunes (_aeb );_adb =append (_adb ,_ab ...);};_gdd ,_bdeg =_gdd .SubsetKeepIndices (_adb );if _bdeg !=nil {_db .Log .Debug ("\u0045R\u0052\u004f\u0052\u0020s\u0075\u0062\u0073\u0065\u0074t\u0069n\u0067 \u0066\u006f\u006e\u0074\u003a\u0020\u0025v",_bdeg );return _bdeg ;};var _ace _cd .Buffer ;_bdeg =_gdd .Write (&_ace );if _bdeg !=nil {_db .Log .Debug ("\u0045\u0052\u0052\u004fR \u0057\u0072\u0069\u0074\u0069\u006e\u0067\u0020\u0066\u006f\u006e\u0074\u003a\u0020%\u0076",_bdeg );return _bdeg ;};if _ace .Len ()> len (_dcf ){_db .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 ;};_ebd ,_bdeg :=_b .MakeStream (_ace .Bytes (),_b .NewFlateEncoder ());if _bdeg !=nil {_db .Log .Debug ("\u0045\u0052\u0052\u004fR \u0057\u0072\u0069\u0074\u0069\u006e\u0067\u0020\u0066\u006f\u006e\u0074\u003a\u0020%\u0076",_bdeg );return _bdeg ;};*_dcbd =*_ebd ;_dcbd .Set ("\u004ce\u006e\u0067\u0074\u0068\u0031",_b .MakeInteger (int64 (_ace .Len ())));return nil ;};
|
2020-08-27 21:45:09 +00:00
|
|
|
|
2020-09-14 09:32:45 +00:00
|
|
|
// CombineDuplicateStreams combines duplicated streams by its data hash.
|
|
|
|
// It implements interface model.Optimizer.
|
|
|
|
type CombineDuplicateStreams struct{};
|
2020-08-27 21:45:09 +00:00
|
|
|
|
2020-09-21 01:20:10 +00:00
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
|
|
func (_ggcg *CombineDuplicateStreams )Optimize (objects []_b .PdfObject )(_cce []_b .PdfObject ,_ceg error ){_ffe :=make (map[_b .PdfObject ]_b .PdfObject );_cfca :=make (map[_b .PdfObject ]struct{});_ebgc :=make (map[string ][]*_b .PdfObjectStream );for _ ,_gcb :=range objects {if _aca ,_efe :=_gcb .(*_b .PdfObjectStream );_efe {_ecd :=_d .New ();_ecd .Write ([]byte (_aca .Stream ));_add :=string (_ecd .Sum (nil ));_ebgc [_add ]=append (_ebgc [_add ],_aca );};};for _ ,_caaf :=range _ebgc {if len (_caaf )< 2{continue ;};_fdc :=_caaf [0];for _bbcf :=1;_bbcf < len (_caaf );_bbcf ++{_bfgb :=_caaf [_bbcf ];_ffe [_bfgb ]=_fdc ;_cfca [_bfgb ]=struct{}{};};};_cce =make ([]_b .PdfObject ,0,len (objects )-len (_cfca ));for _ ,_eae :=range objects {if _ ,_bbcb :=_cfca [_eae ];_bbcb {continue ;};_cce =append (_cce ,_eae );};_ddaf (_cce ,_ffe );return _cce ,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{};
|
2020-08-27 21:45:09 +00:00
|
|
|
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
2020-09-21 01:20:10 +00:00
|
|
|
func (_dcg *CombineIdenticalIndirectObjects )Optimize (objects []_b .PdfObject )(_ffg []_b .PdfObject ,_efc error ){_bbca (objects );_eba :=make (map[_b .PdfObject ]_b .PdfObject );_dac :=make (map[_b .PdfObject ]struct{});_defe :=make (map[string ][]*_b .PdfIndirectObject );for _ ,_caeag :=range objects {_bga ,_adbc :=_caeag .(*_b .PdfIndirectObject );if !_adbc {continue ;};if _edc ,_eaed :=_bga .PdfObject .(*_b .PdfObjectDictionary );_eaed {if _bbd ,_cab :=_edc .Get ("\u0054\u0079\u0070\u0065").(*_b .PdfObjectName );_cab &&*_bbd =="\u0050\u0061\u0067\u0065"{continue ;};_beee :=_d .New ();_beee .Write ([]byte (_edc .WriteString ()));_ddc :=string (_beee .Sum (nil ));_defe [_ddc ]=append (_defe [_ddc ],_bga );};};for _ ,_cfe :=range _defe {if len (_cfe )< 2{continue ;};_gdb :=_cfe [0];for _ccd :=1;_ccd < len (_cfe );_ccd ++{_baa :=_cfe [_ccd ];_eba [_baa ]=_gdb ;_dac [_baa ]=struct{}{};};};_ffg =make ([]_b .PdfObject ,0,len (objects )-len (_dac ));for _ ,_bbab :=range objects {if _ ,_bece :=_dac [_bbab ];_bece {continue ;};_ffg =append (_ffg ,_bbab );};_ddaf (_ffg ,_eba );return _ffg ,nil ;};
|
2020-08-27 21:45:09 +00:00
|
|
|
|
2020-09-21 01:20:10 +00:00
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
|
|
func (_bgdg *Image )Optimize (objects []_b .PdfObject )(_bbdd []_b .PdfObject ,_aab error ){if _bgdg .ImageQuality <=0{return objects ,nil ;};_gbc :=_agg (objects );if len (_gbc )==0{return objects ,nil ;};_adg :=make (map[_b .PdfObject ]_b .PdfObject );_becc :=make (map[_b .PdfObject ]struct{});for _ ,_dcc :=range _gbc {_fdcb :=_dcc .Stream .PdfObjectDictionary .Get (_b .PdfObjectName ("\u0053\u004d\u0061s\u006b"));_becc [_fdcb ]=struct{}{};};for _ebb ,_dfcb :=range _gbc {_cfb :=_dfcb .Stream ;if _ ,_ggeg :=_becc [_cfb ];_ggeg {continue ;};_aege ,_ggfg :=_b .NewEncoderFromStream (_cfb );if _ggfg !=nil {_db .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 ;};_cddd ,_ggfg :=_aege .DecodeStream (_cfb );if _ggfg !=nil {_db .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 ;};_feg :=_b .NewDCTEncoder ();_feg .ColorComponents =_dfcb .ColorComponents ;_feg .Quality =_bgdg .ImageQuality ;_feg .BitsPerComponent =_dfcb .BitsPerComponent ;_feg .Width =_dfcb .Width ;_feg .Height =_dfcb .Height ;_dgf ,_ggfg :=_feg .EncodeBytes (_cddd );if _ggfg !=nil {_db .Log .Debug ("\u0045R\u0052\u004f\u0052\u003a\u0020\u0025v",_ggfg );return nil ,_ggfg ;};var _dfe _b .StreamEncoder ;_dfe =_feg ;{_dfa :=_b .NewFlateEncoder ();_bdcf :=_b .NewMultiEncoder ();_bdcf .AddEncoder (_dfa );_bdcf .AddEncoder (_feg );_ffbd ,_dgae :=_bdcf .EncodeBytes (_cddd );if _dgae !=nil {return nil ,_dgae ;};if len (_ffbd )< len (_dgf ){_db .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 (_dgf ),len (_ffbd ),len (_cfb .Stream ));_dgf =_ffbd ;_dfe =_bdcf ;};};_gga :=len (_cfb .Stream );if _gga < len (_dgf ){continue ;};_agfe :=&_b .PdfObjectStream {Stream :_dgf };_agfe .PdfObjectReference =_cfb .PdfObjectReference ;_agfe .PdfObjectDictionary =_b .MakeDict ();_agfe .Merge (_cfb .PdfObjectDictionary );_agfe .Merge (_dfe .MakeStreamDict ());_agfe .Set ("\u004c\u0065\u006e\u0067\u0074\u0068",_b .MakeInteger (int64 (len (_dgf ))));_adg [_cfb ]=_agfe ;_gbc [_ebb ].Stream =_agfe ;};_bbdd =make ([]_b .PdfObject ,len (objects ));copy (_bbdd ,objects );_ddaf (_bbdd ,_adg );return _bbdd ,nil ;};
|
2020-09-14 09:32:45 +00:00
|
|
|
|
|
|
|
// Options describes PDF optimization parameters.
|
2020-09-21 01:20:10 +00:00
|
|
|
type Options struct{CombineDuplicateStreams bool ;CombineDuplicateDirectObjects bool ;ImageUpperPPI float64 ;ImageQuality int ;UseObjectStreams bool ;CombineIdenticalIndirectObjects bool ;CompressStreams bool ;CleanFonts bool ;SubsetFonts bool ;CleanContentstream bool ;};func _ebc (_bfff _b .PdfObject )[]content {if _bfff ==nil {return nil ;};_gge ,_ebcd :=_b .GetArray (_bfff );if !_ebcd {_db .Log .Debug ("\u0041\u006e\u006e\u006fts\u0020\u006e\u006f\u0074\u0020\u0061\u006e\u0020\u0061\u0072\u0072\u0061\u0079");return nil ;};var _bge []content ;for _ ,_gba :=range _gge .Elements (){_bbc ,_bfcd :=_b .GetDict (_gba );if !_bfcd {_db .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 ;};_edf ,_bfcd :=_b .GetDict (_bbc .Get ("\u0041\u0050"));if !_bfcd {_db .Log .Debug ("\u004e\u006f\u0020\u0041P \u0065\u006e\u0074\u0072\u0079\u0020\u002d\u0020\u0073\u006b\u0069\u0070\u0070\u0069n\u0067");continue ;};_ebg :=_b .TraceToDirectObject (_edf .Get ("\u004e"));if _ebg ==nil {_db .Log .Debug ("N\u006f\u0020\u004e\u0020en\u0074r\u0079\u0020\u002d\u0020\u0073k\u0069\u0070\u0070\u0069\u006e\u0067");continue ;};var _aegb *_b .PdfObjectStream ;switch _bgef :=_ebg .(type ){case *_b .PdfObjectDictionary :_ee ,_bffa :=_b .GetName (_bbc .Get ("\u0041\u0053"));if !_bffa {_db .Log .Debug ("\u004e\u006f\u0020\u0041S \u0065\u006e\u0074\u0072\u0079\u0020\u002d\u0020\u0073\u006b\u0069\u0070\u0070\u0069n\u0067");continue ;};_aegb ,_bffa =_b .GetStream (_bgef .Get (*_ee ));if !_bffa {_db .Log .Debug ("\u0046o\u0072\u006d\u0020\u006eo\u0074\u0020\u0066\u006f\u0075n\u0064 \u002d \u0073\u006b\u0069\u0070\u0070\u0069\u006eg");continue ;};case *_b .PdfObjectStream :_aegb =_bgef ;};if _aegb ==nil {_db .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 ;};_cb ,_bab :=_bd .NewXObjectFormFromStream (_aegb );if _bab !=nil {_db .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",_bab );continue ;};_bgd ,_bab :=_cb .GetContentStream ();if _bab !=nil {_db .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",_bab );continue ;};_bge =append (_bge ,content {_dde :string (_bgd ),_ddec :_cb .Resources });};return _bge ;};
|
|
|
|
|
|
|
|
// ObjectStreams groups PDF objects to object streams.
|
|
|
|
// It implements interface model.Optimizer.
|
|
|
|
type ObjectStreams struct{};type imageInfo struct{ColorSpace _b .PdfObjectName ;BitsPerComponent int ;ColorComponents int ;Width int ;Height int ;Stream *_b .PdfObjectStream ;PPI float64 ;};
|
2020-09-14 09:32:45 +00:00
|
|
|
|
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
2020-09-21 01:20:10 +00:00
|
|
|
func (_geg *CompressStreams )Optimize (objects []_b .PdfObject )(_bcg []_b .PdfObject ,_baba error ){_bcg =make ([]_b .PdfObject ,len (objects ));copy (_bcg ,objects );for _ ,_efg :=range objects {_cdaa ,_dga :=_b .GetStream (_efg );if !_dga {continue ;};if _gfb :=_cdaa .Get ("\u0046\u0069\u006c\u0074\u0065\u0072");_gfb !=nil {if _ ,_gdbf :=_b .GetName (_gfb );_gdbf {continue ;};if _fgb ,_afc :=_b .GetArray (_gfb );_afc &&_fgb .Len ()> 0{continue ;};};_gbad :=_b .NewFlateEncoder ();var _dcff []byte ;_dcff ,_baba =_gbad .EncodeBytes (_cdaa .Stream );if _baba !=nil {return _bcg ,_baba ;};_fab :=_gbad .MakeStreamDict ();if len (_dcff )+len (_fab .WriteString ())< len (_cdaa .Stream ){_cdaa .Stream =_dcff ;_cdaa .PdfObjectDictionary .Merge (_fab );_cdaa .PdfObjectDictionary .Set ("\u004c\u0065\u006e\u0067\u0074\u0068",_b .MakeInteger (int64 (len (_cdaa .Stream ))));};};return _bcg ,nil ;};
|
2020-08-27 21:45:09 +00:00
|
|
|
|
2020-09-21 01:20:10 +00:00
|
|
|
// CompressStreams compresses uncompressed streams.
|
2020-09-07 00:23:12 +00:00
|
|
|
// It implements interface model.Optimizer.
|
2020-09-21 01:20:10 +00:00
|
|
|
type CompressStreams struct{};
|
2020-08-27 21:45:09 +00:00
|
|
|
|
2020-09-21 01:20:10 +00:00
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
|
|
func (_aaac *CleanFonts )Optimize (objects []_b .PdfObject )(_acf []_b .PdfObject ,_bgc error ){var _bce map[*_b .PdfObjectStream ]struct{};if _aaac .Subset {var _bgcc error ;_bce ,_bgcc =_ge (objects );if _bgcc !=nil {return nil ,_bgcc ;};};for _ ,_beb :=range objects {_dab ,_abb :=_b .GetStream (_beb );if !_abb {continue ;};if _ ,_gcf :=_bce [_dab ];_gcf {continue ;};_fe ,_ed :=_b .NewEncoderFromStream (_dab );if _ed !=nil {_db .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",_ed );continue ;};_bed ,_ed :=_fe .DecodeStream (_dab );if _ed !=nil {_db .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",_ed );continue ;};if len (_bed )< 4{continue ;};_egf :=string (_bed [:4]);if _egf =="\u004f\u0054\u0054\u004f"{continue ;};if _egf !="\u0000\u0001\u0000\u0000"&&_egf !="\u0074\u0072\u0075\u0065"{continue ;};_beg ,_ed :=_dg .Parse (_cd .NewReader (_bed ));if _ed !=nil {_db .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",_ed );continue ;};_ed =_beg .Optimize ();if _ed !=nil {continue ;};var _bdc _cd .Buffer ;_ed =_beg .Write (&_bdc );if _ed !=nil {_db .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",_ed );continue ;};if _bdc .Len ()> len (_bed ){_db .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 ;};_fdb ,_ed :=_b .MakeStream (_bdc .Bytes (),_b .NewFlateEncoder ());if _ed !=nil {continue ;};*_dab =*_fdb ;_dab .Set ("\u004ce\u006e\u0067\u0074\u0068\u0031",_b .MakeInteger (int64 (_bdc .Len ())));};return objects ,nil ;};
|
2020-08-27 21:45:09 +00:00
|
|
|
|
2020-09-14 09:32:45 +00:00
|
|
|
// CleanFonts cleans up embedded fonts, reducing font sizes.
|
|
|
|
type CleanFonts struct{
|
|
|
|
|
|
|
|
// Subset embedded fonts if encountered (if true).
|
|
|
|
// Otherwise attempts to reduce the font program.
|
2020-09-21 01:20:10 +00:00
|
|
|
Subset bool ;};func _ge (_cc []_b .PdfObject )(_bca map[*_b .PdfObjectStream ]struct{},_bcb error ){_bca =map[*_b .PdfObjectStream ]struct{}{};_cee :=map[*_bd .PdfFont ]struct{}{};_agf :=_fbb (_cc );for _ ,_cdf :=range _agf ._fdeb {_fb ,_ea :=_b .GetDict (_cdf .PdfObject );if !_ea {continue ;};_bff ,_ea :=_b .GetDict (_fb .Get ("\u0052e\u0073\u006f\u0075\u0072\u0063\u0065s"));if !_ea {continue ;};_eab ,_ :=_ddafb (_fb .Get ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073"));_ceda ,_aed :=_bd .NewPdfPageResourcesFromDict (_bff );if _aed !=nil {return nil ,_aed ;};_gd :=[]content {{_dde :_eab ,_ddec :_ceda }};_aef :=_ebc (_fb .Get ("\u0041\u006e\u006e\u006f\u0074\u0073"));if _aef !=nil {_gd =append (_gd ,_aef ...);};for _ ,_dgc :=range _gd {_efa ,_bccd :=_cf .NewFromContents (_dgc ._dde ,_dgc ._ddec );if _bccd !=nil {return nil ,_bccd ;};_dae ,_ ,_ ,_bccd :=_efa .ExtractPageText ();if _bccd !=nil {return nil ,_bccd ;};for _ ,_fde :=range _dae .Marks ().Elements (){if _fde .Font ==nil {continue ;};if _ ,_gb :=_cee [_fde .Font ];!_gb {_cee [_fde .Font ]=struct{}{};};};};};_ddg :=map[*_b .PdfObjectStream ][]*_bd .PdfFont {};for _faa :=range _cee {_gcg :=_faa .FontDescriptor ();if _gcg ==nil ||_gcg .FontFile2 ==nil {continue ;};_ecb ,_ecf :=_b .GetStream (_gcg .FontFile2 );if !_ecf {continue ;};_ddg [_ecb ]=append (_ddg [_ecb ],_faa );};for _ffb :=range _ddg {var _aeg []rune ;var _bda []_dg .GlyphIndex ;for _ ,_dgb :=range _ddg [_ffb ]{switch _ga :=_dgb .Encoder ().(type ){case *_bad .IdentityEncoder :_gca :=_ga .RegisteredRunes ();_ggc :=make ([]_dg .GlyphIndex ,len (_gca ));for _dgbb ,_fgc :=range _gca {_ggc [_dgbb ]=_dg .GlyphIndex (_fgc );};_bda =append (_bda ,_ggc ...);case *_bad .TrueTypeFontEncoder :_bg :=_ga .RegisteredRunes ();_aeg =append (_aeg ,_bg ...);case _bad .SimpleEncoder :_bee :=_ga .Charcodes ();for _ ,_aaa :=range _bee {_fac ,_cca :=_ga .CharcodeToRune (_aaa );if !_cca {_db .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",_aaa );continue ;};_aeg =append (_aeg ,_fac );};};};_bcb =_fgcd (_ffb ,_aeg ,_bda );if _bcb !=nil {_db .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",_bcb );return nil ,_bcb ;};_bca [_ffb ]=struct{}{};};return _bca ,nil ;};
|
2020-08-27 21:45:09 +00:00
|
|
|
|
2020-08-31 21:12:07 +00:00
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
2020-09-21 01:20:10 +00:00
|
|
|
func (_gcc *CombineDuplicateDirectObjects )Optimize (objects []_b .PdfObject )(_deg []_b .PdfObject ,_fge error ){_bbca (objects );_beed :=make (map[string ][]*_b .PdfObjectDictionary );var _fceb func (_bdf *_b .PdfObjectDictionary );_fceb =func (_dad *_b .PdfObjectDictionary ){for _ ,_cgaa :=range _dad .Keys (){_dabd :=_dad .Get (_cgaa );if _fff ,_cgb :=_dabd .(*_b .PdfObjectDictionary );_cgb {_caea :=_d .New ();_caea .Write ([]byte (_fff .WriteString ()));_ecg :=string (_caea .Sum (nil ));_beed [_ecg ]=append (_beed [_ecg ],_fff );_fceb (_fff );};};};for _ ,_gee :=range objects {_bbe ,_acc :=_gee .(*_b .PdfIndirectObject );if !_acc {continue ;};if _fgg ,_dfc :=_bbe .PdfObject .(*_b .PdfObjectDictionary );_dfc {_fceb (_fgg );};};_cdff :=make ([]_b .PdfObject ,0,len (_beed ));_bgb :=make (map[_b .PdfObject ]_b .PdfObject );for _ ,_bccc :=range _beed {if len (_bccc )< 2{continue ;};_aceg :=_b .MakeDict ();_aceg .Merge (_bccc [0]);_acfg :=_b .MakeIndirectObject (_aceg );_cdff =append (_cdff ,_acfg );for _cafa :=0;_cafa < len (_bccc );_cafa ++{_caff :=_bccc [_cafa ];_bgb [_caff ]=_acfg ;};};_deg =make ([]_b .PdfObject ,len (objects ));copy (_deg ,objects );_deg =append (_cdff ,_deg ...);_ddaf (_deg ,_bgb );return _deg ,nil ;};
|
|
|
|
|
|
|
|
// New creates a optimizers chain from options.
|
|
|
|
func New (options Options )*Chain {_ddgb :=new (Chain );if options .CleanFonts ||options .SubsetFonts {_ddgb .Append (&CleanFonts {Subset :options .SubsetFonts });};if options .CleanContentstream {_ddgb .Append (new (CleanContentstream ));};if options .ImageUpperPPI > 0{_cff :=new (ImagePPI );_cff .ImageUpperPPI =options .ImageUpperPPI ;_ddgb .Append (_cff );};if options .ImageQuality > 0{_abab :=new (Image );_abab .ImageQuality =options .ImageQuality ;_ddgb .Append (_abab );};if options .CombineDuplicateDirectObjects {_ddgb .Append (new (CombineDuplicateDirectObjects ));};if options .CombineDuplicateStreams {_ddgb .Append (new (CombineDuplicateStreams ));};if options .CombineIdenticalIndirectObjects {_ddgb .Append (new (CombineIdenticalIndirectObjects ));};if options .UseObjectStreams {_ddgb .Append (new (ObjectStreams ));};if options .CompressStreams {_ddgb .Append (new (CompressStreams ));};return _ddgb ;};
|
2020-08-27 21:45:09 +00:00
|
|
|
|
2020-09-14 09:32:45 +00:00
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
2020-09-21 01:20:10 +00:00
|
|
|
func (_cbb *ImagePPI )Optimize (objects []_b .PdfObject )(_becb []_b .PdfObject ,_fcc error ){if _cbb .ImageUpperPPI <=0{return objects ,nil ;};_dec :=_agg (objects );if len (_dec )==0{return objects ,nil ;};_bebd :=make (map[_b .PdfObject ]struct{});for _ ,_adc :=range _dec {_ffge :=_adc .Stream .PdfObjectDictionary .Get (_b .PdfObjectName ("\u0053\u004d\u0061s\u006b"));_bebd [_ffge ]=struct{}{};};_fddb :=make (map[*_b .PdfObjectStream ]*imageInfo );for _ ,_dbfa :=range _dec {_fddb [_dbfa .Stream ]=_dbfa ;};var _cbf *_b .PdfObjectDictionary ;for _ ,_aba :=range objects {if _bccef ,_ggg :=_b .GetDict (_aba );_cbf ==nil &&_ggg {if _bae ,_ggcc :=_b .GetName (_bccef .Get (_b .PdfObjectName ("\u0054\u0079\u0070\u0065")));_ggcc &&*_bae =="\u0043a\u0074\u0061\u006c\u006f\u0067"{_cbf =_bccef ;};};};if _cbf ==nil {return objects ,nil ;};_fbg ,_gbg :=_b .GetDict (_cbf .Get (_b .PdfObjectName ("\u0050\u0061\u0067e\u0073")));if !_gbg {return objects ,nil ;};_ddgg ,_acfd :=_b .GetArray (_fbg .Get (_b .PdfObjectName ("\u004b\u0069\u0064\u0073")));if !_acfd {return objects ,nil ;};_fddg :=make (map[string ]*imageInfo );for _ ,_bgf :=range _ddgg .Elements (){_fda ,_ecc :=_b .GetDict (_bgf );if !_ecc {continue ;};_bcge ,_fcfa :=_b .GetArray (_fda .Get ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073"));if !_fcfa {continue ;};_dbce ,_edfg :=_b .GetDict (_fda .Get ("\u0052e\u0073\u006f\u0075\u0072\u0063\u0065s"));if !_edfg {continue ;};_dca ,_daa :=_b .GetDict (_dbce .Get ("\u0058O\u0062\u006a\u0065\u0063\u0074"));if !_daa {continue ;};_fgeb :=_dca .Keys ();for _ ,_ddb :=range _fgeb {if _gbd ,_ddbb :=_b .GetStream (_dca .Get (_ddb ));_ddbb {if _gff ,_ada :=_fddb [_gbd ];_ada {_fddg [string (_ddb )]=_gff ;};};};for _ ,_bag :=range _bcge .Elements (){if _bgdc ,_fddd :=_b .GetStream (_bag );_fddd {_ebca ,_fcd :=_b .NewEncoderFromStream (_bgdc );if _fcd !=nil {return nil ,_fcd ;};_ccg ,_fcd :=_ebca .DecodeStream (_bgdc );if _fcd !=nil {return nil ,_fcd ;};_fbc :=_ca .NewContentStreamParser (string (_ccg ));_bccdb ,_fcd :=_fbc .Parse ();if _fcd !=nil {return nil ,_fcd ;};_eea ,_acfc :=1.0,1.0;for _ ,_aga :=range *_bccdb {if _aga .Operand =="\u0051"{_eea ,_acfc =1.0,1.0;};if _aga .Operand =="\u0063\u006d"&&len (_aga .Params )==6{if _agfc ,_bfa :=_b .GetFloatVal (_aga .Params [0]);_bfa {_eea =_eea *_agfc ;};if _dbfab ,_abf :=_b .GetFloatVal (_aga .Params [3]);_abf {_acfc =_acfc *_dbfab ;};if _cbc ,_aag :=_b .GetIntVal (_aga .Params [0]);_aag {_eea =_eea *float64 (_cbc );};if _fec ,_cbe :=_b .GetIntVal (_aga .Params [3]);_cbe {_acfc =_acfc *float64 (_fec );};};if _aga .Operand =="\u0044\u006f"&&len (_aga .Params )==1{_eead ,_gbf :=_b .GetName (_aga .Params [0]);if !_gbf {continue ;};if _cfef ,_ecfg :=_fddg [string (*_eead )];_ecfg {_gfc ,_gce :=_eea /72.0,_acfc /72.0;_acaa ,_ddce :=float64 (_cfef .Width )/_gfc ,float64 (_cfef .Height )/_gce ;if _gfc ==0||_gce ==0{_acaa =72.0;_ddce =72.0;};_cfef .PPI =_ba .Max (_cfef .PPI ,_acaa );_cfef .PPI =_ba .Max (_cfef .PPI ,_ddce );};};};};};};for _ ,_bdcb :=range _dec {if _ ,_cbfe :=_bebd [_bdcb .Stream ];_cbfe {continue ;};if _bdcb .PPI <=_cbb .ImageUpperPPI {continue ;};_adf :=_cbb .ImageUpperPPI /_bdcb .PPI ;if _caffe :=_dfb (_bdcb .Stream ,_adf );_caffe !=nil {_db .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",_caffe );}else {if _bdg ,_gfg :=_b .GetStream (_bdcb .Stream .PdfObjectDictionary .Get (_b .PdfObjectName ("\u0053\u004d\u0061s\u006b")));_gfg {if _cbbf :=_dfb (_bdg ,_adf );_cbbf !=nil {return nil ,_cbbf ;};};};};return objects ,nil ;};func _eb (_ac *_b .PdfObjectStream )error {_def ,_cfc :=_b .DecodeStream (_ac );if _cfc !=nil {return _cfc ;};_af :=_ca .NewContentStreamParser (string (_def ));_df ,_cfc :=_af .Parse ();if _cfc !=nil {return _cfc ;};_df =_dc (_df );_da :=_df .Bytes ();if len (_da )>=len (_def ){return nil ;};_bc ,_cfc :=_b .MakeStream (_df .Bytes (),_b .NewFlateEncoder ());if
|
2020-09-14 09:32:45 +00:00
|
|
|
|
2020-09-21 01:20:10 +00:00
|
|
|
// CombineIdenticalIndirectObjects combines identical indirect objects.
|
2020-09-07 00:23:12 +00:00
|
|
|
// It implements interface model.Optimizer.
|
2020-09-21 01:20:10 +00:00
|
|
|
type CombineIdenticalIndirectObjects struct{};
|
2020-09-07 00:23:12 +00:00
|
|
|
|
2020-09-21 01:20:10 +00:00
|
|
|
// Chain allows to use sequence of optimizers.
|
2020-09-07 00:23:12 +00:00
|
|
|
// It implements interface model.Optimizer.
|
2020-09-21 01:20:10 +00:00
|
|
|
type Chain struct{_fd []_bd .Optimizer };
|
2020-08-27 21:45:09 +00:00
|
|
|
|
2020-09-21 01:20:10 +00:00
|
|
|
// Image optimizes images by rewrite images into JPEG format with quality equals to ImageQuality.
|
|
|
|
// TODO(a5i): Add support for inline images.
|
|
|
|
// It implements interface model.Optimizer.
|
|
|
|
type Image struct{ImageQuality int ;};func _ddaf (_aedg []_b .PdfObject ,_bdaa map[_b .PdfObject ]_b .PdfObject ){if _bdaa ==nil ||len (_bdaa )==0{return ;};for _adgg ,_bdcff :=range _aedg {if _ged ,_cdb :=_bdaa [_bdcff ];_cdb {_aedg [_adgg ]=_ged ;continue ;};_bdaa [_bdcff ]=_bdcff ;switch _ede :=_bdcff .(type ){case *_b .PdfObjectArray :_cad :=make ([]_b .PdfObject ,_ede .Len ());copy (_cad ,_ede .Elements ());_ddaf (_cad ,_bdaa );for _abe ,_faabe :=range _cad {_ede .Set (_abe ,_faabe );};case *_b .PdfObjectStreams :_ddaf (_ede .Elements (),_bdaa );case *_b .PdfObjectStream :_dcd :=[]_b .PdfObject {_ede .PdfObjectDictionary };_ddaf (_dcd ,_bdaa );_ede .PdfObjectDictionary =_dcd [0].(*_b .PdfObjectDictionary );case *_b .PdfObjectDictionary :_ece :=_ede .Keys ();_cgbb :=make ([]_b .PdfObject ,len (_ece ));for _fdga ,_gae :=range _ece {_cgbb [_fdga ]=_ede .Get (_gae );};_ddaf (_cgbb ,_bdaa );for _gddd ,_cdbb :=range _ece {_ede .Set (_cdbb ,_cgbb [_gddd ]);};case *_b .PdfIndirectObject :_bbb :=[]_b .PdfObject {_ede .PdfObject };_ddaf (_bbb ,_bdaa );_ede .PdfObject =_bbb [0];};};};func _dfb (_aefd *_b .PdfObjectStream ,_gcbe float64 )error {_ggb ,_fgbb :=_bd .NewXObjectImageFromStream (_aefd );if _fgbb !=nil {return _fgbb ;};_dee ,_fgbb :=_ggb .ToImage ();if _fgbb !=nil {return _fgbb ;};_bbcc ,_fgbb :=_dee .ToGoImage ();if _fgbb !=nil {return _fgbb ;};_dea :=int (_ba .RoundToEven (float64 (_dee .Width )*_gcbe ));_bfce :=int (_ba .RoundToEven (float64 (_dee .Height )*_gcbe ));_dgfc :=_f .Rect (0,0,_dea ,_bfce );var _fgce _a .Image ;var _bcgg func (_f .Image )(*_bd .Image ,error );switch _ggb .ColorSpace .String (){case "\u0044e\u0076\u0069\u0063\u0065\u0052\u0047B":_fgce =_f .NewRGBA (_dgfc );_bcgg =_bd .ImageHandling .NewImageFromGoImage ;case "\u0044\u0065\u0076\u0069\u0063\u0065\u0047\u0072\u0061\u0079":_fgce =_f .NewGray (_dgfc );_bcgg =_bd .ImageHandling .NewGrayImageFromGoImage ;default:return _bf .Errorf ("\u006f\u0070\u0074\u0069\u006d\u0069\u007a\u0061t\u0069\u006f\u006e i\u0073\u0020\u006e\u006f\u0074\u0020s\u0075\u0070\u0070\u006f\u0072\u0074\u0065\u0064\u0020\u0066\u006f\u0072\u0020\u0063\u006fl\u006f\u0072\u0020\u0073\u0070\u0061\u0063\u0065 \u0025\u0073",_ggb .ColorSpace .String ());};_a .CatmullRom .Scale (_fgce ,_fgce .Bounds (),_bbcc ,_bbcc .Bounds (),_a .Over ,&_a .Options {});if _dee ,_fgbb =_bcgg (_fgce );_fgbb !=nil {return _fgbb ;};_abd :=_b .MakeDict ();_abd .Set ("\u0051u\u0061\u006c\u0069\u0074\u0079",_b .MakeInteger (100));_abd .Set ("\u0050r\u0065\u0064\u0069\u0063\u0074\u006fr",_b .MakeInteger (1));_ggb .Filter .UpdateParams (_abd );if _fgbb =_ggb .SetImage (_dee ,nil );_fgbb !=nil {return _fgbb ;};_ggb .ToPdfObject ();return nil ;};
|
2020-09-14 09:32:45 +00:00
|
|
|
|
2020-09-21 01:20:10 +00:00
|
|
|
// Optimize optimizes PDF objects to decrease PDF size.
|
|
|
|
func (_ae *CleanContentstream )Optimize (objects []_b .PdfObject )(_aea []_b .PdfObject ,_dbf error ){_caf :=map[*_b .PdfObjectStream ]struct{}{};var _dd []*_b .PdfObjectStream ;_fc :=func (_fg *_b .PdfObjectStream ){if _ ,_ag :=_caf [_fg ];!_ag {_caf [_fg ]=struct{}{};_dd =append (_dd ,_fg );};};for _ ,_gc :=range objects {switch _ce :=_gc .(type ){case *_b .PdfIndirectObject :switch _cfg :=_ce .PdfObject .(type ){case *_b .PdfObjectDictionary :if _gg ,_fdg :=_b .GetName (_cfg .Get ("\u0054\u0079\u0070\u0065"));!_fdg ||_gg .String ()!="\u0050\u0061\u0067\u0065"{continue ;};if _bfg ,_ggf :=_b .GetStream (_cfg .Get ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073"));_ggf {_fc (_bfg );}else if _dff ,_ad :=_b .GetArray (_cfg .Get ("\u0043\u006f\u006e\u0074\u0065\u006e\u0074\u0073"));_ad {for _ ,_bded :=range _dff .Elements (){if _dbg ,_cga :=_b .GetStream (_bded );_cga {_fc (_dbg );};};};};case *_b .PdfObjectStream :if _ced ,_eg :=_b .GetName (_ce .Get ("\u0054\u0079\u0070\u0065"));!_eg ||_ced .String ()!="\u0058O\u0062\u006a\u0065\u0063\u0074"{continue ;};if _bcc ,_ec :=_b .GetName (_ce .Get ("\u0053u\u0062\u0074\u0079\u0070\u0065"));!_ec ||_bcc .String ()!="\u0046\u006f\u0072\u006d"{continue ;};_fc (_ce );};};for _ ,_be :=range _dd {_dbf =_eb (_be );if _dbf !=nil {return nil ,_dbf ;};};return objects ,nil ;};func _bbca (_gfgf []_b .PdfObject ){for _bedf ,_geec :=range _gfgf {switch _cac :=_geec .(type ){case *_b .PdfIndirectObject :_cac .ObjectNumber =int64 (_bedf +1);_cac .GenerationNumber =0;case *_b .PdfObjectStream :_cac .ObjectNumber =int64 (_bedf +1);_cac .GenerationNumber =0;case *_b .PdfObjectStreams :_cac .ObjectNumber =int64 (_bedf +1);_cac .GenerationNumber =0;};};};func _fbb (_edgf []_b .PdfObject )objectStructure {_gfa :=objectStructure {};_ade :=false ;for _ ,_bea :=range _edgf {switch _fgbc :=_bea .(type ){case *_b .PdfIndirectObject :_cgbf ,_eaec :=_b .GetDict (_fgbc );if !_eaec {continue ;};_cddg ,_eaec :=_b .GetName (_cgbf .Get ("\u0054\u0079\u0070\u0065"));if !_eaec {continue ;};switch _cddg .String (){case "\u0043a\u0074\u0061\u006c\u006f\u0067":_gfa ._gfbb =_cgbf ;_ade =true ;};};if _ade {break ;};};if !_ade {return _gfa ;};_efde ,_bcee :=_b .GetDict (_gfa ._gfbb .Get ("\u0050\u0061\u0067e\u0073"));if !_bcee {return _gfa ;};_gfa ._bbff =_efde ;_gdea ,_bcee :=_b .GetArray (_efde .Get ("\u004b\u0069\u0064\u0073"));if !_bcee {return _gfa ;};for _ ,_eaa :=range _gdea .Elements (){_fffd ,_ggfgg :=_b .GetIndirect (_eaa );if !_ggfgg {break ;};_gfa ._fdeb =append (_gfa ._fdeb ,_fffd );};return _gfa ;};func _dc (_cda *_ca .ContentStreamOperations )*_ca .ContentStreamOperations {if _cda ==nil {return nil ;};_de :=_ca .ContentStreamOperations {};for _ ,_bfc :=range *_cda {switch _bfc .Operand {case "\u0042\u0044\u0043","\u0042\u004d\u0043","\u0045\u004d\u0043":continue ;case "\u0054\u006d":if len (_bfc .Params )==6{if _ff ,_g :=_b .GetNumbersAsFloat (_bfc .Params );_g ==nil {if _ff [0]==1&&_ff [1]==0&&_ff [2]==0&&_ff [3]==1{_bfc =&_ca .ContentStreamOperation {Params :[]_b .PdfObject {_bfc .Params [4],_bfc .Params [5]},Operand :"\u0054\u0064"};};};};};_de =append (_de ,_bfc );};return &_de ;};
|