EHS/src/io/img/Img.cpp

1488 lines
31 KiB
C++
Raw Normal View History

2024-02-05 22:25:30 -08:00
#include "ehs/io/img/Img.h"
namespace ehs
{
Array<ImgCodec> Img::codecs;
bool Img::HasCodec(const UInt_64 hashExt)
{
for (UInt_64 i = 0; i < codecs.Size(); ++i)
if (codecs[i].GetHashExt() == hashExt)
return true;
return false;
}
bool Img::HasCodec(const Str_8& ext)
{
return HasCodec(ext.Hash_64());
}
bool Img::AddCodec(ImgCodec codec)
{
if (HasCodec(codec.GetHashExt()))
return false;
codecs.Push(std::move(codec));
return true;
}
const ImgCodec* Img::GetCodec(const UInt_64 hashExt)
{
for (UInt_64 i = 0; i < codecs.Size(); ++i)
if (codecs[i].GetHashExt() == hashExt)
return &codecs[i];
return nullptr;
}
const ImgCodec* Img::GetCodec(const Str_8& ext)
{
return GetCodec(ext.Hash_64());
}
Img::~Img()
{
delete[] data;
}
Img::Img()
: hashId(0), data(nullptr), byteDepth(0), channels(0), size(0)
{
AddType("Img");
}
Img::Img(Str_8 id, const UInt_8 byteDepth, const UInt_8 channels, const Vec2_u64& resolution, const Byte* const data)
: hashId(id.Hash_64()), id((Str_8&&)id), byteDepth(byteDepth), channels(channels), resolution(resolution),
size(resolution.x * byteDepth * channels * resolution.y), data(new Byte[size])
{
Util::Copy(this->data, data, size);
AddType("Img");
}
Img::Img(Str_8 id, const UInt_8 byteDepth, const UInt_8 channels, const Vec2_u64& resolution)
: hashId(id.Hash_64()), id((Str_8&&)id), byteDepth(byteDepth), channels(channels), resolution(resolution),
size(resolution.x * byteDepth * channels * resolution.y), data(new Byte[size])
{
AddType("Img");
}
Img::Img(Str_8 id)
: hashId(id.Hash_64()), id((Str_8&&)id), byteDepth(0), channels(0), size(0), data(nullptr)
{
AddType("Img");
}
Img::Img(Img&& img) noexcept
: BaseObj((BaseObj&&)img), hashId(img.hashId), id((Str_8&&)img.id), byteDepth(img.byteDepth),
channels(img.channels), resolution(img.resolution), size(img.size), data(img.data)
{
img.byteDepth = 0;
img.channels = 0;
img.resolution = {};
img.size = 0;
img.data = nullptr;
}
Img::Img(const Img& img)
: BaseObj(img), hashId(img.hashId), id(img.id), byteDepth(img.byteDepth), channels(img.channels),
resolution(img.resolution), size(img.size), data(new Byte[img.size])
{
Util::Copy(data, img.data, img.size);
}
Img& Img::operator=(Img&& img) noexcept
{
if (this == &img)
return *this;
BaseObj::operator=((BaseObj&&)img);
byteDepth = img.byteDepth;
channels = img.channels;
resolution = img.resolution;
size = img.size;
delete[] data;
data = img.data;
img.byteDepth = 0;
img.channels = 0;
img.resolution = {};
img.size = 0;
img.data = nullptr;
return *this;
}
Img& Img::operator=(const Img& img)
{
if (this == &img)
return *this;
BaseObj::operator=(img);
byteDepth = img.byteDepth;
channels = img.channels;
resolution = img.resolution;
size = img.size;
delete[] data;
data = new Byte[img.size];
Util::Copy(data, img.data, img.size);
return *this;
}
Img::operator const Byte* () const
{
return data;
}
Img::operator Byte* ()
{
return data;
}
void Img::Release()
{
byteDepth = 0;
channels = 0;
resolution = {};
size = 0;
delete[] data;
data = nullptr;
}
UInt_64 Img::GetHashId() const
{
return hashId;
}
void Img::SetId(Str_8 newId)
{
hashId = newId.Hash_64();
id = (Str_8&&)newId;
}
Str_8 Img::GetId() const
{
return id;
}
UInt_8 Img::GetByteDepth() const
{
return byteDepth;
}
UInt_8 Img::GetBitDepth() const
{
return byteDepth * 8;
}
UInt_8 Img::GetChannels() const
{
return channels;
}
Vec2_u64 Img::GetResolution() const
{
return resolution;
}
UInt_64 Img::GetSize() const
{
return size;
}
void Img::SetPixel(const UInt_64 index, const Byte* const pixel)
{
UInt_64 rIndex = index * byteDepth * channels;
for (UInt_64 i = 0; i < byteDepth * channels; ++i)
data[rIndex + i] = pixel[i];
}
void Img::GetPixel(const UInt_64 index, Byte* const pixel) const
{
UInt_64 rIndex = index * byteDepth * channels;
for (UInt_64 i = 0; i < byteDepth * channels; ++i)
pixel[i] = data[rIndex + i];
}
void Img::SetPixel(const UInt_64 x, const UInt_64 y, const Byte* const pixel)
{
UInt_64 rIndex = (y * resolution.x * byteDepth * channels) + (x * byteDepth * channels);
for (UInt_64 i = 0; i < byteDepth * channels; ++i)
data[rIndex + i] = pixel[i];
}
void Img::GetPixel(const UInt_64 x, const UInt_64 y, Byte* const pixel) const
{
UInt_64 rIndex = (y * resolution.x * byteDepth * channels) + (x * byteDepth * channels);
for (UInt_64 i = 0; i < byteDepth * channels; ++i)
pixel[i] = data[rIndex + i];
}
void Img::Resize(const Resampling method, const Vec2_u64& newResolution)
{
switch (method)
{
case Resampling::NEAREST_NEIGHBOR:
{
NearestNeighbor(newResolution);
return;
}
default:
return;
}
}
Img Img::GetResized(const Resampling method, const Vec2_u64& newResolution) const
{
switch (method)
{
case Resampling::NEAREST_NEIGHBOR:
return GetNearestNeighbor(newResolution);
default:
return {};
}
}
void Img::ToRGBA()
{
switch (channels)
{
case 3:
{
size = resolution.x * resolution.y * byteDepth * 4;
Byte* result = new Byte[size];
RGB_To_RGBA(size, result);
channels = 4;
delete[] data;
data = result;
break;
}
case 2:
{
size = resolution.x * resolution.y * byteDepth * 4;
Byte* result = new Byte[size];
MonoA_To_RGBA(size, result);
channels = 4;
delete[] data;
data = result;
break;
}
case 1:
{
size = resolution.x * resolution.y * byteDepth * 4;
Byte* result = new Byte[size];
Mono_To_RGBA(size, result);
channels = 4;
delete[] data;
data = result;
break;
}
default:
{
return;
}
}
}
Img Img::GetAsRGBA() const
{
switch (channels)
{
case 4:
{
return {*this};
}
case 3:
{
Img result(id, byteDepth, 4, resolution);
RGB_To_RGBA(result.GetSize(), result);
return result;
}
case 2:
{
Img result(id, byteDepth, 4, resolution);
MonoA_To_RGBA(result.GetSize(), result);
return result;
}
case 1:
{
Img result(id, byteDepth, 4, resolution);
Mono_To_RGBA(result.GetSize(), result);
return result;
}
default:
{
return {};
}
}
}
void Img::ToRGB()
{
switch (channels)
{
case 4:
{
size = resolution.x * resolution.y * byteDepth * 3;
Byte* result = new Byte[size];
RGBA_To_RGB(size, result);
channels = 3;
delete[] data;
data = result;
break;
}
case 2:
{
size = resolution.x * resolution.y * byteDepth * 3;
Byte* result = new Byte[size];
MonoA_To_RGB(size, result);
channels = 3;
delete[] data;
data = result;
break;
}
case 1:
{
size = resolution.x * resolution.y * byteDepth * 3;
Byte* result = new Byte[size];
Mono_To_RGB(size, result);
channels = 3;
delete[] data;
data = result;
break;
}
default:
{
return;
}
}
}
Img Img::GetAsRGB() const
{
switch (channels)
{
case 4:
{
Img result(id, byteDepth, 3, resolution);
RGBA_To_RGB(result.GetSize(), result);
return result;
}
case 3:
{
return {*this};
}
case 2:
{
Img result(id, byteDepth, 3, resolution);
MonoA_To_RGB(result.GetSize(), result);
return result;
}
case 1:
{
Img result(id, byteDepth, 3, resolution);
Mono_To_RGB(result.GetSize(), result);
return result;
}
default:
{
return {};
}
}
}
void Img::ToMonoA()
{
switch (channels)
{
case 4:
{
size = resolution.x * resolution.y * byteDepth * 2;
Byte* result = new Byte[size];
RGBA_To_MonoA(size, result);
channels = 2;
delete[] data;
data = result;
break;
}
case 3:
{
size = resolution.x * resolution.y * byteDepth * 2;
Byte* result = new Byte[size];
RGB_To_MonoA(size, result);
channels = 2;
delete[] data;
data = result;
break;
}
case 1:
{
size = resolution.x * resolution.y * byteDepth * 2;
Byte* result = new Byte[size];
Mono_To_MonoA(size, result);
channels = 2;
delete[] data;
data = result;
break;
}
default:
{
return;
}
}
}
Img Img::GetAsMonoA() const
{
switch (channels)
{
case 4:
{
Img result(id, byteDepth, 2, resolution);
RGBA_To_MonoA(result.GetSize(), result);
return result;
}
case 3:
{
Img result(id, byteDepth, 2, resolution);
RGB_To_MonoA(result.GetSize(), result);
return result;
}
case 2:
{
return {*this};
}
case 1:
{
Img result(id, byteDepth, 2, resolution);
Mono_To_MonoA(result.GetSize(), result);
return result;
}
default:
{
return {};
}
}
}
void Img::ToMono()
{
switch (channels)
{
case 4:
{
size = resolution.x * resolution.y * byteDepth;
Byte* result = new Byte[size];
RGBA_To_Mono(size, result);
channels = 1;
delete[] data;
data = result;
break;
}
case 3:
{
size = resolution.x * resolution.y * byteDepth;
Byte* result = new Byte[size];
RGB_To_Mono(size, result);
channels = 1;
delete[] data;
data = result;
break;
}
case 2:
{
size = resolution.x * resolution.y * byteDepth;
Byte* result = new Byte[size];
MonoA_To_Mono(size, result);
channels = 1;
delete[] data;
data = result;
break;
}
default:
{
return;
}
}
}
Img Img::GetAsMono() const
{
switch (channels)
{
case 4:
{
Img result(id, byteDepth, 1, resolution);
RGBA_To_Mono(result.GetSize(), result);
return result;
}
case 3:
{
Img result(id, byteDepth, 1, resolution);
RGB_To_Mono(result.GetSize(), result);
return result;
}
case 2:
{
Img result(id, byteDepth, 1, resolution);
MonoA_To_Mono(result.GetSize(), result);
return result;
}
case 1:
{
return {*this};
}
default:
{
return {};
}
}
}
void Img::To32()
{
switch (byteDepth)
{
case 3:
{
size = resolution.x * resolution.y * 4 * channels;
Byte* result = new Byte[size];
BD24_to_BD32(size, result);
byteDepth = 4;
delete[] data;
data = result;
break;
}
case 2:
{
size = resolution.x * resolution.y * 4 * channels;
Byte* result = new Byte[size];
BD16_to_BD32(size, result);
byteDepth = 4;
delete[] data;
data = result;
break;
}
case 1:
{
size = resolution.x * resolution.y * 4 * channels;
Byte* result = new Byte[size];
BD8_to_BD32(size, result);
byteDepth = 4;
delete[] data;
data = result;
break;
}
default:
{
return;
}
}
}
Img Img::GetAs32() const
{
switch (byteDepth)
{
case 4:
{
return {*this};
}
case 3:
{
Img result(id, 4, channels, resolution);
BD24_to_BD32(result.GetSize(), result);
return result;
}
case 2:
{
Img result(id, 4, channels, resolution);
BD16_to_BD32(result.GetSize(), result);
return result;
}
case 1:
{
Img result(id, 4, channels, resolution);
BD8_to_BD32(result.GetSize(), result);
return result;
}
default:
{
return {};
}
}
}
void Img::To24()
{
switch (byteDepth)
{
case 4:
{
size = resolution.x * resolution.y * 3 * channels;
Byte* result = new Byte[size];
BD32_to_BD24(size, result);
byteDepth = 3;
delete[] data;
data = result;
break;
}
case 2:
{
size = resolution.x * resolution.y * 3 * channels;
Byte* result = new Byte[size];
BD16_to_BD24(size, result);
byteDepth = 3;
delete[] data;
data = result;
break;
}
case 1:
{
size = resolution.x * resolution.y * 3 * channels;
Byte* result = new Byte[size];
BD8_to_BD24(size, result);
byteDepth = 3;
delete[] data;
data = result;
break;
}
default:
{
return;
}
}
}
Img Img::GetAs24() const
{
switch (byteDepth)
{
case 4:
{
Img result(id, 3, channels, resolution);
BD32_to_BD24(result.GetSize(), result);
return result;
}
case 3:
{
return {*this};
}
case 2:
{
Img result(id, 3, channels, resolution);
BD16_to_BD24(result.GetSize(), result);
return result;
}
case 1:
{
Img result(id, 3, channels, resolution);
BD8_to_BD24(result.GetSize(), result);
return result;
}
default:
{
return {};
}
}
}
void Img::To16()
{
switch (byteDepth)
{
case 4:
{
size = resolution.x * resolution.y * 2 * channels;
Byte* result = new Byte[size];
BD32_to_BD16(size, result);
byteDepth = 2;
delete[] data;
data = result;
break;
}
case 3:
{
size = resolution.x * resolution.y * 2 * channels;
Byte* result = new Byte[size];
BD24_to_BD16(size, result);
byteDepth = 2;
delete[] data;
data = result;
break;
}
case 1:
{
size = resolution.x * resolution.y * 2 * channels;
Byte* result = new Byte[size];
BD8_to_BD16(size, result);
byteDepth = 2;
delete[] data;
data = result;
break;
}
default:
{
return;
}
}
}
Img Img::GetAs16() const
{
switch (byteDepth)
{
case 4:
{
Img result(id, 2, channels, resolution);
BD32_to_BD16(result.GetSize(), result);
return result;
}
case 3:
{
Img result(id, 2, channels, resolution);
BD24_to_BD16(result.GetSize(), result);
return result;
}
case 2:
{
return {*this};
}
case 1:
{
Img result(id, 2, channels, resolution);
BD8_to_BD16(result.GetSize(), result);
return result;
}
default:
{
return {};
}
}
}
void Img::To8()
{
switch (byteDepth)
{
case 4:
{
size = resolution.x * resolution.y * channels;
Byte* result = new Byte[size];
BD32_to_BD8(size, result);
byteDepth = 1;
delete[] data;
data = result;
break;
}
case 3:
{
size = resolution.x * resolution.y * channels;
Byte* result = new Byte[size];
BD24_to_BD8(size, result);
byteDepth = 1;
delete[] data;
data = result;
break;
}
case 2:
{
size = resolution.x * resolution.y * channels;
Byte* result = new Byte[size];
BD16_to_BD8(size, result);
byteDepth = 1;
delete[] data;
data = result;
break;
}
default:
{
return;
}
}
}
Img Img::GetAs8() const
{
switch (byteDepth)
{
case 4:
{
Img result(id, 1, channels, resolution);
BD32_to_BD8(result.GetSize(), result);
return result;
}
case 3:
{
Img result(id, 1, channels, resolution);
BD24_to_BD8(result.GetSize(), result);
return result;
}
case 2:
{
Img result(id, 1, channels, resolution);
BD16_to_BD8(result.GetSize(), result);
return result;
}
case 1:
{
return {*this};
}
default:
{
return {};
}
}
}
bool Img::IsValid() const
{
return size;
}
bool Img::ToFile(const Str_8& filePath) const
{
Str_8 ext = File::ParseExt_8(filePath);
const ImgCodec* codec = GetCodec(ext);
if (!codec)
{
EHS_LOG_INT("Error", 0, "Codec not found for file extension, \"" + ext + "\".");
return false;
}
Serializer<UInt_64> result;
if (!codec->Encode(result, this))
return false;
File file(filePath, Mode::WRITE, Disposition::CREATE_PERSISTENT);
file.WriteSerializer_64(result);
return true;
}
Img Img::FromFile(const Str_8& filePath)
{
File file(filePath, Mode::READ, Disposition::OPEN);
Str_8 ext = file.GetExtension();
Img result(file.GetName());
const ImgCodec* codec = GetCodec(ext);
if (!codec)
{
EHS_LOG_INT("Error", 0, "Codec not found for file extension, \"" + ext + "\".");
return result;
}
Serializer<UInt_64> data = file.ReadSerializer_64(codec->GetEndianness(), file.Size());
file.Release();
if (!codec->Decode(data, &result))
return {};
return result;
}
Img* Img::FromFile_Heap(const Str_8& filePath)
{
File file(filePath, Mode::READ, Disposition::OPEN);
Str_8 ext = file.GetExtension();
Img* result = nullptr;
const ImgCodec* codec = GetCodec(ext);
if (!codec)
{
EHS_LOG_INT("Error", 0, "Codec not found for file extension, \"" + ext + "\".");
return result;
}
result = new Img(file.GetName());
Serializer<UInt_64> data = file.ReadSerializer_64(codec->GetEndianness(), file.Size());
file.Release();
if (!codec->Decode(data, result))
{
delete result;
return nullptr;
}
return result;
}
Img Img::FromData(Str_8 id, const Str_8& ext, Serializer<UInt_64>& data)
{
Img result((Str_8&&)id);
const ImgCodec* codec = GetCodec(ext);
if (!codec)
{
EHS_LOG_INT("Error", 0, "Codec not found for file extension, \"" + ext + "\".");
return result;
}
if (!codec->Decode(data, &result))
return {};
return result;
}
Img Img::GetNearestNeighbor(const Vec2_u64& newResolution) const
{
Img result(id, byteDepth, channels, newResolution);
Vec2_d ratio = {
(double)resolution.x / (double)newResolution.x,
(double)resolution.y / (double)newResolution.x
};
Vec2_d pixel;
for(UInt_64 y = 0; y < newResolution.y; ++y)
{
for (UInt_64 x = 0; x < newResolution.x; ++x)
{
pixel = {
Math::Floor((double)x * ratio.x),
Math::Floor((double)y * ratio.y)
};
for (UInt_64 b = 0; b < byteDepth * channels; ++b)
result[y * newResolution.x * byteDepth * channels + x * byteDepth * channels + b] = data[(UInt_64)pixel.y * resolution.x * byteDepth * channels + (UInt_64)pixel.x * byteDepth * channels + b];
}
}
return result;
}
void Img::NearestNeighbor(const Vec2_u64& newResolution)
{
Byte* result = new Byte[newResolution.x * byteDepth * channels * newResolution.y];
Vec2_d ratio = {
(double)resolution.x / (double)newResolution.x,
(double)resolution.y / (double)newResolution.x
};
Vec2_d pixel;
for(UInt_64 y = 0; y < newResolution.y; ++y)
{
for (UInt_64 x = 0; x < newResolution.x; ++x)
{
pixel = {
Math::Floor((double)x * ratio.x),
Math::Floor((double)y * ratio.y)
};
for (UInt_64 b = 0; b < byteDepth * channels; ++b)
result[y * newResolution.x * byteDepth * channels + x * byteDepth * channels + b] = data[(UInt_64)pixel.y * resolution.x * byteDepth * channels + (UInt_64)pixel.x * byteDepth * channels + b];
}
}
delete[] data;
data = result;
resolution = newResolution;
}
void Img::RGB_To_RGBA(const UInt_64 newSize, Byte* buffer) const
{
for (UInt_64 i = 0, n = 0; i < newSize; i += byteDepth * 4, n += byteDepth * channels)
{
for (UInt_64 b = 0; b < byteDepth * 3; ++b)
buffer[i + b] = data[n + b];
if (byteDepth == 1)
buffer[i + byteDepth * 3] = EHS_UINT_8_MAX;
else if (byteDepth == 2)
*(UInt_16*)&buffer[i + byteDepth * 3] = EHS_UINT_16_MAX;
else if (byteDepth == 3)
{
UInt_32 value = EHS_UINT_24_MAX;
for (UInt_64 b = 0; b < byteDepth; ++b)
buffer[i + byteDepth * 3 + b] = ((Byte*)&value)[b];
}
else if (byteDepth == 4)
*(UInt_32*)&buffer[i + byteDepth * 3] = EHS_UINT_32_MAX;
}
}
void Img::MonoA_To_RGBA(const UInt_64 newSize, Byte* buffer) const
{
for (UInt_64 i = 0, n = 0; i < newSize; i += byteDepth * 4, n += byteDepth * channels)
{
for (UInt_64 b = 0; b < byteDepth * 4; ++b)
buffer[i + b] = data[n + b % byteDepth];
if (byteDepth == 1)
buffer[i + byteDepth * 3] = data[n + byteDepth];
else if (byteDepth == 2)
*(UInt_16*) &buffer[i + byteDepth * 3] = *(UInt_16*) &data[n + byteDepth];
else if (byteDepth == 3)
{
for (UInt_64 b = 0; b < byteDepth; ++b)
buffer[i + byteDepth * 3 + b] = data[n + byteDepth + b];
}
else if (byteDepth == 4)
*(UInt_32*) &buffer[i + byteDepth * 3] = *(UInt_32*) &data[n + byteDepth];
}
}
void Img::Mono_To_RGBA(const UInt_64 newSize, Byte* buffer) const
{
for (UInt_64 i = 0, n = 0; i < newSize; i += byteDepth * 4, n += byteDepth * channels)
{
for (UInt_64 b = 0; b < byteDepth * 4; ++b)
buffer[i + b] = data[n + b % byteDepth];
if (byteDepth == 1)
buffer[i + byteDepth * 3] = EHS_UINT_8_MAX;
else if (byteDepth == 2)
*(UInt_16*)&buffer[i + byteDepth * 3] = EHS_UINT_16_MAX;
else if (byteDepth == 3)
{
UInt_32 value = EHS_UINT_24_MAX;
for (UInt_64 b = 0; b < byteDepth; ++b)
buffer[i + byteDepth * 3 + b] = ((Byte*)&value)[b];
}
else if (byteDepth == 4)
*(UInt_32*) &buffer[i + byteDepth * 3] = EHS_UINT_32_MAX;
}
}
void Img::RGBA_To_RGB(const UInt_64 newSize, Byte* buffer) const
{
for (UInt_64 i = 0, n = 0; i < newSize; i += byteDepth * 3, n += byteDepth * channels)
for (UInt_64 b = 0; b < byteDepth * 3; ++b)
buffer[i + b] = data[n + b];
}
void Img::MonoA_To_RGB(const UInt_64 newSize, Byte* buffer) const
{
for (UInt_64 i = 0, n = 0; i < newSize; i += byteDepth * 3, n += byteDepth * channels)
for (UInt_64 b = 0; b < byteDepth * 3; ++b)
buffer[i + b] = data[n + b % byteDepth];
}
void Img::Mono_To_RGB(const UInt_64 newSize, Byte* buffer) const
{
for (UInt_64 i = 0, n = 0; i < newSize; i += byteDepth * 3, n += byteDepth * channels)
for (UInt_64 b = 0; b < byteDepth * 3; ++b)
buffer[i + b] = data[n + b % byteDepth];
}
void Img::RGBA_To_MonoA(const UInt_64 newSize, Byte* buffer) const
{
for (UInt_64 i = 0, n = 0; i < newSize; i += byteDepth * 2, n += byteDepth * channels)
{
if (byteDepth == 1)
{
UInt_16 average = 0;
for (UInt_64 b = 0; b < 3; ++b)
average += data[n + b];
buffer[i] = average / 4;
buffer[i + byteDepth] = data[n + 3];
}
else if (byteDepth == 2)
{
UInt_32 average = 0;
for (UInt_64 b = 0; b < byteDepth * 3; b += byteDepth)
average += *(UInt_16*)&data[n + b];
*(UInt_16*)&buffer[i] = average / 4;
*(UInt_16*)&buffer[i + byteDepth] = *(UInt_16*)&data[n + byteDepth * 3];
}
else if (byteDepth == 3)
{
UInt_64 average = 0;
for (UInt_64 b = 0; b < byteDepth * 3; b += byteDepth)
{
UInt_32 num = 0;
num |= data[n + b];
num |= data[n + b + 1] << 8;
num |= data[n + b + 2] << 16;
average += num;
}
average /= 4;
buffer[i] = ((Byte*)&average)[0];
buffer[i + 1] = ((Byte*)&average)[1];
buffer[i + 2] = ((Byte*)&average)[2];
buffer[i + byteDepth] = data[n + byteDepth * 3];
buffer[i + byteDepth + 1] = data[n + byteDepth * 3 + 1];
buffer[i + byteDepth + 2] = data[n + byteDepth * 3 + 2];
}
else if (byteDepth == 4)
{
UInt_64 average = 0;
for (UInt_64 b = 0; b < byteDepth * 3; b += byteDepth)
average += *(UInt_32*)&data[n + b];
*(UInt_32*)&buffer[i] = average / 4;
*(UInt_32*)&buffer[i + byteDepth] = *(UInt_32*)&data[n + byteDepth * 3];
}
}
}
void Img::RGB_To_MonoA(const UInt_64 newSize, Byte* buffer) const
{
for (UInt_64 i = 0, n = 0; i < newSize; i += byteDepth * 2, n += byteDepth * channels)
{
if (byteDepth == 1)
{
UInt_16 average = 0;
for (UInt_64 b = 0; b < 3; ++b)
average += data[n + b];
buffer[i] = average / 4;
buffer[i + byteDepth] = EHS_UINT_8_MAX;
}
else if (byteDepth == 2)
{
UInt_32 average = 0;
for (UInt_64 b = 0; b < byteDepth * 3; b += byteDepth)
average += *(UInt_16*)&data[n + b];
*(UInt_16*)&buffer[i] = average / 4;
*(UInt_16*)&buffer[i + byteDepth] = EHS_UINT_16_MAX;
}
else if (byteDepth == 3)
{
UInt_64 average = 0;
for (UInt_64 b = 0; b < byteDepth * 3; b += byteDepth)
{
UInt_32 num = 0;
num |= data[n + b];
num |= data[n + b + 1] << 8;
num |= data[n + b + 2] << 16;
average += num;
}
average /= 4;
buffer[i] = ((Byte*)&average)[0];
buffer[i + 1] = ((Byte*)&average)[1];
buffer[i + 2] = ((Byte*)&average)[2];
UInt_32 tmp = EHS_UINT_24_MAX;
buffer[i + byteDepth] = ((Byte*)&tmp)[0];
buffer[i + byteDepth + 1] = ((Byte*)&tmp)[1];
buffer[i + byteDepth + 2] = ((Byte*)&tmp)[2];
}
else if (byteDepth == 4)
{
UInt_64 average = 0;
for (UInt_64 b = 0; b < byteDepth * 3; b += byteDepth)
average += *(UInt_32*)&data[n + b];
*(UInt_32*)&buffer[i] = average / 4;
*(UInt_32*)&buffer[i + byteDepth] = EHS_UINT_32_MAX;
}
}
}
void Img::Mono_To_MonoA(const UInt_64 newSize, Byte* buffer) const
{
for (UInt_64 i = 0, n = 0; i < newSize; i += byteDepth * 2, n += byteDepth * channels)
{
if (byteDepth == 1)
{
buffer[i] = data[n];
buffer[i + byteDepth] = EHS_UINT_8_MAX;
}
else if (byteDepth == 2)
{
*(UInt_16*)&buffer[i] = *(UInt_16*)&data[n];
*(UInt_16*)&buffer[i + byteDepth] = EHS_UINT_16_MAX;
}
else if (byteDepth == 3)
{
buffer[i] = data[n];
buffer[i + 1] = data[n + 1];
buffer[i + 2] = data[n + 2];
UInt_32 tmp = EHS_UINT_24_MAX;
buffer[i + byteDepth] = ((Byte*)&tmp)[0];
buffer[i + byteDepth + 1] = ((Byte*)&tmp)[1];
buffer[i + byteDepth + 2] = ((Byte*)&tmp)[2];
}
else if (byteDepth == 4)
{
*(UInt_32*)&buffer[i] = *(UInt_32*)&data[n];
*(UInt_32*)&buffer[i + byteDepth] = EHS_UINT_32_MAX;
}
}
}
void Img::RGBA_To_Mono(const UInt_64 newSize, Byte* buffer) const
{
for (UInt_64 i = 0, n = 0; i < newSize; i += byteDepth, n += byteDepth * channels)
{
if (byteDepth == 1)
{
UInt_16 average = 0;
for (UInt_64 b = 0; b < 3; ++b)
average += data[n + b];
buffer[i] = average / 4;
}
else if (byteDepth == 2)
{
UInt_32 average = 0;
for (UInt_64 b = 0; b < byteDepth * 3; b += byteDepth)
average += *(UInt_16*)&data[n + b];
*(UInt_16*)&buffer[i] = average / 4;
}
else if (byteDepth == 3)
{
UInt_64 average = 0;
for (UInt_64 b = 0; b < byteDepth * 3; b += byteDepth)
{
UInt_32 num = 0;
num |= data[n + b];
num |= data[n + b + 1] << 8;
num |= data[n + b + 2] << 16;
average += num;
}
average /= 4;
buffer[i] = ((Byte*)&average)[0];
buffer[i + 1] = ((Byte*)&average)[1];
buffer[i + 2] = ((Byte*)&average)[2];
}
else if (byteDepth == 4)
{
UInt_64 average = 0;
for (UInt_64 b = 0; b < byteDepth * 3; b += byteDepth)
average += *(UInt_32*)&data[n + b];
*(UInt_32*)&buffer[i] = average / 4;
}
}
}
void Img::RGB_To_Mono(const UInt_64 newSize, Byte* buffer) const
{
for (UInt_64 i = 0, n = 0; i < newSize; i += byteDepth, n += byteDepth * channels)
{
if (byteDepth == 1)
{
UInt_16 average = 0;
for (UInt_64 b = 0; b < 3; ++b)
average += data[n + b];
buffer[i] = average / 4;
}
else if (byteDepth == 2)
{
UInt_32 average = 0;
for (UInt_64 b = 0; b < byteDepth * 3; b += byteDepth)
average += *(UInt_16*)&data[n + b];
*(UInt_16*)&buffer[i] = average / 4;
}
else if (byteDepth == 3)
{
UInt_64 average = 0;
for (UInt_64 b = 0; b < byteDepth * 3; b += byteDepth)
{
UInt_32 num = 0;
num |= data[n + b];
num |= data[n + b + 1] << 8;
num |= data[n + b + 2] << 16;
average += num;
}
average /= 4;
buffer[i] = ((Byte*)&average)[0];
buffer[i + 1] = ((Byte*)&average)[1];
buffer[i + 2] = ((Byte*)&average)[2];
}
else if (byteDepth == 4)
{
UInt_64 average = 0;
for (UInt_64 b = 0; b < byteDepth * 3; b += byteDepth)
average += *(UInt_32*)&data[n + b];
*(UInt_32*)&buffer[i] = average / 4;
}
}
}
void Img::MonoA_To_Mono(const UInt_64 newSize, Byte* buffer) const
{
for (UInt_64 i = 0, n = 0; i < newSize; i += byteDepth, n += byteDepth * channels)
{
if (byteDepth == 1)
{
buffer[i] = data[n];
}
else if (byteDepth == 2)
{
*(UInt_16*)&buffer[i] = *(UInt_16*)&data[n];
}
else if (byteDepth == 3)
{
buffer[i] = data[n];
buffer[i + 1] = data[n + 1];
buffer[i + 2] = data[n + 2];
}
else if (byteDepth == 4)
{
*(UInt_32*)&buffer[i] = *(UInt_32*)&data[n];
}
}
}
void Img::BD24_to_BD32(const UInt_64 newSize, Byte* buffer) const
{
for (UInt_64 i = 0, n = 0; i < newSize; i += 4, n += 3)
{
UInt_32 inValue = 0;
((Byte*)&inValue)[0] = data[n];
((Byte*)&inValue)[1] = data[n + 1];
((Byte*)&inValue)[2] = data[n + 2];
*(UInt_32*)&buffer[i] = (UInt_32)((float)inValue / (float)EHS_UINT_24_MAX * (float)EHS_UINT_32_MAX);
}
}
void Img::BD16_to_BD32(const UInt_64 newSize, Byte* buffer) const
{
for (UInt_64 i = 0, n = 0; i < newSize; i += 4, n += 2)
*(UInt_32*)&buffer[i] = (UInt_32)((float)*(UInt_16*)&data[n] / (float)EHS_UINT_16_MAX * (float)EHS_UINT_32_MAX);
}
void Img::BD8_to_BD32(const UInt_64 newSize, Byte* buffer) const
{
for (UInt_64 i = 0, n = 0; i < newSize; i += 4, ++n)
*(UInt_32*)&buffer[i] = (UInt_32)((float)data[n] / (float)EHS_UINT_8_MAX * (float)EHS_UINT_32_MAX);
}
void Img::BD32_to_BD24(const UInt_64 newSize, Byte* buffer) const
{
for (UInt_64 i = 0, n = 0; i < newSize; i += 3, n += 4)
{
UInt_32 rValue = (UInt_32)((float)*(UInt_32*)&data[n] / (float)EHS_UINT_32_MAX * (float)EHS_UINT_24_MAX);
buffer[i] = ((Byte*)&rValue)[0];
buffer[i + 1] = ((Byte*)&rValue)[1];
buffer[i + 2] = ((Byte*)&rValue)[2];
}
}
void Img::BD16_to_BD24(const UInt_64 newSize, Byte* buffer) const
{
for (UInt_64 i = 0, n = 0; i < newSize; i += 3, n += 2)
{
UInt_32 rValue = (UInt_32)((float)*(UInt_16*)&data[n] / (float)EHS_UINT_16_MAX * (float)EHS_UINT_24_MAX);
buffer[i] = ((Byte*)&rValue)[0];
buffer[i + 1] = ((Byte*)&rValue)[1];
buffer[i + 2] = ((Byte*)&rValue)[2];
}
}
void Img::BD8_to_BD24(const UInt_64 newSize, Byte* buffer) const
{
for (UInt_64 i = 0, n = 0; i < newSize; i += 3, ++n)
{
UInt_32 rValue = (UInt_32)((float)data[n] / (float)EHS_UINT_8_MAX * (float)EHS_UINT_24_MAX);
buffer[i] = ((Byte*)&rValue)[0];
buffer[i + 1] = ((Byte*)&rValue)[1];
buffer[i + 2] = ((Byte*)&rValue)[2];
}
}
void Img::BD32_to_BD16(const UInt_64 newSize, Byte* buffer) const
{
for (UInt_64 i = 0, n = 0; i < newSize; i += 2, n += 4)
*(UInt_16*)&buffer[i] = (UInt_16)((float)*(UInt_32*)&data[n] / (float)EHS_UINT_32_MAX * (float)EHS_UINT_16_MAX);
}
void Img::BD24_to_BD16(const UInt_64 newSize, Byte* buffer) const
{
for (UInt_64 i = 0, n = 0; i < newSize; i += 2, n += 3)
{
UInt_32 inValue = 0;
((Byte*)&inValue)[0] = data[n];
((Byte*)&inValue)[1] = data[n + 1];
((Byte*)&inValue)[2] = data[n + 2];
*(UInt_16*)&buffer[i] = (UInt_16)((float)inValue / (float)EHS_UINT_24_MAX * (float)EHS_UINT_16_MAX);
}
}
void Img::BD8_to_BD16(const UInt_64 newSize, Byte* buffer) const
{
for (UInt_64 i = 0, n = 0; i < newSize; i += 2, ++n)
*(UInt_16*)&buffer[i] = (UInt_16)((float)data[n] / (float)EHS_UINT_8_MAX * (float)EHS_UINT_16_MAX);
}
void Img::BD32_to_BD8(const UInt_64 newSize, Byte* buffer) const
{
for (UInt_64 i = 0, n = 0; i < newSize; ++i, n += 4)
buffer[i] = (Byte)((float)*(UInt_32*)&data[n] / (float)EHS_UINT_32_MAX * (float)EHS_UINT_8_MAX);
}
void Img::BD24_to_BD8(const UInt_64 newSize, Byte* buffer) const
{
for (UInt_64 i = 0, n = 0; i < newSize; ++i, n += 3)
{
UInt_32 inValue = 0;
((Byte*)&inValue)[0] = data[n];
((Byte*)&inValue)[1] = data[n + 1];
((Byte*)&inValue)[2] = data[n + 2];
buffer[i] = (Byte)((float)inValue / (float)EHS_UINT_24_MAX * (float)EHS_UINT_8_MAX);
}
}
void Img::BD16_to_BD8(const UInt_64 newSize, Byte* buffer) const
{
for (UInt_64 i = 0, n = 0; i < newSize; ++i, n += 2)
buffer[i] = (Byte)((float)*(UInt_16*)&data[n] / (float)EHS_UINT_16_MAX * (float)EHS_UINT_8_MAX);
}
}