1 /*
2 * The MIT License (MIT)
3 * This file is part of waifu2x-converter-cpp
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23 
24 #include <stdlib.h>
25 #include <string.h>
26 #include "cvwrap.hpp"
27 
~W2Mat()28 W2Mat::~W2Mat()
29 {
30 	if (data_owner)
31 	{
32 		data_owner=false;
33 		free(data);
34 		data = nullptr;
35 	}
36 }
37 
38 
W2Mat()39 W2Mat::W2Mat()
40 	: data_owner(false),
41 	data(nullptr),
42 	data_byte_width(0),
43 	data_height(0),
44 	view_top(0),
45 	view_left(0),
46 	view_width(0),
47 	view_height(0)
48 {
49 }
50 
W2Mat(int width,int height,int type)51 W2Mat::W2Mat(int width, int height, int type)
52 	: data_owner(true),
53 	data_byte_width(width*CV_ELEM_SIZE(type)),
54 	data_height(height),
55 	view_top(0),
56 	view_left(0),
57 	view_width(width),
58 	view_height(height),
59 	type(type)
60 {
61 	this->data = (char*)calloc(height, data_byte_width);
62 }
63 
W2Mat(int width,int height,int type,void * data,int data_step)64 W2Mat::W2Mat(int width, int height, int type, void *data, int data_step)
65 	: data_owner(true),
66 	data_byte_width(data_step),
67 	data_height(height),
68 	view_top(0),
69 	view_left(0),
70 	view_width(width),
71 	view_height(height),
72 	type(type)
73 {
74 	this->data = (char*)calloc(height, data_byte_width);
75 	memcpy(this->data, data, height * data_byte_width);
76 }
77 
78 
operator =(W2Mat && rhs)79 W2Mat & W2Mat::operator=(W2Mat &&rhs)
80 {
81     this->data_owner = rhs.data_owner;
82     this->data = rhs.data;
83     this->data_byte_width = rhs.data_byte_width;
84     this->data_height = rhs.data_height;
85     this->view_top = rhs.view_top;
86     this->view_left = rhs.view_left;
87     this->view_width = rhs.view_width;
88     this->view_height= rhs.view_height;
89     this->type = rhs.type;
90 
91     rhs.data_owner = false;
92     rhs.data = NULL;
93 
94     return *this;
95 }
96 
W2Mat(const W2Mat & rhs,int view_left_offset,int view_top_offset,int view_width,int view_height)97 W2Mat::W2Mat(const W2Mat & rhs, int view_left_offset, int view_top_offset, int view_width, int view_height)
98 {
99     this->data_owner = false;
100     this->data = rhs.data;
101     this->data_byte_width = rhs.data_byte_width;
102     this->data_height = rhs.data_height;
103 
104     this->view_left = rhs.view_left + view_left_offset;
105     this->view_top = rhs.view_top + view_top_offset;
106     this->view_width = view_width;
107     this->view_height = view_height;
108 
109     this->type = rhs.type;
110 }
111 
copyTo(W2Mat * target)112 void W2Mat::copyTo(W2Mat* target)
113 {
114 	W2Mat ret(this->view_width, this->view_height, this->type);
115 
116 	int elem_size = CV_ELEM_SIZE(this->type);
117 	int w = this->view_width;
118 	int h = this->view_height;
119 
120 	for (int yi = 0; yi < h; yi++)
121 	{
122 		char *out = ret.ptr<char>(yi);
123 		char *in = this->ptr<char>(yi);
124 
125 		memcpy(out, in, w * elem_size);
126 	}
127 	*target = std::move(ret);
128 }
129 
130 #ifdef HAVE_OPENCV
W2Mat(cv::Mat & m)131 W2Mat::W2Mat(cv::Mat &m) : data_owner(true), view_top(0), view_left(0)
132 {
133 	int w = m.size().width;
134 	int h = m.size().height;
135 
136 	this->data_byte_width = w * CV_ELEM_SIZE(m.type());
137 	this->data_height = h;
138 	this->view_width = w;
139 	this->view_height = h;
140 	this->type = m.type();
141 	this->data = (char*)calloc(h, this->data_byte_width);
142 
143 
144 	for (int yi = 0; yi < h; yi++)
145 	{
146 		void *in = m.ptr(yi);
147 		char *out = this->ptr<char>(yi);
148 
149 		memcpy(out, in, this->data_byte_width);
150 	}
151 }
152 
to_cvmat(cv::Mat * target)153 void W2Mat::to_cvmat(cv::Mat *target)
154 {
155 	int w = this->view_width;
156 	int h = this->view_height;
157 
158 	cv::Mat ret = cv::Mat::zeros(cv::Size(w, h), this->type);
159 	int elem_size = CV_ELEM_SIZE(this->type);
160 
161 	for (int yi = 0; yi < h; yi++)
162 	{
163 		void *out = ret.ptr(yi);
164 		void *in = this->ptr<char>(yi);
165 
166 		memcpy(out, in, w * elem_size);
167 	}
168 	*target = ret.clone();
169 }
170 
171 // DO NOT USE IN NORMAL SITUAYION. Return wm is not own their data.
extract_view_from_cvmat(W2Mat & wm,cv::Mat & m)172 void extract_view_from_cvmat(W2Mat &wm, cv::Mat &m)
173 {
174 	wm.data_owner = false;
175 	wm.data = (char*) m.data;
176 	wm.data_byte_width = (int) m.step;
177 	wm.data_height = m.size().height;
178 
179 	wm.view_top = 0;
180 	wm.view_left = 0;
181 	wm.view_width = m.size().width;
182 	wm.view_height = m.size().height;
183 	wm.type = m.type();
184 
185 }
186 
extract_view_to_cvmat(cv::Mat & m,W2Mat & wm)187 void extract_view_to_cvmat(cv::Mat &m, W2Mat &wm)
188 {
189 	int w = wm.view_width;
190 	int h = wm.view_height;
191 
192 	char *data = (char*) wm.data;
193 
194 	int byte_offset = 0;
195 	byte_offset += wm.view_top * wm.data_byte_width;
196 	byte_offset += wm.view_left * CV_ELEM_SIZE(wm.type);
197 
198 	cv::Mat ret(cv::Size(w,h), wm.type, data + byte_offset, wm.data_byte_width);
199 
200 	ret.copyTo(m);
201 }
202 
203 // DO NOT USE IN NORMAL SITUAYION. Return wm is not own their data.
extract_view_from_cvmat_offset(W2Mat & wm,cv::Mat & m,int view_left_offset,int view_top_offset,int view_width,int view_height)204 void extract_view_from_cvmat_offset
205 (
206 	W2Mat &wm,
207 	cv::Mat &m,
208 	int view_left_offset,
209 	int view_top_offset,
210 	int view_width,
211 	int view_height
212 )
213 {
214 	extract_view_from_cvmat(wm, m);
215 
216 	wm.view_top = view_top_offset;
217 	wm.view_left = view_left_offset;
218 	wm.view_width = view_width;
219 	wm.view_height = view_height;
220 }
221 
extract_viewlist_from_cvmat(std::vector<W2Mat> & list,std::vector<cv::Mat> & cvmat)222 void extract_viewlist_from_cvmat(std::vector<W2Mat> &list, std::vector<cv::Mat> &cvmat)
223 {
224 	std::for_each(cvmat.begin(), cvmat.end(),
225 		[&list](cv::Mat &cv) {
226 		W2Mat w2;
227 		extract_view_from_cvmat(w2, cv);
228 		list.push_back(std::move(w2));
229 	});
230 }
231 
extract_viewlist_to_cvmat(std::vector<cv::Mat> & cvmat,std::vector<W2Mat> & list)232 void extract_viewlist_to_cvmat(std::vector<cv::Mat> &cvmat, std::vector<W2Mat> &list)
233 {
234 	std::for_each(list.begin(), list.end(),
235 		[&cvmat](W2Mat &wm) {
236 		cv::Mat cv;
237 		extract_view_to_cvmat(cv, wm);
238 		cvmat.push_back(cv.clone());
239 	});
240 }
241 
242 #endif
243