bitmap2component: Handle mask/alpha

Use alpha and mask components of bitmaps to set boundaries for the image
tracing.

Fixes: lp:1815216
* https://bugs.launchpad.net/kicad/+bug/1815216
This commit is contained in:
Seth Hillbrand 2019-02-01 08:36:32 -08:00
parent c0a86d734d
commit 5cfa37da09
5 changed files with 185 additions and 805 deletions

View File

@ -2,7 +2,7 @@
* This program source code file is part of KICAD, a free EDA CAD application. * This program source code file is part of KICAD, a free EDA CAD application.
* *
* Copyright (C) 1992-2010 jean-pierre.charras * Copyright (C) 1992-2010 jean-pierre.charras
* Copyright (C) 1992-2017 Kicad Developers, see change_log.txt for contributors. * Copyright (C) 1992-2019 Kicad Developers, see change_log.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -35,6 +35,7 @@
#include <kiway.h> #include <kiway.h>
#include <kiface_i.h> #include <kiface_i.h>
#include <wx/rawbmp.h>
#include <potracelib.h> #include <potracelib.h>
#include "bitmap2component.h" #include "bitmap2component.h"
@ -91,7 +92,9 @@ public:
private: private:
// Event handlers // Event handlers
void OnPaint( wxPaintEvent& event ) override; void OnPaintInit( wxPaintEvent& event ) override;
void OnPaintGreyscale( wxPaintEvent& event ) override;
void OnPaintBW( wxPaintEvent& event ) override;
void OnLoadFile( wxCommandEvent& event ) override; void OnLoadFile( wxCommandEvent& event ) override;
void OnExport( wxCommandEvent& event ) override; void OnExport( wxCommandEvent& event ) override;
@ -230,30 +233,59 @@ BM2CMP_FRAME::~BM2CMP_FRAME()
} }
void BM2CMP_FRAME::OnPaint( wxPaintEvent& event ) void BM2CMP_FRAME::OnPaintInit( wxPaintEvent& event )
{ {
#ifdef __WXMAC__ #ifdef __WXMAC__
// Otherwise fails due: using wxPaintDC without being in a native paint event // Otherwise fails due: using wxPaintDC without being in a native paint event
wxClientDC pict_dc( m_InitialPicturePanel ); wxClientDC pict_dc( m_InitialPicturePanel );
wxClientDC greyscale_dc( m_GreyscalePicturePanel );
wxClientDC nb_dc( m_BNPicturePanel );
#else #else
wxPaintDC pict_dc( m_InitialPicturePanel ); wxPaintDC pict_dc( m_InitialPicturePanel );
wxPaintDC greyscale_dc( m_GreyscalePicturePanel );
wxPaintDC nb_dc( m_BNPicturePanel );
#endif #endif
m_InitialPicturePanel->PrepareDC( pict_dc ); m_InitialPicturePanel->PrepareDC( pict_dc );
m_GreyscalePicturePanel->PrepareDC( greyscale_dc );
m_BNPicturePanel->PrepareDC( nb_dc );
// OSX crashes with empty bitmaps (on initial refreshes) // OSX crashes with empty bitmaps (on initial refreshes)
if( m_Pict_Bitmap.IsOk() && m_Greyscale_Bitmap.IsOk() && m_BN_Bitmap.IsOk() ) if( m_Pict_Bitmap.IsOk() )
{ pict_dc.DrawBitmap( m_Pict_Bitmap, 0, 0, !!m_Pict_Bitmap.GetMask() );
pict_dc.DrawBitmap( m_Pict_Bitmap, 0, 0, false );
greyscale_dc.DrawBitmap( m_Greyscale_Bitmap, 0, 0, false ); event.Skip();
nb_dc.DrawBitmap( m_BN_Bitmap, 0, 0, false ); }
}
void BM2CMP_FRAME::OnPaintGreyscale( wxPaintEvent& event )
{
#ifdef __WXMAC__
// Otherwise fails due: using wxPaintDC without being in a native paint event
wxClientDC greyscale_dc( m_GreyscalePicturePanel );
#else
wxPaintDC greyscale_dc( m_GreyscalePicturePanel );
#endif
m_GreyscalePicturePanel->PrepareDC( greyscale_dc );
// OSX crashes with empty bitmaps (on initial refreshes)
if( m_Greyscale_Bitmap.IsOk() )
greyscale_dc.DrawBitmap( m_Greyscale_Bitmap, 0, 0, !!m_Greyscale_Bitmap.GetMask() );
event.Skip();
}
void BM2CMP_FRAME::OnPaintBW( wxPaintEvent& event )
{
#ifdef __WXMAC__
// Otherwise fails due: using wxPaintDC without being in a native paint event
wxClientDC nb_dc( m_BNPicturePanel );
#else
wxPaintDC nb_dc( m_BNPicturePanel );
#endif
m_BNPicturePanel->PrepareDC( nb_dc );
if( m_BN_Bitmap.IsOk() )
nb_dc.DrawBitmap( m_BN_Bitmap, 0, 0, !!m_BN_Bitmap.GetMask() );
event.Skip();
} }
@ -288,8 +320,7 @@ void BM2CMP_FRAME::OnLoadFile( wxCommandEvent& event )
bool BM2CMP_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl ) bool BM2CMP_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl )
{ {
// Prj().MaybeLoadProjectSettings(); m_Pict_Image.Destroy();
m_BitmapFileName = aFileSet[0]; m_BitmapFileName = aFileSet[0];
if( !m_Pict_Image.LoadFile( m_BitmapFileName ) ) if( !m_Pict_Image.LoadFile( m_BitmapFileName ) )
@ -336,11 +367,26 @@ bool BM2CMP_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int
m_Greyscale_Image.Destroy(); m_Greyscale_Image.Destroy();
m_Greyscale_Image = m_Pict_Image.ConvertToGreyscale( ); m_Greyscale_Image = m_Pict_Image.ConvertToGreyscale( );
if( m_Pict_Bitmap.GetMask() )
{
for( int x = 0; x < m_Pict_Bitmap.GetWidth(); x++ )
{
for( int y = 0; y < m_Pict_Bitmap.GetHeight(); y++ )
{
if( m_Pict_Image.GetRed( x, y ) == m_Pict_Image.GetMaskRed() &&
m_Pict_Image.GetGreen( x, y ) == m_Pict_Image.GetMaskGreen() &&
m_Pict_Image.GetBlue( x, y ) == m_Pict_Image.GetMaskBlue() )
{
m_Greyscale_Image.SetRGB( x, y, 255, 255, 255 );
}
}
}
}
if( m_Negative ) if( m_Negative )
NegateGreyscaleImage( ); NegateGreyscaleImage( );
m_Greyscale_Bitmap = wxBitmap( m_Greyscale_Image ); m_Greyscale_Bitmap = wxBitmap( m_Greyscale_Image );
m_NB_Image = m_Greyscale_Image; m_NB_Image = m_Greyscale_Image;
Binarize( (double) m_sliderThreshold->GetValue()/m_sliderThreshold->GetMax() ); Binarize( (double) m_sliderThreshold->GetValue()/m_sliderThreshold->GetMax() );
@ -391,26 +437,30 @@ void BM2CMP_FRAME::OnResolutionChange( wxCommandEvent& event )
void BM2CMP_FRAME::Binarize( double aThreshold ) void BM2CMP_FRAME::Binarize( double aThreshold )
{ {
unsigned int pixin;
unsigned char pixout;
int h = m_Greyscale_Image.GetHeight(); int h = m_Greyscale_Image.GetHeight();
int w = m_Greyscale_Image.GetWidth(); int w = m_Greyscale_Image.GetWidth();
unsigned int threshold = (int)(aThreshold * 256); unsigned char threshold = aThreshold * 255;
unsigned char alpha_thresh = 0.7 * threshold;
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++ )
{ {
pixin = m_Greyscale_Image.GetGreen( x, y ); unsigned char pixout;
auto pixin = m_Greyscale_Image.GetGreen( x, y );
auto alpha = m_Greyscale_Image.HasAlpha() ?
m_Greyscale_Image.GetAlpha( x, y ) : wxALPHA_OPAQUE;
if( pixin < threshold ) if( pixin < threshold || alpha < alpha_thresh )
pixout = 0; pixout = 0;
else else
pixout = 255; pixout = 255;
m_NB_Image.SetRGB( x, y, pixout, pixout, pixout ); m_NB_Image.SetRGB( x, y, pixout, pixout, pixout );
} }
m_BN_Bitmap = wxBitmap( m_NB_Image ); m_BN_Bitmap = wxBitmap( m_NB_Image );
} }
@ -435,6 +485,7 @@ void BM2CMP_FRAME::OnNegativeClicked( wxCommandEvent& )
if( m_checkNegative->GetValue() != m_Negative ) if( m_checkNegative->GetValue() != m_Negative )
{ {
NegateGreyscaleImage(); NegateGreyscaleImage();
m_Greyscale_Bitmap = wxBitmap( m_Greyscale_Image ); m_Greyscale_Bitmap = wxBitmap( m_Greyscale_Image );
Binarize( (double)m_sliderThreshold->GetValue()/m_sliderThreshold->GetMax() ); Binarize( (double)m_sliderThreshold->GetValue()/m_sliderThreshold->GetMax() );
m_Negative = m_checkNegative->GetValue(); m_Negative = m_checkNegative->GetValue();
@ -647,8 +698,8 @@ void BM2CMP_FRAME::ExportFile( FILE* aOutfile, OUTPUT_FMT_ID aFormat )
{ {
for( int x = 0; x < w; x++ ) for( int x = 0; x < w; x++ )
{ {
unsigned char pix = m_NB_Image.GetGreen( x, y ); auto pix = m_NB_Image.GetGreen( x, y );
BM_PUT( potrace_bitmap, x, y, pix ? 1 : 0 ); BM_PUT( potrace_bitmap, x, y, pix ? 0 : 1 );
} }
} }

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Jun 5 2018) // C++ code generated with wxFormBuilder (version Jan 17 2019)
// http://www.wxformbuilder.org/ // http://www.wxformbuilder.org/
// //
// PLEASE DO *NOT* EDIT THIS FILE! // PLEASE DO *NOT* EDIT THIS FILE!
@ -167,12 +167,12 @@ BM2CMP_FRAME_BASE::BM2CMP_FRAME_BASE( wxWindow* parent, wxWindowID id, const wxS
this->SetSizer( bMainSizer ); this->SetSizer( bMainSizer );
this->Layout(); this->Layout();
m_statusBar = this->CreateStatusBar( 1, wxST_SIZEGRIP, wxID_ANY ); m_statusBar = this->CreateStatusBar( 1, wxSTB_SIZEGRIP, wxID_ANY );
// Connect Events // Connect Events
m_InitialPicturePanel->Connect( wxEVT_PAINT, wxPaintEventHandler( BM2CMP_FRAME_BASE::OnPaint ), NULL, this ); m_InitialPicturePanel->Connect( wxEVT_PAINT, wxPaintEventHandler( BM2CMP_FRAME_BASE::OnPaintInit ), NULL, this );
m_GreyscalePicturePanel->Connect( wxEVT_PAINT, wxPaintEventHandler( BM2CMP_FRAME_BASE::OnPaint ), NULL, this ); m_GreyscalePicturePanel->Connect( wxEVT_PAINT, wxPaintEventHandler( BM2CMP_FRAME_BASE::OnPaintGreyscale ), NULL, this );
m_BNPicturePanel->Connect( wxEVT_PAINT, wxPaintEventHandler( BM2CMP_FRAME_BASE::OnPaint ), NULL, this ); m_BNPicturePanel->Connect( wxEVT_PAINT, wxPaintEventHandler( BM2CMP_FRAME_BASE::OnPaintBW ), NULL, this );
m_DPIValueX->Connect( wxEVT_LEAVE_WINDOW, wxMouseEventHandler( BM2CMP_FRAME_BASE::UpdatePPITextValueX ), NULL, this ); m_DPIValueX->Connect( wxEVT_LEAVE_WINDOW, wxMouseEventHandler( BM2CMP_FRAME_BASE::UpdatePPITextValueX ), NULL, this );
m_DPIValueX->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnResolutionChange ), NULL, this ); m_DPIValueX->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnResolutionChange ), NULL, this );
m_DPIValueY->Connect( wxEVT_LEAVE_WINDOW, wxMouseEventHandler( BM2CMP_FRAME_BASE::UpdatePPITextValueY ), NULL, this ); m_DPIValueY->Connect( wxEVT_LEAVE_WINDOW, wxMouseEventHandler( BM2CMP_FRAME_BASE::UpdatePPITextValueY ), NULL, this );
@ -187,9 +187,9 @@ BM2CMP_FRAME_BASE::BM2CMP_FRAME_BASE( wxWindow* parent, wxWindowID id, const wxS
BM2CMP_FRAME_BASE::~BM2CMP_FRAME_BASE() BM2CMP_FRAME_BASE::~BM2CMP_FRAME_BASE()
{ {
// Disconnect Events // Disconnect Events
m_InitialPicturePanel->Disconnect( wxEVT_PAINT, wxPaintEventHandler( BM2CMP_FRAME_BASE::OnPaint ), NULL, this ); m_InitialPicturePanel->Disconnect( wxEVT_PAINT, wxPaintEventHandler( BM2CMP_FRAME_BASE::OnPaintInit ), NULL, this );
m_GreyscalePicturePanel->Disconnect( wxEVT_PAINT, wxPaintEventHandler( BM2CMP_FRAME_BASE::OnPaint ), NULL, this ); m_GreyscalePicturePanel->Disconnect( wxEVT_PAINT, wxPaintEventHandler( BM2CMP_FRAME_BASE::OnPaintGreyscale ), NULL, this );
m_BNPicturePanel->Disconnect( wxEVT_PAINT, wxPaintEventHandler( BM2CMP_FRAME_BASE::OnPaint ), NULL, this ); m_BNPicturePanel->Disconnect( wxEVT_PAINT, wxPaintEventHandler( BM2CMP_FRAME_BASE::OnPaintBW ), NULL, this );
m_DPIValueX->Disconnect( wxEVT_LEAVE_WINDOW, wxMouseEventHandler( BM2CMP_FRAME_BASE::UpdatePPITextValueX ), NULL, this ); m_DPIValueX->Disconnect( wxEVT_LEAVE_WINDOW, wxMouseEventHandler( BM2CMP_FRAME_BASE::UpdatePPITextValueX ), NULL, this );
m_DPIValueX->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnResolutionChange ), NULL, this ); m_DPIValueX->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnResolutionChange ), NULL, this );
m_DPIValueY->Disconnect( wxEVT_LEAVE_WINDOW, wxMouseEventHandler( BM2CMP_FRAME_BASE::UpdatePPITextValueY ), NULL, this ); m_DPIValueY->Disconnect( wxEVT_LEAVE_WINDOW, wxMouseEventHandler( BM2CMP_FRAME_BASE::UpdatePPITextValueY ), NULL, this );

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,11 @@
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Jun 5 2018) // C++ code generated with wxFormBuilder (version Jan 17 2019)
// http://www.wxformbuilder.org/ // http://www.wxformbuilder.org/
// //
// PLEASE DO *NOT* EDIT THIS FILE! // PLEASE DO *NOT* EDIT THIS FILE!
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
#ifndef __BITMAP2CMP_GUI_BASE_H__ #pragma once
#define __BITMAP2CMP_GUI_BASE_H__
#include <wx/artprov.h> #include <wx/artprov.h>
#include <wx/xrc/xmlres.h> #include <wx/xrc/xmlres.h>
@ -75,7 +74,9 @@ class BM2CMP_FRAME_BASE : public KIWAY_PLAYER
wxStatusBar* m_statusBar; wxStatusBar* m_statusBar;
// 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 OnPaintInit( wxPaintEvent& event ) { event.Skip(); }
virtual void OnPaintGreyscale( wxPaintEvent& event ) { event.Skip(); }
virtual void OnPaintBW( wxPaintEvent& event ) { event.Skip(); }
virtual void UpdatePPITextValueX( wxMouseEvent& event ) { event.Skip(); } virtual void UpdatePPITextValueX( wxMouseEvent& event ) { event.Skip(); }
virtual void OnResolutionChange( wxCommandEvent& event ) { event.Skip(); } virtual void OnResolutionChange( wxCommandEvent& event ) { event.Skip(); }
virtual void UpdatePPITextValueY( wxMouseEvent& event ) { event.Skip(); } virtual void UpdatePPITextValueY( wxMouseEvent& event ) { event.Skip(); }
@ -94,4 +95,3 @@ class BM2CMP_FRAME_BASE : public KIWAY_PLAYER
}; };
#endif //__BITMAP2CMP_GUI_BASE_H__

View File

@ -2,7 +2,7 @@
* This program source code file is part of KICAD, a free EDA CAD application. * This program source code file is part of KICAD, a free EDA CAD application.
* *
* Copyright (C) 1992-2013 jean-pierre.charras * Copyright (C) 1992-2013 jean-pierre.charras
* Copyright (C) 1992-2013 Kicad Developers, see change_log.txt for contributors. * Copyright (C) 1992-2019 Kicad Developers, see change_log.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -155,6 +155,7 @@ int bitmap2component( potrace_bitmap_t* aPotrace_bitmap, FILE* aOutfile,
return 1; return 1;
} }
printf("Step 1\n");
BITMAPCONV_INFO info; BITMAPCONV_INFO info;
info.m_PixmapWidth = aPotrace_bitmap->w; info.m_PixmapWidth = aPotrace_bitmap->w;
info.m_PixmapHeight = aPotrace_bitmap->h; // the bitmap size in pixels info.m_PixmapHeight = aPotrace_bitmap->h; // the bitmap size in pixels
@ -434,6 +435,8 @@ void BITMAPCONV_INFO::CreateOutputFile( BMP2CMP_MOD_LAYER aModLayer )
* Bezier curves are approximated by a polyline * Bezier curves are approximated by a polyline
*/ */
potrace_path_t* paths = m_Paths; // the list of paths potrace_path_t* paths = m_Paths; // the list of paths
if(!m_Paths)
printf("NULL Paths!\n");
while( paths != NULL ) while( paths != NULL )
{ {
int cnt = paths->curve.n; int cnt = paths->curve.n;