KiCad PCB EDA Suite
bitmap_base.cpp
Go to the documentation of this file.
1 
5 /*
6  * This program source code file is part of KiCad, a free EDA CAD application.
7  *
8  * Copyright (C) 2017 jean-pierre.charras
9  * Copyright (C) 2011-2017 KiCad Developers, see AUTHORS.txt for contributors.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, you may find one here:
23  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
24  * or you may search the http://www.gnu.org website for the version 2 license,
25  * or you may write to the Free Software Foundation, Inc.,
26  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
27  */
28 
29 #include <bitmap_base.h>
30 #include <eda_rect.h> // for EDA_RECT
31 #include <gal/color4d.h> // for COLOR4D
32 #include <gr_basic.h>
33 #include <math/util.h> // for KiROUND
34 #include <memory> // for make_unique, unique_ptr
35 #include <plotter.h>
36 #include <richio.h>
37 #include <wx/bitmap.h> // for wxBitmap
38 #include <wx/mstream.h>
39 
40 
41 /**********************/
42 /* class BITMAP_BASE */
43 /**********************/
44 
46 {
47  m_scale = 1.0; // 1.0 = original bitmap size
48  m_bitmap = NULL;
49  m_image = NULL;
50  m_ppi = 300; // the bitmap definition. the default is 300PPI
51  m_pixelScaleFactor = 254000.0 / m_ppi; // a value OK for bitmaps using 300 PPI
52  // for Eeschema which uses currently 254000PPI
53 }
54 
55 
57 {
58  m_scale = aSchBitmap.m_scale;
59  m_ppi = aSchBitmap.m_ppi;
61 
62  m_image = nullptr;
63  m_bitmap = nullptr;
64 
65  if( aSchBitmap.m_image )
66  {
67  m_image = new wxImage( *aSchBitmap.m_image );
68  m_bitmap = new wxBitmap( *m_image );
69  }
70 }
71 
72 
78 {
79  *m_image = *aItem->m_image;
80  *m_bitmap = *aItem->m_bitmap;
81  m_scale = aItem->m_scale;
82  m_ppi = aItem->m_ppi;
84 }
85 
86 
87 bool BITMAP_BASE::ReadImageFile( wxInputStream& aInStream )
88 {
89  auto new_image = std::make_unique<wxImage>();
90 
91  if( !new_image->LoadFile( aInStream ) )
92  {
93  return false;
94  }
95 
96  delete m_image;
97  m_image = new_image.release();
98  m_bitmap = new wxBitmap( *m_image );
99 
100  return true;
101 }
102 
103 
104 bool BITMAP_BASE::ReadImageFile( const wxString& aFullFilename )
105 {
106  wxImage* new_image = new wxImage();
107 
108  if( !new_image->LoadFile( aFullFilename ) )
109  {
110  delete new_image;
111  return false;
112  }
113 
114  delete m_image;
115  m_image = new_image;
116  m_bitmap = new wxBitmap( *m_image );
117 
118  return true;
119 }
120 
121 
122 bool BITMAP_BASE::SaveData( FILE* aFile ) const
123 {
124  if( m_image )
125  {
126  wxMemoryOutputStream stream;
127  m_image->SaveFile( stream, wxBITMAP_TYPE_PNG );
128 
129  // Write binary data in hexadecimal form (ASCII)
130  wxStreamBuffer* buffer = stream.GetOutputStreamBuffer();
131  char* begin = (char*) buffer->GetBufferStart();
132 
133  for( int ii = 0; begin < buffer->GetBufferEnd(); begin++, ii++ )
134  {
135  if( ii >= 32 )
136  {
137  ii = 0;
138 
139  if( fprintf( aFile, "\n" ) == EOF )
140  return false;
141  }
142 
143  if( fprintf( aFile, "%2.2X ", *begin & 0xFF ) == EOF )
144  return false;
145  }
146  }
147 
148  return true;
149 }
150 
151 
152 void BITMAP_BASE::SaveData( wxArrayString& aPngStrings ) const
153 {
154  if( m_image )
155  {
156  wxMemoryOutputStream stream;
157  m_image->SaveFile( stream, wxBITMAP_TYPE_PNG );
158 
159  // Write binary data in hexadecimal form (ASCII)
160  wxStreamBuffer* buffer = stream.GetOutputStreamBuffer();
161  char* begin = (char*) buffer->GetBufferStart();
162  wxString line;
163 
164  for( int ii = 0; begin < buffer->GetBufferEnd(); begin++, ii++ )
165  {
166  if( ii >= 32 )
167  {
168  ii = 0;
169  aPngStrings.Add( line );
170  line.Empty();
171  }
172 
173  line << wxString::Format( wxT( "%2.2X " ), *begin & 0xFF );
174  }
175 
176  // Add last line:
177  if( !line.IsEmpty() )
178  aPngStrings.Add( line );
179  }
180 }
181 
182 
183 bool BITMAP_BASE::LoadData( LINE_READER& aLine, wxString& aErrorMsg )
184 {
185  wxMemoryOutputStream stream;
186  char* line;
187 
188  while( true )
189  {
190  if( !aLine.ReadLine() )
191  {
192  aErrorMsg = wxT("Unexpected end of data");
193  return false;
194  }
195 
196  line = aLine.Line();
197 
198  if( strncasecmp( line, "EndData", 4 ) == 0 )
199  {
200  // all the PNG date is read.
201  // We expect here m_image and m_bitmap are void
202  m_image = new wxImage();
203  wxMemoryInputStream istream( stream );
204  m_image->LoadFile( istream, wxBITMAP_TYPE_PNG );
205  m_bitmap = new wxBitmap( *m_image );
206  break;
207  }
208 
209  // Read PNG data, stored in hexadecimal,
210  // each byte = 2 hexadecimal digits and a space between 2 bytes
211  // and put it in memory stream buffer
212  int len = strlen( line );
213 
214  for( ; len > 0; len -= 3, line += 3 )
215  {
216  int value = 0;
217 
218  if( sscanf( line, "%X", &value ) == 1 )
219  stream.PutC( (char) value );
220  else
221  break;
222  }
223  }
224 
225  return true;
226 }
227 
228 
230 {
231  EDA_RECT rect;
232 
233  wxSize size = GetSize();
234 
235  rect.Inflate( size.x / 2, size.y / 2 );
236 
237  return rect;
238 }
239 
240 
241 void BITMAP_BASE::DrawBitmap( wxDC* aDC, const wxPoint& aPos )
242 {
243  if( m_bitmap == NULL )
244  return;
245 
246  wxPoint pos = aPos;
247  wxSize size = GetSize();
248 
249  // This fixes a bug in OSX that should be fixed in the 3.0.3 version or later.
250  if( ( size.x == 0 ) || ( size.y == 0 ) )
251  return;
252 
253  // To draw the bitmap, pos is the upper left corner position
254  pos.x -= size.x / 2;
255  pos.y -= size.y / 2;
256 
257  double scale;
258  int logicalOriginX, logicalOriginY;
259  aDC->GetUserScale( &scale, &scale );
260  aDC->GetLogicalOrigin( &logicalOriginX, &logicalOriginY );
261  aDC->SetUserScale( scale * GetScalingFactor(), scale * GetScalingFactor() );
262  aDC->SetLogicalOrigin( logicalOriginX / GetScalingFactor(),
263  logicalOriginY / GetScalingFactor() );
264 
265  pos.x = KiROUND( pos.x / GetScalingFactor() );
266  pos.y = KiROUND( pos.y / GetScalingFactor() );
267  size.x = KiROUND( size.x / GetScalingFactor() );
268  size.y = KiROUND( size.y / GetScalingFactor() );
269  aDC->SetClippingRegion( pos, size );
270 
272  {
273  wxBitmap result( m_bitmap->ConvertToImage().ConvertToGreyscale() );
274  aDC->DrawBitmap( result, pos.x, pos.y, true );
275  }
276  else
277  {
278  aDC->DrawBitmap( *m_bitmap, pos.x, pos.y, true );
279  }
280 
281  aDC->DestroyClippingRegion();
282  aDC->SetUserScale( scale, scale );
283  aDC->SetLogicalOrigin( logicalOriginX, logicalOriginY );
284 }
285 
286 
287 wxSize BITMAP_BASE::GetSize() const
288 {
289  wxSize size;
290 
291  if( m_bitmap )
292  {
293  size.x = m_bitmap->GetWidth();
294  size.y = m_bitmap->GetHeight();
295 
296  size.x = KiROUND( size.x * GetScalingFactor() );
297  size.y = KiROUND( size.y * GetScalingFactor() );
298  }
299 
300  return size;
301 }
302 
303 
304 void BITMAP_BASE::Mirror( bool aVertically )
305 {
306  if( m_image )
307  {
308  *m_image = m_image->Mirror( not aVertically );
309  RebuildBitmap();
310  }
311 }
312 
313 
314 void BITMAP_BASE::Rotate( bool aRotateCCW )
315 {
316  if( m_image )
317  {
318  *m_image = m_image->Rotate90( aRotateCCW );
319  RebuildBitmap();
320  }
321 }
322 
323 
325  const wxPoint& aPos,
326  COLOR4D aDefaultColor,
327  int aDefaultPensize )
328 {
329  if( m_image == NULL )
330  return;
331 
332  // These 2 lines are useful only for plotters that cannot plot a bitmap
333  // and plot a rectangle instead of.
334  aPlotter->SetColor( aDefaultColor );
335  aPlotter->SetCurrentLineWidth( aDefaultPensize );
336  aPlotter->PlotImage( *m_image, aPos, GetScalingFactor() );
337 }
double GetScalingFactor() const
Function GetScalingFactor.
Definition: bitmap_base.h:125
LINE_READER is an abstract class from which implementation specific LINE_READERs may be derived to re...
Definition: richio.h:81
BITMAP_BASE(const wxPoint &pos=wxPoint(0, 0))
Definition: bitmap_base.cpp:45
char * Line() const
Function Line returns a pointer to the last line that was read in.
Definition: richio.h:139
bool SaveData(FILE *aFile) const
writes the bitmap data to aFile The format is png, in Hexadecimal form: If the hexadecimal data is co...
virtual void SetColor(COLOR4D color)=0
void RebuildBitmap()
Definition: bitmap_base.h:100
void Mirror(bool aVertically)
Function Mirror Mirror image vertically (i.e.
const EDA_RECT GetBoundingBox() const
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes.
This class handle bitmap images in KiCad.
Definition: bitmap_base.h:51
double m_scale
Definition: bitmap_base.h:54
#define NULL
wxSize GetSize() const
Function GetSize.
wxBitmap * m_bitmap
Definition: bitmap_base.h:57
double m_pixelScaleFactor
Definition: bitmap_base.h:58
Base plotter engine class.
Definition: plotter.h:103
virtual void PlotImage(const wxImage &aImage, const wxPoint &aPos, double aScaleFactor)
Function PlotImage Only Postscript plotters can plot bitmaps for plotters that cannot plot a bitmap,...
Definition: plotter.cpp:231
void ImportData(BITMAP_BASE *aItem)
Function ImportData Copy aItem image to me and update m_bitmap.
Definition: bitmap_base.cpp:77
const int scale
virtual char * ReadLine()=0
Function ReadLine reads a line of text into the buffer and increments the line number counter.
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
void PlotImage(PLOTTER *aPlotter, const wxPoint &aPos, KIGFX::COLOR4D aDefaultColor, int aDefaultPensize)
Function PlotImage Plot bitmap on plotter.
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
bool LoadData(LINE_READER &aLine, wxString &aErrorMsg)
Load an image data saved by SaveData (png, in Hexadecimal form)
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:61
void DrawBitmap(wxDC *aDC, const wxPoint &aPos)
bool ReadImageFile(const wxString &aFullFilename)
Reads and stores in memory an image file.
bool GetGRForceBlackPenState(void)
Function GetGRForceBlackPenState.
Definition: gr_basic.cpp:211
void Rotate(bool aRotateCCW)
Function Rotate Rotate image CW or CCW.
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
wxImage * m_image
Definition: bitmap_base.h:56
virtual void SetCurrentLineWidth(int width, void *aData=NULL)=0
Set the line width for the next drawing.
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39