KiCad PCB EDA Suite
bitmap2cmp_gui.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KICAD, a free EDA CAD application.
3 *
4 * Copyright (C) 1992-2010 jean-pierre.charras
5 * Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include "bitmap2cmp_gui.h"
26#include "bitmap2component.h"
27#include <bitmap2cmp_settings.h>
28#include <bitmap_io.h>
29#include <bitmaps.h>
30#include <kiface_base.h>
31#include <math/util.h> // for KiROUND
32#include <kiway.h>
33#include <potracelib.h>
35#include <wx/clipbrd.h>
36#include <wx/rawbmp.h>
37#include <wx/filedlg.h>
38#include <wx/rawbmp.h>
39#include <wx/msgdlg.h>
40#include <wx/dcclient.h>
41#include <wx/log.h>
42
43
44#include "bitmap2cmp_gui_base.h"
45
46
47#define DEFAULT_DPI 300 // the image DPI used in formats that do not define a DPI
48
50{
51 m_outputSize = 0.0;
55}
56
57
59{
60 // Safety-check to guarantee no divide-by-zero
61 m_originalDPI = std::max( 1, m_originalDPI );
62
63 // Set the m_outputSize value from the m_originalSizePixels and the selected unit
65 {
67 }
68 else if( m_unit == EDA_UNITS::INCHES )
69 {
71 }
72 else
73 {
75 }
76
77}
78
79
81{
82 int outputDPI;
83
85 {
86 outputDPI = GetOriginalSizePixels() / ( m_outputSize / 25.4 );
87 }
88 else if( m_unit == EDA_UNITS::INCHES )
89 {
90 outputDPI = GetOriginalSizePixels() / m_outputSize;
91 }
92 else
93 {
94 outputDPI = KiROUND( m_outputSize );
95 }
96
97 // Zero is not a DPI, and may cause divide-by-zero errors...
98 outputDPI = std::max( 1, outputDPI );
99
100 return outputDPI;
101}
102
103
105{
106 // Set the unit used for m_outputSize, and convert the old m_outputSize value
107 // to the value in new unit
108 if( aUnit == m_unit )
109 return;
110
111 // Convert m_outputSize to mm:
112 double size_mm;
113
115 {
116 size_mm = m_outputSize;
117 }
118 else if( m_unit == EDA_UNITS::INCHES )
119 {
120 size_mm = m_outputSize * 25.4;
121 }
122 else
123 {
124 // m_outputSize is the DPI, not an image size
125 // the image size is m_originalSizePixels / m_outputSize (in inches)
126 if( m_outputSize )
127 size_mm = m_originalSizePixels / m_outputSize * 25.4;
128 else
129 size_mm = 0;
130 }
131
132 // Convert m_outputSize to new value:
133 if( aUnit == EDA_UNITS::MILLIMETRES )
134 {
135 m_outputSize = size_mm;
136 }
137 else if( aUnit == EDA_UNITS::INCHES )
138 {
139 m_outputSize = size_mm / 25.4;
140 }
141 else
142 {
143 if( size_mm )
144 m_outputSize = m_originalSizePixels / size_mm * 25.4;
145 else
146 m_outputSize = 0;
147 }
148
149 m_unit = aUnit;
150}
151
152
153
154BM2CMP_FRAME::BM2CMP_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
155 BM2CMP_FRAME_BASE( aParent )
156{
157 SetKiway( this, aKiway );
158
159 for( wxString unit : { _( "mm" ), _( "Inch" ), _( "DPI" ) } )
160 m_PixelUnit->Append( unit );
161
162 LoadSettings( config() );
163
168
171
172 //Set icon for aspect ratio
173 m_AspectRatioLocked = true;
174 m_AspectRatio = 1;
176
177 // Give an icon
178 wxIcon icon;
179 wxIconBundle icon_bundle;
180
181 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_bitmap2component ) );
182 icon_bundle.AddIcon( icon );
183 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_bitmap2component_32 ) );
184 icon_bundle.AddIcon( icon );
185 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_bitmap2component_16 ) );
186 icon_bundle.AddIcon( icon );
187
188 SetIcons( icon_bundle );
189
190 GetSizer()->SetSizeHints( this );
191
192 m_buttonExportFile->Enable( false );
193 m_buttonExportClipboard->Enable( false );
194
195 SetSize( m_framePos.x, m_framePos.y, m_frameSize.x, m_frameSize.y );
196
197 if ( m_framePos == wxDefaultPosition )
198 Centre();
199}
200
201
203{
204 SaveSettings( config() );
205 /*
206 * This needed for OSX: avoids further OnDraw processing after this
207 * destructor and before the native window is destroyed
208 */
209 Freeze();
210}
211
212
214{
215 return m_Notebook->GetCurrentPage();
216}
217
218
220{
222
223 auto cfg = static_cast<BITMAP2CMP_SETTINGS*>( aCfg );
224
225 m_BitmapFileName = cfg->m_BitmapFileName;
226 m_ConvertedFileName = cfg->m_ConvertedFileName;
227
228 int u_select = cfg->m_Units;
229
230 if( u_select < 0 || u_select > 2 ) // Validity control
231 u_select = 0;
232
233 m_PixelUnit->SetSelection( u_select );
234
235 m_sliderThreshold->SetValue( cfg->m_Threshold );
236
237 m_Negative = cfg->m_Negative;
238 m_checkNegative->SetValue( cfg->m_Negative );
239 m_exportToClipboard = false;
240 m_AspectRatioLocked = false;
241
242 int format = cfg->m_LastFormat;
243
244 if( format < 0 || format > FINAL_FMT )
245 format = PCBNEW_KICAD_MOD;
246
247 m_rbOutputFormat->SetSelection( format );
248
249 if( format == PCBNEW_KICAD_MOD )
250 m_rbPCBLayer->Enable( true );
251 else
252 m_rbPCBLayer->Enable( false );
253
254 int last_layer = cfg->m_LastModLayer;
255
256 if( last_layer > static_cast<int>( MOD_LYR_FINAL ) ) // Out of range
257 m_rbPCBLayer->SetSelection( MOD_LYR_FSILKS );
258 else
259 m_rbPCBLayer->SetSelection( last_layer );
260}
261
262
264{
266
267 auto cfg = static_cast<BITMAP2CMP_SETTINGS*>( aCfg );
268
270 cfg->m_ConvertedFileName = m_ConvertedFileName;
271 cfg->m_Threshold = m_sliderThreshold->GetValue();
272 cfg->m_Negative = m_checkNegative->IsChecked();
273 cfg->m_LastFormat = m_rbOutputFormat->GetSelection();
274 cfg->m_LastModLayer = m_rbPCBLayer->GetSelection();
275 cfg->m_Units = m_PixelUnit->GetSelection();
276}
277
278
279void BM2CMP_FRAME::OnPaintInit( wxPaintEvent& event )
280{
281#ifdef __WXMAC__
282 // Otherwise fails due: using wxPaintDC without being in a native paint event
283 wxClientDC pict_dc( m_InitialPicturePanel );
284#else
285 wxPaintDC pict_dc( m_InitialPicturePanel );
286#endif
287
288 m_InitialPicturePanel->PrepareDC( pict_dc );
289
290 // OSX crashes with empty bitmaps (on initial refreshes)
291 if( m_Pict_Bitmap.IsOk() )
292 pict_dc.DrawBitmap( m_Pict_Bitmap, 0, 0, !!m_Pict_Bitmap.GetMask() );
293
294 event.Skip();
295}
296
297
298void BM2CMP_FRAME::OnPaintGreyscale( wxPaintEvent& event )
299{
300#ifdef __WXMAC__
301 // Otherwise fails due: using wxPaintDC without being in a native paint event
302 wxClientDC greyscale_dc( m_GreyscalePicturePanel );
303#else
304 wxPaintDC greyscale_dc( m_GreyscalePicturePanel );
305#endif
306
307 m_GreyscalePicturePanel->PrepareDC( greyscale_dc );
308
309 // OSX crashes with empty bitmaps (on initial refreshes)
310 if( m_Greyscale_Bitmap.IsOk() )
311 greyscale_dc.DrawBitmap( m_Greyscale_Bitmap, 0, 0, !!m_Greyscale_Bitmap.GetMask() );
312
313 event.Skip();
314}
315
316
317void BM2CMP_FRAME::OnPaintBW( wxPaintEvent& event )
318{
319#ifdef __WXMAC__
320 // Otherwise fails due: using wxPaintDC without being in a native paint event
321 wxClientDC nb_dc( m_BNPicturePanel );
322#else
323 wxPaintDC nb_dc( m_BNPicturePanel );
324#endif
325
326 m_BNPicturePanel->PrepareDC( nb_dc );
327
328 if( m_BN_Bitmap.IsOk() )
329 nb_dc.DrawBitmap( m_BN_Bitmap, 0, 0, !!m_BN_Bitmap.GetMask() );
330
331 event.Skip();
332}
333
334
335void BM2CMP_FRAME::OnLoadFile( wxCommandEvent& event )
336{
337 wxFileName fn( m_BitmapFileName );
338 wxString path = fn.GetPath();
339
340 if( path.IsEmpty() || !wxDirExists( path ) )
341 path = m_mruPath;
342
343 wxFileDialog fileDlg( this, _( "Choose Image" ), path, wxEmptyString,
344 _( "Image Files" ) + wxS( " " )+ wxImage::GetImageExtWildcard(),
345 wxFD_OPEN | wxFD_FILE_MUST_EXIST );
346
347 int diag = fileDlg.ShowModal();
348
349 if( diag != wxID_OK )
350 return;
351
352 wxString fullFilename = fileDlg.GetPath();
353
354 if( !OpenProjectFiles( std::vector<wxString>( 1, fullFilename ) ) )
355 return;
356
357 fn = fullFilename;
358 m_mruPath = fn.GetPath();
359 SetStatusText( fullFilename );
360 Refresh();
361}
362
363
364bool BM2CMP_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl )
365{
366 m_Pict_Image.Destroy();
367 m_BitmapFileName = aFileSet[0];
368
369 if( !m_Pict_Image.LoadFile( m_BitmapFileName ) )
370 {
371 // LoadFile has its own UI, no need for further failure notification here
372 return false;
373 }
374
375 m_Pict_Bitmap = wxBitmap( m_Pict_Image );
376
377 // Determine image resolution in DPI (does not existing in all formats).
378 // the resolution can be given in bit per inches or bit per cm in file
379
380 int imageDPIx = m_Pict_Image.GetOptionInt( wxIMAGE_OPTION_RESOLUTIONX );
381 int imageDPIy = m_Pict_Image.GetOptionInt( wxIMAGE_OPTION_RESOLUTIONY );
382
383 if( imageDPIx > 1 && imageDPIy > 1 )
384 {
385 if( m_Pict_Image.GetOptionInt( wxIMAGE_OPTION_RESOLUTIONUNIT ) == wxIMAGE_RESOLUTION_CM )
386 {
387 imageDPIx = KiROUND( imageDPIx * 2.54 );
388 imageDPIy = KiROUND( imageDPIy * 2.54 );
389 }
390 }
391 else // fallback to a default value (DEFAULT_DPI)
392 {
393 imageDPIx = imageDPIy = DEFAULT_DPI;
394 }
395
396 m_InputXValueDPI->SetLabel( wxString::Format( wxT( "%d" ), imageDPIx ) );
397 m_InputYValueDPI->SetLabel( wxString::Format( wxT( "%d" ), imageDPIy ) );
398
399 int h = m_Pict_Bitmap.GetHeight();
400 int w = m_Pict_Bitmap.GetWidth();
401 m_AspectRatio = (double) w / h;
402
403 m_outputSizeX.SetOriginalDPI( imageDPIx );
405 m_outputSizeY.SetOriginalDPI( imageDPIy );
407
408 // Update display to keep aspect ratio
409 auto fakeEvent = wxCommandEvent();
410 OnSizeChangeX( fakeEvent );
411
413
414 m_InitialPicturePanel->SetVirtualSize( w, h );
415 m_GreyscalePicturePanel->SetVirtualSize( w, h );
416 m_BNPicturePanel->SetVirtualSize( w, h );
417
418 m_Greyscale_Image.Destroy();
419 m_Greyscale_Image = m_Pict_Image.ConvertToGreyscale( );
420
421 if( m_Pict_Bitmap.GetMask() )
422 {
423 for( int x = 0; x < m_Pict_Bitmap.GetWidth(); x++ )
424 {
425 for( int y = 0; y < m_Pict_Bitmap.GetHeight(); y++ )
426 {
427 if( m_Pict_Image.GetRed( x, y ) == m_Pict_Image.GetMaskRed() &&
428 m_Pict_Image.GetGreen( x, y ) == m_Pict_Image.GetMaskGreen() &&
429 m_Pict_Image.GetBlue( x, y ) == m_Pict_Image.GetMaskBlue() )
430 {
431 m_Greyscale_Image.SetRGB( x, y, 255, 255, 255 );
432 }
433 }
434 }
435 }
436
437 if( m_Negative )
439
442 Binarize( (double) m_sliderThreshold->GetValue() / m_sliderThreshold->GetMax() );
443
444 m_buttonExportFile->Enable( true );
445 m_buttonExportClipboard->Enable( true );
446
451
452 return true;
453}
454
455
456// return a string giving the output size, according to the selected unit
457wxString BM2CMP_FRAME::FormatOutputSize( double aSize )
458{
459 wxString text;
460
462 {
463 text.Printf( "%.1f", aSize );
464 }
466 {
467 text.Printf( "%.2f", aSize );
468 }
469 else
470 {
471 text.Printf( wxT( "%d" ), KiROUND( aSize ) );
472 }
473
474 return text;
475}
476
478{
479 // Note: the image resolution text controls are not modified
480 // here, to avoid a race between text change when entered by user and
481 // a text change if it is modified here.
482
483 if( m_Pict_Bitmap.IsOk() )
484 {
485 int h = m_Pict_Bitmap.GetHeight();
486 int w = m_Pict_Bitmap.GetWidth();
487 int nb = m_Pict_Bitmap.GetDepth();
488
489 m_SizeXValue->SetLabel( wxString::Format( wxT( "%d" ), w ) );
490 m_SizeYValue->SetLabel( wxString::Format( wxT( "%d" ), h ) );
491 m_BPPValue->SetLabel( wxString::Format( wxT( "%d" ), nb ) );
492 }
493}
494
495
497{
498 // return the EDA_UNITS from the m_PixelUnit choice
499 switch( m_PixelUnit->GetSelection() )
500 {
501 case 1:
502 return EDA_UNITS::INCHES;
503
504 case 2:
505 return EDA_UNITS::UNSCALED;
506
507 case 0:
508 default:
509 break;
510 }
511
513}
514
515
516void BM2CMP_FRAME::OnSizeChangeX( wxCommandEvent& event )
517{
518 double new_size;
519
520 if( m_UnitSizeX->GetValue().ToDouble( &new_size ) )
521 {
523 {
524 double calculatedY = new_size / m_AspectRatio;
525
527 {
528 // for units in DPI, keeping aspect ratio cannot use m_AspectRatioLocked.
529 // just re-scale the other dpi
530 double ratio = new_size / m_outputSizeX.GetOutputSize();
531 calculatedY = m_outputSizeY.GetOutputSize() * ratio;
532 }
533
536 }
537
539 }
540
542}
543
544
545void BM2CMP_FRAME::OnSizeChangeY( wxCommandEvent& event )
546{
547 double new_size;
548
549 if( m_UnitSizeY->GetValue().ToDouble( &new_size ) )
550 {
552 {
553 double calculatedX = new_size * m_AspectRatio;
554
556 {
557 // for units in DPI, keeping aspect ratio cannot use m_AspectRatioLocked.
558 // just re-scale the other dpi
559 double ratio = new_size / m_outputSizeX.GetOutputSize();
560 calculatedX = m_outputSizeX.GetOutputSize() * ratio;
561 }
562
565 }
566
568 }
569
571}
572
573
574void BM2CMP_FRAME::OnSizeUnitChange( wxCommandEvent& event )
575{
579
582}
583
584
585void BM2CMP_FRAME::ToggleAspectRatioLock( wxCommandEvent& event )
586{
588
590 {
592 //Force display update when aspect ratio is locked
593 auto fakeEvent = wxCommandEvent();
594 OnSizeChangeX( fakeEvent );
595 }
596
597 else
598 {
600 }
601}
602
603
604void BM2CMP_FRAME::Binarize( double aThreshold )
605{
606 int h = m_Greyscale_Image.GetHeight();
607 int w = m_Greyscale_Image.GetWidth();
608 unsigned char threshold = aThreshold * 255;
609 unsigned char alpha_thresh = 0.7 * threshold;
610
611 for( int y = 0; y < h; y++ )
612 for( int x = 0; x < w; x++ )
613 {
614 unsigned char pixout;
615 auto pixin = m_Greyscale_Image.GetGreen( x, y );
616 auto alpha = m_Greyscale_Image.HasAlpha() ?
617 m_Greyscale_Image.GetAlpha( x, y ) : wxALPHA_OPAQUE;
618
619 if( pixin < threshold && alpha > alpha_thresh )
620 pixout = 0;
621 else
622 pixout = 255;
623
624 m_NB_Image.SetRGB( x, y, pixout, pixout, pixout );
625
626 }
627
628 m_BN_Bitmap = wxBitmap( m_NB_Image );
629
630}
631
632
634{
635 unsigned char pix;
636 int h = m_Greyscale_Image.GetHeight();
637 int w = m_Greyscale_Image.GetWidth();
638
639 for( int y = 0; y < h; y++ )
640 for( int x = 0; x < w; x++ )
641 {
642 pix = m_Greyscale_Image.GetGreen( x, y );
643 pix = ~pix;
644 m_Greyscale_Image.SetRGB( x, y, pix, pix, pix );
645 }
646}
647
648
649void BM2CMP_FRAME::OnNegativeClicked( wxCommandEvent& )
650{
651 if( m_checkNegative->GetValue() != m_Negative )
652 {
654
656 Binarize( (double)m_sliderThreshold->GetValue()/m_sliderThreshold->GetMax() );
657 m_Negative = m_checkNegative->GetValue();
658
659 Refresh();
660 }
661}
662
663
664void BM2CMP_FRAME::OnThresholdChange( wxScrollEvent& event )
665{
666 Binarize( (double)m_sliderThreshold->GetValue()/m_sliderThreshold->GetMax() );
667 Refresh();
668}
669
670
671void BM2CMP_FRAME::OnExportToFile( wxCommandEvent& event )
672{
673 m_exportToClipboard = false;
674
675 // choices of m_rbOutputFormat are expected to be in same order as
676 // OUTPUT_FMT_ID. See bitmap2component.h
677 OUTPUT_FMT_ID format = (OUTPUT_FMT_ID) m_rbOutputFormat->GetSelection();
678 exportBitmap( format );
679}
680
681
682void BM2CMP_FRAME::OnExportToClipboard( wxCommandEvent& event )
683{
684 m_exportToClipboard = true;
685
686 // choices of m_rbOutputFormat are expected to be in same order as
687 // OUTPUT_FMT_ID. See bitmap2component.h
688 OUTPUT_FMT_ID format = (OUTPUT_FMT_ID) m_rbOutputFormat->GetSelection();
689
690 std::string buffer;
691 ExportToBuffer( buffer, format );
692
693 wxLogNull doNotLog; // disable logging of failed clipboard actions
694
695 // Write buffer to the clipboard
696 if( wxTheClipboard->Open() )
697 {
698 // This data objects are held by the clipboard,
699 // so do not delete them in the app.
700 wxTheClipboard->SetData( new wxTextDataObject( buffer.c_str() ) );
701 wxTheClipboard->Flush(); // Allow data to be available after closing KiCad
702 wxTheClipboard->Close();
703 }
704 else
705 {
706 wxMessageBox( _( "Unable to export to the Clipboard") );
707 }
708}
709
710
712{
713 switch( aFormat )
714 {
715 case EESCHEMA_FMT:
717 break;
718
719 case PCBNEW_KICAD_MOD:
721 break;
722
723 case POSTSCRIPT_FMT:
725 break;
726
727 case KICAD_WKS_LOGO:
728 OnExportLogo();
729 break;
730 }
731}
732
733
735{
736 wxFileName fn( m_ConvertedFileName );
737 wxString path = fn.GetPath();
738
739 if( path.IsEmpty() || !wxDirExists(path) )
740 path = ::wxGetCwd();
741
742 wxFileDialog fileDlg( this, _( "Create Logo File" ), path, wxEmptyString,
743 DrawingSheetFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
744 int diag = fileDlg.ShowModal();
745
746 if( diag != wxID_OK )
747 return;
748
749 fn = fileDlg.GetPath();
750 fn.SetExt( DrawingSheetFileExtension );
751 m_ConvertedFileName = fn.GetFullPath();
752
753 FILE* outfile;
754 outfile = wxFopen( m_ConvertedFileName, wxT( "w" ) );
755
756 if( outfile == nullptr )
757 {
758 wxString msg;
759 msg.Printf( _( "File '%s' could not be created." ), m_ConvertedFileName );
760 wxMessageBox( msg );
761 return;
762 }
763
764 std::string buffer;
766 fputs( buffer.c_str(), outfile );
767 fclose( outfile );
768}
769
770
772{
773 wxFileName fn( m_ConvertedFileName );
774 wxString path = fn.GetPath();
775
776 if( path.IsEmpty() || !wxDirExists( path ) )
777 path = ::wxGetCwd();
778
779 wxFileDialog fileDlg( this, _( "Create PostScript File" ),
780 path, wxEmptyString,
782 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
783
784 int diag = fileDlg.ShowModal();
785
786 if( diag != wxID_OK )
787 return;
788
789 fn = fileDlg.GetPath();
790 fn.SetExt( wxT( "ps" ) );
791 m_ConvertedFileName = fn.GetFullPath();
792
793 FILE* outfile;
794 outfile = wxFopen( m_ConvertedFileName, wxT( "w" ) );
795
796 if( outfile == nullptr )
797 {
798 wxString msg;
799 msg.Printf( _( "File '%s' could not be created." ), m_ConvertedFileName );
800 wxMessageBox( msg );
801 return;
802 }
803
804 std::string buffer;
806 fputs( buffer.c_str(), outfile );
807 fclose( outfile );
808}
809
810
812{
813 wxFileName fn( m_ConvertedFileName );
814 wxString path = fn.GetPath();
815
816 if( path.IsEmpty() || !wxDirExists(path) )
817 path = ::wxGetCwd();
818
819 wxFileDialog fileDlg( this, _( "Create Symbol Library" ),
820 path, wxEmptyString,
822 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
823
824 int diag = fileDlg.ShowModal();
825
826 if( diag != wxID_OK )
827 return;
828
829 fn = fileDlg.GetPath();
830 fn.SetExt( KiCadSymbolLibFileExtension );
831 m_ConvertedFileName = fn.GetFullPath();
832
833 FILE* outfile = wxFopen( m_ConvertedFileName, wxT( "w" ) );
834
835 if( outfile == nullptr )
836 {
837 wxString msg;
838 msg.Printf( _( "File '%s' could not be created." ), m_ConvertedFileName );
839 wxMessageBox( msg );
840 return;
841 }
842
843 std::string buffer;
844 ExportToBuffer( buffer, EESCHEMA_FMT );
845 fputs( buffer.c_str(), outfile );
846 fclose( outfile );
847}
848
849
851{
852 wxFileName fn( m_ConvertedFileName );
853 wxString path = fn.GetPath();
854
855 if( path.IsEmpty() || !wxDirExists( path ) )
856 path = m_mruPath;
857
858 wxFileDialog fileDlg( this, _( "Create Footprint Library" ),
859 path, wxEmptyString,
861 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
862
863 int diag = fileDlg.ShowModal();
864
865 if( diag != wxID_OK )
866 return;
867
868 fn = fileDlg.GetPath();
869 fn.SetExt( KiCadFootprintFileExtension );
870 m_ConvertedFileName = fn.GetFullPath();
871
872 FILE* outfile = wxFopen( m_ConvertedFileName, wxT( "w" ) );
873
874 if( outfile == nullptr )
875 {
876 wxString msg;
877 msg.Printf( _( "File '%s' could not be created." ), m_ConvertedFileName );
878 wxMessageBox( msg );
879 return;
880 }
881
882 std::string buffer;
884 fputs( buffer.c_str(), outfile );
885 fclose( outfile );
886 m_mruPath = fn.GetPath();
887}
888
889
890void BM2CMP_FRAME::ExportToBuffer( std::string& aOutput, OUTPUT_FMT_ID aFormat )
891{
892 // Create a potrace bitmap
893 int h = m_NB_Image.GetHeight();
894 int w = m_NB_Image.GetWidth();
895 potrace_bitmap_t* potrace_bitmap = bm_new( w, h );
896
897 if( !potrace_bitmap )
898 {
899 wxString msg;
900 msg.Printf( _( "Error allocating memory for potrace bitmap" ) );
901 wxMessageBox( msg );
902 return;
903 }
904
905 /* fill the bitmap with data */
906 for( int y = 0; y < h; y++ )
907 {
908 for( int x = 0; x < w; x++ )
909 {
910 auto pix = m_NB_Image.GetGreen( x, y );
911 BM_PUT( potrace_bitmap, x, y, pix ? 0 : 1 );
912 }
913 }
914
915 // choices of m_rbPCBLayer are expected to be in same order as
916 // BMP2CMP_MOD_LAYER. See bitmap2component.h
918
919 if( aFormat == PCBNEW_KICAD_MOD )
920 modLayer = (BMP2CMP_MOD_LAYER) m_rbPCBLayer->GetSelection();
921
922 BITMAPCONV_INFO converter( aOutput );
923 converter.ConvertBitmap( potrace_bitmap, aFormat, m_outputSizeX.GetOutputDPI(),
924 m_outputSizeY.GetOutputDPI(), modLayer );
925
926 if( !converter.GetErrorMessages().empty() )
927 wxMessageBox( converter.GetErrorMessages().c_str(), _( "Errors" ) );
928}
929
930
931void BM2CMP_FRAME::OnFormatChange( wxCommandEvent& event )
932{
933 if( m_rbOutputFormat->GetSelection() == PCBNEW_KICAD_MOD )
934 m_rbPCBLayer->Enable( true );
935 else
936 m_rbPCBLayer->Enable( false );
937}
#define DEFAULT_DPI
BMP2CMP_MOD_LAYER
@ MOD_LYR_FSILKS
@ MOD_LYR_FINAL
OUTPUT_FMT_ID
@ FINAL_FMT
@ KICAD_WKS_LOGO
@ PCBNEW_KICAD_MOD
@ POSTSCRIPT_FMT
@ EESCHEMA_FMT
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:105
@ icon_bitmap2component
@ icon_bitmap2component_32
@ icon_bitmap2component_16
APP_SETTINGS_BASE is a settings class that should be derived for each standalone KiCad application.
Definition: app_settings.h:101
std::string & GetErrorMessages()
int ConvertBitmap(potrace_bitmap_t *aPotrace_bitmap, OUTPUT_FMT_ID aFormat, int aDpi_X, int aDpi_Y, BMP2CMP_MOD_LAYER aModLayer)
Run the conversion of the bitmap.
Class BM2CMP_FRAME_BASE.
wxStaticText * m_InputYValueDPI
wxSlider * m_sliderThreshold
wxButton * m_buttonExportFile
wxTextCtrl * m_UnitSizeX
wxBitmapButton * m_AspectRatioLockButton
wxStaticText * m_SizeXValue
wxStaticText * m_BPPValue
wxStaticText * m_InputXValueDPI
wxScrolledWindow * m_GreyscalePicturePanel
wxCheckBox * m_checkNegative
wxScrolledWindow * m_InitialPicturePanel
wxScrolledWindow * m_BNPicturePanel
wxButton * m_buttonExportClipboard
wxRadioBox * m_rbPCBLayer
wxTextCtrl * m_UnitSizeY
wxRadioBox * m_rbOutputFormat
wxStaticText * m_SizeYValue
void OnSizeChangeX(wxCommandEvent &event) override
void OnExportLogo()
Generate a file suitable to be copied into a drawing sheet (.kicad_wks) file.
void LoadSettings(APP_SETTINGS_BASE *aCfg) override
Load common frame parameters from a configuration file.
void exportEeschemaFormat()
Generate a schematic library which contains one component: the logo.
bool m_AspectRatioLocked
wxImage m_Pict_Image
void exportPostScriptFormat()
Generate a postscript file.
void OnPaintBW(wxPaintEvent &event) override
wxString FormatOutputSize(double aSize)
double m_AspectRatio
IMAGE_SIZE m_outputSizeY
wxBitmap m_Greyscale_Bitmap
void OnThresholdChange(wxScrollEvent &event) override
void NegateGreyscaleImage()
void OnExportToFile(wxCommandEvent &event) override
IMAGE_SIZE m_outputSizeX
void OnLoadFile(wxCommandEvent &event) override
bool OpenProjectFiles(const std::vector< wxString > &aFilenames, int aCtl=0) override
Open a project or set of files given by aFileList.
BM2CMP_FRAME(KIWAY *aKiway, wxWindow *aParent)
wxBitmap m_Pict_Bitmap
void OnSizeUnitChange(wxCommandEvent &event) override
void OnNegativeClicked(wxCommandEvent &event) override
bool m_exportToClipboard
void OnPaintInit(wxPaintEvent &event) override
void Binarize(double aThreshold)
wxString m_BitmapFileName
void updateImageInfo()
wxImage m_NB_Image
void ToggleAspectRatioLock(wxCommandEvent &event) override
void OnSizeChangeY(wxCommandEvent &event) override
wxImage m_Greyscale_Image
wxString m_ConvertedFileName
void OnFormatChange(wxCommandEvent &event) override
void ExportToBuffer(std::string &aOutput, OUTPUT_FMT_ID aFormat)
generate a export data of the current bitmap.
wxWindow * GetToolCanvas() const override
Canvas access.
EDA_UNITS getUnitFromSelection()
void OnPaintGreyscale(wxPaintEvent &event) override
void OnExportToClipboard(wxCommandEvent &event) override
void exportPcbnewFormat()
Generate a footprint in S expr format.
void exportBitmap(OUTPUT_FMT_ID aFormat)
void SaveSettings(APP_SETTINGS_BASE *aCfg) override
Save common frame parameters to a configuration data file.
wxBitmap m_BN_Bitmap
virtual APP_SETTINGS_BASE * config() const
Returns the settings object used in SaveSettings(), and is overloaded in KICAD_MANAGER_FRAME.
virtual void LoadSettings(APP_SETTINGS_BASE *aCfg)
Load common frame parameters from a configuration file.
virtual void SaveSettings(APP_SETTINGS_BASE *aCfg)
Save common frame parameters to a configuration data file.
wxString m_mruPath
void SetUnit(EDA_UNITS aUnit)
double m_outputSize
double GetOutputSize()
EDA_UNITS m_unit
void SetOriginalDPI(int aDPI)
int GetOriginalSizePixels()
int m_originalSizePixels
int GetOutputDPI()
void SetOutputSizeFromInitialImageSize()
void SetOutputSize(double aSize, EDA_UNITS aUnit)
void SetOriginalSizePixels(int aPixels)
void SetKiway(wxWindow *aDest, KIWAY *aKiway)
It is only used for debugging, since "this" is not a wxWindow*.
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition: kiway.h:267
#define _(s)
EDA_UNITS
Definition: eda_units.h:43
const std::string KiCadSymbolLibFileExtension
const std::string KiCadFootprintFileExtension
const std::string DrawingSheetFileExtension
wxString KiCadFootprintLibFileWildcard()
wxString DrawingSheetFileWildcard()
wxString PSFileWildcard()
wxString KiCadSymbolLibFileWildcard()
void Refresh()
Update the board display after modifying it by a python script (note: it is automatically called by a...
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:80
Definition of file extensions used in Kicad.