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/graph.hxx>
22 #include <vcl/graphicfilter.hxx>
23 #include <vcl/virdev.hxx>
24 #include <vcl/svapp.hxx>
25 #include <vcl/settings.hxx>
26 #include <vcl/weld.hxx>
27 #include <svx/strings.hrc>
28 #include <svx/svdograf.hxx>
29 #include <svx/sdgcpitm.hxx>
30 #include <svx/dialmgr.hxx>
32 #include <sfx2/dispatch.hxx>
33 #include <sfx2/module.hxx>
34 #include <comphelper/fileformat.h>
35 #include <com/sun/star/uno/Sequence.hxx>
36 #include <tools/stream.hxx>
38 
39 using namespace com::sun::star::uno;
40 using namespace com::sun::star::beans;
41 
43  GenericDialogController( pParent, "svx/ui/compressgraphicdialog.ui", "CompressGraphicDialog" ),
44  m_xGraphicObj ( pGraphicObj ),
45  m_aGraphic ( pGraphicObj->GetGraphicObject().GetGraphic() ),
46  m_aViewSize100mm ( pGraphicObj->GetLogicRect().GetSize() ),
47  m_rBindings ( rBindings ),
48  m_dResolution ( 300 )
49 {
51  m_aCropRectangle = tools::Rectangle(rCrop.GetLeft(), rCrop.GetTop(), rCrop.GetRight(), rCrop.GetBottom());
52 
53  Initialize();
54 }
55 
56 CompressGraphicsDialog::CompressGraphicsDialog( weld::Window* pParent, Graphic const & rGraphic, Size rViewSize100mm, tools::Rectangle const & rCropRectangle, SfxBindings& rBindings ) :
57  GenericDialogController( pParent, "svx/ui/compressgraphicdialog.ui", "CompressGraphicDialog" ),
58  m_xGraphicObj ( nullptr ),
59  m_aGraphic ( rGraphic ),
60  m_aViewSize100mm ( rViewSize100mm ),
61  m_aCropRectangle ( rCropRectangle ),
62  m_rBindings ( rBindings ),
63  m_dResolution ( 300 )
64 {
65  Initialize();
66 }
67 
69 {
70 }
71 
73 {
74  m_xLabelGraphicType = m_xBuilder->weld_label("label-graphic-type");
75  m_xFixedText2 = m_xBuilder->weld_label("label-original-size");
76  m_xFixedText3 = m_xBuilder->weld_label("label-view-size");
77  m_xFixedText5 = m_xBuilder->weld_label("label-image-capacity");
78  m_xFixedText6 = m_xBuilder->weld_label("label-new-capacity");
79  m_xJpegCompRB = m_xBuilder->weld_radio_button("radio-jpeg");
80  m_xCompressionMF = m_xBuilder->weld_spin_button("spin-compression");
81  m_xCompressionSlider = m_xBuilder->weld_scale("scale-compression");
82  m_xLosslessRB = m_xBuilder->weld_radio_button("radio-lossless");
83  m_xQualityMF = m_xBuilder->weld_spin_button("spin-quality");
84  m_xQualitySlider = m_xBuilder->weld_scale("scale-quality");
85  m_xReduceResolutionCB = m_xBuilder->weld_check_button("checkbox-reduce-resolution");
86  m_xMFNewWidth = m_xBuilder->weld_spin_button("spin-new-width");
87  m_xMFNewHeight = m_xBuilder->weld_spin_button("spin-new-height");
88  m_xResolutionLB = m_xBuilder->weld_combo_box("combo-resolution");
89  m_xBtnCalculate = m_xBuilder->weld_button("calculate");
90  m_xInterpolationCombo = m_xBuilder->weld_combo_box("interpolation-method-combo");
91 
92  m_xInterpolationCombo->set_active_text("Lanczos");
93 
94  m_xInterpolationCombo->connect_changed(LINK(this, CompressGraphicsDialog, NewInterpolationModifiedHdl));
95 
96  m_xMFNewWidth->connect_changed( LINK( this, CompressGraphicsDialog, NewWidthModifiedHdl ));
97  m_xMFNewHeight->connect_changed( LINK( this, CompressGraphicsDialog, NewHeightModifiedHdl ));
98 
99  m_xResolutionLB->connect_changed( LINK( this, CompressGraphicsDialog, ResolutionModifiedHdl ));
100  m_xBtnCalculate->connect_clicked( LINK( this, CompressGraphicsDialog, CalculateClickHdl ) );
101 
102  m_xLosslessRB->connect_toggled( LINK( this, CompressGraphicsDialog, ToggleCompressionRB ) );
103  m_xJpegCompRB->connect_toggled( LINK( this, CompressGraphicsDialog, ToggleCompressionRB ) );
104 
105  m_xReduceResolutionCB->connect_toggled( LINK( this, CompressGraphicsDialog, ToggleReduceResolutionRB ) );
106 
107  m_xQualitySlider->connect_value_changed( LINK( this, CompressGraphicsDialog, SlideHdl ));
108  m_xCompressionSlider->connect_value_changed( LINK( this, CompressGraphicsDialog, SlideHdl ));
109  m_xQualityMF->connect_changed( LINK( this, CompressGraphicsDialog, NewQualityModifiedHdl ));
110  m_xCompressionMF->connect_changed( LINK( this, CompressGraphicsDialog, NewCompressionModifiedHdl ));
111 
112  m_xJpegCompRB->set_active(true);
113  m_xReduceResolutionCB->set_active(true);
114 
118  Update();
119 }
120 
122 {
123  GfxLinkType aLinkType = m_aGraphic.GetGfxLink().GetType();
124  OUString aGraphicTypeString;
125  switch(aLinkType)
126  {
127  case GfxLinkType::NativeGif:
128  aGraphicTypeString = SvxResId(STR_IMAGE_GIF);
129  break;
130  case GfxLinkType::NativeJpg:
131  aGraphicTypeString = SvxResId(STR_IMAGE_JPEG);
132  break;
133  case GfxLinkType::NativePng:
134  aGraphicTypeString = SvxResId(STR_IMAGE_PNG);
135  break;
136  case GfxLinkType::NativeTif:
137  aGraphicTypeString = SvxResId(STR_IMAGE_TIFF);
138  break;
139  case GfxLinkType::NativeWmf:
140  aGraphicTypeString = SvxResId(STR_IMAGE_WMF);
141  break;
142  case GfxLinkType::NativeMet:
143  aGraphicTypeString = SvxResId(STR_IMAGE_MET);
144  break;
145  case GfxLinkType::NativePct:
146  aGraphicTypeString = SvxResId(STR_IMAGE_PCT);
147  break;
148  case GfxLinkType::NativeSvg:
149  aGraphicTypeString = SvxResId(STR_IMAGE_SVG);
150  break;
151  case GfxLinkType::NativeBmp:
152  aGraphicTypeString = SvxResId(STR_IMAGE_BMP);
153  break;
154  default:
155  aGraphicTypeString = SvxResId(STR_IMAGE_UNKNOWN);
156  break;
157  }
158  m_xLabelGraphicType->set_label(aGraphicTypeString);
159 
160  const FieldUnit eFieldUnit = m_rBindings.GetDispatcher()->GetModule()->GetFieldUnit();
162  sal_Unicode cSeparator = rLocaleWrapper.getNumDecimalSep()[0];
163 
165  pDummyVDev->EnableOutput( false );
166  pDummyVDev->SetMapMode( m_aGraphic.GetPrefMapMode() );
167 
168  Size aPixelSize = m_aGraphic.GetSizePixel();
169  Size aOriginalSize100mm(pDummyVDev->PixelToLogic(m_aGraphic.GetSizePixel(), MapMode(MapUnit::Map100thMM)));
170 
171  OUString aBitmapSizeString = SvxResId(STR_IMAGE_ORIGINAL_SIZE);
172  OUString aWidthString = GetUnitString( aOriginalSize100mm.Width(), eFieldUnit, cSeparator );
173  OUString aHeightString = GetUnitString( aOriginalSize100mm.Height(), eFieldUnit, cSeparator );
174  aBitmapSizeString = aBitmapSizeString.replaceAll("$(WIDTH)", aWidthString);
175  aBitmapSizeString = aBitmapSizeString.replaceAll("$(HEIGHT)", aHeightString);
176  aBitmapSizeString = aBitmapSizeString.replaceAll("$(WIDTH_IN_PX)", OUString::number(aPixelSize.Width()));
177  aBitmapSizeString = aBitmapSizeString.replaceAll("$(HEIGHT_IN_PX)", OUString::number(aPixelSize.Height()));
178  m_xFixedText2->set_label(aBitmapSizeString);
179 
180  int aValX = static_cast<int>(aPixelSize.Width() / GetViewWidthInch());
181 
182  OUString aViewSizeString = SvxResId(STR_IMAGE_VIEW_SIZE);
183 
184  aWidthString = GetUnitString( m_aViewSize100mm.Width(), eFieldUnit, cSeparator );
185  aHeightString = GetUnitString( m_aViewSize100mm.Height(), eFieldUnit, cSeparator );
186  aViewSizeString = aViewSizeString.replaceAll("$(WIDTH)", aWidthString);
187  aViewSizeString = aViewSizeString.replaceAll("$(HEIGHT)", aHeightString);
188  aViewSizeString = aViewSizeString.replaceAll("$(DPI)", OUString::number(aValX));
189  m_xFixedText3->set_label(aViewSizeString);
190 
191  SvMemoryStream aMemStream;
193  m_aGraphic.ExportNative(aMemStream);
194  sal_Int32 aNativeSize = aMemStream.TellEnd();
195 
196  OUString aNativeSizeString = SvxResId(STR_IMAGE_CAPACITY);
197  aNativeSizeString = aNativeSizeString.replaceAll("$(CAPACITY)", OUString::number(aNativeSize / 1024));
198  m_xFixedText5->set_label(aNativeSizeString);
199 
200  m_xFixedText6->set_label("??");
201 }
202 
204 {
205  int nPixelX = static_cast<sal_Int32>( GetViewWidthInch() * m_dResolution );
206  m_xMFNewWidth->set_value(nPixelX);
207 }
208 
210 {
211  int nPixelY = static_cast<sal_Int32>( GetViewHeightInch() * m_dResolution );
212  m_xMFNewHeight->set_value(nPixelY);
213 }
214 
216 {
217  m_xResolutionLB->set_entry_text( OUString::number( static_cast<sal_Int32>(m_dResolution) ) );
218 }
219 
221 {
222  return static_cast<double>(MetricField::ConvertValue(m_aViewSize100mm.Width(), 2, MapUnit::Map100thMM, FieldUnit::INCH)) / 100.0;
223 }
224 
226 {
227  return static_cast<double>(MetricField::ConvertValue(m_aViewSize100mm.Height(), 2, MapUnit::Map100thMM, FieldUnit::INCH)) / 100.0;
228 }
229 
231 {
232  OUString aSelectionText = m_xInterpolationCombo->get_active_text();
233 
234  if( aSelectionText == "Lanczos" ) {
235  return BmpScaleFlag::Lanczos;
236  } else if( aSelectionText == "Bilinear" ) {
237  return BmpScaleFlag::BiLinear;
238  } else if( aSelectionText == "Bicubic" ) {
239  return BmpScaleFlag::BiCubic;
240  } else if ( aSelectionText == "None" ) {
241  return BmpScaleFlag::Fast;
242  }
243  return BmpScaleFlag::BestQuality;
244 }
245 
247 {
248  BitmapEx aBitmap = m_aGraphic.GetBitmapEx();
249  if ( m_xReduceResolutionCB->get_active() )
250  {
251  long nPixelX = static_cast<long>( GetViewWidthInch() * m_dResolution );
252  long nPixelY = static_cast<long>( GetViewHeightInch() * m_dResolution );
253 
254  aBitmap.Scale( Size( nPixelX, nPixelY ), GetSelectedInterpolationType() );
255  }
256  Graphic aScaledGraphic( aBitmap );
258 
259  Sequence< PropertyValue > aFilterData( 3 );
260  aFilterData[ 0 ].Name = "Interlaced";
261  aFilterData[ 0 ].Value <<= sal_Int32(0);
262  aFilterData[ 1 ].Name = "Compression";
263  aFilterData[ 1 ].Value <<= static_cast<sal_Int32>(m_xCompressionMF->get_value());
264  aFilterData[ 2 ].Name = "Quality";
265  aFilterData[ 2 ].Value <<= static_cast<sal_Int32>(m_xQualityMF->get_value());
266 
267  OUString aGraphicFormatName = m_xLosslessRB->get_active() ? OUString( "png" ) : OUString( "jpg" );
268 
269  sal_uInt16 nFilterFormat = rFilter.GetExportFormatNumberForShortName( aGraphicFormatName );
270  rFilter.ExportGraphic( aScaledGraphic, "none", aStream, nFilterFormat, &aFilterData );
271 }
272 
273 IMPL_LINK_NOARG( CompressGraphicsDialog, NewWidthModifiedHdl, weld::Entry&, void )
274 {
275  m_dResolution = m_xMFNewWidth->get_value() / GetViewWidthInch();
276 
277  UpdateNewHeightMF();
278  UpdateResolutionLB();
279  Update();
280 }
281 
282 IMPL_LINK( CompressGraphicsDialog, SlideHdl, weld::Scale&, rScale, void )
283 {
284  if (&rScale == m_xQualitySlider.get())
285  m_xQualityMF->set_value(m_xQualitySlider->get_value());
286  else
287  m_xCompressionMF->set_value(m_xCompressionSlider->get_value());
288  Update();
289 }
290 
291 IMPL_LINK_NOARG( CompressGraphicsDialog, NewInterpolationModifiedHdl, weld::ComboBox&, void )
292 {
293  Update();
294 }
295 
296 IMPL_LINK_NOARG( CompressGraphicsDialog, NewQualityModifiedHdl, weld::Entry&, void )
297 {
298  m_xQualitySlider->set_value(m_xQualityMF->get_value());
299  Update();
300 }
301 
302 IMPL_LINK_NOARG( CompressGraphicsDialog, NewCompressionModifiedHdl, weld::Entry&, void )
303 {
304  m_xCompressionSlider->set_value(m_xCompressionMF->get_value());
305  Update();
306 }
307 
308 IMPL_LINK_NOARG( CompressGraphicsDialog, NewHeightModifiedHdl, weld::Entry&, void )
309 {
310  m_dResolution = m_xMFNewHeight->get_value() / GetViewHeightInch();
311 
312  UpdateNewWidthMF();
313  UpdateResolutionLB();
314  Update();
315 }
316 
317 IMPL_LINK_NOARG( CompressGraphicsDialog, ResolutionModifiedHdl, weld::ComboBox&, void )
318 {
319  m_dResolution = static_cast<double>(m_xResolutionLB->get_active_text().toInt32());
320 
321  UpdateNewWidthMF();
322  UpdateNewHeightMF();
323  Update();
324 }
325 
327 {
328  bool choice = m_xLosslessRB->get_active();
329  m_xCompressionMF->set_sensitive(choice);
330  m_xCompressionSlider->set_sensitive(choice);
331  m_xQualityMF->set_sensitive(!choice);
332  m_xQualitySlider->set_sensitive(!choice);
333  Update();
334 }
335 
336 IMPL_LINK_NOARG( CompressGraphicsDialog, ToggleReduceResolutionRB, weld::ToggleButton&, void )
337 {
338  bool choice = m_xReduceResolutionCB->get_active();
339  m_xMFNewWidth->set_sensitive(choice);
340  m_xMFNewHeight->set_sensitive(choice);
341  m_xResolutionLB->set_sensitive(choice);
342  m_xInterpolationCombo->set_sensitive(choice);
343  Update();
344 }
345 
347 {
348  sal_Int32 aSize = 0;
349 
350  if ( m_dResolution > 0.0 )
351  {
352  SvMemoryStream aMemStream;
354  Compress( aMemStream );
355  aSize = aMemStream.TellEnd();
356  }
357 
358  if ( aSize > 0 )
359  {
360  OUString aSizeAsString = OUString::number(aSize / 1024);
361 
362  OUString aNewSizeString = SvxResId(STR_IMAGE_CAPACITY);
363  aNewSizeString = aNewSizeString.replaceAll("$(CAPACITY)", aSizeAsString);
364  m_xFixedText6->set_label(aNewSizeString);
365  }
366 }
367 
369 {
370  if ( m_xReduceResolutionCB->get_active() )
371  {
372  long nPixelX = static_cast<long>( GetViewWidthInch() * m_dResolution );
373  long nPixelY = static_cast<long>( GetViewHeightInch() * m_dResolution );
375  double aScaleX = nPixelX / static_cast<double>(aSize.Width());
376  double aScaleY = nPixelY / static_cast<double>(aSize.Height());
377 
378  return tools::Rectangle(
379  m_aCropRectangle.Left() * aScaleX,
380  m_aCropRectangle.Top() * aScaleY,
381  m_aCropRectangle.Right() * aScaleX,
382  m_aCropRectangle.Bottom()* aScaleY);
383  }
384  else
385  {
386  return m_aCropRectangle;
387  }
388 }
389 
391 {
392  if ( m_dResolution > 0.0 )
393  {
394  SvMemoryStream aMemStream;
396  Compress( aMemStream );
397  aMemStream.Seek( STREAM_SEEK_TO_BEGIN );
398  Graphic aResultGraphic;
400  rFilter.ImportGraphic( aResultGraphic, OUString("import"), aMemStream );
401 
402  return aResultGraphic;
403  }
404  return Graphic();
405 }
406 
408 {
409  if ( m_dResolution > 0.0 )
410  {
412 
413  if ( m_xReduceResolutionCB->get_active() )
414  {
415  tools::Rectangle aScaledCropedRectangle = GetScaledCropRectangle();
416  SdrGrafCropItem aNewCrop(
417  aScaledCropedRectangle.Left(),
418  aScaledCropedRectangle.Top(),
419  aScaledCropedRectangle.Right(),
420  aScaledCropedRectangle.Bottom());
421 
422  pNewObject->SetMergedItem(aNewCrop);
423  }
424  pNewObject->SetGraphic( GetCompressedGraphic() );
425 
426  return pNewObject;
427  }
428  return nullptr;
429 }
430 
431 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
long Width() const
OUString GetUnitString(long nVal_100, FieldUnit eFieldUnit, sal_Unicode cSep)
Definition: dlgunit.hxx:26
std::unique_ptr< weld::Label > m_xFixedText5
FieldUnit
sal_Int32 GetLeft() const
Definition: grfcrop.hxx:61
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
long Height() const
bool ExportNative(SvStream &rOStream) const
bool Scale(const Size &rNewSize, BmpScaleFlag nScaleFlag=BmpScaleFlag::Default)
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
long Right() const
std::unique_ptr< weld::SpinButton > m_xQualityMF
OUString SvxResId(const char *pId)
Definition: dialmgr.cxx:28
void SetGraphic(const Graphic &rGrf)
Definition: svdograf.cxx:322
std::unique_ptr< weld::Button > m_xBtnCalculate
sal_uInt16 GetExportFormatNumberForShortName(const OUString &rShortName)
std::unique_ptr< weld::ComboBox > m_xInterpolationCombo
void Compress(SvStream &aStream)
long Top() const
CompressGraphicsDialog(weld::Window *pParent, SdrGrafObj *pGraphicObj, SfxBindings &rBindings)
std::unique_ptr< weld::Label > m_xLabelGraphicType
const OUString & getNumDecimalSep() const
FieldUnit GetFieldUnit() const
tools::Rectangle GetScaledCropRectangle() const
#define STREAM_SEEK_TO_BEGIN
#define SDRATTR_GRAFCROP
Definition: svddef.hxx:317
long Bottom() const
SdrModel & getSdrModelFromSdrObject() const
Definition: svdobj.cxx:297
BmpScaleFlag
const LocaleDataWrapper & GetLocaleDataWrapper(LanguageType nLang)
void SetMergedItem(const SfxPoolItem &rItem)
Definition: svdobj.cxx:1918
BitmapEx GetBitmapEx(const GraphicConversionParameters &rParameters=GraphicConversionParameters()) const
const SfxPoolItem & GetMergedItem(const sal_uInt16 nWhich) const
Definition: svdobj.cxx:1943
void SetVersion(sal_Int32 n)
This class represents an embedded or linked bitmap graphic object.
Definition: svdograf.hxx:79
GfxLink GetGfxLink() const
std::unique_ptr< weld::Label > m_xFixedText3
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
sal_Int32 GetBottom() const
Definition: grfcrop.hxx:64
IMPL_LINK(CompressGraphicsDialog, SlideHdl, weld::Scale &, rScale, void)
sal_Int32 GetTop() const
Definition: grfcrop.hxx:63
std::unique_ptr< weld::CheckButton > m_xReduceResolutionCB
MapMode GetPrefMapMode() const
static sal_Int64 ConvertValue(sal_Int64 nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits, FieldUnit eInUnit, FieldUnit eOutUnit)
virtual SdrGrafObj * CloneSdrObject(SdrModel &rTargetModel) const override
Definition: svdograf.cxx:719
BmpScaleFlag GetSelectedInterpolationType() const
std::unique_ptr< weld::Scale > m_xCompressionSlider
long Left() const
sal_Int32 GetRight() const
Definition: grfcrop.hxx:62
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
std::unique_ptr< weld::SpinButton > m_xMFNewHeight