@@ -559,7 +559,9 @@ Image::Image(const std::string& filename, ssize_t width, ssize_t height,
559
559
bool has_alpha, uint8_t channel_width, uint64_t max_value) : Image(filename.c_str(), width, height, has_alpha, channel_width, max_value) {}
560
560
561
561
Image::~Image () {
562
- free (this ->data .raw );
562
+ if (this ->data .raw ) {
563
+ free (this ->data .raw );
564
+ }
563
565
}
564
566
565
567
bool Image::operator ==(const Image& other) const {
@@ -1718,4 +1720,140 @@ void Image::resize_blit(const Image& source, ssize_t x, ssize_t y, ssize_t w,
1718
1720
}
1719
1721
}
1720
1722
1723
+ static inline constexpr size_t byte_count_for_bit_count (size_t bit_count) {
1724
+ return (bit_count + 7 ) & (~7 );
1725
+ }
1726
+
1727
+ BitmapImage::BitmapImage () : width(0 ), height(0 ), row_bytes(0 ), data(nullptr ) {}
1728
+
1729
+ BitmapImage::BitmapImage (size_t w, size_t h)
1730
+ : width(w),
1731
+ height(h),
1732
+ row_bytes(byte_count_for_bit_count(this ->height)),
1733
+ data(new uint8_t [this ->get_data_size ()]) {
1734
+ memset (this ->data , 0 , this ->get_data_size ());
1735
+ }
1736
+
1737
+ BitmapImage::BitmapImage (const BitmapImage& im)
1738
+ : width(im.width),
1739
+ height(im.height),
1740
+ row_bytes(byte_count_for_bit_count(this ->height)),
1741
+ data(new uint8_t [this ->get_data_size ()]) {
1742
+ memcpy (this ->data , im.data , this ->get_data_size ());
1743
+ }
1744
+
1745
+ const BitmapImage& BitmapImage::operator =(const BitmapImage& im) {
1746
+ this ->width = im.width ;
1747
+ this ->height = im.height ;
1748
+ this ->row_bytes = im.row_bytes ;
1749
+ size_t num_bytes = this ->get_data_size ();
1750
+ if (this ->data ) {
1751
+ delete[] this ->data ;
1752
+ }
1753
+ this ->data = new uint8_t [num_bytes];
1754
+ memcpy (this ->data , im.data , num_bytes);
1755
+ return *this ;
1756
+ }
1757
+
1758
+ BitmapImage::BitmapImage (BitmapImage&& im) {
1759
+ this ->width = im.width ;
1760
+ this ->height = im.height ;
1761
+ this ->row_bytes = im.row_bytes ;
1762
+ this ->data = im.data ;
1763
+ im.width = 0 ;
1764
+ im.height = 0 ;
1765
+ im.row_bytes = 0 ;
1766
+ im.data = nullptr ;
1767
+ }
1768
+
1769
+ BitmapImage& BitmapImage::operator =(BitmapImage&& im) {
1770
+ this ->width = im.width ;
1771
+ this ->height = im.height ;
1772
+ this ->row_bytes = im.row_bytes ;
1773
+ if (this ->data ) {
1774
+ delete[] this ->data ;
1775
+ }
1776
+ this ->data = im.data ;
1777
+ im.width = 0 ;
1778
+ im.height = 0 ;
1779
+ im.row_bytes = 0 ;
1780
+ im.data = nullptr ;
1781
+ return *this ;
1782
+ }
1783
+
1784
+ BitmapImage::BitmapImage (FILE* f, size_t width, size_t height)
1785
+ : BitmapImage(width, height) {
1786
+ freadx (f, this ->data , this ->get_data_size ());
1787
+ }
1788
+
1789
+ BitmapImage::BitmapImage (const char * filename, size_t width, size_t height)
1790
+ : BitmapImage(width, height) {
1791
+ auto f = fopen_unique (filename, " rb" );
1792
+ freadx (f.get (), this ->data , this ->get_data_size ());
1793
+ }
1794
+
1795
+ BitmapImage::BitmapImage (const std::string& filename, size_t width, size_t height)
1796
+ : BitmapImage(filename.c_str(), width, height) {}
1797
+
1798
+ BitmapImage::~BitmapImage () {
1799
+ if (this ->data ) {
1800
+ delete[] this ->data ;
1801
+ }
1802
+ }
1803
+
1804
+ bool BitmapImage::operator ==(const BitmapImage& other) const {
1805
+ if ((this ->width != other.width ) || (this ->height != other.height ) || (this ->row_bytes != other.row_bytes )) {
1806
+ return false ;
1807
+ }
1808
+ return !memcmp (this ->data , other.data , this ->get_data_size ());
1809
+ }
1810
+
1811
+ bool BitmapImage::operator !=(const BitmapImage& other) const {
1812
+ return !this ->operator ==(other);
1813
+ }
1814
+
1815
+ void BitmapImage::clear (bool v) {
1816
+ memset (this ->data , v ? 0xFF : 0x00 , this ->get_data_size ());
1817
+ }
1818
+
1819
+ bool BitmapImage::read_pixel (size_t x, size_t y) const {
1820
+ if (x >= this ->width || y >= this ->height ) {
1821
+ throw runtime_error (" out of bounds" );
1822
+ }
1823
+ return !!(this ->data [y * byte_count_for_bit_count (this ->width ) + (x >> 3 )] & (0x80 >> (x & 7 )));
1824
+ }
1825
+
1826
+ void BitmapImage::write_pixel (size_t x, size_t y, bool v) {
1827
+ if (x >= this ->width || y >= this ->height ) {
1828
+ throw runtime_error (" out of bounds" );
1829
+ }
1830
+ if (v) {
1831
+ this ->data [y * byte_count_for_bit_count (this ->width ) + (x >> 3 )] |= (0x80 >> (x & 7 ));
1832
+ } else {
1833
+ this ->data [y * byte_count_for_bit_count (this ->width ) + (x >> 3 )] &= (0x7F7F >> (x & 7 ));
1834
+ }
1835
+ }
1836
+
1837
+ void BitmapImage::invert () {
1838
+ size_t num_bytes = this ->get_data_size ();
1839
+ for (size_t z = 0 ; z < num_bytes; z++) {
1840
+ this ->data [z] = ~this ->data [z];
1841
+ }
1842
+ }
1843
+
1844
+ Image BitmapImage::to_color (uint32_t false_color, uint32_t true_color, bool add_alpha) const {
1845
+ Image ret (this ->width , this ->height , add_alpha);
1846
+ uint8_t pending_bits = 0 ;
1847
+ for (size_t y = 0 ; y < this ->height ; y++) {
1848
+ for (size_t x = 0 ; x < this ->width ; x++) {
1849
+ if (!(x & 7 )) {
1850
+ pending_bits = this ->data [(y * this ->row_bytes ) + (x >> 3 )];
1851
+ }
1852
+ ret.write_pixel (x, y, (pending_bits & 0x80 ) ? true_color : false_color);
1853
+ pending_bits <<= 1 ;
1854
+ }
1855
+ }
1856
+ return ret;
1857
+ }
1858
+
1721
1859
} // namespace phosg
0 commit comments