Commit 91c53a94 authored by jean-pierre charras's avatar jean-pierre charras

bitmap2component: add management of image resolution: Is read from file, when...

bitmap2component: add management of image resolution: Is read from file, when exists, and can be modified in bitmap2component.
It also fix issue #747631
parent 59a0ced0
...@@ -27,10 +27,6 @@ ...@@ -27,10 +27,6 @@
#include <confirm.h> #include <confirm.h>
#include <gestfich.h> #include <gestfich.h>
#include <wx/wx.h>
#include <wx/config.h>
#include <wx/filename.h>
#include <bitmap2cmp_gui_base.h> #include <bitmap2cmp_gui_base.h>
#include <potracelib.h> #include <potracelib.h>
...@@ -50,7 +46,10 @@ ...@@ -50,7 +46,10 @@
#define KEYWORD_BINARY_THRESHOLD wxT( "Threshold" ) #define KEYWORD_BINARY_THRESHOLD wxT( "Threshold" )
#define KEYWORD_BW_NEGATIVE wxT( "Negative_choice" ) #define KEYWORD_BW_NEGATIVE wxT( "Negative_choice" )
extern int bitmap2component( potrace_bitmap_t* aPotrace_bitmap, FILE* aOutfile, int aFormat ); #define DEFAULT_DPI 300 // Default resolution in Bit per inches
extern int bitmap2component( potrace_bitmap_t* aPotrace_bitmap, FILE* aOutfile,
int aFormat, int aDpi_X, int aDpi_Y );
/* Class BM2CMP_FRAME_BASE /* Class BM2CMP_FRAME_BASE
This is the main frame for this application This is the main frame for this application
...@@ -64,11 +63,13 @@ private: ...@@ -64,11 +63,13 @@ private:
wxBitmap m_Greyscale_Bitmap; wxBitmap m_Greyscale_Bitmap;
wxImage m_NB_Image; wxImage m_NB_Image;
wxBitmap m_BN_Bitmap; wxBitmap m_BN_Bitmap;
wxSize m_imageDPI; // The initial image resolution. When unknown,
// set to DEFAULT_DPI x DEFAULT_DPI per Inch
wxString m_BitmapFileName; wxString m_BitmapFileName;
wxString m_ConvertedFileName; wxString m_ConvertedFileName;
wxSize m_FrameSize; wxSize m_frameSize;
wxPoint m_FramePos; wxPoint m_framePos;
wxConfig * m_Config; wxConfig* m_config;
public: public:
BM2CMP_FRAME(); BM2CMP_FRAME();
...@@ -109,27 +110,43 @@ private: ...@@ -109,27 +110,43 @@ private:
void Binarize( double aThreshold ); // aThreshold = 0.0 (black level) to 1.0 (white level) void Binarize( double aThreshold ); // aThreshold = 0.0 (black level) to 1.0 (white level)
void OnOptionsSelection( wxCommandEvent& event ); void OnOptionsSelection( wxCommandEvent& event );
void OnThresholdChange( wxScrollEvent& event ); void OnThresholdChange( wxScrollEvent& event );
void OnResolutionChange( wxCommandEvent& event );
// called when texts controls which handle the image resolution
// lose the focus, to ensure the rigyht vaules are displayed
// because the m_imageDPI are clipped to acceptable values, and
// the text displayed could be differ duringa text edition
// We are using ChangeValue here to avoid generating a wxEVT_TEXT event.
void UpdateDPITextValueX( wxMouseEvent& event )
{
m_DPIValueX->ChangeValue( wxString::Format( wxT( "%d" ), m_imageDPI.x ) );
}
void UpdateDPITextValueY( wxMouseEvent& event )
{
m_DPIValueY->ChangeValue( wxString::Format( wxT( "%d" ), m_imageDPI.y ) );
}
void NegateGreyscaleImage( ); void NegateGreyscaleImage( );
void ExportFile( FILE* aOutfile, int aFormat ); void ExportFile( FILE* aOutfile, int aFormat );
void updateImageInfo();
}; };
BM2CMP_FRAME::BM2CMP_FRAME() : BM2CMP_FRAME_BASE( NULL ) BM2CMP_FRAME::BM2CMP_FRAME() : BM2CMP_FRAME_BASE( NULL )
{ {
int tmp; int tmp;
m_Config = new wxConfig(); m_config = new wxConfig();
m_Config->Read( KEYWORD_FRAME_POSX, & m_FramePos.x, -1 ); m_config->Read( KEYWORD_FRAME_POSX, & m_framePos.x, -1 );
m_Config->Read( KEYWORD_FRAME_POSY, & m_FramePos.y, -1 ); m_config->Read( KEYWORD_FRAME_POSY, & m_framePos.y, -1 );
m_Config->Read( KEYWORD_FRAME_SIZEX, & m_FrameSize.x, -1 ); m_config->Read( KEYWORD_FRAME_SIZEX, & m_frameSize.x, -1 );
m_Config->Read( KEYWORD_FRAME_SIZEY, & m_FrameSize.y, -1 ); m_config->Read( KEYWORD_FRAME_SIZEY, & m_frameSize.y, -1 );
m_Config->Read( KEYWORD_LAST_INPUT_FILE, &m_BitmapFileName ); m_config->Read( KEYWORD_LAST_INPUT_FILE, &m_BitmapFileName );
m_Config->Read( KEYWORD_LAST_OUTPUT_FILE, &m_ConvertedFileName ); m_config->Read( KEYWORD_LAST_OUTPUT_FILE, &m_ConvertedFileName );
if( m_Config->Read( KEYWORD_BINARY_THRESHOLD, &tmp ) ) if( m_config->Read( KEYWORD_BINARY_THRESHOLD, &tmp ) )
m_sliderThreshold->SetValue( tmp ); m_sliderThreshold->SetValue( tmp );
if( m_Config->Read( KEYWORD_BW_NEGATIVE, &tmp ) ) if( m_config->Read( KEYWORD_BW_NEGATIVE, &tmp ) )
m_rbOptions->SetSelection( tmp ? 1 : 0 ); m_rbOptions->SetSelection( tmp ? 1 : 0 );
m_Config->Read( KEYWORD_LAST_FORMAT, &tmp ); m_config->Read( KEYWORD_LAST_FORMAT, &tmp );
m_radioBoxFormat->SetSelection( tmp ); m_radioBoxFormat->SetSelection( tmp );
...@@ -140,34 +157,36 @@ BM2CMP_FRAME::BM2CMP_FRAME() : BM2CMP_FRAME_BASE( NULL ) ...@@ -140,34 +157,36 @@ BM2CMP_FRAME::BM2CMP_FRAME() : BM2CMP_FRAME_BASE( NULL )
GetSizer()->SetSizeHints( this ); GetSizer()->SetSizeHints( this );
SetSize( m_FramePos.x, m_FramePos.y, m_FrameSize.x, m_FrameSize.y ); SetSize( m_framePos.x, m_framePos.y, m_frameSize.x, m_frameSize.y );
m_buttonExport->Enable( false ); m_buttonExport->Enable( false );
if ( m_FramePos == wxDefaultPosition ) m_imageDPI.x = m_imageDPI.y = DEFAULT_DPI; // Default resolution in Bit per inches
if ( m_framePos == wxDefaultPosition )
Centre(); Centre();
} }
BM2CMP_FRAME::~BM2CMP_FRAME() BM2CMP_FRAME::~BM2CMP_FRAME()
{ {
if( ( m_Config == NULL ) || IsIconized() ) if( ( m_config == NULL ) || IsIconized() )
return; return;
m_FrameSize = GetSize(); m_frameSize = GetSize();
m_FramePos = GetPosition(); m_framePos = GetPosition();
m_Config->Write( KEYWORD_FRAME_POSX, (long) m_FramePos.x ); m_config->Write( KEYWORD_FRAME_POSX, (long) m_framePos.x );
m_Config->Write( KEYWORD_FRAME_POSY, (long) m_FramePos.y ); m_config->Write( KEYWORD_FRAME_POSY, (long) m_framePos.y );
m_Config->Write( KEYWORD_FRAME_SIZEX, (long) m_FrameSize.x ); m_config->Write( KEYWORD_FRAME_SIZEX, (long) m_frameSize.x );
m_Config->Write( KEYWORD_FRAME_SIZEY, (long) m_FrameSize.y ); m_config->Write( KEYWORD_FRAME_SIZEY, (long) m_frameSize.y );
m_Config->Write( KEYWORD_LAST_INPUT_FILE, m_BitmapFileName ); m_config->Write( KEYWORD_LAST_INPUT_FILE, m_BitmapFileName );
m_Config->Write( KEYWORD_LAST_OUTPUT_FILE, m_ConvertedFileName ); m_config->Write( KEYWORD_LAST_OUTPUT_FILE, m_ConvertedFileName );
m_Config->Write( KEYWORD_BINARY_THRESHOLD, m_sliderThreshold->GetValue() ); m_config->Write( KEYWORD_BINARY_THRESHOLD, m_sliderThreshold->GetValue() );
m_Config->Write( KEYWORD_BW_NEGATIVE, m_rbOptions->GetSelection() ); m_config->Write( KEYWORD_BW_NEGATIVE, m_rbOptions->GetSelection() );
m_Config->Write( KEYWORD_LAST_FORMAT, m_radioBoxFormat->GetSelection() ); m_config->Write( KEYWORD_LAST_FORMAT, m_radioBoxFormat->GetSelection() );
delete m_Config; delete m_config;
/* This needed for OSX: avoids further OnDraw processing after this /* This needed for OSX: avoids further OnDraw processing after this
* destructor and before the native window is destroyed * destructor and before the native window is destroyed
...@@ -246,15 +265,31 @@ bool BM2CMP_FRAME::LoadFile( wxString& aFullFileName ) ...@@ -246,15 +265,31 @@ bool BM2CMP_FRAME::LoadFile( wxString& aFullFileName )
int h = m_Pict_Bitmap.GetHeight(); int h = m_Pict_Bitmap.GetHeight();
int w = m_Pict_Bitmap.GetWidth(); int w = m_Pict_Bitmap.GetWidth();
int nb = m_Pict_Bitmap.GetDepth(); // Determine image resolution in DPI (does not existing in all formats).
// the resolution can be given in bit per inches or bit per cm in file
m_imageDPI.x = m_Pict_Image.GetOptionInt( wxIMAGE_OPTION_RESOLUTIONX );
m_imageDPI.y = m_Pict_Image.GetOptionInt( wxIMAGE_OPTION_RESOLUTIONY );
if( m_imageDPI.x > 1 && m_imageDPI.y > 1 )
{
if( m_Pict_Image.GetOptionInt( wxIMAGE_OPTION_RESOLUTIONUNIT ) == wxIMAGE_RESOLUTION_CM )
{
// When the initial resolution is given in bits per cm,
// experience shows adding 1.27 to the resolution converted in dpi
// before convert to int value reduce the conversion error
// but it is not perfect
m_imageDPI.x = m_imageDPI.x * 2.54 + 1.27;
m_imageDPI.y = m_imageDPI.y * 2.54 + 1.27;
}
}
else // fallback to the default value
m_imageDPI.x = m_imageDPI.y = DEFAULT_DPI;
wxString msg; // Display image info:
msg.Printf( wxT( "%d" ), w ); // We are using ChangeValue here to avoid generating a wxEVT_TEXT event.
m_SizeXValue->SetLabel(msg); m_DPIValueX->ChangeValue( wxString::Format( wxT( "%d" ), m_imageDPI.x ) );
msg.Printf( wxT( "%d" ), h ); m_DPIValueY->ChangeValue( wxString::Format( wxT( "%d" ), m_imageDPI.y ) );
m_SizeYValue->SetLabel(msg); updateImageInfo();
msg.Printf( wxT( "%d" ), nb );
m_BPPValue->SetLabel(msg);
m_InitialPicturePanel->SetVirtualSize( w, h ); m_InitialPicturePanel->SetVirtualSize( w, h );
m_GreyscalePicturePanel->SetVirtualSize( w, h ); m_GreyscalePicturePanel->SetVirtualSize( w, h );
...@@ -272,6 +307,43 @@ bool BM2CMP_FRAME::LoadFile( wxString& aFullFileName ) ...@@ -272,6 +307,43 @@ bool BM2CMP_FRAME::LoadFile( wxString& aFullFileName )
return true; return true;
} }
void BM2CMP_FRAME::updateImageInfo()
{
// Note: the image resolution text controls are not modified
// here, to avoid a race between text change when entered by user and
// a text change if it is modifed here.
int h = m_Pict_Bitmap.GetHeight();
int w = m_Pict_Bitmap.GetWidth();
int nb = m_Pict_Bitmap.GetDepth();
m_SizeXValue->SetLabel( wxString::Format( wxT( "%d" ), w ) );
m_SizeYValue->SetLabel( wxString::Format( wxT( "%d" ), h ) );
m_BPPValue->SetLabel( wxString::Format( wxT( "%d" ), nb ) );
m_SizeXValue_mm->SetLabel( wxString::Format( wxT( "%.1f" ),
(double) w / m_imageDPI.x * 25.4 ) );
m_SizeYValue_mm->SetLabel( wxString::Format( wxT( "%.1f" ),
(double) h / m_imageDPI.y * 25.4 ) );
}
void BM2CMP_FRAME::OnResolutionChange( wxCommandEvent& event )
{
long tmp;
if( m_DPIValueX->GetValue().ToLong( &tmp ) )
m_imageDPI.x = tmp;
if( m_DPIValueY->GetValue().ToLong( &tmp ) )
m_imageDPI.y = tmp;
if( m_imageDPI.x < 32 )
m_imageDPI.x = 32;
if( m_imageDPI.y < 32 )
m_imageDPI.y = 32;
updateImageInfo();
}
void BM2CMP_FRAME::Binarize( double aThreshold ) void BM2CMP_FRAME::Binarize( double aThreshold )
{ {
...@@ -514,14 +586,14 @@ void BM2CMP_FRAME::ExportFile( FILE* aOutfile, int aFormat ) ...@@ -514,14 +586,14 @@ void BM2CMP_FRAME::ExportFile( FILE* aOutfile, int aFormat )
/* fill the bitmap with data */ /* fill the bitmap with data */
for( int y = 0; y < h; y++ ) for( int y = 0; y < h; y++ )
{ {
for( int x = 0; x<w; x++ ) for( int x = 0; x < w; x++ )
{ {
unsigned char pix = m_NB_Image.GetGreen( x, y ); unsigned char pix = m_NB_Image.GetGreen( x, y );
BM_PUT( potrace_bitmap, x, y, pix ? 1 : 0 ); BM_PUT( potrace_bitmap, x, y, pix ? 1 : 0 );
} }
} }
bitmap2component( potrace_bitmap, aOutfile, aFormat ); bitmap2component( potrace_bitmap, aOutfile, aFormat, m_imageDPI.x, m_imageDPI.y );
} }
......
This diff is collapsed.
This diff is collapsed.
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Oct 8 2012) // C++ code generated with wxFormBuilder (version Nov 6 2013)
// http://www.wxformbuilder.org/ // http://www.wxformbuilder.org/
// //
// PLEASE DO "NOT" EDIT THIS FILE! // PLEASE DO "NOT" EDIT THIS FILE!
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <wx/icon.h> #include <wx/icon.h>
#include <wx/notebook.h> #include <wx/notebook.h>
#include <wx/stattext.h> #include <wx/stattext.h>
#include <wx/textctrl.h>
#include <wx/sizer.h> #include <wx/sizer.h>
#include <wx/statbox.h> #include <wx/statbox.h>
#include <wx/button.h> #include <wx/button.h>
...@@ -47,15 +48,21 @@ class BM2CMP_FRAME_BASE : public wxFrame ...@@ -47,15 +48,21 @@ class BM2CMP_FRAME_BASE : public wxFrame
wxScrolledWindow* m_GreyscalePicturePanel; wxScrolledWindow* m_GreyscalePicturePanel;
wxScrolledWindow* m_BNPicturePanel; wxScrolledWindow* m_BNPicturePanel;
wxPanel* m_panelRight; wxPanel* m_panelRight;
wxStaticText* m_staticTextSizeX; wxStaticText* m_staticTextSize;
wxStaticText* m_SizeXValue; wxStaticText* m_SizeXValue;
wxStaticText* m_SizeXunits;
wxStaticText* m_staticTextSizeY;
wxStaticText* m_SizeYValue; wxStaticText* m_SizeYValue;
wxStaticText* m_SizeYunits; wxStaticText* m_SizePixUnits;
wxStaticText* m_staticTextSize1;
wxStaticText* m_SizeXValue_mm;
wxStaticText* m_SizeYValue_mm;
wxStaticText* m_Size_mmxUnits;
wxStaticText* m_staticTextBPP; wxStaticText* m_staticTextBPP;
wxStaticText* m_BPPValue; wxStaticText* m_BPPValue;
wxStaticText* m_BPPunits; wxStaticText* m_BPPunits;
wxStaticText* m_staticTextBPI;
wxTextCtrl* m_DPIValueX;
wxTextCtrl* m_DPIValueY;
wxStaticText* m_DPI_Units;
wxButton* m_buttonLoad; wxButton* m_buttonLoad;
wxButton* m_buttonExport; wxButton* m_buttonExport;
wxRadioBox* m_radioBoxFormat; wxRadioBox* m_radioBoxFormat;
...@@ -66,6 +73,9 @@ class BM2CMP_FRAME_BASE : public wxFrame ...@@ -66,6 +73,9 @@ class BM2CMP_FRAME_BASE : public wxFrame
// Virtual event handlers, overide them in your derived class // Virtual event handlers, overide them in your derived class
virtual void OnPaint( wxPaintEvent& event ) { event.Skip(); } virtual void OnPaint( wxPaintEvent& event ) { event.Skip(); }
virtual void UpdatePPITextValueX( wxMouseEvent& event ) { event.Skip(); }
virtual void OnResolutionChange( wxCommandEvent& event ) { event.Skip(); }
virtual void UpdatePPITextValueY( wxMouseEvent& event ) { event.Skip(); }
virtual void OnLoadFile( wxCommandEvent& event ) { event.Skip(); } virtual void OnLoadFile( wxCommandEvent& event ) { event.Skip(); }
virtual void OnExport( wxCommandEvent& event ) { event.Skip(); } virtual void OnExport( wxCommandEvent& event ) { event.Skip(); }
virtual void OnOptionsSelection( wxCommandEvent& event ) { event.Skip(); } virtual void OnOptionsSelection( wxCommandEvent& event ) { event.Skip(); }
......
...@@ -138,12 +138,12 @@ BITMAPCONV_INFO::BITMAPCONV_INFO() ...@@ -138,12 +138,12 @@ BITMAPCONV_INFO::BITMAPCONV_INFO()
} }
int bitmap2component( potrace_bitmap_t* aPotrace_bitmap, FILE* aOutfile, int aFormat ) int bitmap2component( potrace_bitmap_t* aPotrace_bitmap, FILE* aOutfile,
int aFormat, int aDpi_X, int aDpi_Y )
{ {
potrace_param_t* param; potrace_param_t* param;
potrace_state_t* st; potrace_state_t* st;
// set tracing parameters, starting from defaults // set tracing parameters, starting from defaults
param = potrace_param_default(); param = potrace_param_default();
if( !param ) if( !param )
...@@ -171,8 +171,8 @@ int bitmap2component( potrace_bitmap_t* aPotrace_bitmap, FILE* aOutfile, int aFo ...@@ -171,8 +171,8 @@ int bitmap2component( potrace_bitmap_t* aPotrace_bitmap, FILE* aOutfile, int aFo
{ {
case 4: case 4:
info.m_Format = KICAD_LOGO; info.m_Format = KICAD_LOGO;
info.m_ScaleX = 1e3 * 25.4 / 300; // the conversion scale from PPI to micro info.m_ScaleX = 1e3 * 25.4 / aDpi_X; // the conversion scale from PPI to micro
info.m_ScaleY = info.m_ScaleX; // Y axis is top to bottom info.m_ScaleY = 1e3 * 25.4 / aDpi_Y; // Y axis is top to bottom
info.CreateOutputFile(); info.CreateOutputFile();
break; break;
...@@ -186,22 +186,22 @@ int bitmap2component( potrace_bitmap_t* aPotrace_bitmap, FILE* aOutfile, int aFo ...@@ -186,22 +186,22 @@ int bitmap2component( potrace_bitmap_t* aPotrace_bitmap, FILE* aOutfile, int aFo
case 2: case 2:
info.m_Format = EESCHEMA_FMT; info.m_Format = EESCHEMA_FMT;
info.m_ScaleX = 1000.0 / 300; // the conversion scale from PPI to UI info.m_ScaleX = 1000.0 / aDpi_X; // the conversion scale from PPI to UI
info.m_ScaleY = -info.m_ScaleX; // Y axis is bottom to Top for components in libs info.m_ScaleY = -1000.0 / aDpi_Y; // Y axis is bottom to Top for components in libs
info.CreateOutputFile(); info.CreateOutputFile();
break; break;
case 1: case 1:
info.m_Format = PCBNEW_KICAD_MOD; info.m_Format = PCBNEW_KICAD_MOD;
info.m_ScaleX = 1e6 * 25.4 / 300; // the conversion scale from PPI to UI info.m_ScaleX = 1e6 * 25.4 / aDpi_X; // the conversion scale from PPI to UI
info.m_ScaleY = info.m_ScaleX; // Y axis is top to bottom in modedit info.m_ScaleY = 1e6 * 25.4 / aDpi_Y; // Y axis is top to bottom in modedit
info.CreateOutputFile(); info.CreateOutputFile();
break; break;
case 0: case 0:
info.m_Format = PCBNEW_LEGACY_EMP; info.m_Format = PCBNEW_LEGACY_EMP;
info.m_ScaleX = 10000.0 / 300; // the conversion scale info.m_ScaleX = 10000.0 / aDpi_X; // the conversion scale
info.m_ScaleY = info.m_ScaleX; // Y axis is top to bottom in modedit info.m_ScaleY = 10000.0 / aDpi_Y; // Y axis is top to bottom in modedit
info.CreateOutputFile(); info.CreateOutputFile();
break; break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment