KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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-2023 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 <common.h>
31#include <kiface_base.h>
32#include <math/util.h> // for KiROUND
33#include <kiway.h>
34#include <potracelib.h>
36#include <tool/tool_manager.h>
37#include <tool/common_control.h>
38#include <wx/clipbrd.h>
39#include <wx/rawbmp.h>
40#include <wx/filedlg.h>
41#include <wx/msgdlg.h>
42#include <wx/dcclient.h>
43#include <wx/log.h>
44
45
46#include "bitmap2cmp_gui_base.h"
47#include "pgm_base.h"
48
49#define DEFAULT_DPI 300 // the image DPI used in formats that do not define a DPI
50
52{
53 m_outputSize = 0.0;
56 m_unit = EDA_UNITS::MILLIMETRES;
57}
58
59
61{
62 // Safety-check to guarantee no divide-by-zero
63 m_originalDPI = std::max( 1, m_originalDPI );
64
65 // Set the m_outputSize value from the m_originalSizePixels and the selected unit
66 if( m_unit == EDA_UNITS::MILLIMETRES )
68 else if( m_unit == EDA_UNITS::INCHES )
70 else
72}
73
74
76{
77 int outputDPI;
78
79 if( m_unit == EDA_UNITS::MILLIMETRES )
80 outputDPI = GetOriginalSizePixels() / ( m_outputSize / 25.4 );
81 else if( m_unit == EDA_UNITS::INCHES )
82 outputDPI = GetOriginalSizePixels() / m_outputSize;
83 else
84 outputDPI = KiROUND( m_outputSize );
85
86 // Zero is not a DPI, and may cause divide-by-zero errors...
87 outputDPI = std::max( 1, outputDPI );
88
89 return outputDPI;
90}
91
92
94{
95 // Set the unit used for m_outputSize, and convert the old m_outputSize value
96 // to the value in new unit
97 if( aUnit == m_unit )
98 return;
99
100 // Convert m_outputSize to mm:
101 double size_mm;
102
103 if( m_unit == EDA_UNITS::MILLIMETRES )
104 {
105 size_mm = m_outputSize;
106 }
107 else if( m_unit == EDA_UNITS::INCHES )
108 {
109 size_mm = m_outputSize * 25.4;
110 }
111 else
112 {
113 // m_outputSize is the DPI, not an image size
114 // the image size is m_originalSizePixels / m_outputSize (in inches)
115 if( m_outputSize )
116 size_mm = m_originalSizePixels / m_outputSize * 25.4;
117 else
118 size_mm = 0;
119 }
120
121 // Convert m_outputSize to new value:
122 if( aUnit == EDA_UNITS::MILLIMETRES )
123 {
124 m_outputSize = size_mm;
125 }
126 else if( aUnit == EDA_UNITS::INCHES )
127 {
128 m_outputSize = size_mm / 25.4;
129 }
130 else
131 {
132 if( size_mm )
133 m_outputSize = m_originalSizePixels / size_mm * 25.4;
134 else
135 m_outputSize = 0;
136 }
137
138 m_unit = aUnit;
139}
140
141
142BEGIN_EVENT_TABLE( BM2CMP_FRAME, BM2CMP_FRAME_BASE )
143 EVT_MENU( wxID_EXIT, BM2CMP_FRAME::OnExit )
144 EVT_MENU( wxID_OPEN, BM2CMP_FRAME::OnLoadFile )
145END_EVENT_TABLE()
146
147
148BM2CMP_FRAME::BM2CMP_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
149 BM2CMP_FRAME_BASE( aParent )
150{
151 SetKiway( this, aKiway );
152
153 for( wxString unit : { _( "mm" ), _( "Inch" ), _( "DPI" ) } )
154 m_PixelUnit->Append( unit );
155
156 LoadSettings( config() );
157
158 m_outputSizeX.SetUnit( getUnitFromSelection() );
159 m_outputSizeY.SetUnit( getUnitFromSelection() );
160 m_outputSizeX.SetOutputSize( 0, getUnitFromSelection() );
161 m_outputSizeY.SetOutputSize( 0, getUnitFromSelection() );
162
163 m_UnitSizeX->ChangeValue( FormatOutputSize( m_outputSizeX.GetOutputSize() ) );
164 m_UnitSizeY->ChangeValue( FormatOutputSize( m_outputSizeY.GetOutputSize() ) );
165
166 // Give an icon
167 wxIcon icon;
168 wxIconBundle icon_bundle;
169
170 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_bitmap2component ) );
171 icon_bundle.AddIcon( icon );
172 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_bitmap2component_32 ) );
173 icon_bundle.AddIcon( icon );
174 icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_bitmap2component_16 ) );
175 icon_bundle.AddIcon( icon );
176
177 SetIcons( icon_bundle );
178
179 ReCreateMenuBar();
180
181 GetSizer()->SetSizeHints( this );
182
183 m_buttonExportFile->Enable( false );
184 m_buttonExportClipboard->Enable( false );
185
186 SetSize( m_framePos.x, m_framePos.y, m_frameSize.x, m_frameSize.y );
187
188 if ( m_framePos == wxDefaultPosition )
189 Centre();
190}
191
192
194{
195 SaveSettings( config() );
196 /*
197 * This needed for OSX: avoids further OnDraw processing after this
198 * destructor and before the native window is destroyed
199 */
200 Freeze();
201}
202
203
205{
206 return m_Notebook->GetCurrentPage();
207}
208
209
211{
212 // wxWidgets handles the Mac Application menu behind the scenes, but that means
213 // we always have to start from scratch with a new wxMenuBar.
214 wxMenuBar* oldMenuBar = GetMenuBar();
215 wxMenuBar* menuBar = new wxMenuBar();
216
217 wxMenu* fileMenu = new wxMenu;
218
219 wxMenuItem* item = new wxMenuItem( fileMenu, wxID_OPEN, _( "Open..." ) + wxT( "\tCtrl+O" ),
220 _( "Load source image" ) );
221
222 fileMenu->Append( item );
223
224#ifndef __WXMAC__
225 // Mac moves Quit to the App menu so we don't need a separator on Mac
226 fileMenu->AppendSeparator();
227#endif
228
229 item = new wxMenuItem( fileMenu, wxID_EXIT, _( "Quit" ) + wxT( "\tCtrl+Q" ),
230 _( "Quit Image Converter" ) );
231
232 if( Pgm().GetCommonSettings()->m_Appearance.use_icons_in_menus )
233 item->SetBitmap( KiBitmap( BITMAPS::exit ) );
234
235 fileMenu->Append( item );
236
237 menuBar->Append( fileMenu, _( "&File" ) );
238
239 SetMenuBar( menuBar );
240 delete oldMenuBar;
241}
242
243
244void BM2CMP_FRAME::OnExit( wxCommandEvent& event )
245{
246 Destroy();
247}
248
249
251{
253
254 BITMAP2CMP_SETTINGS* cfg = static_cast<BITMAP2CMP_SETTINGS*>( aCfg );
255
258
259 int u_select = cfg->m_Units;
260
261 if( u_select < 0 || u_select > 2 ) // Validity control
262 u_select = 0;
263
264 m_PixelUnit->SetSelection( u_select );
265
266 m_sliderThreshold->SetValue( cfg->m_Threshold );
267
268 m_Negative = cfg->m_Negative;
269 m_checkNegative->SetValue( cfg->m_Negative );
270
271 m_AspectRatio = 1.0;
272 m_aspectRatioCheckbox->SetValue( true );
273
274 int format = cfg->m_LastFormat;
275
276 if( format < 0 || format > FINAL_FMT )
277 format = PCBNEW_KICAD_MOD;
278
279 m_rbOutputFormat->SetSelection( format );
280
281 bool enable = format == PCBNEW_KICAD_MOD;
282 m_chPCBLayer->Enable( enable );
283
284 int last_layer = cfg->m_LastModLayer;
285
286 if( last_layer < 0 || last_layer > static_cast<int>( MOD_LYR_FINAL ) ) // Out of range
287 last_layer = MOD_LYR_FSILKS;
288
289 m_chPCBLayer->SetSelection( last_layer );
290}
291
292
294{
296
297 BITMAP2CMP_SETTINGS* cfg = static_cast<BITMAP2CMP_SETTINGS*>( aCfg );
298
301 cfg->m_Threshold = m_sliderThreshold->GetValue();
302 cfg->m_Negative = m_checkNegative->IsChecked();
303 cfg->m_LastFormat = m_rbOutputFormat->GetSelection();
304 cfg->m_LastModLayer = m_chPCBLayer->GetSelection();
305 cfg->m_Units = m_PixelUnit->GetSelection();
306}
307
308
309void BM2CMP_FRAME::OnPaintInit( wxPaintEvent& event )
310{
311#ifdef __WXMAC__
312 // Otherwise fails due: using wxPaintDC without being in a native paint event
313 wxClientDC pict_dc( m_InitialPicturePanel );
314#else
315 wxPaintDC pict_dc( m_InitialPicturePanel );
316#endif
317
318 m_InitialPicturePanel->PrepareDC( pict_dc );
319
320 // OSX crashes with empty bitmaps (on initial refreshes)
321 if( m_Pict_Bitmap.IsOk() )
322 pict_dc.DrawBitmap( m_Pict_Bitmap, 0, 0, !!m_Pict_Bitmap.GetMask() );
323
324 event.Skip();
325}
326
327
328void BM2CMP_FRAME::OnPaintGreyscale( wxPaintEvent& event )
329{
330#ifdef __WXMAC__
331 // Otherwise fails due: using wxPaintDC without being in a native paint event
332 wxClientDC greyscale_dc( m_GreyscalePicturePanel );
333#else
334 wxPaintDC greyscale_dc( m_GreyscalePicturePanel );
335#endif
336
337 m_GreyscalePicturePanel->PrepareDC( greyscale_dc );
338
339 // OSX crashes with empty bitmaps (on initial refreshes)
340 if( m_Greyscale_Bitmap.IsOk() )
341 greyscale_dc.DrawBitmap( m_Greyscale_Bitmap, 0, 0, !!m_Greyscale_Bitmap.GetMask() );
342
343 event.Skip();
344}
345
346
347void BM2CMP_FRAME::OnPaintBW( wxPaintEvent& event )
348{
349#ifdef __WXMAC__
350 // Otherwise fails due: using wxPaintDC without being in a native paint event
351 wxClientDC nb_dc( m_BNPicturePanel );
352#else
353 wxPaintDC nb_dc( m_BNPicturePanel );
354#endif
355
356 m_BNPicturePanel->PrepareDC( nb_dc );
357
358 if( m_BN_Bitmap.IsOk() )
359 nb_dc.DrawBitmap( m_BN_Bitmap, 0, 0, !!m_BN_Bitmap.GetMask() );
360
361 event.Skip();
362}
363
364
365void BM2CMP_FRAME::OnLoadFile( wxCommandEvent& event )
366{
367 wxFileName fn( m_BitmapFileName );
368 wxString path = fn.GetPath();
369
370 if( path.IsEmpty() || !wxDirExists( path ) )
371 path = m_mruPath;
372
373 wxFileDialog fileDlg( this, _( "Choose Image" ), path, wxEmptyString,
374 _( "Image Files" ) + wxS( " " )+ wxImage::GetImageExtWildcard(),
375 wxFD_OPEN | wxFD_FILE_MUST_EXIST );
376
377 int diag = fileDlg.ShowModal();
378
379 if( diag != wxID_OK )
380 return;
381
382 wxString fullFilename = fileDlg.GetPath();
383
384 if( !OpenProjectFiles( std::vector<wxString>( 1, fullFilename ) ) )
385 return;
386
387 fn = fullFilename;
388 m_mruPath = fn.GetPath();
389 SetStatusText( fullFilename );
390 Refresh();
391}
392
393
394bool BM2CMP_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl )
395{
396 m_Pict_Image.Destroy();
397 m_BitmapFileName = aFileSet[0];
398
399 if( !m_Pict_Image.LoadFile( m_BitmapFileName ) )
400 {
401 // LoadFile has its own UI, no need for further failure notification here
402 return false;
403 }
404
405 m_Pict_Bitmap = wxBitmap( m_Pict_Image );
406
407 // Determine image resolution in DPI (does not existing in all formats).
408 // the resolution can be given in bit per inches or bit per cm in file
409
410 int imageDPIx = m_Pict_Image.GetOptionInt( wxIMAGE_OPTION_RESOLUTIONX );
411 int imageDPIy = m_Pict_Image.GetOptionInt( wxIMAGE_OPTION_RESOLUTIONY );
412
413 if( imageDPIx > 1 && imageDPIy > 1 )
414 {
415 if( m_Pict_Image.GetOptionInt( wxIMAGE_OPTION_RESOLUTIONUNIT ) == wxIMAGE_RESOLUTION_CM )
416 {
417 imageDPIx = KiROUND( imageDPIx * 2.54 );
418 imageDPIy = KiROUND( imageDPIy * 2.54 );
419 }
420 }
421 else // fallback to a default value (DEFAULT_DPI)
422 {
423 imageDPIx = imageDPIy = DEFAULT_DPI;
424 }
425
426 m_InputXValueDPI->SetLabel( wxString::Format( wxT( "%d" ), imageDPIx ) );
427 m_InputYValueDPI->SetLabel( wxString::Format( wxT( "%d" ), imageDPIy ) );
428
429 int h = m_Pict_Bitmap.GetHeight();
430 int w = m_Pict_Bitmap.GetWidth();
431 m_AspectRatio = (double) w / h;
432
433 m_outputSizeX.SetOriginalDPI( imageDPIx );
435 m_outputSizeY.SetOriginalDPI( imageDPIy );
437
438 // Update display to keep aspect ratio
439 wxCommandEvent dummy;
441
443
444 m_InitialPicturePanel->SetVirtualSize( w, h );
445 m_GreyscalePicturePanel->SetVirtualSize( w, h );
446 m_BNPicturePanel->SetVirtualSize( w, h );
447
448 m_Greyscale_Image.Destroy();
449 m_Greyscale_Image = m_Pict_Image.ConvertToGreyscale( );
450
451 if( m_Pict_Bitmap.GetMask() )
452 {
453 for( int x = 0; x < m_Pict_Bitmap.GetWidth(); x++ )
454 {
455 for( int y = 0; y < m_Pict_Bitmap.GetHeight(); y++ )
456 {
457 if( m_Pict_Image.GetRed( x, y ) == m_Pict_Image.GetMaskRed() &&
458 m_Pict_Image.GetGreen( x, y ) == m_Pict_Image.GetMaskGreen() &&
459 m_Pict_Image.GetBlue( x, y ) == m_Pict_Image.GetMaskBlue() )
460 {
461 m_Greyscale_Image.SetRGB( x, y, 255, 255, 255 );
462 }
463 }
464 }
465 }
466
467 if( m_Negative )
469
472 Binarize( (double) m_sliderThreshold->GetValue() / m_sliderThreshold->GetMax() );
473
474 m_buttonExportFile->Enable( true );
475 m_buttonExportClipboard->Enable( true );
476
481
482 return true;
483}
484
485
486// return a string giving the output size, according to the selected unit
487wxString BM2CMP_FRAME::FormatOutputSize( double aSize )
488{
489 wxString text;
490
491 if( getUnitFromSelection() == EDA_UNITS::MILLIMETRES )
492 text.Printf( wxS( "%.1f" ), aSize );
493 else if( getUnitFromSelection() == EDA_UNITS::INCHES )
494 text.Printf( wxS( "%.2f" ), aSize );
495 else
496 text.Printf( wxT( "%d" ), KiROUND( aSize ) );
497
498 return text;
499}
500
502{
503 // Note: the image resolution text controls are not modified here, to avoid a race between
504 // text change when entered by user and a text change if it is modified here.
505
506 if( m_Pict_Bitmap.IsOk() )
507 {
508 int h = m_Pict_Bitmap.GetHeight();
509 int w = m_Pict_Bitmap.GetWidth();
510 int nb = m_Pict_Bitmap.GetDepth();
511
512 m_SizeXValue->SetLabel( wxString::Format( wxT( "%d" ), w ) );
513 m_SizeYValue->SetLabel( wxString::Format( wxT( "%d" ), h ) );
514 m_BPPValue->SetLabel( wxString::Format( wxT( "%d" ), nb ) );
515 }
516}
517
518
520{
521 // return the EDA_UNITS from the m_PixelUnit choice
522 switch( m_PixelUnit->GetSelection() )
523 {
524 case 1: return EDA_UNITS::INCHES;
525 case 2: return EDA_UNITS::UNSCALED;
526 case 0:
527 default: return EDA_UNITS::MILLIMETRES;
528 }
529}
530
531
532void BM2CMP_FRAME::OnSizeChangeX( wxCommandEvent& event )
533{
534 double new_size;
535
536 if( m_UnitSizeX->GetValue().ToDouble( &new_size ) )
537 {
538 if( m_aspectRatioCheckbox->GetValue() )
539 {
540 double calculatedY = new_size / m_AspectRatio;
541
542 if( getUnitFromSelection() == EDA_UNITS::UNSCALED )
543 {
544 // for units in DPI, keeping aspect ratio cannot use m_AspectRatioLocked.
545 // just re-scale the other dpi
546 double ratio = new_size / m_outputSizeX.GetOutputSize();
547 calculatedY = m_outputSizeY.GetOutputSize() * ratio;
548 }
549
552 }
553
555 }
556
558}
559
560
561void BM2CMP_FRAME::OnSizeChangeY( wxCommandEvent& event )
562{
563 double new_size;
564
565 if( m_UnitSizeY->GetValue().ToDouble( &new_size ) )
566 {
567 if( m_aspectRatioCheckbox->GetValue() )
568 {
569 double calculatedX = new_size * m_AspectRatio;
570
571 if( getUnitFromSelection() == EDA_UNITS::UNSCALED )
572 {
573 // for units in DPI, keeping aspect ratio cannot use m_AspectRatioLocked.
574 // just re-scale the other dpi
575 double ratio = new_size / m_outputSizeX.GetOutputSize();
576 calculatedX = m_outputSizeX.GetOutputSize() * ratio;
577 }
578
581 }
582
584 }
585
587}
588
589
590void BM2CMP_FRAME::OnSizeUnitChange( wxCommandEvent& event )
591{
595
598}
599
600
601void BM2CMP_FRAME::ToggleAspectRatioLock( wxCommandEvent& event )
602{
603 if( m_aspectRatioCheckbox->GetValue() )
604 {
605 // Force display update when aspect ratio is locked
606 wxCommandEvent dummy;
608 }
609}
610
611
612void BM2CMP_FRAME::Binarize( double aThreshold )
613{
614 int h = m_Greyscale_Image.GetHeight();
615 int w = m_Greyscale_Image.GetWidth();
616 unsigned char threshold = aThreshold * 255;
617 unsigned char alpha_thresh = 0.7 * threshold;
618
619 for( int y = 0; y < h; y++ )
620 {
621 for( int x = 0; x < w; x++ )
622 {
623 unsigned char pixout;
624 unsigned char pixin = m_Greyscale_Image.GetGreen( x, y );
625 unsigned char alpha = m_Greyscale_Image.HasAlpha() ? m_Greyscale_Image.GetAlpha( x, y )
626 : wxALPHA_OPAQUE;
627
628 if( pixin < threshold && alpha > alpha_thresh )
629 pixout = 0;
630 else
631 pixout = 255;
632
633 m_NB_Image.SetRGB( x, y, pixout, pixout, pixout );
634 }
635 }
636
637 m_BN_Bitmap = wxBitmap( m_NB_Image );
638}
639
640
642{
643 unsigned char pix;
644 int h = m_Greyscale_Image.GetHeight();
645 int w = m_Greyscale_Image.GetWidth();
646
647 for( int y = 0; y < h; y++ )
648 {
649 for( int x = 0; x < w; x++ )
650 {
651 pix = m_Greyscale_Image.GetGreen( x, y );
652 pix = ~pix;
653 m_Greyscale_Image.SetRGB( x, y, pix, pix, pix );
654 }
655 }
656}
657
658
659void BM2CMP_FRAME::OnNegativeClicked( wxCommandEvent& )
660{
661 if( m_checkNegative->GetValue() != m_Negative )
662 {
664
666 Binarize( (double)m_sliderThreshold->GetValue()/m_sliderThreshold->GetMax() );
667 m_Negative = m_checkNegative->GetValue();
668
669 Refresh();
670 }
671}
672
673
674void BM2CMP_FRAME::OnThresholdChange( wxScrollEvent& event )
675{
676 Binarize( (double)m_sliderThreshold->GetValue()/m_sliderThreshold->GetMax() );
677 Refresh();
678}
679
680
681void BM2CMP_FRAME::OnExportToFile( wxCommandEvent& event )
682{
683 // choices of m_rbOutputFormat are expected to be in same order as
684 // OUTPUT_FMT_ID. See bitmap2component.h
685 OUTPUT_FMT_ID format = (OUTPUT_FMT_ID) m_rbOutputFormat->GetSelection();
686 exportBitmap( format );
687}
688
689
690void BM2CMP_FRAME::OnExportToClipboard( wxCommandEvent& event )
691{
692 // choices of m_rbOutputFormat are expected to be in same order as
693 // OUTPUT_FMT_ID. See bitmap2component.h
694 OUTPUT_FMT_ID format = (OUTPUT_FMT_ID) m_rbOutputFormat->GetSelection();
695
696 std::string buffer;
697 ExportToBuffer( buffer, format );
698
699 wxLogNull doNotLog; // disable logging of failed clipboard actions
700
701 // Write buffer to the clipboard
702 if( wxTheClipboard->Open() )
703 {
704 // This data objects are held by the clipboard,
705 // so do not delete them in the app.
706 wxTheClipboard->SetData( new wxTextDataObject( buffer.c_str() ) );
707 wxTheClipboard->Flush(); // Allow data to be available after closing KiCad
708 wxTheClipboard->Close();
709 }
710 else
711 {
712 wxMessageBox( _( "Unable to export to the Clipboard") );
713 }
714}
715
716
718{
719 switch( aFormat )
720 {
721 case EESCHEMA_FMT: exportEeschemaFormat(); break;
724 case KICAD_WKS_LOGO: exportLogo(); break;
725 }
726}
727
728
730{
731 wxFileName fn( m_ConvertedFileName );
732 wxString path = fn.GetPath();
733
734 if( path.IsEmpty() || !wxDirExists(path) )
735 path = ::wxGetCwd();
736
737 wxFileDialog fileDlg( this, _( "Create Logo File" ), path, wxEmptyString,
738 DrawingSheetFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
739 int diag = fileDlg.ShowModal();
740
741 if( diag != wxID_OK )
742 return;
743
744 fn = fileDlg.GetPath();
745 fn.SetExt( DrawingSheetFileExtension );
746 m_ConvertedFileName = fn.GetFullPath();
747
748 FILE* outfile;
749 outfile = wxFopen( m_ConvertedFileName, wxT( "w" ) );
750
751 if( outfile == nullptr )
752 {
753 wxString msg;
754 msg.Printf( _( "File '%s' could not be created." ), m_ConvertedFileName );
755 wxMessageBox( msg );
756 return;
757 }
758
759 std::string buffer;
761 fputs( buffer.c_str(), outfile );
762 fclose( outfile );
763}
764
765
767{
768 wxFileName fn( m_ConvertedFileName );
769 wxString path = fn.GetPath();
770
771 if( path.IsEmpty() || !wxDirExists( path ) )
772 path = ::wxGetCwd();
773
774 wxFileDialog fileDlg( this, _( "Create PostScript File" ), path, wxEmptyString,
775 PSFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
776
777 if( fileDlg.ShowModal() != wxID_OK )
778 return;
779
780 fn = fileDlg.GetPath();
781 fn.SetExt( wxT( "ps" ) );
782 m_ConvertedFileName = fn.GetFullPath();
783
784 FILE* outfile;
785 outfile = wxFopen( m_ConvertedFileName, wxT( "w" ) );
786
787 if( outfile == nullptr )
788 {
789 wxString msg;
790 msg.Printf( _( "File '%s' could not be created." ), m_ConvertedFileName );
791 wxMessageBox( msg );
792 return;
793 }
794
795 std::string buffer;
797 fputs( buffer.c_str(), outfile );
798 fclose( outfile );
799}
800
801
803{
804 wxFileName fn( m_ConvertedFileName );
805 wxString path = fn.GetPath();
806
807 if( path.IsEmpty() || !wxDirExists(path) )
808 path = ::wxGetCwd();
809
810 wxFileDialog fileDlg( this, _( "Create Symbol Library" ), path, wxEmptyString,
811 KiCadSymbolLibFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
812
813 if( fileDlg.ShowModal() != wxID_OK )
814 return;
815
816 fn = EnsureFileExtension( fileDlg.GetPath(), KiCadSymbolLibFileExtension );
817 m_ConvertedFileName = fn.GetFullPath();
818
819 FILE* outfile = wxFopen( m_ConvertedFileName, wxT( "w" ) );
820
821 if( outfile == nullptr )
822 {
823 wxString msg;
824 msg.Printf( _( "File '%s' could not be created." ), m_ConvertedFileName );
825 wxMessageBox( msg );
826 return;
827 }
828
829 std::string buffer;
830 ExportToBuffer( buffer, EESCHEMA_FMT );
831 fputs( buffer.c_str(), outfile );
832 fclose( outfile );
833}
834
835
837{
838 wxFileName fn( m_ConvertedFileName );
839 wxString path = fn.GetPath();
840
841 if( path.IsEmpty() || !wxDirExists( path ) )
842 path = m_mruPath;
843
844 wxFileDialog fileDlg( this, _( "Create Footprint Library" ), path, wxEmptyString,
845 KiCadFootprintLibFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
846
847 if( fileDlg.ShowModal() != wxID_OK )
848 return;
849
850 fn = EnsureFileExtension( fileDlg.GetPath(), KiCadFootprintFileExtension );
851 m_ConvertedFileName = fn.GetFullPath();
852
853 FILE* outfile = wxFopen( m_ConvertedFileName, wxT( "w" ) );
854
855 if( outfile == nullptr )
856 {
857 wxString msg;
858 msg.Printf( _( "File '%s' could not be created." ), m_ConvertedFileName );
859 wxMessageBox( msg );
860 return;
861 }
862
863 std::string buffer;
865 fputs( buffer.c_str(), outfile );
866 fclose( outfile );
867 m_mruPath = fn.GetPath();
868}
869
870
871void BM2CMP_FRAME::ExportToBuffer( std::string& aOutput, OUTPUT_FMT_ID aFormat )
872{
873 // Create a potrace bitmap
874 int h = m_NB_Image.GetHeight();
875 int w = m_NB_Image.GetWidth();
876 potrace_bitmap_t* potrace_bitmap = bm_new( w, h );
877
878 if( !potrace_bitmap )
879 {
880 wxString msg;
881 msg.Printf( _( "Error allocating memory for potrace bitmap" ) );
882 wxMessageBox( msg );
883 return;
884 }
885
886 /* fill the bitmap with data */
887 for( int y = 0; y < h; y++ )
888 {
889 for( int x = 0; x < w; x++ )
890 {
891 unsigned char pix = m_NB_Image.GetGreen( x, y );
892 BM_PUT( potrace_bitmap, x, y, pix ? 0 : 1 );
893 }
894 }
895
896 // choices of m_rbPCBLayer are expected to be in same order as
897 // BMP2CMP_MOD_LAYER. See bitmap2component.h
899
900 if( aFormat == PCBNEW_KICAD_MOD )
901 modLayer = (BMP2CMP_MOD_LAYER) m_chPCBLayer->GetSelection();
902
903 BITMAPCONV_INFO converter( aOutput );
904 converter.ConvertBitmap( potrace_bitmap, aFormat, m_outputSizeX.GetOutputDPI(),
905 m_outputSizeY.GetOutputDPI(), modLayer );
906
907 if( !converter.GetErrorMessages().empty() )
908 wxMessageBox( converter.GetErrorMessages().c_str(), _( "Errors" ) );
909}
910
911
912void BM2CMP_FRAME::OnFormatChange( wxCommandEvent& event )
913{
914 bool enable = m_rbOutputFormat->GetSelection() == PCBNEW_KICAD_MOD;
915 m_chPCBLayer->Enable( enable );
916}
#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:106
@ 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:110
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
wxCheckBox * m_aspectRatioCheckbox
wxSlider * m_sliderThreshold
wxButton * m_buttonExportFile
wxTextCtrl * m_UnitSizeX
wxStaticText * m_SizeXValue
wxStaticText * m_BPPValue
wxStaticText * m_InputXValueDPI
wxScrolledWindow * m_GreyscalePicturePanel
wxCheckBox * m_checkNegative
wxScrolledWindow * m_InitialPicturePanel
wxScrolledWindow * m_BNPicturePanel
wxButton * m_buttonExportClipboard
wxTextCtrl * m_UnitSizeY
wxRadioBox * m_rbOutputFormat
wxStaticText * m_SizeYValue
void OnSizeChangeX(wxCommandEvent &event) override
void LoadSettings(APP_SETTINGS_BASE *aCfg) override
Load common frame parameters from a configuration file.
void doReCreateMenuBar() override
void exportEeschemaFormat()
Generate a schematic library which contains one component: the logo.
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.
wxBitmap m_Pict_Bitmap
void OnSizeUnitChange(wxCommandEvent &event) override
void OnNegativeClicked(wxCommandEvent &event) override
void OnPaintInit(wxPaintEvent &event) override
void Binarize(double aThreshold)
wxString m_BitmapFileName
void updateImageInfo()
wxImage m_NB_Image
void ToggleAspectRatioLock(wxCommandEvent &event) override
void exportLogo()
Generate a file suitable to be copied into a drawing sheet (.kicad_wks) file.
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 OnExit(wxCommandEvent &event)
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)
bool Destroy() override
Our version of Destroy() which is virtual from wxWidgets.
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition: kiway.h:279
wxString EnsureFileExtension(const wxString &aFilename, const wxString &aExtension)
It's annoying to throw up nag dialogs when the extension isn't right.
Definition: common.cpp:380
The common library.
#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...
see class PGM_BASE
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:115
std::vector< FAB_LAYER_COLOR > dummy
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:85
Definition of file extensions used in Kicad.