Initial Cross Platform Work
This commit is contained in:
@ -22,6 +22,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef PD_IMAGE_BUILD_SHARED
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#include <pd/external/stb_image.h>
|
||||
|
||||
#include <cstring>
|
||||
@ -30,31 +34,121 @@ SOFTWARE.
|
||||
#include <pd/image/img_convert.hpp>
|
||||
|
||||
namespace PD {
|
||||
void Image::Load(const std::string& path) {
|
||||
u8* img = stbi_load(path.c_str(), &w, &h, &fmt, 4);
|
||||
PD_IMAGE_API void Image::Load(const std::string& path) {
|
||||
u8* img = stbi_load(path.c_str(), &pWidth, &pHeight, &fmt, 4);
|
||||
if (fmt == 3) {
|
||||
stbi_image_free(img);
|
||||
img = stbi_load(path.c_str(), &w, &h, &fmt, 3);
|
||||
buffer.resize(w * h * 4);
|
||||
PD::ImgConvert::RGB24toRGBA32(
|
||||
buffer, std::vector<u8>(img, img + (w * h * 3)), w, h);
|
||||
} else {
|
||||
buffer.assign(img, img + (w * h * 4));
|
||||
img = stbi_load(path.c_str(), &pWidth, &pHeight, &fmt, 3);
|
||||
pBuffer = std::vector<PD::u8>(img, img + (pWidth * pHeight * 3));
|
||||
pFmt = RGB;
|
||||
stbi_image_free(img);
|
||||
} else if (fmt == 4) {
|
||||
pBuffer = std::vector<PD::u8>(img, img + (pWidth * pHeight * 4));
|
||||
pFmt = RGBA;
|
||||
stbi_image_free(img);
|
||||
}
|
||||
}
|
||||
void Image::Load(const std::vector<u8>& buf) {
|
||||
u8* img = stbi_load_from_memory(buf.data(), buf.size(), &w, &h, &fmt, 4);
|
||||
PD_IMAGE_API void Image::Load(const std::vector<u8>& buf) {
|
||||
u8* img =
|
||||
stbi_load_from_memory(buf.data(), buf.size(), &pWidth, &pHeight, &fmt, 4);
|
||||
if (fmt == 3) {
|
||||
stbi_image_free(img);
|
||||
img = stbi_load_from_memory(buf.data(), buf.size(), &w, &h, &fmt, 3);
|
||||
buffer.resize(w * h * 4);
|
||||
PD::ImgConvert::RGB24toRGBA32(
|
||||
buffer, std::vector<u8>(img, img + (w * h * 3)), w, h);
|
||||
} else {
|
||||
buffer.assign(img, img + (w * h * 4));
|
||||
img = stbi_load_from_memory(buf.data(), buf.size(), &pWidth, &pHeight, &fmt,
|
||||
3);
|
||||
pBuffer = std::vector<PD::u8>(img, img + (pWidth * pHeight * 3));
|
||||
pFmt = RGB;
|
||||
stbi_image_free(img);
|
||||
} else if (fmt == 4) {
|
||||
pBuffer = std::vector<PD::u8>(img, img + (pWidth * pHeight * 4));
|
||||
stbi_image_free(img);
|
||||
pFmt = RGBA;
|
||||
}
|
||||
}
|
||||
PD_IMAGE_API void Image::Copy(const std::vector<u8>& buf, int w, int h,
|
||||
int bpp) {
|
||||
this->fmt = bpp;
|
||||
if (buf.size() != (size_t)w * h * bpp) {
|
||||
// Size Error
|
||||
return;
|
||||
}
|
||||
this->pBuffer.resize(w * h * bpp);
|
||||
for (size_t i = 0; i < this->pBuffer.size(); i++) {
|
||||
pBuffer[i] = buf[i];
|
||||
}
|
||||
}
|
||||
|
||||
PD_IMAGE_API void Image::Convert(Image::Ref img, Image::Format dst) {
|
||||
if (img->Fmt() == dst) {
|
||||
return;
|
||||
} else if (img->Fmt() == Image::RGB && dst == Image::BGR) {
|
||||
ImgConvert::ReverseBuf(img->pBuffer, 3, img->pWidth, img->pHeight);
|
||||
} else if (img->Fmt() == Image::RGB && dst == Image::RGBA) {
|
||||
std::vector<PD::u8> cpy = img->pBuffer;
|
||||
img->pBuffer.resize(img->pWidth * img->pHeight * 4);
|
||||
ImgConvert::RGB24toRGBA32(img->pBuffer, cpy, img->pWidth, img->pHeight);
|
||||
} else if (img->Fmt() == Image::RGBA && dst == Image::RGB) {
|
||||
std::vector<PD::u8> cpy = img->pBuffer;
|
||||
img->pBuffer.resize(img->pWidth * img->pHeight * 3);
|
||||
ImgConvert::RGB32toRGBA24(img->pBuffer, cpy, img->pWidth, img->pHeight);
|
||||
} else if (img->Fmt() == Image::RGBA && dst == Image::RGB565) {
|
||||
Convert(img, Image::RGB);
|
||||
Convert(img, Image::RGB565);
|
||||
} else if (img->Fmt() == Image::RGB && dst == Image::RGB565) {
|
||||
auto f = [](u8 r, u8 g, u8 b) -> u16 {
|
||||
u16 _r = (r >> 3);
|
||||
u16 _g = (g >> 2);
|
||||
u16 _b = (b >> 3);
|
||||
return (_r << 11) | (_g << 5) | _b;
|
||||
};
|
||||
std::vector<PD::u8> cpy = img->pBuffer;
|
||||
img->pBuffer.resize(img->pWidth * img->pHeight * 2);
|
||||
for (int y = 0; y < img->pWidth; y++) {
|
||||
for (int x = 0; x < img->pHeight; x++) {
|
||||
int src = (y * img->pWidth + x) * 3;
|
||||
int dst = (y * img->pWidth + x) * 2;
|
||||
u16 new_px = f(cpy[src + 0], cpy[src + 1], cpy[src + 2]);
|
||||
img->pBuffer[dst + 0] = new_px >> 8;
|
||||
img->pBuffer[dst + 1] = new_px & 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PD_IMAGE_API int Image::Fmt2Bpp(Format fmt) {
|
||||
switch (fmt) {
|
||||
case RGBA:
|
||||
case ABGR:
|
||||
return 4;
|
||||
break;
|
||||
case RGB:
|
||||
case BGR:
|
||||
return 3;
|
||||
break;
|
||||
case RGB565:
|
||||
return 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PD_IMAGE_API void Image::ReTile(Image::Ref img,
|
||||
std::function<u32(int x, int y, int w)> src,
|
||||
std::function<u32(int x, int y, int w)> dst) {
|
||||
std::vector<PD::u8> cpy = img->pBuffer;
|
||||
/** could use fmt here but for 565 that woulnt work as it is not supported by
|
||||
* file loading where fmt is used */
|
||||
int bpp = Fmt2Bpp(img->pFmt);
|
||||
for (int y = 0; y < img->pHeight; y++) {
|
||||
for (int x = 0; x < img->pWidth; x++) {
|
||||
int src_idx = src(x, y, img->pWidth);
|
||||
int dst_idx = dst(x, y, img->pWidth);
|
||||
for (int i = 0; i < bpp; i++) {
|
||||
img->pBuffer[dst_idx + i] = cpy[src_idx + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void Image::Copy(const std::vector<u8>& buf, int w, int h, int fmt) {}
|
||||
} // namespace PD
|
@ -29,7 +29,7 @@ SOFTWARE.
|
||||
|
||||
namespace PD {
|
||||
namespace ImgBlur {
|
||||
std::vector<float> GaussianKernel(int r, float si) {
|
||||
PD_IMAGE_API std::vector<float> GaussianKernel(int r, float si) {
|
||||
/// Define radius as r to be shorter
|
||||
int size = 2 * r + 1;
|
||||
std::vector<float> kernel(size);
|
||||
@ -45,13 +45,15 @@ std::vector<float> GaussianKernel(int r, float si) {
|
||||
}
|
||||
return kernel;
|
||||
}
|
||||
void GaussianBlur(std::vector<u8> &buf, int w, int h, float radius, float si,
|
||||
std::function<int(int, int, int)> idxfn) {
|
||||
PD_IMAGE_API void GaussianBlur(std::vector<u8> &buf, int w, int h, float radius,
|
||||
float si,
|
||||
std::function<int(int, int, int)> idxfn) {
|
||||
GaussianBlur(buf.data(), w, h, 4, radius, si, idxfn);
|
||||
}
|
||||
|
||||
void GaussianBlur(void *buf, int w, int h, int bpp, float radius, float si,
|
||||
std::function<int(int, int, int)> idxfn) {
|
||||
PD_IMAGE_API void GaussianBlur(void *buf, int w, int h, int bpp, float radius,
|
||||
float si,
|
||||
std::function<int(int, int, int)> idxfn) {
|
||||
if (bpp != 4 && bpp != 3) {
|
||||
return;
|
||||
}
|
||||
|
@ -24,8 +24,9 @@ SOFTWARE.
|
||||
#include <pd/image/img_convert.hpp>
|
||||
|
||||
namespace PD::ImgConvert {
|
||||
void RGB24toRGBA32(std::vector<u8> &out, const std::vector<u8> &in,
|
||||
const int &w, const int &h) {
|
||||
|
||||
PD_IMAGE_API void RGB24toRGBA32(std::vector<u8> &out, const std::vector<u8> &in,
|
||||
const int &w, const int &h) {
|
||||
// Converts RGB24 to RGBA32
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
@ -38,7 +39,22 @@ void RGB24toRGBA32(std::vector<u8> &out, const std::vector<u8> &in,
|
||||
}
|
||||
}
|
||||
}
|
||||
void Reverse32(std::vector<u8> &buf, const int &w, const int &h) {
|
||||
|
||||
PD_IMAGE_API void RGB32toRGBA24(std::vector<u8> &out, const std::vector<u8> &in,
|
||||
const int &w, const int &h) {
|
||||
// Converts RGB24 to RGBA32
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
int src = (y * w + x) * 4;
|
||||
int dst = (y * w + x) * 3;
|
||||
out[dst + 0] = in[src + 0];
|
||||
out[dst + 1] = in[src + 1];
|
||||
out[dst + 2] = in[src + 2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PD_IMAGE_API void Reverse32(std::vector<u8> &buf, const int &w, const int &h) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
for (int y = 0; y < h; y++) {
|
||||
int i = y * w + x;
|
||||
@ -51,4 +67,71 @@ void Reverse32(std::vector<u8> &buf, const int &w, const int &h) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PD_IMAGE_API void ReverseBuf(std::vector<u8> &buf, size_t bpp, int w, int h) {
|
||||
std::vector<u8> cpy = buf;
|
||||
for (int x = 0; x < w; x++) {
|
||||
for (int y = 0; y < h; y++) {
|
||||
int pos = (y * w + x) * bpp;
|
||||
for (size_t i = 0; i < bpp; i++) {
|
||||
buf[pos + bpp - 1 - i] = cpy[pos + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PD_IMAGE_API void RGB24toRGBA32(PD::Vec<u8> &out, const PD::Vec<u8> &in,
|
||||
const int &w, const int &h) {
|
||||
// Converts RGB24 to RGBA32
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
int src = (y * w + x) * 3;
|
||||
int dst = (y * w + x) * 4;
|
||||
out[dst + 0] = in[src + 0];
|
||||
out[dst + 1] = in[src + 1];
|
||||
out[dst + 2] = in[src + 2];
|
||||
out[dst + 3] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PD_IMAGE_API void RGB32toRGBA24(PD::Vec<u8> &out, const PD::Vec<u8> &in,
|
||||
const int &w, const int &h) {
|
||||
// Converts RGB24 to RGBA32
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
int src = (y * w + x) * 4;
|
||||
int dst = (y * w + x) * 3;
|
||||
out[dst + 0] = in[src + 0];
|
||||
out[dst + 1] = in[src + 1];
|
||||
out[dst + 2] = in[src + 2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PD_IMAGE_API void Reverse32(PD::Vec<u8> &buf, const int &w, const int &h) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
for (int y = 0; y < h; y++) {
|
||||
int i = y * w + x;
|
||||
u8 t0 = buf[i + 0];
|
||||
u8 t1 = buf[i + 1];
|
||||
buf[i + 0] = buf[i + 3];
|
||||
buf[i + 1] = buf[i + 2];
|
||||
buf[i + 3] = t0;
|
||||
buf[i + 2] = t1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PD_IMAGE_API void ReverseBuf(PD::Vec<u8> &buf, size_t bpp, int w, int h) {
|
||||
PD::Vec<u8> cpy = buf;
|
||||
for (int x = 0; x < w; x++) {
|
||||
for (int y = 0; y < h; y++) {
|
||||
int pos = (y * w + x) * bpp;
|
||||
for (size_t i = 0; i < bpp; i++) {
|
||||
buf[pos + bpp - 1 - i] = cpy[pos + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace PD::ImgConvert
|
Reference in New Issue
Block a user