From 473979d686ba6331280ff61fcbbbc2348b6940ad Mon Sep 17 00:00:00 2001 From: Jon Evans Date: Tue, 14 Feb 2023 19:41:54 -0500 Subject: [PATCH] Fix handling of PPI when loading embedded images Fixes https://gitlab.com/kicad/code/kicad/-/issues/13884 --- common/bitmap_base.cpp | 29 ++++++++++++++-------- include/bitmap_base.h | 2 ++ pcbnew/dialogs/dialog_image_properties.cpp | 4 +-- pcbnew/pcb_bitmap.cpp | 7 ++++++ pcbnew/pcb_bitmap.h | 12 ++++++++- pcbnew/plugins/kicad/pcb_parser.cpp | 6 ++--- 6 files changed, 43 insertions(+), 17 deletions(-) diff --git a/common/bitmap_base.cpp b/common/bitmap_base.cpp index cb380f54e3..ffede07364 100644 --- a/common/bitmap_base.cpp +++ b/common/bitmap_base.cpp @@ -75,6 +75,7 @@ void BITMAP_BASE::SetImage( wxImage* aImage ) delete m_originalImage; m_originalImage = new wxImage( *aImage ); rebuildBitmap(); + updatePPI(); } @@ -90,6 +91,21 @@ void BITMAP_BASE::rebuildBitmap( bool aResetID ) } +void BITMAP_BASE::updatePPI() +{ + // Todo: eventually we need to support dpi / scaling in both dimensions + int dpiX = m_originalImage->GetOptionInt( wxIMAGE_OPTION_RESOLUTIONX ); + + if( dpiX > 1 ) + { + if( m_originalImage->GetOptionInt( wxIMAGE_OPTION_RESOLUTIONUNIT ) == wxIMAGE_RESOLUTION_CM ) + m_ppi = KiROUND( dpiX * 2.54 ); + else + m_ppi = dpiX; + } +} + + void BITMAP_BASE::ImportData( BITMAP_BASE* aItem ) { *m_image = *aItem->m_image; @@ -116,6 +132,7 @@ bool BITMAP_BASE::ReadImageFile( wxInputStream& aInStream ) delete m_originalImage; m_originalImage = new wxImage( *m_image ); rebuildBitmap(); + updatePPI(); return true; } @@ -136,17 +153,7 @@ bool BITMAP_BASE::ReadImageFile( const wxString& aFullFilename ) delete m_originalImage; m_originalImage = new wxImage( *m_image ); rebuildBitmap(); - - // Todo: eventually we need to support dpi / scaling in both dimensions - int dpiX = m_originalImage->GetOptionInt( wxIMAGE_OPTION_RESOLUTIONX ); - - if( dpiX > 1 ) - { - if( m_originalImage->GetOptionInt( wxIMAGE_OPTION_RESOLUTIONUNIT ) == wxIMAGE_RESOLUTION_CM ) - m_ppi = KiROUND( dpiX * 2.54 ); - else - m_ppi = dpiX; - } + updatePPI(); return true; } diff --git a/include/bitmap_base.h b/include/bitmap_base.h index 89c510c710..fc9681f58d 100644 --- a/include/bitmap_base.h +++ b/include/bitmap_base.h @@ -236,6 +236,8 @@ private: */ void rebuildBitmap( bool aResetID = true ); + void updatePPI(); + double m_scale; // The scaling factor of the bitmap // With m_pixelSizeIu, controls the actual draw size wxImage* m_image; // the raw image data (png format) diff --git a/pcbnew/dialogs/dialog_image_properties.cpp b/pcbnew/dialogs/dialog_image_properties.cpp index 65a3905507..5a5a4b75a7 100644 --- a/pcbnew/dialogs/dialog_image_properties.cpp +++ b/pcbnew/dialogs/dialog_image_properties.cpp @@ -37,7 +37,7 @@ DIALOG_IMAGE_PROPERTIES::DIALOG_IMAGE_PROPERTIES( PCB_BASE_FRAME* aParent, PCB_B m_posY( aParent, m_YPosLabel, m_ModPositionY, m_YPosUnit ) { // Create the image editor page - m_imageEditor = new PANEL_IMAGE_EDITOR( m_Notebook, aBitmap->GetImage() ); + m_imageEditor = new PANEL_IMAGE_EDITOR( m_Notebook, aBitmap->MutableImage() ); m_Notebook->AddPage( m_imageEditor, _( "Image" ), false ); m_posX.SetCoordType( ORIGIN_TRANSFORMS::ABS_X_COORD ); @@ -97,7 +97,7 @@ bool DIALOG_IMAGE_PROPERTIES::TransferDataFromWindow() m_frame->SaveCopyInUndoList( m_bitmap, UNDO_REDO::CHANGED ); // Update our bitmap from the editor - m_imageEditor->TransferToImage( m_bitmap->GetImage() ); + m_imageEditor->TransferToImage( m_bitmap->MutableImage() ); // Set position, etc. m_bitmap->SetPosition( VECTOR2I( m_posX.GetValue(), m_posY.GetValue() ) ); diff --git a/pcbnew/pcb_bitmap.cpp b/pcbnew/pcb_bitmap.cpp index deb7864cff..239ded025d 100644 --- a/pcbnew/pcb_bitmap.cpp +++ b/pcbnew/pcb_bitmap.cpp @@ -82,6 +82,13 @@ PCB_BITMAP& PCB_BITMAP::operator=( const BOARD_ITEM& aItem ) } +void PCB_BITMAP::SetImage( wxImage* aImage ) +{ + m_image->SetImage( aImage ); + m_image->SetPixelSizeIu( (float) pcbIUScale.MilsToIU( 1000 ) / m_image->GetPPI() ); +} + + bool PCB_BITMAP::ReadImageFile( const wxString& aFullFilename ) { if( m_image->ReadImageFile( aFullFilename ) ) diff --git a/pcbnew/pcb_bitmap.h b/pcbnew/pcb_bitmap.h index 09efb0f324..4f09603b6a 100644 --- a/pcbnew/pcb_bitmap.h +++ b/pcbnew/pcb_bitmap.h @@ -50,12 +50,22 @@ public: PCB_BITMAP& operator=( const BOARD_ITEM& aItem ); - BITMAP_BASE* GetImage() const + const BITMAP_BASE* GetImage() const { wxCHECK_MSG( m_image != nullptr, nullptr, "Invalid PCB_BITMAP init, m_image is NULL." ); return m_image; } + /** + * Only use this if you really need to modify the underlying image + */ + BITMAP_BASE* MutableImage() const + { + return m_image; + } + + void SetImage( wxImage* aImage ); + /** * @return the image "zoom" value. * scale = 1.0 = original size of bitmap. diff --git a/pcbnew/plugins/kicad/pcb_parser.cpp b/pcbnew/plugins/kicad/pcb_parser.cpp index a450323eb3..b367a8d8c1 100644 --- a/pcbnew/plugins/kicad/pcb_parser.cpp +++ b/pcbnew/plugins/kicad/pcb_parser.cpp @@ -2876,10 +2876,10 @@ PCB_BITMAP* PCB_PARSER::parsePCB_BITMAP( BOARD_ITEM* aParent ) break; case T_scale: - bitmap->GetImage()->SetScale( parseDouble( "image scale factor" ) ); + bitmap->SetImageScale( parseDouble( "image scale factor" ) ); if( !std::isnormal( bitmap->GetImage()->GetScale() ) ) - bitmap->GetImage()->SetScale( 1.0 ); + bitmap->SetImageScale( 1.0 ); NeedRIGHT(); break; @@ -2908,7 +2908,7 @@ PCB_BITMAP* PCB_PARSER::parsePCB_BITMAP( BOARD_ITEM* aParent ) wxImage* image = new wxImage(); wxMemoryInputStream istream( stream ); image->LoadFile( istream, wxBITMAP_TYPE_PNG ); - bitmap->GetImage()->SetImage( image ); + bitmap->SetImage( image ); break; }