1 /*
2     Scan Tailor - Interactive post-processing tool for scanned pages.
3     Copyright (C)  Joseph Artsimovich <joseph.artsimovich@gmail.com>
4 
5     This program is free software: you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation, either version 3 of the License, or
8     (at your option) any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifndef IMAGEPROC_GRAYIMAGE_H_
20 #define IMAGEPROC_GRAYIMAGE_H_
21 
22 #include <QImage>
23 #include <QRect>
24 #include <QSize>
25 #include <cstdint>
26 
27 namespace imageproc {
28 /**
29  * \brief A wrapper class around QImage that is always guaranteed to be 8-bit grayscale.
30  */
31 class GrayImage {
32  public:
33   /**
34    * \brief Creates a 8-bit grayscale image with specified dimensions.
35    *
36    * The image contents won't be initialized.  You can use fill() to initialize them.
37    * If size.isEmpty() is true, creates a null image.
38    *
39    * \throw std::bad_alloc Unlike the underlying QImage, GrayImage reacts to
40    *        out-of-memory situations by throwing an exception rather than
41    *        constructing a null image.
42    */
43   explicit GrayImage(QSize size = QSize());
44 
45   /**
46    * \brief Constructs a 8-bit grayscale image by converting an arbitrary QImage.
47    *
48    * The QImage may be in any format and may be null.
49    */
50   explicit GrayImage(const QImage& image);
51 
52   /**
53    * \brief Returns a const reference to the underlying QImage.
54    *
55    * The underlying QImage is either a null image or a 8-bit indexed
56    * image with a grayscale palette.
57    */
toQImage()58   const QImage& toQImage() const { return m_image; }
59 
60   operator const QImage&() const { return m_image; }
61 
isNull()62   bool isNull() const { return m_image.isNull(); }
63 
fill(uint8_t color)64   void fill(uint8_t color) { m_image.fill(color); }
65 
data()66   uint8_t* data() { return m_image.bits(); }
67 
data()68   const uint8_t* data() const { return m_image.bits(); }
69 
70   /**
71    * \brief Number of bytes per line.
72    *
73    * This value may be larger than image width.
74    * An additional guaranee provided by the underlying QImage
75    * is that this value is a multiple of 4.
76    */
stride()77   int stride() const { return m_image.bytesPerLine(); }
78 
size()79   QSize size() const { return m_image.size(); }
80 
rect()81   QRect rect() const { return m_image.rect(); }
82 
width()83   int width() const { return m_image.width(); }
84 
height()85   int height() const { return m_image.height(); }
86 
87   void invert();
88 
89   GrayImage inverted() const;
90 
91   int dotsPerMeterX() const;
92 
93   int dotsPerMeterY() const;
94 
95   void setDotsPerMeterX(int value);
96 
97   void setDotsPerMeterY(int value);
98 
99  private:
100   QImage m_image;
101 };
102 
103 
104 inline bool operator==(const GrayImage& lhs, const GrayImage& rhs) {
105   return lhs.toQImage() == rhs.toQImage();
106 }
107 
108 inline bool operator!=(const GrayImage& lhs, const GrayImage& rhs) {
109   return lhs.toQImage() != rhs.toQImage();
110 }
111 }  // namespace imageproc
112 #endif  // ifndef IMAGEPROC_GRAYIMAGE_H_
113