1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
5  * Copyright (C) 2015-2020 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  /**
26  * @file image.h
27  * @brief one 8bit-channel image definition.
28  */
29 
30 #ifndef IMAGE_H
31 #define IMAGE_H
32 
33 #include <wx/string.h>
34 
35 /// Image operation type
36 enum class IMAGE_OP
37 {
38     RAW,
39     ADD,
40     SUB,
41     DIF,
42     MUL,
43     AND,
44     OR,
45     XOR,
46     BLEND50,
47     MIN,
48     MAX
49 };
50 
51 
52 /// Image wrap type enumeration
53 enum class IMAGE_WRAP
54 {
55     ZERO,  ///< Coords that wraps are not evaluated
56     CLAMP, ///< Coords are clamped to image size
57     WRAP   ///< Coords are wrapped around
58 };
59 
60 
61 /// Filter type enumeration
62 enum class IMAGE_FILTER
63 {
64     HIPASS,
65     GAUSSIAN_BLUR,
66     GAUSSIAN_BLUR2,
67     INVERT_BLUR,
68     CARTOON,
69     EMBOSS,
70     SHARPEN,
71     MELT,
72     SOBEL_GX,
73     SOBEL_GY,
74     BLUR_3X3,
75 };
76 
77 /// 5x5 Filter struct parameters
78 struct S_FILTER
79 {
80     signed char    kernel[5][5];
81     unsigned int   div;
82     unsigned char  offset;
83 };
84 
85 
86 /**
87  * Manage an 8-bit channel image.
88  */
89 class IMAGE
90 {
91 public:
92     /**
93      * Construct a IMAGE based on image size.
94      *
95      * @param aXsize x size
96      * @param aYsize y size
97      */
98     IMAGE( unsigned int aXsize, unsigned int aYsize );
99 
100     /**
101      * Construct a IMAGE based from an existing image.
102      *
103      * It will make a copy the \a aSrcImage.
104      *
105      * @param aSrcImage
106      */
107     IMAGE( const IMAGE& aSrcImage );
108 
109     ~IMAGE();
110 
111     /**
112      * Set a value in a pixel position, position is clamped in accordance with the
113      * current clamp settings.
114      *
115      * @param aX x position
116      * @param aY y position
117      * @param aValue value to set the pixel
118      */
119     void Setpixel( int aX, int aY, unsigned char aValue );
120 
121     /**
122      * Get the pixel value from pixel position, position is clamped in accord with the
123      * current clamp settings.
124      *
125      * @param aX x position
126      * @param aY y position
127      * @return unsigned char - pixel value
128      */
129     unsigned char Getpixel( int aX, int aY ) const;
130 
131     /**
132      * Draw a horizontal line.
133      *
134      * @param aXStart x start position
135      * @param aXEnd x end position
136      * @param aY y position
137      * @param aValue  value to add
138      */
139     void Hline( int aXStart, int aXEnd, int aY, unsigned char aValue );
140 
141     void CircleFilled( int aCx, int aCy, int aRadius, unsigned char aValue );
142 
143     /**
144      * Perform a copy operation based on \a aOperation type.
145      *
146      * The available image operations.
147      *  - IMAGE_OP::RAW        this <- aImgA
148      *  - IMAGE_OP::ADD        this <- CLAMP(aImgA + aImgB)
149      *  - IMAGE_OP::SUB        this <- CLAMP(aImgA - aImgB)
150      *  - IMAGE_OP::DIF        this <- abs(aImgA - aImgB)
151      *  - IMAGE_OP::MUL        this <- aImgA * aImgB
152      *  - IMAGE_OP::AND        this <- aImgA & aImgB
153      *  - IMAGE_OP::OR         this <- aImgA | aImgB
154      *  - IMAGE_OP::XOR        this <- aImgA ^ aImgB
155      *  - IMAGE_OP::BLEND50    this <- (aImgA + aImgB) / 2
156      *  - IMAGE_OP::MIN        this <- (aImgA < aImgB) ? aImgA : aImgB
157      *  - IMAGE_OP::MAX        this <- (aImgA > aImgB) ? aImgA : aImgB
158      *
159      * @param aImgA an image input.
160      * @param aImgB an image input.
161      * @param aOperation operation to perform
162      */
163     void CopyFull( const IMAGE* aImgA, const IMAGE* aImgB, IMAGE_OP aOperation );
164 
165     /**
166      * Invert the values of this image <- (255 - this)
167      */
168     void Invert();
169 
170     /**
171      * Apply a filter to the input image and store it in the image class.
172      *
173      * @param aInImg input image
174      * @param aFilterType filter type to apply
175      */
176     void EfxFilter( IMAGE* aInImg, IMAGE_FILTER aFilterType );
177 
178     /**
179      * Apply a filter to the input image and store it in the image class.
180      * skip the circle center defined by radius
181      *
182      * @param aInImg input image
183      * @param aFilterType filter type to apply
184      * @param aRadius center circle that the effect will not be applied
185      */
186     void EfxFilter_SkipCenter( IMAGE* aInImg, IMAGE_FILTER aFilterType, unsigned int aRadius );
187 
188     /**
189      * Save image buffer to a PNG file into the working folder.
190      *
191      * Each RGB channel will have the 8bit-channel from the image.
192      *
193      * @param aFileName file name (without extension)
194      */
195     void SaveAsPNG( const wxString& aFileName ) const;
196 
197     /**
198      * Set the current channel from a float normalized (0.0 - 1.0) buffer.
199      *
200      * this <- CLAMP(NormalizedFloat * 255)
201      *
202      * @param aNormalizedFloatArray a float array with the same size of the image
203      */
204     void SetPixelsFromNormalizedFloat( const float* aNormalizedFloatArray );
205 
206     /**
207      * Get the image buffer pointer.
208      *
209      * @return unsigned char* the pointer of the buffer 8bit channel.
210      */
211     unsigned char* GetBuffer() const;
212 
GetWidth()213     unsigned int GetWidth() const { return m_width; }
GetHeight()214     unsigned int GetHeight() const { return m_height; }
215 
216 private:
217     /**
218      * Calculate the coordinates points in accord with the current clamping settings.
219      *
220      * @param aXo X coordinate to be converted (output).
221      * @param aXo Y coordinate to be converted (output).
222      * @return bool - true if the coordinates are inside the image, false otherwise.
223      */
224     bool wrapCoords( int* aXo, int* aYo ) const;
225 
226     void plot8CircleLines( int aCx, int aCy, int aX, int aY, unsigned char aValue );
227 
228     unsigned char*  m_pixels;           ///< buffer to store the image 8bit-channel
229     unsigned int    m_width;            ///< width of the image
230     unsigned int    m_height;           ///< height of the image
231     unsigned int    m_wxh;              ///< width * height precalc value
232     IMAGE_WRAP      m_wraping;          ///< current wrapping type
233 };
234 
235 #endif   // IMAGE_H
236