/* ----------------------------------------------------------------------------- GSFramework Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. ----------------------------------------------------------------------------- */ #include #include #include "picture/pict.h" #include "log/log.h" using namespace GS; //------------------------------------------------------------------------------ bool Picture::HasAlpha() const { uchar *pdata = GetData(); if (!pdata || !width || !height) return false; for (uint y = 0; y < height; y++) for (uint x = 0; x < width; x++) { union { uint packed; uchar ppack[4]; }; switch (pxformat.GetBpp()) { case 8: ppack[0] = pdata[0]; pdata++; break; case 16: ppack[0] = pdata[0]; ppack[1] = pdata[1]; pdata += 2; break; case 24: ppack[0] = pdata[0]; ppack[1] = pdata[1]; ppack[2] = pdata[2]; pdata += 3; break; case 32: ppack[0] = pdata[0]; ppack[1] = pdata[1]; ppack[2] = pdata[2]; ppack[3] = pdata[3]; pdata += 4; break; } int a = (int)(((packed & pxformat.desc.amask) >> pxformat.ashift) << (8 - pxformat.acount)); if (a < ((1 << pxformat.acount) - 1)) return true; } return false; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ uint Picture::ColorBlend(uint u, uint v, float opacity) { int fk = (int)(opacity * 65536), ik = 65536 - fk; uint ta = ((u >> 24) & 0xff) * ik + ((v >> 24) & 0xff) * fk, tr = ((u >> 16) & 0xff) * ik + ((v >> 16) & 0xff) * fk, tg = ((u >> 8) & 0xff) * ik + ((v >> 8) & 0xff) * fk, tb = (u & 0xff) * ik + (v & 0xff) * fk; return ((ta << 8) & 0xff000000) + (tr & 0xff0000) + ((tg >> 8) & 0xff00) + (tb >> 16); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ bool Picture::Compare(const Picture &picture) const { if (pxformat != picture.GetPixelFormat().GetDesc()) return false; // Binary comparison. return !Memory::Compare(data, picture.GetData(), width * height * (pxformat.GetBpp() >> 3)); } bool Picture::ComputeHash() { uchar *pdata = GetData(); if (!pdata || !width || !height) return false; hash = 0; for (uint y = 0; y < height; y++) for (uint x = 0; x < width; x++) { union { uint packed; uchar ppack[4]; }; switch (pxformat.GetBpp()) { case 8: ppack[0] = pdata[0]; pdata++; break; case 16: ppack[0] = pdata[0]; ppack[1] = pdata[1]; pdata += 2; break; case 24: ppack[0] = pdata[0]; ppack[1] = pdata[1]; ppack[2] = pdata[2]; pdata += 3; break; case 32: ppack[0] = pdata[0]; ppack[1] = pdata[1]; ppack[2] = pdata[2]; ppack[3] = pdata[3]; pdata += 4; break; } int a = (int)(((packed & pxformat.desc.amask) >> pxformat.ashift) << (8 - pxformat.acount)); int r = (int)(((packed & pxformat.desc.rmask) >> pxformat.rshift) << (8 - pxformat.rcount)); int g = (int)(((packed & pxformat.desc.gmask) >> pxformat.gshift) << (8 - pxformat.gcount)); int b = (int)(((packed & pxformat.desc.bmask) >> pxformat.bshift) << (8 - pxformat.bcount)); hash += (a << 24) + (r << 16) + (g << 8) + b; } return true; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void Picture::SetData(void *ud, uint w, uint h, const PixelFormatDescription &fmt, bool take_ownership) { if (!ud) return; FreeData(); hash = 0; data = (uchar *)ud; if (!take_ownership) pic_flag.Set(HasForeignData); width = w; height = h; pxformat.Set(fmt); } bool Picture::AllocAs(uint w, uint h, const PixelFormatDescription &fmt) { if (!pic_flag.IsSet(HasForeignData) && data && (width == w) && (height == h) && (pxformat.GetBpp() == fmt.bpp)) { pxformat.Set(fmt); return true; } FreeData(); if (w && h && fmt.bpp) { size_t count = w * h * (fmt.bpp / 8); data = AllocMemory(count); if (data) memset(data, 0, sizeof(uchar) * count); else __ERR__(__LOG_E__ << "Failed to allocate picture buffer (" << w << "x" << h << "@" << fmt.bpp << "bpp).\n", false); width = w; height = h; pxformat.Set(fmt); } return true; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void Picture::Clone(const Picture &src, bool clone_data) { Free(); if (src.IsStub()) Stub(src.GetWidth(), src.GetHeight()); else { if (clone_data) { if (AllocAs(src.GetWidth(), src.GetHeight(), src.pxformat.GetDesc())) Memory::Copy((char *)data, (char *)src.GetData(), width * height * (pxformat.GetBpp() / 8)); } else SetData(src.GetData(), src.GetWidth(), src.GetHeight(), src.pxformat.GetDesc(), false); } } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void Picture::Stub(uint w, uint h) { Free(); protected_flag.Set(PictureIsStub); width = w; height = h; } void Picture::Zeroify() { data = NULL; hash = 0; width = height = 0; pxformat.Set(PixelFormat::NONE); pic_flag = 0; protected_flag = 0; } void Picture::FreeData() { if (!pic_flag.IsSet(HasForeignData)) FreeMemory(data); data = NULL; pic_flag.Remove(HasForeignData); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ uchar *Picture::AllocMemory(size_t size) { return (uchar *)Alloc::DefaultAllocator::Alloc(size, Alloc::Picture); } void Picture::FreeMemory(uchar *data) { Alloc::DefaultAllocator::Delete(data, Alloc::Picture); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ Picture::~Picture() { Free(); } //------------------------------------------------------------------------------