1///////////////////////////////////////////////////////////////////////////////////////////////////
2// OpenGL Image Copyright (c) 2008 - 2011 G-Truc Creation (www.g-truc.net)
3///////////////////////////////////////////////////////////////////////////////////////////////////
4// Created : 2008-12-19
5// Updated : 2010-09-08
6// Licence : This source is under MIT License
7// File    : gli/core/operation.inl
8///////////////////////////////////////////////////////////////////////////////////////////////////
9
10#include <cstring>
11
12namespace gli
13{
14	namespace detail
15	{
16		inline image2D duplicate(image2D const & Mipmap2D)
17		{
18			image2D Result(Mipmap2D.dimensions(), Mipmap2D.format());
19			memcpy(Result.data(), Mipmap2D.data(), Mipmap2D.capacity());
20			return Result;
21		}
22
23		inline image2D flip(image2D const & Mipmap2D)
24		{
25			image2D Result(Mipmap2D.dimensions(), Mipmap2D.format());
26
27			std::size_t ValueSize = Result.value_size();
28			glm::byte * DstPtr = Result.data();
29			glm::byte const * const SrcPtr = Mipmap2D.data();
30
31			for(std::size_t j = 0; j < Result.dimensions().y; ++j)
32			for(std::size_t i = 0; i < Result.dimensions().x; ++i)
33			{
34				std::size_t DstIndex = (i + j * Result.dimensions().y) * ValueSize;
35				std::size_t SrcIndex = (i + (Result.dimensions().y - j) * Result.dimensions().x) * ValueSize;
36				memcpy(DstPtr + DstIndex, SrcPtr + SrcIndex, ValueSize);
37			}
38
39			return Result;
40		}
41
42		inline image2D mirror(image2D const & Mipmap2D)
43		{
44			image2D Result(Mipmap2D.dimensions(), Mipmap2D.format());
45
46			std::size_t ValueSize = Mipmap2D.value_size();
47			glm::byte * DstPtr = Result.data();
48			glm::byte const * const SrcPtr = Mipmap2D.data();
49
50			for(std::size_t j = 0; j < Result.dimensions().y; ++j)
51			for(std::size_t i = 0; i < Result.dimensions().x; ++i)
52			{
53				std::size_t DstIndex = (i + j * Result.dimensions().x) * ValueSize;
54				std::size_t SrcIndex = ((Result.dimensions().x - i) + j * Result.dimensions().x) * ValueSize;
55				memcpy(DstPtr + DstIndex, SrcPtr + SrcIndex, ValueSize);
56			}
57
58			return Result;
59		}
60
61		inline image2D swizzle
62		(
63			image2D const & Mipmap,
64			glm::uvec4 const & Channel
65		)
66		{
67			image2D Result = detail::duplicate(Mipmap);
68
69			glm::byte * DataDst = Result.data();
70			glm::byte const * const DataSrc = Mipmap.data();
71
72			gli::texture2D::size_type CompSize = Mipmap.value_size() / Mipmap.components();
73			gli::texture2D::size_type TexelCount = Mipmap.capacity() / Mipmap.value_size();
74
75			for(gli::texture2D::size_type t = 0; t < TexelCount; ++t)
76			for(gli::texture2D::size_type c = 0; c < Mipmap.components(); ++c)
77			{
78				gli::texture2D::size_type IndexSrc = t * Mipmap.components() + Channel[static_cast<int>(c)];
79				gli::texture2D::size_type IndexDst = t * Mipmap.components() + c;
80
81				memcpy(DataDst + IndexDst, DataSrc + IndexSrc, CompSize);
82			}
83
84			return Result;
85		}
86
87		inline image2D crop
88		(
89			image2D const & Image,
90			image2D::dimensions_type const & Position,
91			image2D::dimensions_type const & Size
92		)
93		{
94			assert((Position.x + Size.x) <= Image.dimensions().x && (Position.y + Size.y) <= Image.dimensions().y);
95
96			image2D Result(Size, Image.format());
97
98			glm::byte* DstData = Result.data();
99			glm::byte const * const SrcData = Image.data();
100
101			for(std::size_t j = 0; j < Size.y; ++j)
102			{
103				std::size_t DstIndex = 0                                + (0          + j) * Size.x         * Image.value_size();
104				std::size_t SrcIndex = Position.x * Image.value_size() + (Position.y + j) * Image.dimensions().x * Image.value_size();
105				memcpy(DstData + DstIndex, SrcData + SrcIndex, Image.value_size() * Size.x);
106			}
107
108			return Result;
109		}
110
111		inline image2D copy
112		(
113			image2D const & SrcMipmap,
114			image2D::dimensions_type const & SrcPosition,
115			image2D::dimensions_type const & SrcSize,
116			image2D & DstMipmap,
117			image2D::dimensions_type const & DstPosition
118		)
119		{
120			assert((SrcPosition.x + SrcSize.x) <= SrcMipmap.dimensions().x && (SrcPosition.y + SrcSize.y) <= SrcMipmap.dimensions().y);
121			assert(SrcMipmap.format() == DstMipmap.format());
122
123			glm::byte * DstData = DstMipmap.data();
124			glm::byte const * const SrcData = SrcMipmap.data();
125
126			std::size_t SizeX = glm::min(std::size_t(SrcSize.x + SrcPosition.x), std::size_t(DstMipmap.dimensions().x  + DstPosition.x));
127			std::size_t SizeY = glm::min(std::size_t(SrcSize.y + SrcPosition.y), std::size_t(DstMipmap.dimensions().y + DstPosition.y));
128
129			for(std::size_t j = 0; j < SizeY; ++j)
130			{
131				std::size_t DstIndex = DstPosition.x * DstMipmap.value_size() + (DstPosition.y + j) * DstMipmap.dimensions().x * DstMipmap.value_size();
132				std::size_t SrcIndex = SrcPosition.x * SrcMipmap.value_size() + (SrcPosition.y + j) * SrcMipmap.dimensions().x * SrcMipmap.value_size();
133				memcpy(DstData + DstIndex, SrcData + SrcIndex, SrcMipmap.value_size() * SizeX);
134			}
135
136			return DstMipmap;
137		}
138
139	}//namespace detail
140
141	inline texture2D duplicate(texture2D const & Texture2D)
142	{
143		texture2D Result(Texture2D.levels());
144		for(texture2D::level_type Level = 0; Level < Texture2D.levels(); ++Level)
145			Result[Level] = detail::duplicate(Texture2D[Level]);
146		return Result;
147	}
148
149	inline texture2D flip(texture2D const & Texture2D)
150	{
151		texture2D Result(Texture2D.levels());
152		for(texture2D::level_type Level = 0; Level < Texture2D.levels(); ++Level)
153			Result[Level] = detail::flip(Texture2D[Level]);
154		return Result;
155	}
156
157	inline texture2D mirror(texture2D const & Texture2D)
158	{
159		texture2D Result(Texture2D.levels());
160		for(texture2D::level_type Level = 0; Level < Texture2D.levels(); ++Level)
161			Result[Level] = detail::mirror(Texture2D[Level]);
162		return Result;
163	}
164
165	inline texture2D crop
166	(
167		texture2D const & Texture2D,
168		texture2D::dimensions_type const & Position,
169		texture2D::dimensions_type const & Size
170	)
171	{
172		texture2D Result(Texture2D.levels());
173		for(texture2D::level_type Level = 0; Level < Texture2D.levels(); ++Level)
174			Result[Level] = detail::crop(
175				Texture2D[Level],
176				Position >> texture2D::dimensions_type(Level),
177				Size >> texture2D::dimensions_type(Level));
178		return Result;
179	}
180
181	inline texture2D swizzle
182	(
183		texture2D const & Texture2D,
184		glm::uvec4 const & Channel
185	)
186	{
187		texture2D Result(Texture2D.levels());
188		for(texture2D::level_type Level = 0; Level < Texture2D.levels(); ++Level)
189			Result[Level] = detail::swizzle(Texture2D[Level], Channel);
190		return Result;
191	}
192
193	inline texture2D copy
194	(
195		texture2D const & SrcImage,
196		texture2D::level_type const & SrcLevel,
197		texture2D::dimensions_type const & SrcPosition,
198		texture2D::dimensions_type const & SrcDimensions,
199		texture2D & DstMipmap,
200		texture2D::level_type const & DstLevel,
201		texture2D::dimensions_type const & DstDimensions
202	)
203	{
204		detail::copy(
205			SrcImage[SrcLevel],
206			SrcPosition,
207			SrcDimensions,
208			DstMipmap[DstLevel],
209			DstDimensions);
210		return DstMipmap;
211	}
212
213	//inline image operator+(image const & MipmapA, image const & MipmapB)
214	//{
215	//
216	//}
217
218	//inline image operator-(image const & MipmapA, image const & MipmapB)
219	//{
220	//
221	//}
222
223	//inline image operator*(image const & MipmapA, image const & MipmapB)
224	//{
225	//
226	//}
227
228	//inline image operator/(image const & MipmapA, image const & MipmapB)
229	//{
230	//
231	//}
232
233}//namespace gli
234