7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2025-04-21 00:21:25 +00:00

Use REFERENCE_IMAGE for SCH_BITMAP

Also wire in the transform origin handling to the point editor
and the properties panel in eeschema.
This commit is contained in:
John Beard 2024-09-29 23:34:27 +01:00
parent 3f131e2011
commit 460e575457
18 changed files with 301 additions and 260 deletions

View File

@ -276,7 +276,7 @@ const BOX2I BITMAP_BASE::GetBoundingBox() const
void BITMAP_BASE::DrawBitmap( wxDC* aDC, const VECTOR2I& aPos,
const KIGFX::COLOR4D& aBackgroundColor )
const KIGFX::COLOR4D& aBackgroundColor ) const
{
if( m_bitmap == nullptr )
return;

View File

@ -29,13 +29,14 @@
#include <sch_commit.h>
DIALOG_IMAGE_PROPERTIES::DIALOG_IMAGE_PROPERTIES( SCH_EDIT_FRAME* aParent, SCH_BITMAP* aBitmap ) :
DIALOG_IMAGE_PROPERTIES::DIALOG_IMAGE_PROPERTIES( SCH_EDIT_FRAME* aParent, SCH_BITMAP& aBitmap ) :
DIALOG_IMAGE_PROPERTIES_BASE( aParent ), m_frame( aParent ), m_bitmap( aBitmap ),
m_posX( aParent, m_XPosLabel, m_ModPositionX, m_XPosUnit ),
m_posY( aParent, m_YPosLabel, m_ModPositionY, m_YPosUnit )
{
// Create the image editor page
m_imageEditor = new PANEL_IMAGE_EDITOR( m_Notebook, aBitmap->GetImage() );
const REFERENCE_IMAGE& refImage = aBitmap.GetReferenceImage();
m_imageEditor = new PANEL_IMAGE_EDITOR( m_Notebook, refImage.GetImage() );
m_Notebook->AddPage( m_imageEditor, _( "Image" ), false );
m_posX.SetCoordType( ORIGIN_TRANSFORMS::ABS_X_COORD );
@ -49,8 +50,8 @@ DIALOG_IMAGE_PROPERTIES::DIALOG_IMAGE_PROPERTIES( SCH_EDIT_FRAME* aParent, SCH_B
bool DIALOG_IMAGE_PROPERTIES::TransferDataToWindow()
{
m_posX.SetValue( m_bitmap->GetPosition().x );
m_posY.SetValue( m_bitmap->GetPosition().y );
m_posX.SetValue( m_bitmap.GetPosition().x );
m_posY.SetValue( m_bitmap.GetPosition().y );
return true;
}
@ -58,18 +59,19 @@ bool DIALOG_IMAGE_PROPERTIES::TransferDataToWindow()
bool DIALOG_IMAGE_PROPERTIES::TransferDataFromWindow()
{
REFERENCE_IMAGE& refImage = m_bitmap.GetReferenceImage();
if( m_imageEditor->TransferDataFromWindow() )
{
SCH_COMMIT commit( m_frame );
// Save old image in undo list if not already in edit
if( m_bitmap->GetEditFlags() == 0 )
commit.Modify( m_bitmap, m_frame->GetScreen() );
if( m_bitmap.GetEditFlags() == 0 )
commit.Modify( &m_bitmap, m_frame->GetScreen() );
// Update our bitmap from the editor
m_imageEditor->TransferToImage( m_bitmap->GetImage() );
m_imageEditor->TransferToImage( refImage.MutableImage() );
m_bitmap->SetPosition( VECTOR2I( m_posX.GetValue(), m_posY.GetValue() ) );
m_bitmap.SetPosition( VECTOR2I( m_posX.GetValue(), m_posY.GetValue() ) );
if( !commit.Empty() )
commit.Push( _( "Image Properties" ) );

View File

@ -36,7 +36,7 @@ class PANEL_IMAGE_EDITOR;
class DIALOG_IMAGE_PROPERTIES : public DIALOG_IMAGE_PROPERTIES_BASE
{
public:
DIALOG_IMAGE_PROPERTIES( SCH_EDIT_FRAME* aParent, SCH_BITMAP* aBitmap );
DIALOG_IMAGE_PROPERTIES( SCH_EDIT_FRAME* aParent, SCH_BITMAP& aBitmap );
~DIALOG_IMAGE_PROPERTIES() override {}
private:
@ -45,7 +45,7 @@ private:
private:
SCH_EDIT_FRAME* m_frame;
SCH_BITMAP* m_bitmap;
SCH_BITMAP& m_bitmap;
PANEL_IMAGE_EDITOR* m_imageEditor;
UNIT_BINDER m_posX;

View File

@ -25,38 +25,37 @@
/**
* @file sch_bitmap.cpp
*/
#include "sch_bitmap.h"
#include <sch_draw_panel.h>
#include <plotters/plotter.h>
#include <settings/color_settings.h>
#include <bitmap_base.h>
#include <bitmaps.h>
#include <base_units.h>
#include <common.h>
#include <eda_draw_frame.h>
#include <core/mirror.h>
#include <sch_bitmap.h>
#include <eda_draw_frame.h>
#include <geometry/geometry_utils.h>
#include <plotters/plotter.h>
#include <sch_draw_panel.h>
#include <settings/color_settings.h>
#include <trigo.h>
#include <wx/mstream.h>
SCH_BITMAP::SCH_BITMAP( const VECTOR2I& pos ) :
SCH_ITEM( nullptr, SCH_BITMAP_T )
SCH_ITEM( nullptr, SCH_BITMAP_T ),
m_referenceImage( schIUScale)
{
m_pos = pos;
m_referenceImage.SetPosition( pos );
m_layer = LAYER_NOTES; // used only to draw/plot a rectangle,
// when a bitmap cannot be drawn or plotted
m_bitmapBase = new BITMAP_BASE();
m_bitmapBase->SetPixelSizeIu( (double) schIUScale.MilsToIU( 1000 ) / m_bitmapBase->GetPPI() );
}
SCH_BITMAP::SCH_BITMAP( const SCH_BITMAP& aSchBitmap ) :
SCH_ITEM( aSchBitmap )
SCH_ITEM( aSchBitmap ),
m_referenceImage( aSchBitmap.m_referenceImage )
{
m_pos = aSchBitmap.m_pos;
m_layer = aSchBitmap.m_layer;
m_bitmapBase = new BITMAP_BASE( *aSchBitmap.m_bitmapBase );
}
@ -70,41 +69,14 @@ SCH_BITMAP& SCH_BITMAP::operator=( const SCH_ITEM& aItem )
{
SCH_ITEM::operator=( aItem );
SCH_BITMAP* bitmap = (SCH_BITMAP*) &aItem;
delete m_bitmapBase;
m_bitmapBase = new BITMAP_BASE( *bitmap->m_bitmapBase );
m_pos = bitmap->m_pos;
const SCH_BITMAP& bitmap = static_cast<const SCH_BITMAP&>( aItem );
m_referenceImage = bitmap.m_referenceImage;
}
return *this;
}
bool SCH_BITMAP::ReadImageFile( const wxString& aFullFilename )
{
if( m_bitmapBase->ReadImageFile( aFullFilename ) )
{
m_bitmapBase->SetPixelSizeIu( (double) schIUScale.MilsToIU( 1000 ) / m_bitmapBase->GetPPI() );
return true;
}
return false;
}
bool SCH_BITMAP::ReadImageFile( wxMemoryBuffer& aBuffer )
{
if( m_bitmapBase->ReadImageFile( aBuffer ) )
{
m_bitmapBase->SetPixelSizeIu( (double) schIUScale.MilsToIU( 1000 ) / m_bitmapBase->GetPPI() );
return true;
}
return false;
}
EDA_ITEM* SCH_BITMAP::Clone() const
{
return new SCH_BITMAP( *this );
@ -120,53 +92,59 @@ void SCH_BITMAP::SwapData( SCH_ITEM* aItem )
aItem->GetClass() ) );
SCH_BITMAP* item = (SCH_BITMAP*) aItem;
std::swap( m_pos, item->m_pos );
std::swap( m_bitmapBase, item->m_bitmapBase );
m_referenceImage.SwapData( item->m_referenceImage );
}
const BOX2I SCH_BITMAP::GetBoundingBox() const
{
BOX2I bbox = m_bitmapBase->GetBoundingBox();
bbox.Move( m_pos );
return bbox;
return m_referenceImage.GetBoundingBox();
}
void SCH_BITMAP::Print( const SCH_RENDER_SETTINGS* aSettings, int aUnit, int aBodyStyle,
const VECTOR2I& aOffset, bool aForceNoFill, bool aDimmed )
{
VECTOR2I pos = m_pos + aOffset;
VECTOR2I pos = GetPosition() + aOffset;
m_bitmapBase->DrawBitmap( aSettings->GetPrintDC(), pos, aSettings->GetBackgroundColor() );
m_referenceImage.GetImage().DrawBitmap( aSettings->GetPrintDC(), pos,
aSettings->GetBackgroundColor() );
}
VECTOR2I SCH_BITMAP::GetSize() const
VECTOR2I SCH_BITMAP::GetPosition() const
{
return m_bitmapBase->GetSize();
return m_referenceImage.GetPosition();
}
void SCH_BITMAP::SetPosition( const VECTOR2I& aPosition )
{
m_referenceImage.SetPosition( aPosition );
}
void SCH_BITMAP::Move( const VECTOR2I& aMoveVector )
{
SetPosition( GetPosition() + aMoveVector );
}
void SCH_BITMAP::MirrorVertically( int aCenter )
{
MIRROR( m_pos.y, aCenter );
m_bitmapBase->Mirror( FLIP_DIRECTION::TOP_BOTTOM );
m_referenceImage.Flip( VECTOR2I( 0, aCenter ), FLIP_DIRECTION::TOP_BOTTOM );
}
void SCH_BITMAP::MirrorHorizontally( int aCenter )
{
MIRROR( m_pos.x, aCenter );
m_bitmapBase->Mirror( FLIP_DIRECTION::LEFT_RIGHT );
m_referenceImage.Flip( VECTOR2I( aCenter, 0 ), FLIP_DIRECTION::LEFT_RIGHT );
}
void SCH_BITMAP::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
{
RotatePoint( m_pos, aCenter, aRotateCCW ? ANGLE_90 : ANGLE_270 );
m_bitmapBase->Rotate( aRotateCCW );
m_referenceImage.Rotate( aCenter, aRotateCCW ? ANGLE_90 : ANGLE_270 );
}
@ -176,31 +154,20 @@ void SCH_BITMAP::Show( int nestLevel, std::ostream& os ) const
// XML output:
wxString s = GetClass();
NestedSpace( nestLevel, os ) << '<' << s.Lower().mb_str() << m_pos << "/>\n";
NestedSpace( nestLevel, os ) << '<' << s.Lower().mb_str() << GetPosition() << "/>\n";
}
#endif
bool SCH_BITMAP::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
{
BOX2I rect = GetBoundingBox();
rect.Inflate( aAccuracy );
return rect.Contains( aPosition );
return KIGEOM::BoxHitTest( aPosition, GetBoundingBox(), aAccuracy );
}
bool SCH_BITMAP::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
{
BOX2I rect = aRect;
rect.Inflate( aAccuracy );
if( aContained )
return rect.Contains( GetBoundingBox() );
return rect.Intersects( GetBoundingBox() );
return KIGEOM::BoxHitTest( aRect, GetBoundingBox(), aContained, aAccuracy );
}
@ -209,9 +176,9 @@ void SCH_BITMAP::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS&
{
if( aBackground )
{
m_bitmapBase->PlotImage( aPlotter, m_pos,
aPlotter->RenderSettings()->GetLayerColor( GetLayer() ),
aPlotter->RenderSettings()->GetDefaultPenWidth() );
m_referenceImage.GetImage().PlotImage(
aPlotter, GetPosition(), aPlotter->RenderSettings()->GetLayerColor( GetLayer() ),
aPlotter->RenderSettings()->GetDefaultPenWidth() );
}
}
@ -226,11 +193,15 @@ void SCH_BITMAP::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_
{
aList.emplace_back( _( "Bitmap" ), wxEmptyString );
aList.emplace_back( _( "PPI" ), wxString::Format( wxT( "%d "), GetImage()->GetPPI() ) );
aList.emplace_back( _( "Scale" ), wxString::Format( wxT( "%f "), GetImageScale() ) );
aList.emplace_back( _( "PPI" ),
wxString::Format( wxT( "%d " ), m_referenceImage.GetImage().GetPPI() ) );
aList.emplace_back( _( "Scale" ),
wxString::Format( wxT( "%f " ), m_referenceImage.GetImageScale() ) );
aList.emplace_back( _( "Width" ), aFrame->MessageTextFromValue( GetSize().x ) );
aList.emplace_back( _( "Height" ), aFrame->MessageTextFromValue( GetSize().y ) );
aList.emplace_back( _( "Width" ),
aFrame->MessageTextFromValue( m_referenceImage.GetSize().x ) );
aList.emplace_back( _( "Height" ),
aFrame->MessageTextFromValue( m_referenceImage.GetSize().y ) );
}
@ -247,18 +218,8 @@ bool SCH_BITMAP::operator==( const SCH_ITEM& aItem ) const
if( Type() != aItem.Type() )
return false;
const SCH_BITMAP* bitmap = static_cast<const SCH_BITMAP*>( &aItem );
if( GetPosition() != bitmap->GetPosition() )
return false;
if( GetSize() != bitmap->GetSize() )
return false;
if( GetImage() != bitmap->GetImage() )
return false;
return true;
const SCH_BITMAP& bitmap = static_cast<const SCH_BITMAP&>( aItem );
return m_referenceImage == bitmap.m_referenceImage;
}
@ -270,17 +231,48 @@ double SCH_BITMAP::Similarity( const SCH_ITEM& aItem ) const
if( m_Uuid == aItem.m_Uuid )
return 1.0;
const SCH_BITMAP* bitmap = static_cast<const SCH_BITMAP*>( &aItem );
const SCH_BITMAP& bitmap = static_cast<const SCH_BITMAP&>( aItem );
return m_referenceImage.Similarity( bitmap.m_referenceImage );
}
if( GetImage() != bitmap->GetImage() )
return 0.0;
// If it is the same image but a different UUID and a different size,
// then it _might be different_.
if( GetSize() != bitmap->GetSize() )
return 0.5;
int SCH_BITMAP::GetTransformOriginOffsetX() const
{
return m_referenceImage.GetTransformOriginOffset().x;
}
return 1.0;
void SCH_BITMAP::SetTransformOriginOffsetX( int aX )
{
VECTOR2I offset = m_referenceImage.GetTransformOriginOffset();
offset.x = aX;
m_referenceImage.SetTransformOriginOffset( offset );
}
int SCH_BITMAP::GetTransformOriginOffsetY() const
{
return m_referenceImage.GetTransformOriginOffset().y;
}
void SCH_BITMAP::SetTransformOriginOffsetY( int aY )
{
VECTOR2I offset = m_referenceImage.GetTransformOriginOffset();
offset.y = aY;
m_referenceImage.SetTransformOriginOffset( offset );
}
double SCH_BITMAP::GetImageScale() const
{
return m_referenceImage.GetImageScale();
}
void SCH_BITMAP::SetImageScale( double aScale )
{
m_referenceImage.SetImageScale( aScale );
}
@ -301,11 +293,25 @@ static struct SCH_BITMAP_DESC
&SCH_BITMAP::GetY,
PROPERTY_DISPLAY::PT_COORD ) );
const wxString groupBITMAP = _HKI( "Image Properties" );
const wxString groupImage = _HKI( "Image Properties" );
propMgr.AddProperty( new PROPERTY<SCH_BITMAP, double>( _HKI( "Scale" ),
&SCH_BITMAP::SetImageScale,
&SCH_BITMAP::GetImageScale ),
groupBITMAP );
groupImage );
propMgr.AddProperty( new PROPERTY<SCH_BITMAP, int>(
_HKI( "Transform Offset X" ),
&SCH_BITMAP::SetTransformOriginOffsetX,
&SCH_BITMAP::GetTransformOriginOffsetX,
PROPERTY_DISPLAY::PT_COORD, ORIGIN_TRANSFORMS::ABS_X_COORD ),
groupImage );
propMgr.AddProperty( new PROPERTY<SCH_BITMAP, int>(
_HKI( "Transform Offset Y" ),
&SCH_BITMAP::SetTransformOriginOffsetY,
&SCH_BITMAP::GetTransformOriginOffsetY,
PROPERTY_DISPLAY::PT_COORD, ORIGIN_TRANSFORMS::ABS_Y_COORD ),
groupImage );
}
} _SCH_BITMAP_DESC;

View File

@ -26,12 +26,11 @@
* @file sch_bitmap.h
*/
#ifndef _SCH_BITMAP_H_
#define _SCH_BITMAP_H_
#pragma once
#include <sch_item.h>
#include <bitmap_base.h>
#include <reference_image.h>
/**
@ -44,19 +43,13 @@ public:
SCH_BITMAP( const SCH_BITMAP& aSchBitmap );
~SCH_BITMAP()
{
delete m_bitmapBase;
}
SCH_BITMAP& operator=( const SCH_ITEM& aItem );
BITMAP_BASE* GetImage() const
{
wxCHECK_MSG( m_bitmapBase != nullptr, nullptr,
"Invalid SCH_BITMAP init, m_bitmapBase is NULL." );
return m_bitmapBase;
}
/**
* @return the underlying reference image object.
*/
REFERENCE_IMAGE& GetReferenceImage() { return m_referenceImage; }
const REFERENCE_IMAGE& GetReferenceImage() const { return m_referenceImage; }
int GetX() const { return GetPosition().x; };
void SetX( int aX ) { SetPosition( VECTOR2I( aX, GetY() ) ); }
@ -64,22 +57,6 @@ public:
int GetY() const { return GetPosition().y; }
void SetY( int aY ) { SetPosition( VECTOR2I( GetX(), aY ) ); }
/**
* @return the image "zoom" value.
* scale = 1.0 = original size of bitmap.
* scale < 1.0 = the bitmap is drawn smaller than its original size.
* scale > 1.0 = the bitmap is drawn bigger than its original size.
*/
double GetImageScale() const
{
return m_bitmapBase->GetScale();
}
void SetImageScale( double aScale )
{
m_bitmapBase->SetScale( aScale );
}
static inline bool ClassOf( const EDA_ITEM* aItem )
{
return aItem && SCH_BITMAP_T == aItem->Type();
@ -90,11 +67,6 @@ public:
return wxT( "SCH_BITMAP" );
}
/**
* @return the actual size (in user units, not in pixels) of the image.
*/
VECTOR2I GetSize() const;
const BOX2I GetBoundingBox() const override;
void SwapData( SCH_ITEM* aItem ) override;
@ -102,30 +74,7 @@ public:
/// @copydoc VIEW_ITEM::ViewGetLayers()
virtual void ViewGetLayers( int aLayers[], int& aCount ) const override;
/**
* Read and store an image file.
*
* Initialize the bitmap used to draw this item format.
*
* @param aFullFilename is the full filename of the image file to read.
* @return true if success reading else false.
*/
bool ReadImageFile( const wxString& aFullFilename );
/**
* Read and store an image file.
*
* Initialize the bitmap used to draw this item format.
*
* @param aBuf is the memory buffer containing the image file to read.
* @return true if success reading else false.
*/
bool ReadImageFile( wxMemoryBuffer& aBuf );
void Move( const VECTOR2I& aMoveVector ) override
{
m_pos += aMoveVector;
}
void Move( const VECTOR2I& aMoveVector ) override;
/**
* Return true for items which are moved with the anchor point at mouse cursor and false
@ -148,8 +97,8 @@ public:
void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
VECTOR2I GetPosition() const override { return m_pos; }
void SetPosition( const VECTOR2I& aPosition ) override { m_pos = aPosition; }
VECTOR2I GetPosition() const override;
void SetPosition( const VECTOR2I& aPosition ) override;
bool HitTest( const VECTOR2I& aPosition, int aAccuracy = 0 ) const override;
bool HitTest( const BOX2I& aRect, bool aContained, int aAccuracy = 0 ) const override;
@ -171,9 +120,16 @@ public:
#endif
private:
VECTOR2I m_pos; // XY coordinates of center of the bitmap
BITMAP_BASE* m_bitmapBase; // the BITMAP_BASE item
friend struct SCH_BITMAP_DESC;
// Property manager interfaces
int GetTransformOriginOffsetX() const;
void SetTransformOriginOffsetX( int aX );
int GetTransformOriginOffsetY() const;
void SetTransformOriginOffsetY( int aY );
double GetImageScale() const;
void SetImageScale( double aScale );
REFERENCE_IMAGE m_referenceImage;
};
#endif // _SCH_BITMAP_H_

View File

@ -3750,6 +3750,7 @@ void SCH_IO_ALTIUM::ParseImage( const std::map<wxString, wxString>& aProperties
VECTOR2I center = ( elem.location + elem.corner ) / 2 + m_sheetOffset;
std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>( center );
REFERENCE_IMAGE& refImage = bitmap->GetReferenceImage();
SCH_SCREEN* screen = getCurrentScreen();
wxCHECK( screen, /* void */ );
@ -3775,7 +3776,7 @@ void SCH_IO_ALTIUM::ParseImage( const std::map<wxString, wxString>& aProperties
outputStream.Write( zlibInputStream );
outputStream.Close();
if( !bitmap->ReadImageFile( storagePath ) )
if( !refImage.ReadImageFile( storagePath ) )
{
m_reporter->Report( wxString::Format( _( "Error reading image %s." ), storagePath ),
RPT_SEVERITY_ERROR );
@ -3794,7 +3795,7 @@ void SCH_IO_ALTIUM::ParseImage( const std::map<wxString, wxString>& aProperties
return;
}
if( !bitmap->ReadImageFile( elem.filename ) )
if( !refImage.ReadImageFile( elem.filename ) )
{
m_reporter->Report( wxString::Format( _( "Error reading image %s." ), elem.filename ),
RPT_SEVERITY_ERROR );
@ -3803,11 +3804,13 @@ void SCH_IO_ALTIUM::ParseImage( const std::map<wxString, wxString>& aProperties
}
// we only support one scale, thus we need to select one in case it does not keep aspect ratio
VECTOR2I currentImageSize = bitmap->GetSize();
VECTOR2I expectedImageSize = elem.location - elem.corner;
double scaleX = std::abs( static_cast<double>( expectedImageSize.x ) / currentImageSize.x );
double scaleY = std::abs( static_cast<double>( expectedImageSize.y ) / currentImageSize.y );
bitmap->SetImageScale( std::min( scaleX, scaleY ) );
const VECTOR2I currentImageSize = refImage.GetSize();
const VECTOR2I expectedImageSize = elem.location - elem.corner;
const double scaleX =
std::abs( static_cast<double>( expectedImageSize.x ) / currentImageSize.x );
const double scaleY =
std::abs( static_cast<double>( expectedImageSize.y ) / currentImageSize.y );
refImage.SetImageScale( std::min( scaleX, scaleY ) );
bitmap->SetFlags( IS_NEW );
screen->Append( bitmap.release() );

View File

@ -1594,16 +1594,17 @@ void SCH_EASYEDA_PARSER::ParseSchematic( SCHEMATIC* aSchematic, SCH_SHEET* aRoot
else
{
std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>();
REFERENCE_IMAGE& refImage = bitmap->GetReferenceImage();
wxImage::SetDefaultLoadFlags( wxImage::GetDefaultLoadFlags()
& ~wxImage::Load_Verbose );
if( bitmap->ReadImageFile( buf ) )
if( refImage.ReadImageFile( buf ) )
{
VECTOR2D kcenter = kstart + ksize / 2;
double scaleFactor = ScaleSize( size.x ) / bitmap->GetSize().x;
bitmap->SetImageScale( scaleFactor );
double scaleFactor = ScaleSize( size.x ) / refImage.GetSize().x;
refImage.SetImageScale( scaleFactor );
bitmap->SetPosition( kcenter );
applyTransform( bitmap.get() );

View File

@ -1057,16 +1057,17 @@ void SCH_EASYEDAPRO_PARSER::ParseSchematic( SCHEMATIC* aSchematic, SCH_SHEET* aR
else
{
std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>();
REFERENCE_IMAGE& refImage = bitmap->GetReferenceImage();
wxImage::SetDefaultLoadFlags( wxImage::GetDefaultLoadFlags()
& ~wxImage::Load_Verbose );
if( bitmap->ReadImageFile( buf ) )
if( refImage.ReadImageFile( buf ) )
{
VECTOR2D kcenter = kstart + ksize / 2;
double scaleFactor = ScaleSize( size.x ) / bitmap->GetSize().x;
bitmap->SetImageScale( scaleFactor );
double scaleFactor = ScaleSize( size.x ) / refImage.GetSize().x;
refImage.SetImageScale( scaleFactor );
bitmap->SetPosition( kcenter );
for( double i = angle; i > 0; i -= 90 )

View File

@ -33,6 +33,7 @@
#include <wx/tokenzr.h>
#include <wx_filename.h> // For ::ResolvePossibleSymlinks()
#include <bitmap_base.h>
#include <kiway.h>
#include <string_utils.h>
#include <locale_io.h>
@ -646,6 +647,7 @@ SCH_SHEET* SCH_IO_KICAD_LEGACY::loadSheet( LINE_READER& aReader )
SCH_BITMAP* SCH_IO_KICAD_LEGACY::loadBitmap( LINE_READER& aReader )
{
std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>();
REFERENCE_IMAGE& refImage = bitmap->GetReferenceImage();
const char* line = aReader.Line();
@ -674,7 +676,7 @@ SCH_BITMAP* SCH_IO_KICAD_LEGACY::loadBitmap( LINE_READER& aReader )
if( !std::isnormal( scalefactor ) )
scalefactor = 1.0;
bitmap->GetImage()->SetScale( scalefactor );
refImage.SetImageScale( scalefactor );
}
else if( strCompare( "Data", line, &line ) )
{
@ -690,12 +692,12 @@ SCH_BITMAP* SCH_IO_KICAD_LEGACY::loadBitmap( LINE_READER& aReader )
if( strCompare( "EndData", line ) )
{
// all the PNG date is read.
bitmap->GetImage()->ReadImageFile( buffer );
refImage.ReadImageFile( buffer );
// Legacy file formats assumed 300 image PPI at load.
BITMAP_BASE* bitmapImage = bitmap->GetImage();
bitmapImage->SetScale( bitmapImage->GetScale() * bitmapImage->GetPPI()
/ 300.0 );
const BITMAP_BASE& bitmapImage = refImage.GetImage();
refImage.SetImageScale( refImage.GetImageScale() * bitmapImage.GetPPI()
/ 300.0 );
break;
}
@ -1592,7 +1594,7 @@ void SCH_IO_KICAD_LEGACY::Format( SCH_SHEET* aSheet )
saveSymbol( static_cast<SCH_SYMBOL*>( item ) );
break;
case SCH_BITMAP_T:
saveBitmap( static_cast<SCH_BITMAP*>( item ) );
saveBitmap( static_cast<const SCH_BITMAP&>( *item ) );
break;
case SCH_SHEET_T:
saveSheet( static_cast<SCH_SHEET*>( item ) );
@ -1639,7 +1641,7 @@ void SCH_IO_KICAD_LEGACY::Format( SELECTION* aSelection, OUTPUTFORMATTER* aForma
saveSymbol( static_cast< SCH_SYMBOL* >( item ) );
break;
case SCH_BITMAP_T:
saveBitmap( static_cast< SCH_BITMAP* >( item ) );
saveBitmap( static_cast< const SCH_BITMAP& >( *item ) );
break;
case SCH_SHEET_T:
saveSheet( static_cast< SCH_SHEET* >( item ) );
@ -1812,19 +1814,19 @@ void SCH_IO_KICAD_LEGACY::saveField( SCH_FIELD* aField )
}
void SCH_IO_KICAD_LEGACY::saveBitmap( SCH_BITMAP* aBitmap )
void SCH_IO_KICAD_LEGACY::saveBitmap( const SCH_BITMAP& aBitmap )
{
wxCHECK_RET( aBitmap != nullptr, "SCH_BITMAP* is NULL" );
const REFERENCE_IMAGE& refImage = aBitmap.GetReferenceImage();
const wxImage* image = aBitmap->GetImage()->GetImageData();
const wxImage* image = refImage.GetImage().GetImageData();
wxCHECK_RET( image != nullptr, "wxImage* is NULL" );
m_out->Print( 0, "$Bitmap\n" );
m_out->Print( 0, "Pos %-4d %-4d\n",
schIUScale.IUToMils( aBitmap->GetPosition().x ),
schIUScale.IUToMils( aBitmap->GetPosition().y ) );
m_out->Print( 0, "Scale %f\n", aBitmap->GetImage()->GetScale() );
schIUScale.IUToMils( aBitmap.GetPosition().x ),
schIUScale.IUToMils( aBitmap.GetPosition().y ) );
m_out->Print( 0, "Scale %f\n", refImage.GetImageScale() );
m_out->Print( 0, "Data\n" );
wxMemoryOutputStream stream;

View File

@ -159,7 +159,7 @@ private:
void saveSymbol( SCH_SYMBOL* aSymbol );
void saveField( SCH_FIELD* aField );
void saveBitmap( SCH_BITMAP* aBitmap );
void saveBitmap( const SCH_BITMAP& aBitmap );
void saveSheet( SCH_SHEET* aSheet );
void saveJunction( SCH_JUNCTION* aJunction );
void saveNoConnect( SCH_NO_CONNECT* aNoConnect );

View File

@ -32,6 +32,7 @@
#include <advanced_config.h>
#include <base_units.h>
#include <bitmap_base.h>
#include <build_version.h>
#include <ee_selection.h>
#include <font/fontconfig.h>
@ -444,7 +445,7 @@ void SCH_IO_KICAD_SEXPR::Format( SCH_SHEET* aSheet )
break;
case SCH_BITMAP_T:
saveBitmap( static_cast<SCH_BITMAP*>( item ), 1 );
saveBitmap( static_cast<SCH_BITMAP&>( *item ), 1 );
break;
case SCH_SHEET_T:
@ -597,7 +598,7 @@ void SCH_IO_KICAD_SEXPR::Format( EE_SELECTION* aSelection, SCH_SHEET_PATH* aSele
break;
case SCH_BITMAP_T:
saveBitmap( static_cast< SCH_BITMAP* >( item ), 0 );
saveBitmap( static_cast< SCH_BITMAP& >( *item ), 0 );
break;
case SCH_SHEET_T:
@ -964,28 +965,30 @@ void SCH_IO_KICAD_SEXPR::saveField( SCH_FIELD* aField, int aNestLevel )
}
void SCH_IO_KICAD_SEXPR::saveBitmap( SCH_BITMAP* aBitmap, int aNestLevel )
void SCH_IO_KICAD_SEXPR::saveBitmap( const SCH_BITMAP& aBitmap, int aNestLevel )
{
wxCHECK_RET( aBitmap != nullptr && m_out != nullptr, "" );
wxCHECK_RET( m_out != nullptr, "" );
const wxImage* image = aBitmap->GetImage()->GetImageData();
const REFERENCE_IMAGE& refImage = aBitmap.GetReferenceImage();
const BITMAP_BASE& bitmapBase = refImage.GetImage();
const wxImage* image = bitmapBase.GetImageData();
wxCHECK_RET( image != nullptr, "wxImage* is NULL" );
m_out->Print( aNestLevel, "(image (at %s %s)",
EDA_UNIT_UTILS::FormatInternalUnits( schIUScale,
aBitmap->GetPosition().x ).c_str(),
refImage.GetPosition().x ).c_str(),
EDA_UNIT_UTILS::FormatInternalUnits( schIUScale,
aBitmap->GetPosition().y ).c_str() );
refImage.GetPosition().y ).c_str() );
double scale = aBitmap->GetImage()->GetScale();
double scale = refImage.GetImageScale();
// 20230121 or older file format versions assumed 300 image PPI at load/save.
// Let's keep compatibility by changing image scale.
if( SEXPR_SCHEMATIC_FILE_VERSION <= 20230121 )
{
BITMAP_BASE* bm_image = aBitmap->GetImage();
scale = scale * 300.0 / bm_image->GetPPI();
scale = scale * 300.0 / bitmapBase.GetPPI();
}
if( scale != 1.0 )
@ -993,11 +996,11 @@ void SCH_IO_KICAD_SEXPR::saveBitmap( SCH_BITMAP* aBitmap, int aNestLevel )
m_out->Print( 0, "\n" );
KICAD_FORMAT::FormatUuid( m_out, aBitmap->m_Uuid );
KICAD_FORMAT::FormatUuid( m_out, aBitmap.m_Uuid );
m_out->Print( aNestLevel + 1, "(data" );
wxString out = wxBase64Encode( aBitmap->GetImage()->GetImageDataBuffer() );
wxString out = wxBase64Encode( bitmapBase.GetImageDataBuffer() );
// Apparently the MIME standard character width for base64 encoding is 76 (unconfirmed)
// so use it in a vein attempt to be standard like.

View File

@ -145,7 +145,7 @@ private:
const SCH_SHEET_LIST& aSheetList, int aNestLevel,
bool aForClipboard, const SCH_SHEET_PATH* aRelativePath = nullptr );
void saveField( SCH_FIELD* aField, int aNestLevel );
void saveBitmap( SCH_BITMAP* aBitmap, int aNestLevel );
void saveBitmap( const SCH_BITMAP& aBitmap, int aNestLevel );
void saveSheet( SCH_SHEET* aSheet, const SCH_SHEET_LIST& aSheetList, int aNestLevel );
void saveJunction( SCH_JUNCTION* aJunction, int aNestLevel );
void saveNoConnect( SCH_NO_CONNECT* aNoConnect, int aNestLevel );

View File

@ -36,6 +36,7 @@
#include <wx/tokenzr.h>
#include <base_units.h>
#include <bitmap_base.h>
#include <lib_id.h>
#include <sch_pin.h>
#include <math/util.h> // KiROUND
@ -3266,6 +3267,7 @@ SCH_BITMAP* SCH_IO_KICAD_SEXPR_PARSER::parseImage()
T token;
std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>();
REFERENCE_IMAGE& refImage = bitmap->GetReferenceImage();
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
{
@ -3282,14 +3284,13 @@ SCH_BITMAP* SCH_IO_KICAD_SEXPR_PARSER::parseImage()
break;
case T_scale:
bitmap->GetImage()->SetScale( parseDouble( "image scale factor" ) );
if( !std::isnormal( bitmap->GetImage()->GetScale() ) )
bitmap->GetImage()->SetScale( 1.0 );
{
const double scale = parseDouble( "image scale factor" );
refImage.SetImageScale( std::isnormal( scale ) ? scale : 1.0 );
NeedRIGHT();
break;
}
case T_uuid:
NeedSYMBOL();
const_cast<KIID&>( bitmap->m_Uuid ) = parseKIID();
@ -3317,7 +3318,7 @@ SCH_BITMAP* SCH_IO_KICAD_SEXPR_PARSER::parseImage()
wxMemoryBuffer buffer = wxBase64Decode( data );
if( !bitmap->GetImage()->ReadImageFile( buffer ) )
if( !refImage.ReadImageFile( buffer ) )
THROW_IO_ERROR( _( "Failed to read image data." ) );
break;
@ -3328,15 +3329,13 @@ SCH_BITMAP* SCH_IO_KICAD_SEXPR_PARSER::parseImage()
}
}
// Adjust the image pixel size in iu
BITMAP_BASE* image = bitmap->GetImage();
image->SetPixelSizeIu( (double) schIUScale.MilsToIU( 1000 ) / image->GetPPI() );
// The image will be scaled by PPI in ReadImageFile.
// 20230121 or older file format versions assumed 300 image PPI at load/save.
// Let's keep compatibility by changing image scale.
if( m_requiredVersion <= 20230121 )
{
image->SetScale( image->GetScale() * image->GetPPI() / 300.0 );
refImage.SetImageScale( refImage.GetImageScale() * refImage.GetImage().GetPPI() / 300.0 );
}
return bitmap.release();

View File

@ -26,6 +26,7 @@
#include <trigo.h>
#include <bitmap_base.h>
#include <connection_graph.h>
#include <gal/graphics_abstraction_layer.h>
#include <callback_gal.h>
@ -2953,37 +2954,39 @@ void SCH_PAINTER::draw( const SCH_BITMAP* aBitmap, int aLayer )
m_gal->Save();
m_gal->Translate( aBitmap->GetPosition() );
const REFERENCE_IMAGE& refImage = aBitmap->GetReferenceImage();
// When the image scale factor is not 1.0, we need to modify the actual as the image scale
// factor is similar to a local zoom
double img_scale = aBitmap->GetImageScale();
const double img_scale = refImage.GetImageScale();
if( img_scale != 1.0 )
m_gal->Scale( VECTOR2D( img_scale, img_scale ) );
if( aLayer == LAYER_DRAW_BITMAPS )
{
m_gal->DrawBitmap( *aBitmap->GetImage() );
m_gal->DrawBitmap( refImage.GetImage() );
}
if( aLayer == LAYER_SELECTION_SHADOWS )
{
if( aBitmap->IsSelected() || aBitmap->IsBrightened() )
{
COLOR4D color = getRenderColor( aBitmap, LAYER_DRAW_BITMAPS, true );
const COLOR4D color = getRenderColor( aBitmap, LAYER_DRAW_BITMAPS, true );
m_gal->SetIsStroke( true );
m_gal->SetStrokeColor( color );
m_gal->SetLineWidth ( getShadowWidth( aBitmap->IsBrightened() ) );
m_gal->SetIsFill( false );
// Draws a bounding box.
VECTOR2D bm_size( aBitmap->GetSize() );
VECTOR2D bm_size( refImage.GetSize() );
// bm_size is the actual image size in UI.
// but m_gal scale was previously set to img_scale
// so recalculate size relative to this image size.
bm_size.x /= img_scale;
bm_size.y /= img_scale;
VECTOR2D origin( -bm_size.x / 2.0, -bm_size.y / 2.0 );
VECTOR2D end = origin + bm_size;
const VECTOR2D origin( -bm_size.x / 2.0, -bm_size.y / 2.0 );
const VECTOR2D end = origin + bm_size;
m_gal->DrawRectangle( origin, end );
}

View File

@ -75,6 +75,13 @@ enum RECTANGLE_LINES
RECT_TOP, RECT_RIGHT, RECT_BOT, RECT_LEFT
};
enum REFIMAGE_POINTS
{
REFIMG_ORIGIN = RECT_BOTRIGHT + 1
};
enum TABLECELL_POINTS
{
COL_WIDTH, ROW_HEIGHT
@ -246,14 +253,17 @@ public:
case SCH_BITMAP_T:
{
SCH_BITMAP* bitmap = (SCH_BITMAP*) aItem;
VECTOR2I topLeft = bitmap->GetPosition() - bitmap->GetSize() / 2;
VECTOR2I botRight = bitmap->GetPosition() + bitmap->GetSize() / 2;
const SCH_BITMAP& bitmap = static_cast<const SCH_BITMAP&>( *aItem );
const REFERENCE_IMAGE& refImage = bitmap.GetReferenceImage();
const VECTOR2I topLeft = refImage.GetPosition() - refImage.GetSize() / 2;
const VECTOR2I botRight = refImage.GetPosition() + refImage.GetSize() / 2;
points->AddPoint( topLeft );
points->AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
points->AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
points->AddPoint( botRight );
points->AddPoint( refImage.GetPosition() + refImage.GetTransformOriginOffset() );
break;
}
@ -844,30 +854,81 @@ void EE_POINT_EDITOR::updateParentItem( bool aSnapToGrid ) const
case SCH_BITMAP_T:
{
EE_GRID_HELPER gridHelper( m_toolMgr );
SCH_BITMAP* bitmap = (SCH_BITMAP*) item;
VECTOR2I topLeft = m_editPoints->Point( RECT_TOPLEFT ).GetPosition();
VECTOR2I topRight = m_editPoints->Point( RECT_TOPRIGHT ).GetPosition();
VECTOR2I botLeft = m_editPoints->Point( RECT_BOTLEFT ).GetPosition();
VECTOR2I botRight = m_editPoints->Point( RECT_BOTRIGHT ).GetPosition();
SCH_BITMAP& bitmap = static_cast<SCH_BITMAP&>( *item );
REFERENCE_IMAGE& refImg = bitmap.GetReferenceImage();
const VECTOR2I topLeft = m_editPoints->Point( RECT_TOPLEFT ).GetPosition();
const VECTOR2I topRight = m_editPoints->Point( RECT_TOPRIGHT ).GetPosition();
const VECTOR2I botLeft = m_editPoints->Point( RECT_BOTLEFT ).GetPosition();
const VECTOR2I botRight = m_editPoints->Point( RECT_BOTRIGHT ).GetPosition();
const VECTOR2I xfrmOrigin = m_editPoints->Point( REFIMG_ORIGIN ).GetPosition();
gridHelper.SetSnap( aSnapToGrid );
if( isModified( m_editPoints->Point( REFIMG_ORIGIN ) ) )
{
// Moving the transform origin
// As the other points didn't move, we can get the image extent from them
const VECTOR2I newOffset = xfrmOrigin - ( topLeft + botRight ) / 2;
refImg.SetTransformOriginOffset( newOffset );
}
else
{
const VECTOR2I oldOrigin = refImg.GetPosition() + refImg.GetTransformOriginOffset();
const VECTOR2I oldSize = refImg.GetSize();
const VECTOR2I pos = refImg.GetPosition();
pinEditedCorner( schIUScale.MilsToIU( 50 ), schIUScale.MilsToIU( 50 ), topLeft, topRight,
botLeft, botRight, &gridHelper );
OPT_VECTOR2I newCorner;
VECTOR2I oldCorner = pos;
double oldWidth = bitmap->GetSize().x;
double newWidth = topRight.x - topLeft.x;
double widthRatio = newWidth / oldWidth;
if( isModified( m_editPoints->Point( RECT_TOPLEFT ) ) )
{
newCorner = topLeft;
oldCorner -= oldSize / 2;
}
else if( isModified( m_editPoints->Point( RECT_TOPRIGHT ) ) )
{
newCorner = topRight;
oldCorner -= VECTOR2I( -oldSize.x, oldSize.y ) / 2;
}
else if( isModified( m_editPoints->Point( RECT_BOTLEFT ) ) )
{
newCorner = botLeft;
oldCorner -= VECTOR2I( oldSize.x, -oldSize.y ) / 2;
}
else if( isModified( m_editPoints->Point( RECT_BOTRIGHT ) ) )
{
newCorner = botRight;
oldCorner += oldSize / 2;
}
double oldHeight = bitmap->GetSize().y;
double newHeight = botLeft.y - topLeft.y;
double heightRatio = newHeight / oldHeight;
if( newCorner )
{
// Turn in the respective vectors from the origin
*newCorner -= xfrmOrigin;
oldCorner -= oldOrigin;
bitmap->SetImageScale( bitmap->GetImageScale() * std::min( widthRatio, heightRatio ) );
// If we tried to cross the origin, clamp it to stop it
if( sign( newCorner->x ) != sign( oldCorner.x )
|| sign( newCorner->y ) != sign( oldCorner.y ) )
{
*newCorner = VECTOR2I( 0, 0 );
}
const double newLength = newCorner->EuclideanNorm();
const double oldLength = oldCorner.EuclideanNorm();
double ratio = oldLength > 0 ? ( newLength / oldLength ) : 1.0;
// Clamp the scaling to a minimum of 50 mils
VECTOR2I newSize = oldSize * ratio;
double newWidth = std::max( newSize.x, EDA_UNIT_UTILS::Mils2IU( pcbIUScale, 50 ) );
double newHeight = std::max( newSize.y, EDA_UNIT_UTILS::Mils2IU( pcbIUScale, 50 ) );
ratio = std::min( newWidth / oldSize.x, newHeight / oldSize.y );
// Also handles the origin offset
refImg.SetImageScale( refImg.GetImageScale() * ratio );
}
}
break;
}
case SCH_SHEET_T:
{
SCH_SHEET* sheet = (SCH_SHEET*) item;
@ -1099,14 +1160,18 @@ void EE_POINT_EDITOR::updatePoints()
case SCH_BITMAP_T:
{
SCH_BITMAP* bitmap = (SCH_BITMAP*) item;
VECTOR2I topLeft = bitmap->GetPosition() - bitmap->GetSize() / 2;
VECTOR2I botRight = bitmap->GetPosition() + bitmap->GetSize() / 2;
const SCH_BITMAP& bitmap = static_cast<SCH_BITMAP&>( *item );
const REFERENCE_IMAGE& refImage = bitmap.GetReferenceImage();
const VECTOR2I topLeft = refImage.GetPosition() - refImage.GetSize() / 2;
const VECTOR2I botRight = refImage.GetPosition() + refImage.GetSize() / 2;
m_editPoints->Point( RECT_TOPLEFT ).SetPosition( topLeft );
m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( botRight.x, topLeft.y );
m_editPoints->Point( RECT_BOTLEFT ).SetPosition( topLeft.x, botRight.y );
m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight );
m_editPoints->Point( REFIMG_ORIGIN )
.SetPosition( refImage.GetPosition() + refImage.GetTransformOriginOffset() );
break;
}

View File

@ -987,7 +987,7 @@ int SCH_DRAWING_TOOLS::PlaceImage( const TOOL_EVENT& aEvent )
if( wxFileExists( fullFilename ) )
image = new SCH_BITMAP( cursorPos );
if( !image || !image->ReadImageFile( fullFilename ) )
if( !image || !image->GetReferenceImage().ReadImageFile( fullFilename ) )
{
wxMessageBox( wxString::Format( _( "Could not load image from '%s'." ), fullFilename ) );
delete image;

View File

@ -2197,7 +2197,7 @@ int SCH_EDIT_TOOL::Properties( const TOOL_EVENT& aEvent )
case SCH_BITMAP_T:
{
SCH_BITMAP* bitmap = static_cast<SCH_BITMAP*>( curr_item );
SCH_BITMAP& bitmap = static_cast<SCH_BITMAP&>( *curr_item );
DIALOG_IMAGE_PROPERTIES dlg( m_frame, bitmap );
if( dlg.ShowModal() == wxID_OK )

View File

@ -130,7 +130,7 @@ public:
const BOX2I GetBoundingBox() const;
void DrawBitmap( wxDC* aDC, const VECTOR2I& aPos,
const KIGFX::COLOR4D& aBackgroundColor = KIGFX::COLOR4D::UNSPECIFIED );
const KIGFX::COLOR4D& aBackgroundColor = KIGFX::COLOR4D::UNSPECIFIED ) const;
/**
* Reads and stores in memory an image file.