/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include "dlgunit.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // tdf#146929 - remember user settings within the current session // memp is filled in dtor and restored after initialization namespace { struct memParam { bool ReduceResolutionCB = true; int MFNewWidth = 1; int MFNewHeight = 1; bool LosslessRB = true; bool JpegCompRB = false; int CompressionMF = 6; int QualityMF = 80; int InterpolationCombo = 3; }; memParam memp; } using namespace com::sun::star::uno; using namespace com::sun::star::beans; CompressGraphicsDialog::CompressGraphicsDialog( weld::Window* pParent, SdrGrafObj* pGraphicObj, SfxBindings& rBindings ) : GenericDialogController( pParent, u"svx/ui/compressgraphicdialog.ui"_ustr, u"CompressGraphicDialog"_ustr ), m_xGraphicObj ( pGraphicObj ), m_aGraphic ( pGraphicObj->GetGraphicObject().GetGraphic() ), m_aViewSize100mm ( pGraphicObj->GetLogicRect().GetSize() ), m_rBindings ( rBindings ), m_dResolution ( 300 ) { const SdrGrafCropItem& rCrop = m_xGraphicObj->GetMergedItem(SDRATTR_GRAFCROP); m_aCropRectangle = tools::Rectangle(rCrop.GetLeft(), rCrop.GetTop(), rCrop.GetRight(), rCrop.GetBottom()); Initialize(); recallParameter(); } CompressGraphicsDialog::CompressGraphicsDialog( weld::Window* pParent, Graphic aGraphic, Size rViewSize100mm, tools::Rectangle const & rCropRectangle, SfxBindings& rBindings ) : GenericDialogController( pParent, u"svx/ui/compressgraphicdialog.ui"_ustr, u"CompressGraphicDialog"_ustr ), m_xGraphicObj ( nullptr ), m_aGraphic (std::move( aGraphic )), m_aViewSize100mm ( rViewSize100mm ), m_aCropRectangle ( rCropRectangle ), m_rBindings ( rBindings ), m_dResolution ( 300 ) { Initialize(); recallParameter(); } CompressGraphicsDialog::~CompressGraphicsDialog() { } void CompressGraphicsDialog::recallParameter() { m_xReduceResolutionCB->set_active( memp.ReduceResolutionCB ); if (memp.ReduceResolutionCB && (memp.MFNewWidth > 1)) m_xMFNewWidth->set_value( memp.MFNewWidth ); if (memp.ReduceResolutionCB && (memp.MFNewHeight > 1)) m_xMFNewHeight->set_value( memp.MFNewHeight ); m_xLosslessRB->set_active( memp.LosslessRB ); m_xJpegCompRB->set_active( memp.JpegCompRB ); m_xCompressionMF->set_value( memp.CompressionMF ); m_xCompressionSlider->set_value( memp.CompressionMF ); m_xQualityMF->set_value( memp.QualityMF ); m_xQualitySlider->set_value( memp.QualityMF ); m_xInterpolationCombo->set_active( memp.InterpolationCombo ); UpdateSensitivity(m_xReduceResolutionCB->get_active()); } void CompressGraphicsDialog::Initialize() { m_xLabelGraphicType = m_xBuilder->weld_label(u"label-graphic-type"_ustr); m_xFixedText2 = m_xBuilder->weld_label(u"label-original-size"_ustr); m_xFixedText3 = m_xBuilder->weld_label(u"label-view-size"_ustr); m_xFixedText5 = m_xBuilder->weld_label(u"label-image-capacity"_ustr); m_xFixedText6 = m_xBuilder->weld_label(u"label-new-capacity"_ustr); m_xJpegCompRB = m_xBuilder->weld_radio_button(u"radio-jpeg"_ustr); m_xCompressionMF = m_xBuilder->weld_spin_button(u"spin-compression"_ustr); m_xCompressionSlider = m_xBuilder->weld_scale(u"scale-compression"_ustr); m_xLosslessRB = m_xBuilder->weld_radio_button(u"radio-lossless"_ustr); m_xQualityMF = m_xBuilder->weld_spin_button(u"spin-quality"_ustr); m_xQualitySlider = m_xBuilder->weld_scale(u"scale-quality"_ustr); m_xReduceResolutionCB = m_xBuilder->weld_check_button(u"checkbox-change-resolution"_ustr); m_xMFNewWidth = m_xBuilder->weld_spin_button(u"spin-new-width"_ustr); m_xMFNewHeight = m_xBuilder->weld_spin_button(u"spin-new-height"_ustr); m_xResolutionLB = m_xBuilder->weld_combo_box(u"combo-resolution"_ustr); m_xBtnCalculate = m_xBuilder->weld_button(u"calculate"_ustr); m_xInterpolationCombo = m_xBuilder->weld_combo_box(u"interpolation-method-combo"_ustr); m_xBtnOkay = m_xBuilder->weld_button(u"ok"_ustr); m_xInterpolationCombo->set_active_text(u"Lanczos"_ustr); m_xInterpolationCombo->connect_changed(LINK(this, CompressGraphicsDialog, NewInterpolationModifiedHdl)); m_xMFNewWidth->connect_value_changed( LINK( this, CompressGraphicsDialog, NewWidthModifiedHdl )); m_xMFNewHeight->connect_value_changed( LINK( this, CompressGraphicsDialog, NewHeightModifiedHdl )); m_xResolutionLB->connect_changed( LINK( this, CompressGraphicsDialog, ResolutionModifiedHdl )); m_xBtnCalculate->connect_clicked( LINK( this, CompressGraphicsDialog, CalculateClickHdl ) ); m_xLosslessRB->connect_toggled( LINK( this, CompressGraphicsDialog, ToggleCompressionRB ) ); m_xJpegCompRB->connect_toggled( LINK( this, CompressGraphicsDialog, ToggleCompressionRB ) ); m_xReduceResolutionCB->connect_toggled( LINK( this, CompressGraphicsDialog, ToggleReduceResolutionRB ) ); m_xQualitySlider->connect_value_changed( LINK( this, CompressGraphicsDialog, SlideHdl )); m_xCompressionSlider->connect_value_changed( LINK( this, CompressGraphicsDialog, SlideHdl )); m_xQualityMF->connect_value_changed( LINK( this, CompressGraphicsDialog, NewQualityModifiedHdl )); m_xCompressionMF->connect_value_changed( LINK( this, CompressGraphicsDialog, NewCompressionModifiedHdl )); m_xJpegCompRB->set_active(true); m_xReduceResolutionCB->set_active(true); m_xBtnOkay->connect_clicked( LINK( this, CompressGraphicsDialog, OkayClickHdl ) ); UpdateNewWidthMF(); UpdateNewHeightMF(); UpdateResolutionLB(); Update(); } void CompressGraphicsDialog::Update() { auto pGfxLink = m_aGraphic.GetSharedGfxLink(); m_xLabelGraphicType->set_label(GraphicHelper::GetImageType(m_aGraphic)); const FieldUnit eFieldUnit = m_rBindings.GetDispatcher()->GetModule()->GetFieldUnit(); const LocaleDataWrapper& rLocaleWrapper( Application::GetSettings().GetLocaleDataWrapper() ); sal_Unicode cSeparator = rLocaleWrapper.getNumDecimalSep()[0]; ScopedVclPtrInstance pDummyVDev; pDummyVDev->EnableOutput( false ); pDummyVDev->SetMapMode( m_aGraphic.GetPrefMapMode() ); Size aPixelSize = m_aGraphic.GetSizePixel(); Size aOriginalSize100mm(pDummyVDev->PixelToLogic(m_aGraphic.GetSizePixel(), MapMode(MapUnit::Map100thMM))); OUString aBitmapSizeString = SvxResId(STR_IMAGE_ORIGINAL_SIZE); OUString aWidthString = GetUnitString( aOriginalSize100mm.Width(), eFieldUnit, cSeparator ); OUString aHeightString = GetUnitString( aOriginalSize100mm.Height(), eFieldUnit, cSeparator ); aBitmapSizeString = aBitmapSizeString.replaceAll("$(WIDTH)", aWidthString); aBitmapSizeString = aBitmapSizeString.replaceAll("$(HEIGHT)", aHeightString); aBitmapSizeString = aBitmapSizeString.replaceAll("$(WIDTH_IN_PX)", OUString::number(aPixelSize.Width())); aBitmapSizeString = aBitmapSizeString.replaceAll("$(HEIGHT_IN_PX)", OUString::number(aPixelSize.Height())); m_xFixedText2->set_label(aBitmapSizeString); int aValX = static_cast(aPixelSize.Width() / GetViewWidthInch()); OUString aViewSizeString = SvxResId(STR_IMAGE_VIEW_SIZE); aWidthString = GetUnitString( m_aViewSize100mm.Width(), eFieldUnit, cSeparator ); aHeightString = GetUnitString( m_aViewSize100mm.Height(), eFieldUnit, cSeparator ); aViewSizeString = aViewSizeString.replaceAll("$(WIDTH)", aWidthString); aViewSizeString = aViewSizeString.replaceAll("$(HEIGHT)", aHeightString); aViewSizeString = aViewSizeString.replaceAll("$(DPI)", OUString::number(aValX)); m_xFixedText3->set_label(aViewSizeString); m_aNativeSize = pGfxLink ? pGfxLink->GetDataSize() : 0; OUString aNativeSizeString = SvxResId(STR_IMAGE_CAPACITY); aNativeSizeString = aNativeSizeString.replaceAll("$(CAPACITY)", OUString::number( m_aNativeSize / 1024 )); m_xFixedText5->set_label(aNativeSizeString); m_xFixedText6->set_label(u"??"_ustr); } void CompressGraphicsDialog::UpdateSensitivity(const bool bSensitive) { m_xMFNewWidth->set_sensitive(bSensitive); m_xMFNewHeight->set_sensitive(bSensitive); m_xResolutionLB->set_sensitive(bSensitive); m_xInterpolationCombo->set_sensitive(bSensitive); } void CompressGraphicsDialog::UpdateNewWidthMF() { int nPixelX = static_cast( GetViewWidthInch() * m_dResolution ); m_xMFNewWidth->set_value(nPixelX); } void CompressGraphicsDialog::UpdateNewHeightMF() { int nPixelY = static_cast( GetViewHeightInch() * m_dResolution ); m_xMFNewHeight->set_value(nPixelY); } void CompressGraphicsDialog::UpdateResolutionLB() { m_xResolutionLB->set_entry_text( OUString::number( static_cast(m_dResolution) ) ); } double CompressGraphicsDialog::GetViewWidthInch() const { return static_cast(vcl::ConvertValue(m_aViewSize100mm.Width(), 2, MapUnit::Map100thMM, FieldUnit::INCH)) / 100.0; } double CompressGraphicsDialog::GetViewHeightInch() const { return static_cast(vcl::ConvertValue(m_aViewSize100mm.Height(), 2, MapUnit::Map100thMM, FieldUnit::INCH)) / 100.0; } BmpScaleFlag CompressGraphicsDialog::GetSelectedInterpolationType() const { OUString aSelectionText = m_xInterpolationCombo->get_active_text(); if( aSelectionText == "Lanczos" ) { return BmpScaleFlag::Lanczos; } else if( aSelectionText == "Bilinear" ) { return BmpScaleFlag::BiLinear; } else if( aSelectionText == "Bicubic" ) { return BmpScaleFlag::BiCubic; } else if ( aSelectionText == "None" ) { return BmpScaleFlag::Fast; } return BmpScaleFlag::BestQuality; } void CompressGraphicsDialog::Compress(SvStream& aStream) { BitmapEx aBitmap = m_aGraphic.GetBitmapEx(); if ( m_xReduceResolutionCB->get_active() ) { tools::Long nPixelX = static_cast( GetViewWidthInch() * m_dResolution ); tools::Long nPixelY = static_cast( GetViewHeightInch() * m_dResolution ); aBitmap.Scale( Size( nPixelX, nPixelY ), GetSelectedInterpolationType() ); } Graphic aScaledGraphic( aBitmap ); GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter(); Sequence< PropertyValue > aFilterData{ comphelper::makePropertyValue(u"Interlaced"_ustr, sal_Int32(0)), comphelper::makePropertyValue(u"Compression"_ustr, static_cast(m_xCompressionMF->get_value())), comphelper::makePropertyValue(u"Quality"_ustr, static_cast(m_xQualityMF->get_value())) }; OUString aGraphicFormatName = m_xLosslessRB->get_active() ? u"png"_ustr : u"jpg"_ustr; sal_uInt16 nFilterFormat = rFilter.GetExportFormatNumberForShortName( aGraphicFormatName ); rFilter.ExportGraphic( aScaledGraphic, u"none", aStream, nFilterFormat, &aFilterData ); } IMPL_LINK_NOARG( CompressGraphicsDialog, OkayClickHdl, weld::Button&, void ) { memp.ReduceResolutionCB = m_xReduceResolutionCB->get_active(); memp.MFNewWidth = m_xMFNewWidth->get_value(); memp.MFNewHeight = m_xMFNewHeight->get_value(); memp.LosslessRB = m_xLosslessRB->get_active(); memp.JpegCompRB = m_xJpegCompRB->get_active(); memp.CompressionMF = m_xCompressionMF->get_value(); memp.QualityMF = m_xQualityMF->get_value(); memp.InterpolationCombo = m_xInterpolationCombo->get_active(); CompressGraphicsDialog::response(RET_OK); } IMPL_LINK_NOARG( CompressGraphicsDialog, NewWidthModifiedHdl, weld::SpinButton&, void ) { m_dResolution = m_xMFNewWidth->get_value() / GetViewWidthInch(); UpdateNewHeightMF(); UpdateResolutionLB(); Update(); } IMPL_LINK( CompressGraphicsDialog, SlideHdl, weld::Scale&, rScale, void ) { if (&rScale == m_xQualitySlider.get()) m_xQualityMF->set_value(m_xQualitySlider->get_value()); else m_xCompressionMF->set_value(m_xCompressionSlider->get_value()); Update(); } IMPL_LINK_NOARG( CompressGraphicsDialog, NewInterpolationModifiedHdl, weld::ComboBox&, void ) { Update(); } IMPL_LINK_NOARG( CompressGraphicsDialog, NewQualityModifiedHdl, weld::SpinButton&, void ) { m_xQualitySlider->set_value(m_xQualityMF->get_value()); Update(); } IMPL_LINK_NOARG( CompressGraphicsDialog, NewCompressionModifiedHdl, weld::SpinButton&, void ) { m_xCompressionSlider->set_value(m_xCompressionMF->get_value()); Update(); } IMPL_LINK_NOARG( CompressGraphicsDialog, NewHeightModifiedHdl, weld::SpinButton&, void ) { m_dResolution = m_xMFNewHeight->get_value() / GetViewHeightInch(); UpdateNewWidthMF(); UpdateResolutionLB(); Update(); } IMPL_LINK_NOARG( CompressGraphicsDialog, ResolutionModifiedHdl, weld::ComboBox&, void ) { m_dResolution = static_cast(m_xResolutionLB->get_active_text().toInt32()); UpdateNewWidthMF(); UpdateNewHeightMF(); Update(); } IMPL_LINK_NOARG( CompressGraphicsDialog, ToggleCompressionRB, weld::Toggleable&, void ) { bool choice = m_xLosslessRB->get_active(); m_xCompressionMF->set_sensitive(choice); m_xCompressionSlider->set_sensitive(choice); m_xQualityMF->set_sensitive(!choice); m_xQualitySlider->set_sensitive(!choice); Update(); } IMPL_LINK_NOARG( CompressGraphicsDialog, ToggleReduceResolutionRB, weld::Toggleable&, void ) { UpdateSensitivity(m_xReduceResolutionCB->get_active()); Update(); } IMPL_LINK_NOARG( CompressGraphicsDialog, CalculateClickHdl, weld::Button&, void ) { sal_Int32 aSize = 0; if ( m_dResolution > 0.0 ) { SvMemoryStream aMemStream; aMemStream.SetVersion( SOFFICE_FILEFORMAT_CURRENT ); Compress( aMemStream ); aSize = aMemStream.TellEnd(); } if ( aSize > 0 ) { OUString aSizeAsString = OUString::number(aSize / 1024); OUString aReductionSizeAsString; if (m_aNativeSize > 0 ) aReductionSizeAsString = OUString::number( static_cast((m_aNativeSize - aSize) * 100.0 / m_aNativeSize) ); else aReductionSizeAsString = "0"; OUString aNewSizeString = SvxResId(STR_IMAGE_CAPACITY_WITH_REDUCTION); aNewSizeString = aNewSizeString.replaceAll("$(CAPACITY)", aSizeAsString); aNewSizeString = aNewSizeString.replaceAll("$(REDUCTION)", aReductionSizeAsString); m_xFixedText6->set_label(aNewSizeString); } } tools::Rectangle CompressGraphicsDialog::GetScaledCropRectangle() const { if ( m_xReduceResolutionCB->get_active() ) { tools::Long nPixelX = static_cast( GetViewWidthInch() * m_dResolution ); tools::Long nPixelY = static_cast( GetViewHeightInch() * m_dResolution ); Size aSize = m_aGraphic.GetBitmapEx().GetSizePixel(); double aScaleX = nPixelX / static_cast(aSize.Width()); double aScaleY = nPixelY / static_cast(aSize.Height()); return tools::Rectangle( m_aCropRectangle.Left() * aScaleX, m_aCropRectangle.Top() * aScaleY, m_aCropRectangle.Right() * aScaleX, m_aCropRectangle.Bottom()* aScaleY); } else { return m_aCropRectangle; } } Graphic CompressGraphicsDialog::GetCompressedGraphic() { if ( m_dResolution > 0.0 ) { SvMemoryStream aMemStream; aMemStream.SetVersion( SOFFICE_FILEFORMAT_CURRENT ); Compress( aMemStream ); aMemStream.Seek( STREAM_SEEK_TO_BEGIN ); Graphic aResultGraphic; GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter(); rFilter.ImportGraphic( aResultGraphic, u"import", aMemStream ); return aResultGraphic; } return Graphic(); } rtl::Reference CompressGraphicsDialog::GetCompressedSdrGrafObj() { if ( m_dResolution > 0.0 ) { rtl::Reference pNewObject = SdrObject::Clone(*m_xGraphicObj, m_xGraphicObj->getSdrModelFromSdrObject()); if ( m_xReduceResolutionCB->get_active() ) { tools::Rectangle aScaledCropedRectangle = GetScaledCropRectangle(); SdrGrafCropItem aNewCrop( aScaledCropedRectangle.Left(), aScaledCropedRectangle.Top(), aScaledCropedRectangle.Right(), aScaledCropedRectangle.Bottom()); pNewObject->SetMergedItem(aNewCrop); } pNewObject->SetGraphic( GetCompressedGraphic() ); return pNewObject; } return nullptr; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */