LibreOffice Module svx (master)  1
compressgraphicdialog.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include "dlgunit.hxx"
21 #include <vcl/fieldvalues.hxx>
22 #include <vcl/graph.hxx>
23 #include <vcl/graphicfilter.hxx>
24 #include <vcl/virdev.hxx>
25 #include <vcl/svapp.hxx>
26 #include <vcl/settings.hxx>
27 #include <vcl/weld.hxx>
28 #include <svx/strings.hrc>
29 #include <svx/svdograf.hxx>
30 #include <svx/sdgcpitm.hxx>
31 #include <svx/dialmgr.hxx>
32 #include <svx/graphichelper.hxx>
34 #include <sfx2/dispatch.hxx>
35 #include <sfx2/module.hxx>
36 #include <comphelper/fileformat.h>
37 #include <com/sun/star/uno/Sequence.hxx>
38 #include <tools/stream.hxx>
40 
41 using namespace com::sun::star::uno;
42 using namespace com::sun::star::beans;
43 
45  GenericDialogController( pParent, "svx/ui/compressgraphicdialog.ui", "CompressGraphicDialog" ),
46  m_xGraphicObj ( pGraphicObj ),
47  m_aGraphic ( pGraphicObj->GetGraphicObject().GetGraphic() ),
48  m_aViewSize100mm ( pGraphicObj->GetLogicRect().GetSize() ),
49  m_rBindings ( rBindings ),
50  m_dResolution ( 300 )
51 {
52  const SdrGrafCropItem& rCrop = m_xGraphicObj->GetMergedItem(SDRATTR_GRAFCROP);
53  m_aCropRectangle = tools::Rectangle(rCrop.GetLeft(), rCrop.GetTop(), rCrop.GetRight(), rCrop.GetBottom());
54 
55  Initialize();
56 }
57 
58 CompressGraphicsDialog::CompressGraphicsDialog( weld::Window* pParent, Graphic const & rGraphic, Size rViewSize100mm, tools::Rectangle const & rCropRectangle, SfxBindings& rBindings ) :
59  GenericDialogController( pParent, "svx/ui/compressgraphicdialog.ui", "CompressGraphicDialog" ),
60  m_xGraphicObj ( nullptr ),
61  m_aGraphic ( rGraphic ),
62  m_aViewSize100mm ( rViewSize100mm ),
63  m_aCropRectangle ( rCropRectangle ),
64  m_rBindings ( rBindings ),
65  m_dResolution ( 300 )
66 {
67  Initialize();
68 }
69 
71 {
72 }
73 
75 {
76  m_xLabelGraphicType = m_xBuilder->weld_label("label-graphic-type");
77  m_xFixedText2 = m_xBuilder->weld_label("label-original-size");
78  m_xFixedText3 = m_xBuilder->weld_label("label-view-size");
79  m_xFixedText5 = m_xBuilder->weld_label("label-image-capacity");
80  m_xFixedText6 = m_xBuilder->weld_label("label-new-capacity");
81  m_xJpegCompRB = m_xBuilder->weld_radio_button("radio-jpeg");
82  m_xCompressionMF = m_xBuilder->weld_spin_button("spin-compression");
83  m_xCompressionSlider = m_xBuilder->weld_scale("scale-compression");
84  m_xLosslessRB = m_xBuilder->weld_radio_button("radio-lossless");
85  m_xQualityMF = m_xBuilder->weld_spin_button("spin-quality");
86  m_xQualitySlider = m_xBuilder->weld_scale("scale-quality");
87  m_xReduceResolutionCB = m_xBuilder->weld_check_button("checkbox-reduce-resolution");
88  m_xMFNewWidth = m_xBuilder->weld_spin_button("spin-new-width");
89  m_xMFNewHeight = m_xBuilder->weld_spin_button("spin-new-height");
90  m_xResolutionLB = m_xBuilder->weld_combo_box("combo-resolution");
91  m_xBtnCalculate = m_xBuilder->weld_button("calculate");
92  m_xInterpolationCombo = m_xBuilder->weld_combo_box("interpolation-method-combo");
93 
94  m_xInterpolationCombo->set_active_text("Lanczos");
95 
96  m_xInterpolationCombo->connect_changed(LINK(this, CompressGraphicsDialog, NewInterpolationModifiedHdl));
97 
98  m_xMFNewWidth->connect_changed( LINK( this, CompressGraphicsDialog, NewWidthModifiedHdl ));
99  m_xMFNewHeight->connect_changed( LINK( this, CompressGraphicsDialog, NewHeightModifiedHdl ));
100 
101  m_xResolutionLB->connect_changed( LINK( this, CompressGraphicsDialog, ResolutionModifiedHdl ));
102  m_xBtnCalculate->connect_clicked( LINK( this, CompressGraphicsDialog, CalculateClickHdl ) );
103 
104  m_xLosslessRB->connect_toggled( LINK( this, CompressGraphicsDialog, ToggleCompressionRB ) );
105  m_xJpegCompRB->connect_toggled( LINK( this, CompressGraphicsDialog, ToggleCompressionRB ) );
106 
107  m_xReduceResolutionCB->connect_toggled( LINK( this, CompressGraphicsDialog, ToggleReduceResolutionRB ) );
108 
109  m_xQualitySlider->connect_value_changed( LINK( this, CompressGraphicsDialog, SlideHdl ));
110  m_xCompressionSlider->connect_value_changed( LINK( this, CompressGraphicsDialog, SlideHdl ));
111  m_xQualityMF->connect_changed( LINK( this, CompressGraphicsDialog, NewQualityModifiedHdl ));
112  m_xCompressionMF->connect_changed( LINK( this, CompressGraphicsDialog, NewCompressionModifiedHdl ));
113 
114  m_xJpegCompRB->set_active(true);
115  m_xReduceResolutionCB->set_active(true);
116 
120  Update();
121 }
122 
124 {
125  auto pGfxLink = m_aGraphic.GetSharedGfxLink();
126 
127  m_xLabelGraphicType->set_label(GraphicHelper::GetImageType(m_aGraphic));
128 
129  const FieldUnit eFieldUnit = m_rBindings.GetDispatcher()->GetModule()->GetFieldUnit();
131  sal_Unicode cSeparator = rLocaleWrapper.getNumDecimalSep()[0];
132 
134  pDummyVDev->EnableOutput( false );
135  pDummyVDev->SetMapMode( m_aGraphic.GetPrefMapMode() );
136 
137  Size aPixelSize = m_aGraphic.GetSizePixel();
138  Size aOriginalSize100mm(pDummyVDev->PixelToLogic(m_aGraphic.GetSizePixel(), MapMode(MapUnit::Map100thMM)));
139 
140  OUString aBitmapSizeString = SvxResId(STR_IMAGE_ORIGINAL_SIZE);
141  OUString aWidthString = GetUnitString( aOriginalSize100mm.Width(), eFieldUnit, cSeparator );
142  OUString aHeightString = GetUnitString( aOriginalSize100mm.Height(), eFieldUnit, cSeparator );
143  aBitmapSizeString = aBitmapSizeString.replaceAll("$(WIDTH)", aWidthString);
144  aBitmapSizeString = aBitmapSizeString.replaceAll("$(HEIGHT)", aHeightString);
145  aBitmapSizeString = aBitmapSizeString.replaceAll("$(WIDTH_IN_PX)", OUString::number(aPixelSize.Width()));
146  aBitmapSizeString = aBitmapSizeString.replaceAll("$(HEIGHT_IN_PX)", OUString::number(aPixelSize.Height()));
147  m_xFixedText2->set_label(aBitmapSizeString);
148 
149  int aValX = static_cast<int>(aPixelSize.Width() / GetViewWidthInch());
150 
151  OUString aViewSizeString = SvxResId(STR_IMAGE_VIEW_SIZE);
152 
153  aWidthString = GetUnitString( m_aViewSize100mm.Width(), eFieldUnit, cSeparator );
154  aHeightString = GetUnitString( m_aViewSize100mm.Height(), eFieldUnit, cSeparator );
155  aViewSizeString = aViewSizeString.replaceAll("$(WIDTH)", aWidthString);
156  aViewSizeString = aViewSizeString.replaceAll("$(HEIGHT)", aHeightString);
157  aViewSizeString = aViewSizeString.replaceAll("$(DPI)", OUString::number(aValX));
158  m_xFixedText3->set_label(aViewSizeString);
159 
160  m_aNativeSize = pGfxLink ? pGfxLink->GetDataSize() : 0;
161 
162  OUString aNativeSizeString = SvxResId(STR_IMAGE_CAPACITY);
163  aNativeSizeString = aNativeSizeString.replaceAll("$(CAPACITY)", OUString::number( m_aNativeSize / 1024 ));
164  m_xFixedText5->set_label(aNativeSizeString);
165 
166  m_xFixedText6->set_label("??");
167 }
168 
170 {
171  int nPixelX = static_cast<sal_Int32>( GetViewWidthInch() * m_dResolution );
172  m_xMFNewWidth->set_value(nPixelX);
173 }
174 
176 {
177  int nPixelY = static_cast<sal_Int32>( GetViewHeightInch() * m_dResolution );
178  m_xMFNewHeight->set_value(nPixelY);
179 }
180 
182 {
183  m_xResolutionLB->set_entry_text( OUString::number( static_cast<sal_Int32>(m_dResolution) ) );
184 }
185 
187 {
188  return static_cast<double>(vcl::ConvertValue(m_aViewSize100mm.Width(), 2, MapUnit::Map100thMM, FieldUnit::INCH)) / 100.0;
189 }
190 
192 {
193  return static_cast<double>(vcl::ConvertValue(m_aViewSize100mm.Height(), 2, MapUnit::Map100thMM, FieldUnit::INCH)) / 100.0;
194 }
195 
197 {
198  OUString aSelectionText = m_xInterpolationCombo->get_active_text();
199 
200  if( aSelectionText == "Lanczos" ) {
201  return BmpScaleFlag::Lanczos;
202  } else if( aSelectionText == "Bilinear" ) {
203  return BmpScaleFlag::BiLinear;
204  } else if( aSelectionText == "Bicubic" ) {
205  return BmpScaleFlag::BiCubic;
206  } else if ( aSelectionText == "None" ) {
207  return BmpScaleFlag::Fast;
208  }
209  return BmpScaleFlag::BestQuality;
210 }
211 
213 {
214  BitmapEx aBitmap = m_aGraphic.GetBitmapEx();
215  if ( m_xReduceResolutionCB->get_active() )
216  {
217  tools::Long nPixelX = static_cast<tools::Long>( GetViewWidthInch() * m_dResolution );
218  tools::Long nPixelY = static_cast<tools::Long>( GetViewHeightInch() * m_dResolution );
219 
220  aBitmap.Scale( Size( nPixelX, nPixelY ), GetSelectedInterpolationType() );
221  }
222  Graphic aScaledGraphic( aBitmap );
224 
225  Sequence< PropertyValue > aFilterData( 3 );
226  aFilterData[ 0 ].Name = "Interlaced";
227  aFilterData[ 0 ].Value <<= sal_Int32(0);
228  aFilterData[ 1 ].Name = "Compression";
229  aFilterData[ 1 ].Value <<= static_cast<sal_Int32>(m_xCompressionMF->get_value());
230  aFilterData[ 2 ].Name = "Quality";
231  aFilterData[ 2 ].Value <<= static_cast<sal_Int32>(m_xQualityMF->get_value());
232 
233  OUString aGraphicFormatName = m_xLosslessRB->get_active() ? OUString( "png" ) : OUString( "jpg" );
234 
235  sal_uInt16 nFilterFormat = rFilter.GetExportFormatNumberForShortName( aGraphicFormatName );
236  rFilter.ExportGraphic( aScaledGraphic, "none", aStream, nFilterFormat, &aFilterData );
237 }
238 
239 IMPL_LINK_NOARG( CompressGraphicsDialog, NewWidthModifiedHdl, weld::Entry&, void )
240 {
241  m_dResolution = m_xMFNewWidth->get_value() / GetViewWidthInch();
242 
243  UpdateNewHeightMF();
244  UpdateResolutionLB();
245  Update();
246 }
247 
248 IMPL_LINK( CompressGraphicsDialog, SlideHdl, weld::Scale&, rScale, void )
249 {
250  if (&rScale == m_xQualitySlider.get())
251  m_xQualityMF->set_value(m_xQualitySlider->get_value());
252  else
253  m_xCompressionMF->set_value(m_xCompressionSlider->get_value());
254  Update();
255 }
256 
257 IMPL_LINK_NOARG( CompressGraphicsDialog, NewInterpolationModifiedHdl, weld::ComboBox&, void )
258 {
259  Update();
260 }
261 
262 IMPL_LINK_NOARG( CompressGraphicsDialog, NewQualityModifiedHdl, weld::Entry&, void )
263 {
264  m_xQualitySlider->set_value(m_xQualityMF->get_value());
265  Update();
266 }
267 
268 IMPL_LINK_NOARG( CompressGraphicsDialog, NewCompressionModifiedHdl, weld::Entry&, void )
269 {
270  m_xCompressionSlider->set_value(m_xCompressionMF->get_value());
271  Update();
272 }
273 
274 IMPL_LINK_NOARG( CompressGraphicsDialog, NewHeightModifiedHdl, weld::Entry&, void )
275 {
276  m_dResolution = m_xMFNewHeight->get_value() / GetViewHeightInch();
277 
278  UpdateNewWidthMF();
279  UpdateResolutionLB();
280  Update();
281 }
282 
283 IMPL_LINK_NOARG( CompressGraphicsDialog, ResolutionModifiedHdl, weld::ComboBox&, void )
284 {
285  m_dResolution = static_cast<double>(m_xResolutionLB->get_active_text().toInt32());
286 
287  UpdateNewWidthMF();
288  UpdateNewHeightMF();
289  Update();
290 }
291 
293 {
294  bool choice = m_xLosslessRB->get_active();
295  m_xCompressionMF->set_sensitive(choice);
296  m_xCompressionSlider->set_sensitive(choice);
297  m_xQualityMF->set_sensitive(!choice);
298  m_xQualitySlider->set_sensitive(!choice);
299  Update();
300 }
301 
302 IMPL_LINK_NOARG( CompressGraphicsDialog, ToggleReduceResolutionRB, weld::ToggleButton&, void )
303 {
304  bool choice = m_xReduceResolutionCB->get_active();
305  m_xMFNewWidth->set_sensitive(choice);
306  m_xMFNewHeight->set_sensitive(choice);
307  m_xResolutionLB->set_sensitive(choice);
308  m_xInterpolationCombo->set_sensitive(choice);
309  Update();
310 }
311 
313 {
314  sal_Int32 aSize = 0;
315 
316  if ( m_dResolution > 0.0 )
317  {
318  SvMemoryStream aMemStream;
320  Compress( aMemStream );
321  aSize = aMemStream.TellEnd();
322  }
323 
324  if ( aSize > 0 )
325  {
326  OUString aSizeAsString = OUString::number(aSize / 1024);
327 
328  OUString aReductionSizeAsString = OUString::number( m_aNativeSize > 0 ? (m_aNativeSize - aSize) * 100 / m_aNativeSize : 0 );
329 
330  OUString aNewSizeString = SvxResId(STR_IMAGE_CAPACITY_WITH_REDUCTION);
331  aNewSizeString = aNewSizeString.replaceAll("$(CAPACITY)", aSizeAsString);
332  aNewSizeString = aNewSizeString.replaceAll("$(REDUCTION)", aReductionSizeAsString);
333  m_xFixedText6->set_label(aNewSizeString);
334  }
335 }
336 
338 {
339  if ( m_xReduceResolutionCB->get_active() )
340  {
341  tools::Long nPixelX = static_cast<tools::Long>( GetViewWidthInch() * m_dResolution );
342  tools::Long nPixelY = static_cast<tools::Long>( GetViewHeightInch() * m_dResolution );
344  double aScaleX = nPixelX / static_cast<double>(aSize.Width());
345  double aScaleY = nPixelY / static_cast<double>(aSize.Height());
346 
347  return tools::Rectangle(
348  m_aCropRectangle.Left() * aScaleX,
349  m_aCropRectangle.Top() * aScaleY,
350  m_aCropRectangle.Right() * aScaleX,
351  m_aCropRectangle.Bottom()* aScaleY);
352  }
353  else
354  {
355  return m_aCropRectangle;
356  }
357 }
358 
360 {
361  if ( m_dResolution > 0.0 )
362  {
363  SvMemoryStream aMemStream;
365  Compress( aMemStream );
366  aMemStream.Seek( STREAM_SEEK_TO_BEGIN );
367  Graphic aResultGraphic;
369  rFilter.ImportGraphic( aResultGraphic, OUString("import"), aMemStream );
370 
371  return aResultGraphic;
372  }
373  return Graphic();
374 }
375 
377 {
378  if ( m_dResolution > 0.0 )
379  {
381 
382  if ( m_xReduceResolutionCB->get_active() )
383  {
384  tools::Rectangle aScaledCropedRectangle = GetScaledCropRectangle();
385  SdrGrafCropItem aNewCrop(
386  aScaledCropedRectangle.Left(),
387  aScaledCropedRectangle.Top(),
388  aScaledCropedRectangle.Right(),
389  aScaledCropedRectangle.Bottom());
390 
391  pNewObject->SetMergedItem(aNewCrop);
392  }
393  pNewObject->SetGraphic( GetCompressedGraphic() );
394 
395  return pNewObject;
396  }
397  return nullptr;
398 }
399 
400 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::unique_ptr< weld::Label > m_xFixedText5
FieldUnit
ErrCode ImportGraphic(Graphic &rGraphic, const INetURLObject &rPath, sal_uInt16 nFormat=GRFILTER_FORMAT_DONTKNOW, sal_uInt16 *pDeterminedFormat=nullptr, GraphicFilterImportFlags nImportFlags=GraphicFilterImportFlags::NONE)
std::unique_ptr< weld::Builder > m_xBuilder
Size GetSizePixel(const OutputDevice *pRefDevice=nullptr) const
bool Scale(const Size &rNewSize, BmpScaleFlag nScaleFlag=BmpScaleFlag::Default)
long Long
static const AllSettings & GetSettings()
std::unique_ptr< weld::SpinButton > m_xMFNewWidth
#define SOFFICE_FILEFORMAT_CURRENT
std::unique_ptr< weld::RadioButton > m_xLosslessRB
sal_uInt64 Seek(sal_uInt64 nPos)
virtual ~CompressGraphicsDialog() override
std::unique_ptr< weld::RadioButton > m_xJpegCompRB
virtual sal_uInt64 TellEnd() override
IMPL_LINK_NOARG(CompressGraphicsDialog, NewWidthModifiedHdl, weld::Entry &, void)
std::unique_ptr< weld::Scale > m_xQualitySlider
SfxModule * GetModule() const
sal_uInt16 sal_Unicode
tools::Long Left() const
std::unique_ptr< weld::SpinButton > m_xQualityMF
OUString SvxResId(const char *pId)
Definition: dialmgr.cxx:25
std::shared_ptr< GfxLink > GetSharedGfxLink() const
void SetGraphic(const Graphic &rGrf)
Definition: svdograf.cxx:310
tools::Long Bottom() const
std::unique_ptr< weld::Button > m_xBtnCalculate
std::unique_ptr< weld::ComboBox > m_xInterpolationCombo
void Compress(SvStream &aStream)
sal_uInt16 GetExportFormatNumberForShortName(std::u16string_view rShortName)
CompressGraphicsDialog(weld::Window *pParent, SdrGrafObj *pGraphicObj, SfxBindings &rBindings)
std::unique_ptr< weld::Label > m_xLabelGraphicType
const OUString & getNumDecimalSep() const
OUString GetUnitString(tools::Long nVal_100, FieldUnit eFieldUnit, sal_Unicode cSep)
Definition: dlgunit.hxx:27
FieldUnit GetFieldUnit() const
tools::Rectangle GetScaledCropRectangle() const
#define STREAM_SEEK_TO_BEGIN
tools::Long Width() const
SdrModel & getSdrModelFromSdrObject() const
Definition: svdobj.cxx:273
BmpScaleFlag
const LocaleDataWrapper & GetLocaleDataWrapper(LanguageType nLang)
void SetMergedItem(const SfxPoolItem &rItem)
Definition: svdobj.cxx:1912
BitmapEx GetBitmapEx(const GraphicConversionParameters &rParameters=GraphicConversionParameters()) const
const SfxPoolItem & GetMergedItem(const sal_uInt16 nWhich) const
Definition: svdobj.cxx:1937
void SetVersion(sal_Int32 n)
This class represents an embedded or linked bitmap graphic object.
Definition: svdograf.hxx:77
tools::Long Top() const
std::unique_ptr< weld::Label > m_xFixedText3
constexpr TypedWhichId< SdrGrafCropItem > SDRATTR_GRAFCROP(SDRATTR_GRAF_FIRST+9)
ErrCode ExportGraphic(const Graphic &rGraphic, const INetURLObject &rPath, sal_uInt16 nFormat, const css::uno::Sequence< css::beans::PropertyValue > *pFilterData=nullptr)
std::unique_ptr< weld::Label > m_xFixedText6
IMPL_LINK(CompressGraphicsDialog, SlideHdl, weld::Scale &, rScale, void)
std::unique_ptr< weld::CheckButton > m_xReduceResolutionCB
MapMode GetPrefMapMode() const
virtual SdrGrafObj * CloneSdrObject(SdrModel &rTargetModel) const override
Definition: svdograf.cxx:715
tools::Long Height() const
BmpScaleFlag GetSelectedInterpolationType() const
std::unique_ptr< weld::Scale > m_xCompressionSlider
sal_Int64 ConvertValue(sal_Int64 nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits, FieldUnit eInUnit, FieldUnit eOutUnit)
std::unique_ptr< weld::Label > m_xFixedText2
SfxDispatcher * GetDispatcher() const
static GraphicFilter & GetGraphicFilter()
std::unique_ptr< weld::SpinButton > m_xCompressionMF
const Size & GetSizePixel() const
std::unique_ptr< weld::ComboBox > m_xResolutionLB
tools::Long Right() const
std::unique_ptr< weld::SpinButton > m_xMFNewHeight