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;
         }