From 661da0f8debe01c37b3d812e51a31da0015dcefa Mon Sep 17 00:00:00 2001
From: IzmaylovI <75639514+IzmaylovI@users.noreply.github.com>
Date: Tue, 4 Apr 2023 21:56:14 +0300
Subject: [PATCH 01/57] Update README.md
---
README.md | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 8eaf3a9..789e8d1 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,2 @@
-# itlab_2022
\ No newline at end of file
+# itlab_2022
+## Optimization of Computer Vision Algorithms on ARM Architecture Processors
From c769929d58dc32dbc41356c25991940a12872a80 Mon Sep 17 00:00:00 2001
From: IzmaylovI <75639514+IzmaylovI@users.noreply.github.com>
Date: Tue, 4 Apr 2023 22:02:45 +0300
Subject: [PATCH 02/57] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 789e8d1..d734e4b 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,2 @@
# itlab_2022
-## Optimization of Computer Vision Algorithms on ARM Architecture Processors
+## Low-level optimization of computer vision algorithms on ARM architectures
From a80972ced56ac545204d2f55c0280f9b6cb39a5e Mon Sep 17 00:00:00 2001
From: IzmaylovI <75639514+IzmaylovI@users.noreply.github.com>
Date: Tue, 4 Apr 2023 22:48:33 +0300
Subject: [PATCH 03/57] Update README.md
---
README.md | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/README.md b/README.md
index d734e4b..9445178 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,6 @@
# itlab_2022
## Low-level optimization of computer vision algorithms on ARM architectures
+Objectives of this project:
+- Study of classical computer vision algorithms, as well as work with artificial neural networks;
+- Optimization of these algorithms on ARM architectures. The study of parallel programming. Using Vector instructions;
+- Working with Raspberry PI devices in practice.
From 8bda5f7cb2a95154836b461a26d75f3bb1f5a6bb Mon Sep 17 00:00:00 2001
From: IzmaylovI <75639514+IzmaylovI@users.noreply.github.com>
Date: Tue, 4 Apr 2023 23:24:33 +0300
Subject: [PATCH 04/57] Create README.md
---
README.md | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 9445178..854000f 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,15 @@
# itlab_2022
-## Low-level optimization of computer vision algorithms on ARM architectures
-Objectives of this project:
+
+## Low-level optimization of computer vision algorithms on ARM architectures
+#### Objectives of this project:
- Study of classical computer vision algorithms, as well as work with artificial neural networks;
- Optimization of these algorithms on ARM architectures. The study of parallel programming. Using Vector instructions;
- Working with Raspberry PI devices in practice.
+
+#### Software modules:
+ - Module 1. A module for generating data/reading images and storing images. The Image class is independent when reading format images .bmp (OpenCV library is used for other formats).
+ - Module 2. The algorithms module. At the moment, it contains the following matrix multiplication algorithms: classical multiplication,multiplication using OpenMP and Neon_intrinsics
+ - Module 3. The test module. In development...
+ - Module 4. The Benchmarks module. In development...
+
+
From a0a0271e17a0c426732fd6e93f1ddfba27bcb783 Mon Sep 17 00:00:00 2001
From: IzmaylovI <75639514+IzmaylovI@users.noreply.github.com>
Date: Tue, 4 Apr 2023 23:31:13 +0300
Subject: [PATCH 05/57] Update README.md
---
README.md | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/README.md b/README.md
index 854000f..852d988 100644
--- a/README.md
+++ b/README.md
@@ -1,15 +1,20 @@
# itlab_2022
-## Low-level optimization of computer vision algorithms on ARM architectures
-#### Objectives of this project:
+# Low-level optimization of computer vision algorithms on ARM architectures
+## Objectives of this project:
- Study of classical computer vision algorithms, as well as work with artificial neural networks;
- Optimization of these algorithms on ARM architectures. The study of parallel programming. Using Vector instructions;
- Working with Raspberry PI devices in practice.
-#### Software modules:
- - Module 1. A module for generating data/reading images and storing images. The Image class is independent when reading format images .bmp (OpenCV library is used for other formats).
- - Module 2. The algorithms module. At the moment, it contains the following matrix multiplication algorithms: classical multiplication,multiplication using OpenMP and Neon_intrinsics
- - Module 3. The test module. In development...
- - Module 4. The Benchmarks module. In development...
+## Software modules:
+### Module 1.
+A module for generating data/reading images and storing images. The Image class is independent when reading format images `.bmp` (`OpenCV` library is used for other formats).
+### Module 2.
+The algorithms module. At the moment, it contains the following matrix multiplication algorithms: classical multiplication,multiplication using OpenMP and Neon_intrinsics
+### Module 3.
+The test module. In development...
+###Module 4. The Benchmarks module. In development...
+
+## Clone the repo
From 89304f1528bccc1bce1991ad03eaef6fdfa7be34 Mon Sep 17 00:00:00 2001
From: IzmaylovI <75639514+IzmaylovI@users.noreply.github.com>
Date: Tue, 4 Apr 2023 23:38:40 +0300
Subject: [PATCH 06/57] Update README.md
---
README.md | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 852d988..5cab01a 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# itlab_2022
-# Low-level optimization of computer vision algorithms on ARM architectures
+# low-level optimization of computer vision algorithms on ARM architectures
## Objectives of this project:
- Study of classical computer vision algorithms, as well as work with artificial neural networks;
- Optimization of these algorithms on ARM architectures. The study of parallel programming. Using Vector instructions;
@@ -16,5 +16,4 @@ The test module. In development...
###Module 4. The Benchmarks module. In development...
## Clone the repo
-
-
+`git clone https://github.com/IzmaylovI/itlab_2022.git`
From 91c14d38645cb7370affd17c83cf4a24b23a45ab Mon Sep 17 00:00:00 2001
From: IzmaylovI
Date: Wed, 5 Apr 2023 00:09:37 +0300
Subject: [PATCH 07/57] first_request
---
CMakeLists.txt | 21 ++++
headers/Color.hpp | 163 +++++++++++++++++++++++++++
headers/Function.hpp | 199 +++++++++++++++++++++++++++++++++
headers/Structer.hpp | 239 ++++++++++++++++++++++++++++++++++++++++
headers/data_render.hpp | 17 +++
main.cpp | 12 ++
6 files changed, 651 insertions(+)
create mode 100644 CMakeLists.txt
create mode 100644 headers/Color.hpp
create mode 100644 headers/Function.hpp
create mode 100644 headers/Structer.hpp
create mode 100644 headers/data_render.hpp
create mode 100644 main.cpp
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..982dfa0
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,21 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 3.25.0)
+
+set(CMAKE_CXX_COMPILER "C:/MinGW/bin/g++.exe")
+set(CMAKE_C_COMPILER "C:/MinGW/bin/gcc.exe")
+
+project(computer_vision)
+
+include_directories(./headers)
+
+find_package(OpenMP)
+if(OpenMP_FOUND)
+ message(STATUS "Link OpenMP")
+else()
+ message(STATUS "Not link OpenMP")
+endif()
+
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
+set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
+
+add_executable(computer_vision main.cpp ./headers/Structer.hpp ./headers/data_render.hpp ./headers/Color.hpp )
diff --git a/headers/Color.hpp b/headers/Color.hpp
new file mode 100644
index 0000000..9c6abd5
--- /dev/null
+++ b/headers/Color.hpp
@@ -0,0 +1,163 @@
+#ifndef _COLOR_
+#define _COLOR_
+#include
+enum mode { rgb, bgr };
+
+template
+class Color {
+private:
+ unsigned char components[4];
+public:
+
+ Color(const unsigned char& a = 0, const unsigned char& b = 0, const unsigned char& c = 0, const unsigned char& d = 0);
+ Color(const Color& color_m);
+
+ ~Color() {}
+
+ Color& operator=(const Color& color_m);
+ Color& operator=(const unsigned char& char_m);
+
+ unsigned char& R();
+ const unsigned char& R() const;
+ unsigned char& G();
+ const unsigned char& G() const;
+ unsigned char& B();
+ const unsigned char& B() const;
+ unsigned char& A();
+ const unsigned char& A() const;
+ void set_color(const unsigned char& a = 0, const unsigned char& b = 0, const unsigned char& c = 0, const unsigned char& d = 0);
+ unsigned char* getComp();
+ friend std::ostream& operator<<(std::ostream& out, const Color& color_m);
+};
+
+template
+Color::Color(const unsigned char& a, const unsigned char& b, const unsigned char& c, const unsigned char& d)
+{
+ components[0] = a;
+ components[1] = b;
+ components[2] = c;
+ components[3] = d;
+} /*-------------------------------------------------------------------------*/
+
+template
+Color::Color(const Color& color_m) {
+ components[0] = color_m.components[0];
+ components[1] = color_m.components[1];
+ components[2] = color_m.components[2];
+ components[3] = color_m.components[3];
+} /*-------------------------------------------------------------------------*/
+
+template
+Color& Color::operator=(const Color& color_m) {
+ components[0] = color_m.components[0];
+ components[1] = color_m.components[1];
+ components[2] = color_m.components[2];
+ components[3] = color_m.components[3];
+ return *this;
+} /*-------------------------------------------------------------------------*/
+
+template
+Color& Color::operator=(const unsigned char& char_m) {
+ components[0] = char_m;
+ components[1] = char_m;
+ components[2] = char_m;
+ components[3] = char_m;
+ return *this;
+} /*-------------------------------------------------------------------------*/
+
+template <>
+unsigned char& Color::R() {
+ return components[0];
+} /*-------------------------------------------------------------------------*/
+
+template <>
+const unsigned char& Color::R() const{
+ return components[0];
+} /*-------------------------------------------------------------------------*/
+
+template <>
+unsigned char& Color::R() {
+ return components[2];
+} /*-------------------------------------------------------------------------*/
+
+template <>
+const unsigned char& Color::R() const {
+ return components[2];
+} /*-------------------------------------------------------------------------*/
+
+template
+unsigned char& Color::G() {
+ return components[1];
+} /*-------------------------------------------------------------------------*/
+
+template
+const unsigned char& Color::G() const {
+ return components[1];
+} /*-------------------------------------------------------------------------*/
+
+template <>
+unsigned char& Color::B() {
+ return components[2];
+} /*-------------------------------------------------------------------------*/
+
+template <>
+const unsigned char& Color::B() const {
+ return components[2];
+} /*-------------------------------------------------------------------------*/
+
+template <>
+unsigned char& Color::B() {
+ return components[0];
+} /*-------------------------------------------------------------------------*/
+
+template <>
+const unsigned char& Color::B() const {
+ return components[0];
+} /*-------------------------------------------------------------------------*/
+
+template
+unsigned char& Color::A() {
+ return components[3];
+} /*-------------------------------------------------------------------------*/
+
+template
+const unsigned char& Color::A() const {
+ return components[3];
+} /*-------------------------------------------------------------------------*/
+
+template <>
+void Color::set_color(const unsigned char& a, const unsigned char& b, const unsigned char& c, const unsigned char& d) {
+ components[0] = a;
+ components[1] = b;
+ components[2] = c;
+ components[3] = d;
+} /*-------------------------------------------------------------------------*/
+
+template <>
+void Color::set_color(const unsigned char& a, const unsigned char& b, const unsigned char& c, const unsigned char& d) {
+ components[0] = c;
+ components[1] = b;
+ components[2] = a;
+ components[3] = d;
+} /*-------------------------------------------------------------------------*/
+
+template
+unsigned char* Color::getComp(){
+ unsigned char* a = new unsigned char[4];
+ a[0] = components[0];
+ a[1] = components[1];
+ a[2] = components[2];
+ a[3] = components[3];
+ return a;
+}
+
+std::ostream& operator<<(std::ostream& out, const Color& color_m) {
+ out << (int)color_m.R() << ',' << (int)color_m.G() << ',' << (int)color_m.B();
+ return out;
+}
+
+std::ostream& operator<<(std::ostream& out, const Color& color_m) {
+ out << (int)color_m.B() << ',' << (int)color_m.G() << ',' << (int)color_m.R();
+ return out;
+}
+#endif
\ No newline at end of file
diff --git a/headers/Function.hpp b/headers/Function.hpp
new file mode 100644
index 0000000..7954d3e
--- /dev/null
+++ b/headers/Function.hpp
@@ -0,0 +1,199 @@
+#ifndef _FUNCTION_
+#define _FUNCTION_
+
+#include
+//#include
+
+#define cllps 3
+#define thr 4
+
+template
+T multiplication_omp(const T& data1, const T& data2) {
+ int row1 = data1.height;
+ int row2 = data2.height;
+ int col1 = data1.width;
+ int col2 = data2.width;
+ T res(row1, col2, 0);
+ omp_set_num_threads(thr);
+#pragma omp parallel for collapse(cllps)
+ for (int i = 0; i < row1; ++i)
+ for (int j = 0; j < col2; ++j)
+ for (int k = 0; k < col1; ++k)
+ res[i * col2 + j] += data1[i * col1 + k] * data2[k * col2 + j];
+ return res;
+}
+
+/*
+template
+void multiplication_neon_float_4x4(const T& A, const T& B, const T& C) {
+ int row1 = data1.height;
+ int row2 = data2.height;
+ int col1 = data1.width;
+ int col2 = data2.width
+
+ int A_indx;
+ int B_indx;
+ int C_indx;
+
+ // remainder of dividing matrix sizes by 4
+ int row1_mod = row1 % 4;
+ int col1_mod = col1 % 4;
+ int col2_mod = col2 % 4;
+
+ float32x4_t A0;
+ float32x4_t A1;
+ float32x4_t A2;
+ float32x4_t A3;
+
+ float32x4_t B0;
+ float32x4_t B1;
+ float32x4_t B2;
+ float32x4_t B3;
+
+ float32x4_t C0;
+ float32x4_t C1;
+ float32x4_t C2;
+ float32x4_t C3;
+
+ for (int i = 0; i < row1 - row1_mod; i += 4){
+ for (int j = 0; j < col2 - col2_mod; j += 4) {
+ // zero accumulators before matrix op
+ C0 = vmovq_n_f32(0);
+ C1 = vmovq_n_f32(0);
+ C2 = vmovq_n_f32(0);
+ C3 = vmovq_n_f32(0);
+
+ for (int k = 0; k < col1 - col1_mod; k += 4) {
+ //compute base index to 4x4 block in matrix B
+ A_indx = i * col1 + k;
+ B_indx = k * col2 + j;
+
+ A0 = vld1q_f32(A + A_indx);
+ A1 = vld1q_f32(A + A_indx + col1);
+ A2 = vld1q_f32(A + A_indx + 2 * col1);
+ A3 = vld1q_f32(A + A_indx + 3 * col1);
+
+ B0 = vld1q_f32(B + B_indx);
+ B1 = vld1q_f32(B + B_indx + col1);
+ B2 = vld1q_f32(B + B_indx + 2 * col1);
+ B3 = vld1q_f32(B + B_indx + 3 * col1);
+
+ // multiply accumulate 4x4 blocks i.e. each column C
+ C0 = vfmaq_laneq_f32(C0, B0, A0, 0);
+ C0 = vfmaq_laneq_f32(C0, B1, A0, 1);
+ C0 = vfmaq_laneq_f32(C0, B2, A0, 2);
+ C0 = vfmaq_laneq_f32(C0, B3, A0, 3);
+
+ C1 = vfmaq_laneq_f32(C1, B0, A1, 0);
+ C1 = vfmaq_laneq_f32(C1, B1, A1, 1);
+ C1 = vfmaq_laneq_f32(C1, B2, A1, 2);
+ C1 = vfmaq_laneq_f32(C1, B3, A1, 3);
+
+ C2 = vfmaq_laneq_f32(C2, B0, A2, 0);
+ C2 = vfmaq_laneq_f32(C2, B1, A2, 1);
+ C2 = vfmaq_laneq_f32(C2, B2, A2, 2);
+ C2 = vfmaq_laneq_f32(C2, B3, A2, 3);
+
+ C3 = vfmaq_laneq_f32(C3, B0, A3, 0);
+ C3 = vfmaq_laneq_f32(C3, B1, A3, 1);
+ C3 = vfmaq_laneq_f32(C3, B2, A3, 2);
+ C3 = vfmaq_laneq_f32(C3, B3, A3, 3);
+ }
+ C_indx = i * col2 + j;
+
+ vst1q_f32(C + C_indx, C0);
+ vst1q_f32(C + C_indx + col2, C1);
+ vst1q_f32(C + C_indx + 2 * col2, C2);
+ vst1q_f32(C + C_indx + 3 * col3, C3);
+ }
+ }
+
+ // multiplication of matrix elements
+ // that could not be calculated using the 4x4 blocks
+ for (int i = 0; i < row1 - row1_mod; ++i) {
+ for (int j = 0; j < col2 - col2_mod; ++j)
+ for (int k = col1 - col1_mod; k < col1; ++k)
+ C[i * col2 + j] += A[i * col1 + k] * B[k * col2 + j];
+ for (int j = col2 - col2_mod; j < col2; ++j)
+ for (int k = 0; k < col1; ++k)
+ C[i * col2 + j] += A[i * col1 + k] * B[k * col2 + j];
+ }
+
+ for (int i = row1 - row1_mod; i < row1; ++i)
+ for (int j = 0; j < col1; ++j)
+ for (int k = 0; k < col1; ++k)
+ C[i * col2 + j] += A[i * col1 + k] * B[k * col2 + j];
+}
+
+template
+void multiplication_neon_float_2x2(const T& data1, const T& data2, const T& C) {
+ int row1 = data1.height;
+ int row2 = data2.height;
+ int col1 = data1.width;
+ int col2 = data2.width;
+
+ int A_indx;
+ int B_indx;
+ int C_indx;
+
+ // remainder of dividing matrix sizes by 2
+ int row1_mod = row1 % 2;
+ int col1_mod = col1 % 2;
+ int col2_mod = col2 % 2;
+
+ float32x2_t A0;
+ float32x2_t A1;
+
+ float32x2_t B0;
+ float32x2_t B1;
+
+ float32x2_t C0;
+ float32x2_t C1;
+
+ for (int i = 0; i < row1 - row1_mod; i += 2){
+ for (int j = 0; j < col2 - col2_mod; j += 2) {
+ C0 = vdup_n_f32(0);
+ C1 = vdup_n_f32(0);
+
+ for (int k = 0; k < col1 - col1_mod; k += 2) {
+ A_indx = i * col1 + k;
+ B_indx = k * col2 + j;
+
+ A0 = vld1_f32(A + A_indx);
+ A1 = vld1_f32(A + A_indx + col1);
+
+ B0 = vld1_f32(B + B_indx);
+ B1 = vld1_f32(B + B_indx);
+
+ C0 = vfma_lane_f32(C0, B0, A0, 0);
+ C0 = vfma_lane_f32(C0, B1, A0, 1);
+
+ C1 = vfma_lane_f32(C1, B0, A1, 0);
+ C1 = vfma_lane_f32(C1, B1, A1, 1);
+ }
+ C_indx = i * col2 + j;
+ vst1_f32(C + C_indx, C0);
+ vst1_f32(C + C_indx + col2, C1);
+ }
+ }
+
+ // multiplication of matrix elements
+ // that could not be calculated using the 2x2 blocks
+ for (int i = 0; i < row1 - row1_mod; ++i) {
+ for (int j = 0; j < col2 - col2_mod; ++j)
+ for (int k = col1 - col1_mod; k < col1; ++k)
+ C[i * col2 + j] += A[i * col1 + k] * B[k * col2 + j];
+
+ for (int j = col2 - col2_mod; j < col2; ++j)
+ for (int k = 0; k < col1; ++k)
+ C[i * col2 + j] += A[i * col1 + k] * B[k * col2 + j];
+ }
+
+ for (int i = row1 - row1_mod; i < row1; ++i)
+ for (int j = 0; j < col2; ++j)
+ for (int k = 0; k < col1; ++k)
+ C[i * col2 + j] += A[i * col1 + k] * B[k * col2 + j];
+}
+*/
+
+#endif
\ No newline at end of file
diff --git a/headers/Structer.hpp b/headers/Structer.hpp
new file mode 100644
index 0000000..54ebb4e
--- /dev/null
+++ b/headers/Structer.hpp
@@ -0,0 +1,239 @@
+#ifndef _MTRX_
+#define _MTRX_
+
+#include "Color.hpp"
+
+template
+class Mtrx {
+protected:
+ ValType* data = nullptr;
+public:
+ int height;
+ int width;
+
+ Mtrx(int height_m = 0, int width_m = 0, ValType element = 0);
+ Mtrx(const Mtrx& mtrx_m); // copy constructor
+ Mtrx(Mtrx&& mtrx_m);
+
+ ~Mtrx() { delete[] data; } // destructor
+
+ ValType det();
+
+ Mtrx& operator=(const Mtrx& mtrx_m); // assignment operator
+ Mtrx& operator=(Mtrx&& mtrx_m); // assignment operator
+ ValType& operator[](int position_m); // access
+ const ValType& operator[](int position_m) const; // const access
+
+ // scalar operation
+ Mtrx operator*(const ValType& val); // multiply by a scalar
+ Mtrx operator/(const ValType& val); // division by a scalar
+
+ // matrix operation
+ template
+ friend Mtrx operator*(const Mtrx& mtrx_left, const Mtrx& mtrx_right); // multiplication
+
+ template
+ friend Mtrx Adamar(const Mtrx& mtrx_left, const Mtrx& mtrx_right); // comp. multiplication
+
+ // input-output
+ template
+ friend std::ostream& operator<<(std::ostream& out, const Mtrx& mtrx_m);
+};
+
+template
+class Image : public Mtrx>
+{
+public:
+ Image(int height_m = 0, int width_m = 0, Color color_m = 0) // constructor
+ : Mtrx>(height_m, width_m, color_m) {}
+
+ unsigned char* splitR(); // split component
+ unsigned char* splitG();
+ unsigned char* splitB();
+ unsigned char* getMemory(int a, int b);
+};
+
+///
+///
+/// Mtrx
+///
+///
+
+template //contructor
+Mtrx::Mtrx(int height_m, int width_m, ValType element)
+ : height(height_m)
+ , width(width_m)
+{
+ data = new ValType[height * width];
+ for (int i = 0; i < height; ++i) {
+ for (int j = 0; j < width; ++j) {
+ data[i * width + j] = element;
+ }
+ }
+} /*-------------------------------------------------------------------------*/
+
+template //copy constructor
+Mtrx::Mtrx(const Mtrx& mtrx_m)
+ : height(mtrx_m.height)
+ , width(mtrx_m.width)
+{
+ data = new ValType[height * width];
+
+ for (int i = 0; i < height; ++i) {
+ for (int j = 0; j < width; ++j) {
+ data[i * width + j] = mtrx_m[i * width + j];
+ }
+ }
+} /*-------------------------------------------------------------------------*/
+
+template
+Mtrx::Mtrx(Mtrx&& mtrx_m)
+ : height(mtrx_m.height)
+ , width(mtrx_m.width)
+ , data(mtrx_m.data)
+{
+ mtrx_m.data = nullptr;
+} /*-------------------------------------------------------------------------*/
+
+template
+Mtrx& Mtrx::operator=(const Mtrx& mtrx_m) {
+ if (this != &mtrx_m) {
+ delete[] data;
+
+ height = mtrx_m.height;
+ width = mtrx_m.width;
+ data = new ValType[height * width];
+
+ for (int i = 0; i < height; i++) {
+ for (int j = 0; j < width; j++) {
+ data[i * height + j] = mtrx_m[i * height + j];
+ }
+ }
+ }
+ return *this;
+} /*-------------------------------------------------------------------------*/
+
+template
+Mtrx& Mtrx::operator=(Mtrx&& mtrx_m) {
+ height = mtrx_m.height;
+ width = mtrx_m.width;
+ std::swap(data, mtrx_m.data);
+
+ return *this;
+} /*-------------------------------------------------------------------------*/
+
+template
+const ValType& Mtrx::operator[](int position_m) const {
+ return data[position_m];
+
+} /*-------------------------------------------------------------------------*/
+
+template
+ValType& Mtrx::operator[](int position_m) {
+ return data[position_m];
+} /*-------------------------------------------------------------------------*/
+
+template
+Mtrx Mtrx::operator*(const ValType& val) {
+ Mtrx res(*this);
+ for (int i = 0; i < height; i++)
+ for (int j = 0; j < width; j++)
+ res[i * width + j] *= val;
+ return res;
+} /*-------------------------------------------------------------------------*/
+
+template
+Mtrx Mtrx::operator/(const ValType& val) {
+ Mtrx res(*this);
+ for (int i = 0; i < height; ++i)
+ for (int j = 0; j < width; j++) {
+ res[i * width + j] /= val;
+ }
+ return res;
+} /*-------------------------------------------------------------------------*/
+
+template
+Mtrx operator*(const Mtrx& mtrx_left, const Mtrx& mtrx_right) {
+ Mtrx mtrx_result(mtrx_left.height, mtrx_right.width);
+
+ for (int i = 0; i < mtrx_left.height; i++) {
+ for (int j = 0; j < mtrx_right.width; j++) {
+ for (int k = 0; k < mtrx_left.width; k++) {
+ mtrx_result.data[i * mtrx_result.width + j] += mtrx_left.data[i * mtrx_left.width + k] * mtrx_right.data[k * mtrx_right.width + j];
+ }
+ }
+ }
+
+ return mtrx_result;
+} /*-------------------------------------------------------------------------*/
+
+template
+Mtrx Adamar(const Mtrx& mtrx_left, const Mtrx& mtrx_right) {
+ Mtrx mtrx_result(mtrx_left.height, mtrx_left.width);
+
+ for (int i = 0; i < mtrx_result.height; ++i) {
+ for (int j = 0; j < mtrx_result.width; ++j) {
+ mtrx_result[i * mtrx_result.width + j] = mtrx_left[i * mtrx_left.width + j] * mtrx_right[i * mtrx_right.width + j];
+ }
+ }
+
+ return mtrx_result;
+} /*-------------------------------------------------------------------------*/
+
+template
+std::ostream& operator<<(std::ostream& out, const Mtrx& mtrx_m) {
+ for (int i = 0; i < mtrx_m.height; ++i) {
+ for (int j = 0; j < mtrx_m.width; ++j) {
+ out << mtrx_m.data[i * mtrx_m.width + j] << ' ';
+ }
+ out << '\n';
+ }
+ return out;
+} /*-------------------------------------------------------------------------*/
+
+///
+///
+/// Image
+///
+///
+
+template
+unsigned char* Image::splitR() {
+ unsigned char* R = new unsigned char[this->height * this->width];
+ for (int i = 0; i < this->height * this->width; i++) {
+ R[i] = this->data[i].R();
+ }
+ return R;
+} /*-------------------------------------------------------------------------*/
+
+template
+unsigned char* Image::splitG() {
+ unsigned char* G = new unsigned char[this->height * this->width];
+ for (int i = 0; i < this->height * this->width; i++) {
+ G[i] = this->data[i].G();
+ }
+ return G;
+} /*-------------------------------------------------------------------------*/
+
+template
+unsigned char* Image::splitB() {
+ unsigned char* B = new unsigned char[this->height * this->width];
+ for (int i = 0; i < this->height * this->width; i++) {
+ B[i] = this->data[i].B();
+ }
+ return B;
+} /*-------------------------------------------------------------------------*/
+
+template
+unsigned char* Image::getMemory(int a, int b){
+ unsigned char* ret = new unsigned char[4*(b-a)];
+ for(int i = 0; i < b-a; i++){
+ unsigned char* tmp = this->data[i+a].getComp();
+ for(int j = 0; j < 4; j++){
+ ret[i*4 + j] = tmp[j];
+ }
+ }
+ return ret;
+}
+
+#endif
\ No newline at end of file
diff --git a/headers/data_render.hpp b/headers/data_render.hpp
new file mode 100644
index 0000000..bee3138
--- /dev/null
+++ b/headers/data_render.hpp
@@ -0,0 +1,17 @@
+#ifndef _DATA_RENDER_
+#define _DATA_RENDER_
+
+#include
+#include
+
+namespace data_render {
+ template
+ void get_random(T& source, int size, int mmax = 256) {
+ srand(time(0));
+
+ for (int i = 0; i < size; ++i)
+ source[i] = (unsigned char)(rand() % mmax);
+ }
+}
+
+#endif
\ No newline at end of file
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..45bcf59
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,12 @@
+#include
+#include "Structer.hpp"
+#include "data_render.hpp"
+#include "Function.hpp"
+#include "Color.hpp"
+
+int main(){
+ Image a(10, 10);
+ Image b(10,10);
+ std::cout << a;
+ return 0;
+}
\ No newline at end of file
From bf4d7aa22be5d00939b25671d2aadf1ef7951f4f Mon Sep 17 00:00:00 2001
From: IzmaylovI <75639514+IzmaylovI@users.noreply.github.com>
Date: Wed, 5 Apr 2023 00:10:55 +0300
Subject: [PATCH 08/57] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 5cab01a..33cd27d 100644
--- a/README.md
+++ b/README.md
@@ -16,4 +16,4 @@ The test module. In development...
###Module 4. The Benchmarks module. In development...
## Clone the repo
-`git clone https://github.com/IzmaylovI/itlab_2022.git`
+`git clone https://github.com/embedded-dev-research/itlab_2022.git`
From 7f9681441ec0ee3110019180fc0240dc0c31fa6b Mon Sep 17 00:00:00 2001
From: IzmaylovI
Date: Wed, 5 Apr 2023 22:41:23 +0300
Subject: [PATCH 09/57] First_correction
---
CMakeLists.txt | 3 ---
headers/Color.hpp | 64 ++++++++++++++++++++++----------------------
headers/Function.hpp | 6 ++---
headers/Structer.hpp | 26 +++++++++---------
4 files changed, 48 insertions(+), 51 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 982dfa0..e43d687 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,8 +1,5 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.25.0)
-set(CMAKE_CXX_COMPILER "C:/MinGW/bin/g++.exe")
-set(CMAKE_C_COMPILER "C:/MinGW/bin/gcc.exe")
-
project(computer_vision)
include_directories(./headers)
diff --git a/headers/Color.hpp b/headers/Color.hpp
index 9c6abd5..c4a5a5b 100644
--- a/headers/Color.hpp
+++ b/headers/Color.hpp
@@ -1,9 +1,9 @@
#ifndef _COLOR_
#define _COLOR_
#include
-enum mode { rgb, bgr };
+enum layout { rgb, bgr };
-template
+template
class Color {
private:
unsigned char components[4];
@@ -30,8 +30,8 @@ class Color {
friend std::ostream& operator<<(std::ostream& out, const Color& color_m);
};
-template
-Color::Color(const unsigned char& a, const unsigned char& b, const unsigned char& c, const unsigned char& d)
+template
+Color::Color(const unsigned char& a, const unsigned char& b, const unsigned char& c, const unsigned char& d)
{
components[0] = a;
components[1] = b;
@@ -39,16 +39,16 @@ Color::Color(const unsigned char& a, const unsigned char& b, const unsigne
components[3] = d;
} /*-------------------------------------------------------------------------*/
-template
-Color::Color(const Color& color_m) {
+template
+Color::Color(const Color& color_m) {
components[0] = color_m.components[0];
components[1] = color_m.components[1];
components[2] = color_m.components[2];
components[3] = color_m.components[3];
} /*-------------------------------------------------------------------------*/
-template
-Color& Color::operator=(const Color& color_m) {
+template
+Color& Color::operator=(const Color& color_m) {
components[0] = color_m.components[0];
components[1] = color_m.components[1];
components[2] = color_m.components[2];
@@ -56,8 +56,8 @@ Color& Color::operator=(const Color& color_m) {
return *this;
} /*-------------------------------------------------------------------------*/
-template
-Color& Color::operator=(const unsigned char& char_m) {
+template
+Color& Color::operator=(const unsigned char& char_m) {
components[0] = char_m;
components[1] = char_m;
components[2] = char_m;
@@ -66,67 +66,67 @@ Color& Color::operator=(const unsigned char& char_m) {
} /*-------------------------------------------------------------------------*/
template <>
-unsigned char& Color::R() {
+unsigned char& Color::R() {
return components[0];
} /*-------------------------------------------------------------------------*/
template <>
-const unsigned char& Color::R() const{
+const unsigned char& Color::R() const{
return components[0];
} /*-------------------------------------------------------------------------*/
template <>
-unsigned char& Color::R() {
+unsigned char& Color::R() {
return components[2];
} /*-------------------------------------------------------------------------*/
template <>
-const unsigned char& Color::R() const {
+const unsigned char& Color::R() const {
return components[2];
} /*-------------------------------------------------------------------------*/
-template
-unsigned char& Color::G() {
+template
+unsigned char& Color::G() {
return components[1];
} /*-------------------------------------------------------------------------*/
-template
-const unsigned char& Color::G() const {
+template
+const unsigned char& Color::G() const {
return components[1];
} /*-------------------------------------------------------------------------*/
template <>
-unsigned char& Color::B() {
+unsigned char& Color::B() {
return components[2];
} /*-------------------------------------------------------------------------*/
template <>
-const unsigned char& Color::B() const {
+const unsigned char& Color::B() const {
return components[2];
} /*-------------------------------------------------------------------------*/
template <>
-unsigned char& Color::B() {
+unsigned char& Color::B() {
return components[0];
} /*-------------------------------------------------------------------------*/
template <>
-const unsigned char& Color::B() const {
+const unsigned char& Color::B() const {
return components[0];
} /*-------------------------------------------------------------------------*/
-template
-unsigned char& Color::A() {
+template
+unsigned char& Color::A() {
return components[3];
} /*-------------------------------------------------------------------------*/
-template
-const unsigned char& Color::A() const {
+template
+const unsigned char& Color::A() const {
return components[3];
} /*-------------------------------------------------------------------------*/
template <>
-void Color::set_color(const unsigned char& a, const unsigned char& b, const unsigned char& c, const unsigned char& d) {
+void Color::set_color(const unsigned char& a, const unsigned char& b, const unsigned char& c, const unsigned char& d) {
components[0] = a;
components[1] = b;
components[2] = c;
@@ -134,15 +134,15 @@ void Color::set_color(const unsigned char& a, const unsigned char& b,
} /*-------------------------------------------------------------------------*/
template <>
-void Color::set_color(const unsigned char& a, const unsigned char& b, const unsigned char& c, const unsigned char& d) {
+void Color::set_color(const unsigned char& a, const unsigned char& b, const unsigned char& c, const unsigned char& d) {
components[0] = c;
components[1] = b;
components[2] = a;
components[3] = d;
} /*-------------------------------------------------------------------------*/
-template
-unsigned char* Color::getComp(){
+template
+unsigned char* Color::getComp(){
unsigned char* a = new unsigned char[4];
a[0] = components[0];
a[1] = components[1];
@@ -151,12 +151,12 @@ unsigned char* Color::getComp(){
return a;
}
-std::ostream& operator<<(std::ostream& out, const Color& color_m) {
+std::ostream& operator<<(std::ostream& out, const Color& color_m) {
out << (int)color_m.R() << ',' << (int)color_m.G() << ',' << (int)color_m.B();
return out;
}
-std::ostream& operator<<(std::ostream& out, const Color& color_m) {
+std::ostream& operator<<(std::ostream& out, const Color& color_m) {
out << (int)color_m.B() << ',' << (int)color_m.G() << ',' << (int)color_m.R();
return out;
}
diff --git a/headers/Function.hpp b/headers/Function.hpp
index 7954d3e..88f0fd2 100644
--- a/headers/Function.hpp
+++ b/headers/Function.hpp
@@ -2,7 +2,7 @@
#define _FUNCTION_
#include
-//#include
+#include
#define cllps 3
#define thr 4
@@ -23,7 +23,7 @@ T multiplication_omp(const T& data1, const T& data2) {
return res;
}
-/*
+
template
void multiplication_neon_float_4x4(const T& A, const T& B, const T& C) {
int row1 = data1.height;
@@ -194,6 +194,6 @@ void multiplication_neon_float_2x2(const T& data1, const T& data2, const T& C) {
for (int k = 0; k < col1; ++k)
C[i * col2 + j] += A[i * col1 + k] * B[k * col2 + j];
}
-*/
+
#endif
\ No newline at end of file
diff --git a/headers/Structer.hpp b/headers/Structer.hpp
index 54ebb4e..69a6e19 100644
--- a/headers/Structer.hpp
+++ b/headers/Structer.hpp
@@ -11,7 +11,7 @@ class Mtrx {
int height;
int width;
- Mtrx(int height_m = 0, int width_m = 0, ValType element = 0);
+ Mtrx(int height_m, int width_m, ValType element = 0);
Mtrx(const Mtrx& mtrx_m); // copy constructor
Mtrx(Mtrx&& mtrx_m);
@@ -40,12 +40,12 @@ class Mtrx {
friend std::ostream& operator<<(std::ostream& out, const Mtrx& mtrx_m);
};
-template
-class Image : public Mtrx>
+template
+class Image : public Mtrx>
{
public:
- Image(int height_m = 0, int width_m = 0, Color color_m = 0) // constructor
- : Mtrx>(height_m, width_m, color_m) {}
+ Image(int height_m, int width_m, Color color_m = 0) // constructor
+ : Mtrx>(height_m, width_m, color_m) {}
unsigned char* splitR(); // split component
unsigned char* splitG();
@@ -197,8 +197,8 @@ std::ostream& operator<<(std::ostream& out, const Mtrx& mtrx_m) {
///
///
-template
-unsigned char* Image::splitR() {
+template
+unsigned char* Image::splitR() {
unsigned char* R = new unsigned char[this->height * this->width];
for (int i = 0; i < this->height * this->width; i++) {
R[i] = this->data[i].R();
@@ -206,8 +206,8 @@ unsigned char* Image::splitR() {
return R;
} /*-------------------------------------------------------------------------*/
-template
-unsigned char* Image::splitG() {
+template
+unsigned char* Image::splitG() {
unsigned char* G = new unsigned char[this->height * this->width];
for (int i = 0; i < this->height * this->width; i++) {
G[i] = this->data[i].G();
@@ -215,8 +215,8 @@ unsigned char* Image::splitG() {
return G;
} /*-------------------------------------------------------------------------*/
-template
-unsigned char* Image::splitB() {
+template
+unsigned char* Image::splitB() {
unsigned char* B = new unsigned char[this->height * this->width];
for (int i = 0; i < this->height * this->width; i++) {
B[i] = this->data[i].B();
@@ -224,8 +224,8 @@ unsigned char* Image::splitB() {
return B;
} /*-------------------------------------------------------------------------*/
-template
-unsigned char* Image::getMemory(int a, int b){
+template
+unsigned char* Image::getMemory(int a, int b){
unsigned char* ret = new unsigned char[4*(b-a)];
for(int i = 0; i < b-a; i++){
unsigned char* tmp = this->data[i+a].getComp();
From 04b352af318b006239c06a6d871ef7633db97bc5 Mon Sep 17 00:00:00 2001
From: IzmaylovI
Date: Tue, 11 Apr 2023 16:27:51 +0300
Subject: [PATCH 10/57] BMP_parsing
---
CMakeLists.txt | 11 ++-
headers/BMP.hpp | 87 ++++++++++++++++++++
headers/Function.hpp | 6 +-
headers/Imaging.hpp | 29 +++++++
headers/Structer.hpp | 105 +++++++++++++++++++++---
main.cpp | 9 ++-
sources/BMP.cpp | 185 +++++++++++++++++++++++++++++++++++++++++++
sources/Imaging.cpp | 69 ++++++++++++++++
8 files changed, 484 insertions(+), 17 deletions(-)
create mode 100644 headers/BMP.hpp
create mode 100644 headers/Imaging.hpp
create mode 100644 sources/BMP.cpp
create mode 100644 sources/Imaging.cpp
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e43d687..7455846 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,9 +1,17 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.25.0)
+set(CMAKE_CXX_COMPILER "C:/MinGW/bin/g++.exe")
+set(CMAKE_C_COMPILER "C:/MinGW/bin/gcc.exe")
+
project(computer_vision)
include_directories(./headers)
+set(HRD headers/BMP.hpp)
+set(SRC sources/BMP.cpp)
+
+add_library(func_algo ${HDR} ${SRC})
+
find_package(OpenMP)
if(OpenMP_FOUND)
message(STATUS "Link OpenMP")
@@ -15,4 +23,5 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
-add_executable(computer_vision main.cpp ./headers/Structer.hpp ./headers/data_render.hpp ./headers/Color.hpp )
+add_executable(computer_vision main.cpp ./headers/Structer.hpp ./headers/data_render.hpp ./headers/Color.hpp ./headers/BMP.hpp)
+target_link_libraries(computer_vision func_algo)
\ No newline at end of file
diff --git a/headers/BMP.hpp b/headers/BMP.hpp
new file mode 100644
index 0000000..743e2dd
--- /dev/null
+++ b/headers/BMP.hpp
@@ -0,0 +1,87 @@
+#ifndef __BMP__
+#define __BMP__
+
+#include
+#include
+#include
+#include
+#include
+
+#pragma pack(push, 1)
+struct BMPFileHeader {
+ uint16_t file_type{ 0x4D42 };
+ uint32_t file_size{ 0 };
+ uint16_t reserved1{ 0 };
+ uint16_t reserved2{ 0 };
+ uint32_t offset_data{ 0 };
+};
+
+struct BMPInfoHeader {
+ uint32_t size{ 0 };
+ int32_t width{ 0 };
+ int32_t height{ 0 };
+
+
+ uint16_t planes{ 1 };
+ uint16_t bit_count{ 0 };
+ uint32_t compression{ 0 };
+ uint32_t size_image{ 0 };
+ int32_t x_pixels_per_meter{ 0 };
+ int32_t y_pixels_per_meter{ 0 };
+ uint32_t colors_used{ 0 };
+ uint32_t colors_important{ 0 };
+};
+
+struct BMPColorHeader {
+ uint32_t red_mask{ 0x00ff0000 };
+ uint32_t green_mask{ 0x0000ff00 };
+ uint32_t blue_mask{ 0x000000ff };
+ uint32_t alpha_mask{ 0xff000000 };
+ uint32_t color_space_type{ 0x73524742 };
+ uint32_t unused[16]{ 0 };
+};
+
+int count_channels = 3;
+
+void check_color_header(BMPColorHeader& bmp_color_header) {
+ BMPColorHeader expected_color_header;
+ if (expected_color_header.red_mask != bmp_color_header.red_mask ||
+ expected_color_header.blue_mask != bmp_color_header.blue_mask ||
+ expected_color_header.green_mask != bmp_color_header.green_mask ||
+ expected_color_header.alpha_mask != bmp_color_header.alpha_mask) {
+ throw std::runtime_error("Unexpected color mask format! The program expects the pixel data to be in the BGRA format");
+ }
+ if (expected_color_header.color_space_type != bmp_color_header.color_space_type) {
+ throw std::runtime_error("Unexpected color space type! The program expects sRGB values");
+ }
+}
+/*
+struct BMP {
+ BMPFileHeader file_header;
+ BMPInfoHeader bmp_info_header;
+ BMPColorHeader bmp_color_header;
+ std::vector data;
+
+ BMP(const char* fname) { read(fname); }
+ BMP(int32_t width, int32_t height, bool has_alpha = true);
+
+ void read(const char* fname);
+ void write(const char* fname);
+ void fill_region(uint32_t x0, uint32_t y0, uint32_t w, uint32_t h, uint8_t B, uint8_t G, uint8_t R, uint8_t A);
+
+
+private:
+ uint32_t row_stride{ 0 };
+
+ void write_headers(std::ofstream& of);
+ void write_headers_and_data(std::ofstream& of);
+
+ // Add 1 to the raw_stride until it is divisible with align_stride
+ uint32_t make_stride_aligned(uint32_t align_stride);
+
+ // Check if the pixel data is stored as BGRA and if the color space type is sRGB
+ void check_color_header(BMPColorHeader& bmp_color_header);
+};
+*/
+#pragma pack(pop)
+#endif
\ No newline at end of file
diff --git a/headers/Function.hpp b/headers/Function.hpp
index 88f0fd2..7954d3e 100644
--- a/headers/Function.hpp
+++ b/headers/Function.hpp
@@ -2,7 +2,7 @@
#define _FUNCTION_
#include
-#include
+//#include
#define cllps 3
#define thr 4
@@ -23,7 +23,7 @@ T multiplication_omp(const T& data1, const T& data2) {
return res;
}
-
+/*
template
void multiplication_neon_float_4x4(const T& A, const T& B, const T& C) {
int row1 = data1.height;
@@ -194,6 +194,6 @@ void multiplication_neon_float_2x2(const T& data1, const T& data2, const T& C) {
for (int k = 0; k < col1; ++k)
C[i * col2 + j] += A[i * col1 + k] * B[k * col2 + j];
}
-
+*/
#endif
\ No newline at end of file
diff --git a/headers/Imaging.hpp b/headers/Imaging.hpp
new file mode 100644
index 0000000..cd0fd6f
--- /dev/null
+++ b/headers/Imaging.hpp
@@ -0,0 +1,29 @@
+#ifndef _IMAGING_
+#define _IMAGING_
+#include "Structer.hpp"
+
+class Color {
+private:
+ unsigned char c[3];
+public:
+ Color(unsigned char r_m = 0, unsigned char g_m = 0, unsigned char b_m = 0); // constructor
+ Color(const Color& color_m); // copy constructor
+
+ ~Color() {} // destructor
+
+ Color& operator=(const Color& color_m); // assignment operator
+ Color& operator=(const unsigned char& char_m);
+ unsigned char& R();
+ const unsigned char& R() const;
+ unsigned char& G();
+ const unsigned char& G() const;
+ unsigned char& B();
+ const unsigned char& B() const;
+ void set_color(unsigned char r_m, unsigned char g_m, unsigned char b_m);
+
+ friend std::ostream& operator<<(std::ostream& out, const Color& color_m);
+};
+
+using Image = Mtrx;
+
+#endif
\ No newline at end of file
diff --git a/headers/Structer.hpp b/headers/Structer.hpp
index 69a6e19..05b8ddd 100644
--- a/headers/Structer.hpp
+++ b/headers/Structer.hpp
@@ -1,6 +1,7 @@
#ifndef _MTRX_
#define _MTRX_
+#include "BMP.hpp"
#include "Color.hpp"
template
@@ -10,10 +11,11 @@ class Mtrx {
public:
int height;
int width;
-
+ Mtrx() {};
Mtrx(int height_m, int width_m, ValType element = 0);
Mtrx(const Mtrx& mtrx_m); // copy constructor
Mtrx(Mtrx&& mtrx_m);
+ ValType* DData() { return data; }
~Mtrx() { delete[] data; } // destructor
@@ -23,6 +25,8 @@ class Mtrx {
Mtrx& operator=(Mtrx&& mtrx_m); // assignment operator
ValType& operator[](int position_m); // access
const ValType& operator[](int position_m) const; // const access
+ ValType& operator()(int i,int j);
+ const ValType& operator()(int i, int j) const;
// scalar operation
Mtrx operator*(const ValType& val); // multiply by a scalar
@@ -46,11 +50,17 @@ class Image : public Mtrx>
public:
Image(int height_m, int width_m, Color color_m = 0) // constructor
: Mtrx>(height_m, width_m, color_m) {}
+ Image(const char* fname)
+ : Mtrx>()
+ {
+ readBMP(fname);
+ }
- unsigned char* splitR(); // split component
- unsigned char* splitG();
- unsigned char* splitB();
+ unsigned char* splitR(); // split component R
+ unsigned char* splitG(); // split component G
+ unsigned char* splitB(); // split component B
unsigned char* getMemory(int a, int b);
+ void readBMP(const char* fname);
};
///
@@ -133,6 +143,16 @@ ValType& Mtrx::operator[](int position_m) {
return data[position_m];
} /*-------------------------------------------------------------------------*/
+template
+ValType& Mtrx::operator()(int i, int j) {
+ return data[i * width + j];
+} /*-------------------------------------------------------------------------*/
+
+template
+const ValType& Mtrx::operator()(int i, int j) const {
+ return data[i * width + j];
+} /*-------------------------------------------------------------------------*/
+
template
Mtrx Mtrx::operator*(const ValType& val) {
Mtrx