/* ----------------------------------------------------------------------------- GSFramework Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. ----------------------------------------------------------------------------- */ #include "picture/pict.h" #include "color/color.h" using namespace GS; //------------------------------------------------------------------------------ bool Picture::Resize(uint nwidth, uint nheight) { if (!nwidth && !nheight) return false; if (!nwidth) nwidth = (GetWidth() * nheight) / GetHeight(); if (!nheight) nheight = (GetHeight() * nwidth) / GetWidth(); if ((nwidth == GetWidth()) && (nheight == GetHeight())) return true; if (pxformat.IsReal()) { float *new_data = (float *)AllocMemory(sizeof(float) * nwidth * nheight * 3); if (!new_data) return false; float *pdst = (float *)new_data; float ku = 1.f / (float)nwidth, kv = 1.f / (float)nheight; Color out; float v = kv * 0.5f - 0.5f / height; if (data) for (uint y = 0; y < nheight; ++y) { float u = ku * 0.5f - 0.5f / width; for (uint x = 0; x < nwidth; ++x) { Sample(u, v, out); pdst[0] = out.x; pdst[1] = out.y; pdst[2] = out.z; pdst += 3; u += ku; } v += kv; } SetData(new_data, nwidth, nheight, PixelFormat::RGBAF, true); //SetData(new_data, nwidth, nheight, PixelFormat::RGBF, true); } else if (GetBpp() == 32) { uchar *new_data = (uchar *)AllocMemory(sizeof(uchar) * nwidth * nheight * 4); if (!new_data) return false; uint *pdst = (uint*)new_data; float ku = 1.f / (float)nwidth, kv = 1.f / (float)nheight; float v = kv * 0.5f - 0.5f / height; if (data) for (uint y = 0; y < nheight; ++y) { float u = ku * 0.5f - 0.5f / width; for (uint x = 0; x < nwidth; ++x) { Sample(u, v, *pdst++); u += ku; } v += kv; } SetData(new_data, nwidth, nheight, GetPixelFormat().GetDesc(), true); } else return false; return true; } bool Picture::Downscale(uint nwidth, uint nheight) { if (!nwidth && !nheight) return false; if (!nwidth) nwidth = (GetWidth() * nheight) / GetHeight(); if (!nheight) nheight = (GetHeight() * nwidth) / GetWidth(); if ((nwidth > GetWidth()) || (nheight > GetHeight())) return Resize(nwidth, nheight); if (GetBpp() == 32) { uchar *new_data = (uchar *)AllocMemory(sizeof(uchar) * nwidth * nheight * 4); if (!new_data) return false; uchar *pdst = new_data; Array accu(nwidth * 4); if (accu) { float ku = (float)GetWidth() / (float)nwidth, kv = (float)GetHeight() / (float)nheight; float u, v; // v = 0.f; // Accumulate scan lines. uchar *psrc = GetData(); for (uint y = 0; y < nheight; y++) { uint n; for (n = 0; n < (nwidth * 4); n++) accu[n] = 0.f; float tv = kv, nv = kv; for (;;) { float k = GS::Math::Ceil(v) - v; tv -= k; if (tv < 0.f) k += tv; // readjust v += k; if (v >= GetHeight()) { nv -= k; break; } // u = 0.f; // Accumulate texels. uchar *lsrc = psrc; float *paccu = accu; float texel[4]; for (uint x = 0; x < nwidth; x++) { for (n = 0; n < 4; n++) texel[n] = 0.f; float tu = ku, nu = ku; for (;;) { float k = GS::Math::Ceil(u) - u; tu -= k; if (tu < 0.f) k += tu; // readjust u += k; if (u >= GetWidth()) { nu -= k; break; } for (n = 0; n < 4; n++) texel[n] += (float)(lsrc[n]) * k; if (tu < 0.f) break; lsrc += 4; } tu = k / nu; for (n = 0; n < 4; n++) paccu[n] += texel[n] * tu; paccu += 4; } if (tv < 0.f) break; psrc += GetWidth() * 4; } tv = 1.f / nv; for (n = 0; n < (nwidth * 4); n++) pdst[n] = (uchar)(accu[n] * tv); pdst += nwidth * 4; } SetData(new_data, nwidth, nheight, GetPixelFormat().GetDesc(), true); return true; } } return false; } //------------------------------------------------------------------------------