You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

159 lines
5.2 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2023 Alex Shvartzkop <dudesuchamazing@gmail.com>
  5. * Copyright The 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. #include "gfx_import_utils.h"
  25. #include <stdint.h>
  26. #include <lib_symbol.h>
  27. #include <sch_shape.h>
  28. #include <import_gfx/graphics_importer_lib_symbol.h>
  29. #include <import_gfx/svg_import_plugin.h>
  30. std::unordered_map<uint32_t, SHAPE_POLY_SET> ConvertImageToPolygons( wxImage img,
  31. VECTOR2D pixelScale )
  32. {
  33. bool hasAlpha = img.HasAlpha();
  34. // Quantize the image
  35. for( int y = 0; y < img.GetHeight(); y++ )
  36. {
  37. for( int x = 0; x < img.GetWidth(); x++ )
  38. {
  39. int r = img.GetRed( x, y );
  40. int g = img.GetGreen( x, y );
  41. int b = img.GetBlue( x, y );
  42. int a = hasAlpha ? img.GetAlpha( x, y ) : 255;
  43. int roundBits = 5; // 32
  44. r = std::min( r >> roundBits << roundBits, 0xFF );
  45. g = std::min( g >> roundBits << roundBits, 0xFF );
  46. b = std::min( b >> roundBits << roundBits, 0xFF );
  47. a = std::min( a >> roundBits << roundBits, 0xFF );
  48. img.SetRGB( x, y, r, g, b );
  49. if( hasAlpha )
  50. img.SetAlpha( x, y, a );
  51. }
  52. }
  53. std::unordered_map<uint32_t, SHAPE_POLY_SET> colorPolys;
  54. // Create polygon sets
  55. for( int y = 0; y < img.GetHeight(); y++ )
  56. {
  57. for( int x = 0; x < img.GetWidth(); x++ )
  58. {
  59. uint32_t r = img.GetRed( x, y );
  60. uint32_t g = img.GetGreen( x, y );
  61. uint32_t b = img.GetBlue( x, y );
  62. uint32_t a = hasAlpha ? img.GetAlpha( x, y ) : 255;
  63. if( a > 0 )
  64. {
  65. uint32_t color = r | ( g << 8 ) | ( b << 16 ) | ( a << 24 );
  66. SHAPE_POLY_SET& colorPoly = colorPolys[color];
  67. SHAPE_LINE_CHAIN chain;
  68. chain.Append( x * pixelScale.x, y * pixelScale.y, true );
  69. chain.Append( ( x + 1 ) * pixelScale.x, y * pixelScale.y, true );
  70. chain.Append( ( x + 1 ) * pixelScale.x, ( y + 1 ) * pixelScale.y, true );
  71. chain.Append( x * pixelScale.x, ( y + 1 ) * pixelScale.y, true );
  72. chain.SetClosed( true );
  73. colorPoly.AddOutline( chain );
  74. }
  75. }
  76. }
  77. for( auto& [color, polySet] : colorPolys )
  78. {
  79. polySet.Simplify();
  80. for( int i = 0; i < polySet.OutlineCount(); i++ )
  81. {
  82. SHAPE_POLY_SET::POLYGON& poly = polySet.Polygon( i );
  83. for( SHAPE_LINE_CHAIN& chain : poly )
  84. chain.Simplify();
  85. }
  86. }
  87. return colorPolys;
  88. }
  89. void ConvertImageToLibShapes( LIB_SYMBOL* aSymbol, int unit, wxImage img, VECTOR2D pixelScale,
  90. VECTOR2D offset )
  91. {
  92. std::unordered_map<uint32_t, SHAPE_POLY_SET> colorPolys =
  93. ConvertImageToPolygons( img, pixelScale );
  94. for( auto& [color, polySet] : colorPolys )
  95. {
  96. polySet.Fracture();
  97. for( const SHAPE_POLY_SET::POLYGON& poly : polySet.CPolygons() )
  98. {
  99. auto shape = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY, LAYER_DEVICE );
  100. shape->SetPolyShape( poly );
  101. int r = color & 0xFF;
  102. int g = ( color >> 8 ) & 0xFF;
  103. int b = ( color >> 16 ) & 0xFF;
  104. int a = ( color >> 24 ) & 0xFF;
  105. shape->SetWidth( -1 );
  106. shape->SetFillMode( FILL_T::FILLED_WITH_COLOR );
  107. shape->SetFillColor( COLOR4D( r / 255.0, g / 255.0, b / 255.0, a / 255.0 ) );
  108. shape->SetUnit( unit );
  109. shape->Move( offset );
  110. aSymbol->AddDrawItem( shape.release(), false );
  111. }
  112. }
  113. aSymbol->GetDrawItems().sort();
  114. }
  115. void ConvertSVGToLibShapes( LIB_SYMBOL* aSymbol, int unit, const wxMemoryBuffer& aImageData,
  116. VECTOR2D pixelScale, VECTOR2D offset )
  117. {
  118. SVG_IMPORT_PLUGIN svgImportPlugin;
  119. GRAPHICS_IMPORTER_LIB_SYMBOL libeditImporter( aSymbol, unit );
  120. libeditImporter.SetScale( pixelScale );
  121. libeditImporter.SetImportOffsetMM(
  122. VECTOR2D( schIUScale.IUTomm( offset.x ), schIUScale.IUTomm( offset.y ) ) );
  123. svgImportPlugin.SetImporter( &libeditImporter );
  124. svgImportPlugin.LoadFromMemory( aImageData );
  125. svgImportPlugin.Import();
  126. }