1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "dlgunit.hxx"
22 #include <vcl/fieldvalues.hxx>
23 #include <vcl/graph.hxx>
24 #include <vcl/graphicfilter.hxx>
25 #include <vcl/virdev.hxx>
26 #include <vcl/svapp.hxx>
27 #include <vcl/settings.hxx>
28 #include <vcl/weld.hxx>
29 #include <svx/strings.hrc>
30 #include <svx/svdograf.hxx>
31 #include <svx/sdgcpitm.hxx>
32 #include <svx/dialmgr.hxx>
33 #include <svx/graphichelper.hxx>
34 #include <svx/compressgraphicdialog.hxx>
35 #include <sfx2/dispatch.hxx>
36 #include <sfx2/module.hxx>
37 #include <comphelper/fileformat.h>
38 #include <comphelper/propertyvalue.hxx>
39 #include <com/sun/star/uno/Sequence.hxx>
40 #include <tools/stream.hxx>
41 #include <unotools/localedatawrapper.hxx>
43 // tdf#146929 - remember user settings within the current session
44 // memp is filled in dtor and restored after initialization
48 bool ReduceResolutionCB
= false;
51 bool LosslessRB
= true;
52 bool JpegCompRB
= false;
53 int CompressionMF
= 6;
55 int InterpolationCombo
= 3;
60 using namespace com::sun::star::uno
;
61 using namespace com::sun::star::beans
;
63 CompressGraphicsDialog::CompressGraphicsDialog( weld::Window
* pParent
, SdrGrafObj
* pGraphicObj
, SfxBindings
& rBindings
) :
64 GenericDialogController( pParent
, "svx/ui/compressgraphicdialog.ui", "CompressGraphicDialog" ),
65 m_xGraphicObj ( pGraphicObj
),
66 m_aGraphic ( pGraphicObj
->GetGraphicObject().GetGraphic() ),
67 m_aViewSize100mm ( pGraphicObj
->GetLogicRect().GetSize() ),
68 m_rBindings ( rBindings
),
71 const SdrGrafCropItem
& rCrop
= m_xGraphicObj
->GetMergedItem(SDRATTR_GRAFCROP
);
72 m_aCropRectangle
= tools::Rectangle(rCrop
.GetLeft(), rCrop
.GetTop(), rCrop
.GetRight(), rCrop
.GetBottom());
78 CompressGraphicsDialog::CompressGraphicsDialog( weld::Window
* pParent
, Graphic aGraphic
, Size rViewSize100mm
, tools::Rectangle
const & rCropRectangle
, SfxBindings
& rBindings
) :
79 GenericDialogController( pParent
, "svx/ui/compressgraphicdialog.ui", "CompressGraphicDialog" ),
80 m_xGraphicObj ( nullptr ),
81 m_aGraphic (std::move( aGraphic
)),
82 m_aViewSize100mm ( rViewSize100mm
),
83 m_aCropRectangle ( rCropRectangle
),
84 m_rBindings ( rBindings
),
91 CompressGraphicsDialog::~CompressGraphicsDialog()
95 void CompressGraphicsDialog::recallParameter()
97 m_xReduceResolutionCB
->set_active( memp
.ReduceResolutionCB
);
98 if (memp
.ReduceResolutionCB
&& (memp
.MFNewWidth
> 1))
99 m_xMFNewWidth
->set_value( memp
.MFNewWidth
);
100 if (memp
.ReduceResolutionCB
&& (memp
.MFNewHeight
> 1))
101 m_xMFNewHeight
->set_value( memp
.MFNewHeight
);
103 m_xLosslessRB
->set_active( memp
.LosslessRB
);
104 m_xJpegCompRB
->set_active( memp
.JpegCompRB
);
105 m_xCompressionMF
->set_value( memp
.CompressionMF
);
106 m_xCompressionSlider
->set_value( memp
.CompressionMF
);
107 m_xQualityMF
->set_value( memp
.QualityMF
);
108 m_xQualitySlider
->set_value( memp
.QualityMF
);
110 m_xInterpolationCombo
->set_active( memp
.InterpolationCombo
);
113 void CompressGraphicsDialog::Initialize()
115 m_xLabelGraphicType
= m_xBuilder
->weld_label("label-graphic-type");
116 m_xFixedText2
= m_xBuilder
->weld_label("label-original-size");
117 m_xFixedText3
= m_xBuilder
->weld_label("label-view-size");
118 m_xFixedText5
= m_xBuilder
->weld_label("label-image-capacity");
119 m_xFixedText6
= m_xBuilder
->weld_label("label-new-capacity");
120 m_xJpegCompRB
= m_xBuilder
->weld_radio_button("radio-jpeg");
121 m_xCompressionMF
= m_xBuilder
->weld_spin_button("spin-compression");
122 m_xCompressionSlider
= m_xBuilder
->weld_scale("scale-compression");
123 m_xLosslessRB
= m_xBuilder
->weld_radio_button("radio-lossless");
124 m_xQualityMF
= m_xBuilder
->weld_spin_button("spin-quality");
125 m_xQualitySlider
= m_xBuilder
->weld_scale("scale-quality");
126 m_xReduceResolutionCB
= m_xBuilder
->weld_check_button("checkbox-reduce-resolution");
127 m_xMFNewWidth
= m_xBuilder
->weld_spin_button("spin-new-width");
128 m_xMFNewHeight
= m_xBuilder
->weld_spin_button("spin-new-height");
129 m_xResolutionLB
= m_xBuilder
->weld_combo_box("combo-resolution");
130 m_xBtnCalculate
= m_xBuilder
->weld_button("calculate");
131 m_xInterpolationCombo
= m_xBuilder
->weld_combo_box("interpolation-method-combo");
132 m_xBtnOkay
= m_xBuilder
->weld_button("ok");
134 m_xInterpolationCombo
->set_active_text("Lanczos");
136 m_xInterpolationCombo
->connect_changed(LINK(this, CompressGraphicsDialog
, NewInterpolationModifiedHdl
));
138 m_xMFNewWidth
->connect_value_changed( LINK( this, CompressGraphicsDialog
, NewWidthModifiedHdl
));
139 m_xMFNewHeight
->connect_value_changed( LINK( this, CompressGraphicsDialog
, NewHeightModifiedHdl
));
141 m_xResolutionLB
->connect_changed( LINK( this, CompressGraphicsDialog
, ResolutionModifiedHdl
));
142 m_xBtnCalculate
->connect_clicked( LINK( this, CompressGraphicsDialog
, CalculateClickHdl
) );
144 m_xLosslessRB
->connect_toggled( LINK( this, CompressGraphicsDialog
, ToggleCompressionRB
) );
145 m_xJpegCompRB
->connect_toggled( LINK( this, CompressGraphicsDialog
, ToggleCompressionRB
) );
147 m_xReduceResolutionCB
->connect_toggled( LINK( this, CompressGraphicsDialog
, ToggleReduceResolutionRB
) );
149 m_xQualitySlider
->connect_value_changed( LINK( this, CompressGraphicsDialog
, SlideHdl
));
150 m_xCompressionSlider
->connect_value_changed( LINK( this, CompressGraphicsDialog
, SlideHdl
));
151 m_xQualityMF
->connect_value_changed( LINK( this, CompressGraphicsDialog
, NewQualityModifiedHdl
));
152 m_xCompressionMF
->connect_value_changed( LINK( this, CompressGraphicsDialog
, NewCompressionModifiedHdl
));
154 m_xJpegCompRB
->set_active(true);
155 m_xReduceResolutionCB
->set_active(true);
157 m_xBtnOkay
->connect_clicked( LINK( this, CompressGraphicsDialog
, OkayClickHdl
) );
160 UpdateResolutionLB();
164 void CompressGraphicsDialog::Update()
166 auto pGfxLink
= m_aGraphic
.GetSharedGfxLink();
168 m_xLabelGraphicType
->set_label(GraphicHelper::GetImageType(m_aGraphic
));
170 const FieldUnit eFieldUnit
= m_rBindings
.GetDispatcher()->GetModule()->GetFieldUnit();
171 const LocaleDataWrapper
& rLocaleWrapper( Application::GetSettings().GetLocaleDataWrapper() );
172 sal_Unicode cSeparator
= rLocaleWrapper
.getNumDecimalSep()[0];
174 ScopedVclPtrInstance
<VirtualDevice
> pDummyVDev
;
175 pDummyVDev
->EnableOutput( false );
176 pDummyVDev
->SetMapMode( m_aGraphic
.GetPrefMapMode() );
178 Size aPixelSize
= m_aGraphic
.GetSizePixel();
179 Size
aOriginalSize100mm(pDummyVDev
->PixelToLogic(m_aGraphic
.GetSizePixel(), MapMode(MapUnit::Map100thMM
)));
181 OUString aBitmapSizeString
= SvxResId(STR_IMAGE_ORIGINAL_SIZE
);
182 OUString aWidthString
= GetUnitString( aOriginalSize100mm
.Width(), eFieldUnit
, cSeparator
);
183 OUString aHeightString
= GetUnitString( aOriginalSize100mm
.Height(), eFieldUnit
, cSeparator
);
184 aBitmapSizeString
= aBitmapSizeString
.replaceAll("$(WIDTH)", aWidthString
);
185 aBitmapSizeString
= aBitmapSizeString
.replaceAll("$(HEIGHT)", aHeightString
);
186 aBitmapSizeString
= aBitmapSizeString
.replaceAll("$(WIDTH_IN_PX)", OUString::number(aPixelSize
.Width()));
187 aBitmapSizeString
= aBitmapSizeString
.replaceAll("$(HEIGHT_IN_PX)", OUString::number(aPixelSize
.Height()));
188 m_xFixedText2
->set_label(aBitmapSizeString
);
190 int aValX
= static_cast<int>(aPixelSize
.Width() / GetViewWidthInch());
192 OUString aViewSizeString
= SvxResId(STR_IMAGE_VIEW_SIZE
);
194 aWidthString
= GetUnitString( m_aViewSize100mm
.Width(), eFieldUnit
, cSeparator
);
195 aHeightString
= GetUnitString( m_aViewSize100mm
.Height(), eFieldUnit
, cSeparator
);
196 aViewSizeString
= aViewSizeString
.replaceAll("$(WIDTH)", aWidthString
);
197 aViewSizeString
= aViewSizeString
.replaceAll("$(HEIGHT)", aHeightString
);
198 aViewSizeString
= aViewSizeString
.replaceAll("$(DPI)", OUString::number(aValX
));
199 m_xFixedText3
->set_label(aViewSizeString
);
201 m_aNativeSize
= pGfxLink
? pGfxLink
->GetDataSize() : 0;
203 OUString aNativeSizeString
= SvxResId(STR_IMAGE_CAPACITY
);
204 aNativeSizeString
= aNativeSizeString
.replaceAll("$(CAPACITY)", OUString::number( m_aNativeSize
/ 1024 ));
205 m_xFixedText5
->set_label(aNativeSizeString
);
207 m_xFixedText6
->set_label("??");
210 void CompressGraphicsDialog::UpdateNewWidthMF()
212 int nPixelX
= static_cast<sal_Int32
>( GetViewWidthInch() * m_dResolution
);
213 m_xMFNewWidth
->set_value(nPixelX
);
216 void CompressGraphicsDialog::UpdateNewHeightMF()
218 int nPixelY
= static_cast<sal_Int32
>( GetViewHeightInch() * m_dResolution
);
219 m_xMFNewHeight
->set_value(nPixelY
);
222 void CompressGraphicsDialog::UpdateResolutionLB()
224 m_xResolutionLB
->set_entry_text( OUString::number( static_cast<sal_Int32
>(m_dResolution
) ) );
227 double CompressGraphicsDialog::GetViewWidthInch() const
229 return static_cast<double>(vcl::ConvertValue(m_aViewSize100mm
.Width(), 2, MapUnit::Map100thMM
, FieldUnit::INCH
)) / 100.0;
232 double CompressGraphicsDialog::GetViewHeightInch() const
234 return static_cast<double>(vcl::ConvertValue(m_aViewSize100mm
.Height(), 2, MapUnit::Map100thMM
, FieldUnit::INCH
)) / 100.0;
237 BmpScaleFlag
CompressGraphicsDialog::GetSelectedInterpolationType() const
239 OUString aSelectionText
= m_xInterpolationCombo
->get_active_text();
241 if( aSelectionText
== "Lanczos" ) {
242 return BmpScaleFlag::Lanczos
;
243 } else if( aSelectionText
== "Bilinear" ) {
244 return BmpScaleFlag::BiLinear
;
245 } else if( aSelectionText
== "Bicubic" ) {
246 return BmpScaleFlag::BiCubic
;
247 } else if ( aSelectionText
== "None" ) {
248 return BmpScaleFlag::Fast
;
250 return BmpScaleFlag::BestQuality
;
253 void CompressGraphicsDialog::Compress(SvStream
& aStream
)
255 BitmapEx aBitmap
= m_aGraphic
.GetBitmapEx();
256 if ( m_xReduceResolutionCB
->get_active() )
258 tools::Long nPixelX
= static_cast<tools::Long
>( GetViewWidthInch() * m_dResolution
);
259 tools::Long nPixelY
= static_cast<tools::Long
>( GetViewHeightInch() * m_dResolution
);
261 aBitmap
.Scale( Size( nPixelX
, nPixelY
), GetSelectedInterpolationType() );
263 Graphic
aScaledGraphic( aBitmap
);
264 GraphicFilter
& rFilter
= GraphicFilter::GetGraphicFilter();
266 Sequence
< PropertyValue
> aFilterData
{
267 comphelper::makePropertyValue("Interlaced", sal_Int32(0)),
268 comphelper::makePropertyValue("Compression", static_cast<sal_Int32
>(m_xCompressionMF
->get_value())),
269 comphelper::makePropertyValue("Quality", static_cast<sal_Int32
>(m_xQualityMF
->get_value()))
272 OUString aGraphicFormatName
= m_xLosslessRB
->get_active() ? OUString( "png" ) : OUString( "jpg" );
274 sal_uInt16 nFilterFormat
= rFilter
.GetExportFormatNumberForShortName( aGraphicFormatName
);
275 rFilter
.ExportGraphic( aScaledGraphic
, u
"none", aStream
, nFilterFormat
, &aFilterData
);
278 IMPL_LINK_NOARG( CompressGraphicsDialog
, OkayClickHdl
, weld::Button
&, void )
280 memp
.ReduceResolutionCB
= m_xReduceResolutionCB
->get_active();
281 memp
.MFNewWidth
= m_xMFNewWidth
->get_value();
282 memp
.MFNewHeight
= m_xMFNewHeight
->get_value();
283 memp
.LosslessRB
= m_xLosslessRB
->get_active();
284 memp
.JpegCompRB
= m_xJpegCompRB
->get_active();
285 memp
.CompressionMF
= m_xCompressionMF
->get_value();
286 memp
.QualityMF
= m_xQualityMF
->get_value();
287 memp
.InterpolationCombo
= m_xInterpolationCombo
->get_active();
288 CompressGraphicsDialog::response(RET_OK
);
291 IMPL_LINK_NOARG( CompressGraphicsDialog
, NewWidthModifiedHdl
, weld::SpinButton
&, void )
293 m_dResolution
= m_xMFNewWidth
->get_value() / GetViewWidthInch();
296 UpdateResolutionLB();
300 IMPL_LINK( CompressGraphicsDialog
, SlideHdl
, weld::Scale
&, rScale
, void )
302 if (&rScale
== m_xQualitySlider
.get())
303 m_xQualityMF
->set_value(m_xQualitySlider
->get_value());
305 m_xCompressionMF
->set_value(m_xCompressionSlider
->get_value());
309 IMPL_LINK_NOARG( CompressGraphicsDialog
, NewInterpolationModifiedHdl
, weld::ComboBox
&, void )
314 IMPL_LINK_NOARG( CompressGraphicsDialog
, NewQualityModifiedHdl
, weld::SpinButton
&, void )
316 m_xQualitySlider
->set_value(m_xQualityMF
->get_value());
320 IMPL_LINK_NOARG( CompressGraphicsDialog
, NewCompressionModifiedHdl
, weld::SpinButton
&, void )
322 m_xCompressionSlider
->set_value(m_xCompressionMF
->get_value());
326 IMPL_LINK_NOARG( CompressGraphicsDialog
, NewHeightModifiedHdl
, weld::SpinButton
&, void )
328 m_dResolution
= m_xMFNewHeight
->get_value() / GetViewHeightInch();
331 UpdateResolutionLB();
335 IMPL_LINK_NOARG( CompressGraphicsDialog
, ResolutionModifiedHdl
, weld::ComboBox
&, void )
337 m_dResolution
= static_cast<double>(m_xResolutionLB
->get_active_text().toInt32());
344 IMPL_LINK_NOARG( CompressGraphicsDialog
, ToggleCompressionRB
, weld::Toggleable
&, void )
346 bool choice
= m_xLosslessRB
->get_active();
347 m_xCompressionMF
->set_sensitive(choice
);
348 m_xCompressionSlider
->set_sensitive(choice
);
349 m_xQualityMF
->set_sensitive(!choice
);
350 m_xQualitySlider
->set_sensitive(!choice
);
354 IMPL_LINK_NOARG( CompressGraphicsDialog
, ToggleReduceResolutionRB
, weld::Toggleable
&, void )
356 bool choice
= m_xReduceResolutionCB
->get_active();
357 m_xMFNewWidth
->set_sensitive(choice
);
358 m_xMFNewHeight
->set_sensitive(choice
);
359 m_xResolutionLB
->set_sensitive(choice
);
360 m_xInterpolationCombo
->set_sensitive(choice
);
364 IMPL_LINK_NOARG( CompressGraphicsDialog
, CalculateClickHdl
, weld::Button
&, void )
368 if ( m_dResolution
> 0.0 )
370 SvMemoryStream aMemStream
;
371 aMemStream
.SetVersion( SOFFICE_FILEFORMAT_CURRENT
);
372 Compress( aMemStream
);
373 aSize
= aMemStream
.TellEnd();
378 OUString aSizeAsString
= OUString::number(aSize
/ 1024);
380 OUString aReductionSizeAsString
;
381 if (m_aNativeSize
> 0 )
382 aReductionSizeAsString
= OUString::number( static_cast<sal_Int32
>((m_aNativeSize
- aSize
) * 100.0 / m_aNativeSize
) );
384 aReductionSizeAsString
= "0";
386 OUString aNewSizeString
= SvxResId(STR_IMAGE_CAPACITY_WITH_REDUCTION
);
387 aNewSizeString
= aNewSizeString
.replaceAll("$(CAPACITY)", aSizeAsString
);
388 aNewSizeString
= aNewSizeString
.replaceAll("$(REDUCTION)", aReductionSizeAsString
);
389 m_xFixedText6
->set_label(aNewSizeString
);
393 tools::Rectangle
CompressGraphicsDialog::GetScaledCropRectangle() const
395 if ( m_xReduceResolutionCB
->get_active() )
397 tools::Long nPixelX
= static_cast<tools::Long
>( GetViewWidthInch() * m_dResolution
);
398 tools::Long nPixelY
= static_cast<tools::Long
>( GetViewHeightInch() * m_dResolution
);
399 Size aSize
= m_aGraphic
.GetBitmapEx().GetSizePixel();
400 double aScaleX
= nPixelX
/ static_cast<double>(aSize
.Width());
401 double aScaleY
= nPixelY
/ static_cast<double>(aSize
.Height());
403 return tools::Rectangle(
404 m_aCropRectangle
.Left() * aScaleX
,
405 m_aCropRectangle
.Top() * aScaleY
,
406 m_aCropRectangle
.Right() * aScaleX
,
407 m_aCropRectangle
.Bottom()* aScaleY
);
411 return m_aCropRectangle
;
415 Graphic
CompressGraphicsDialog::GetCompressedGraphic()
417 if ( m_dResolution
> 0.0 )
419 SvMemoryStream aMemStream
;
420 aMemStream
.SetVersion( SOFFICE_FILEFORMAT_CURRENT
);
421 Compress( aMemStream
);
422 aMemStream
.Seek( STREAM_SEEK_TO_BEGIN
);
423 Graphic aResultGraphic
;
424 GraphicFilter
& rFilter
= GraphicFilter::GetGraphicFilter();
425 rFilter
.ImportGraphic( aResultGraphic
, u
"import", aMemStream
);
427 return aResultGraphic
;
432 rtl::Reference
<SdrGrafObj
> CompressGraphicsDialog::GetCompressedSdrGrafObj()
434 if ( m_dResolution
> 0.0 )
436 rtl::Reference
<SdrGrafObj
> pNewObject
= SdrObject::Clone(*m_xGraphicObj
, m_xGraphicObj
->getSdrModelFromSdrObject());
438 if ( m_xReduceResolutionCB
->get_active() )
440 tools::Rectangle aScaledCropedRectangle
= GetScaledCropRectangle();
441 SdrGrafCropItem
aNewCrop(
442 aScaledCropedRectangle
.Left(),
443 aScaledCropedRectangle
.Top(),
444 aScaledCropedRectangle
.Right(),
445 aScaledCropedRectangle
.Bottom());
447 pNewObject
->SetMergedItem(aNewCrop
);
449 pNewObject
->SetGraphic( GetCompressedGraphic() );
456 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */