/* static */ bool gfxAlphaRecovery::RecoverAlpha(gfxImageSurface* blackSurf, const gfxImageSurface* whiteSurf) { mozilla::gfx::IntSize size = blackSurf->GetSize(); if (size != whiteSurf->GetSize() || (blackSurf->Format() != mozilla::gfx::SurfaceFormat::A8R8G8B8_UINT32 && blackSurf->Format() != mozilla::gfx::SurfaceFormat::X8R8G8B8_UINT32) || (whiteSurf->Format() != mozilla::gfx::SurfaceFormat::A8R8G8B8_UINT32 && whiteSurf->Format() != mozilla::gfx::SurfaceFormat::X8R8G8B8_UINT32)) return false; #ifdef MOZILLA_MAY_SUPPORT_SSE2 if (mozilla::supports_sse2() && RecoverAlphaSSE2(blackSurf, whiteSurf)) { return true; } #endif blackSurf->Flush(); whiteSurf->Flush(); unsigned char* blackData = blackSurf->Data(); unsigned char* whiteData = whiteSurf->Data(); for (int32_t i = 0; i < size.height; ++i) { uint32_t* blackPixel = reinterpret_cast<uint32_t*>(blackData); const uint32_t* whitePixel = reinterpret_cast<uint32_t*>(whiteData); for (int32_t j = 0; j < size.width; ++j) { uint32_t recovered = RecoverPixel(blackPixel[j], whitePixel[j]); blackPixel[j] = recovered; } blackData += blackSurf->Stride(); whiteData += whiteSurf->Stride(); } blackSurf->MarkDirty(); return true; }
/* static */ PRBool gfxAlphaRecovery::RecoverAlpha(gfxImageSurface* blackSurf, const gfxImageSurface* whiteSurf, Analysis* analysis) { gfxIntSize size = blackSurf->GetSize(); if (size != whiteSurf->GetSize() || (blackSurf->Format() != gfxASurface::ImageFormatARGB32 && blackSurf->Format() != gfxASurface::ImageFormatRGB24) || (whiteSurf->Format() != gfxASurface::ImageFormatARGB32 && whiteSurf->Format() != gfxASurface::ImageFormatRGB24)) return PR_FALSE; if (!analysis && RecoverAlphaSSE2(blackSurf, whiteSurf)) { return PR_TRUE; } blackSurf->Flush(); whiteSurf->Flush(); unsigned char* blackData = blackSurf->Data(); unsigned char* whiteData = whiteSurf->Data(); /* Get the alpha value of 'first' */ PRUint32 first; if (size.width == 0 || size.height == 0) { first = 0; } else { if (!blackData || !whiteData) return PR_FALSE; first = RecoverPixel(*reinterpret_cast<PRUint32*>(blackData), *reinterpret_cast<PRUint32*>(whiteData)); } PRUint32 deltas = 0; for (PRInt32 i = 0; i < size.height; ++i) { PRUint32* blackPixel = reinterpret_cast<PRUint32*>(blackData); const PRUint32* whitePixel = reinterpret_cast<PRUint32*>(whiteData); for (PRInt32 j = 0; j < size.width; ++j) { PRUint32 recovered = RecoverPixel(blackPixel[j], whitePixel[j]); blackPixel[j] = recovered; deltas |= (first ^ recovered); } blackData += blackSurf->Stride(); whiteData += whiteSurf->Stride(); } blackSurf->MarkDirty(); if (analysis) { analysis->uniformAlpha = (deltas >> 24) == 0; analysis->uniformColor = PR_FALSE; if (analysis->uniformAlpha) { double d_first_alpha = first >> 24; analysis->alpha = d_first_alpha/255.0; /* we only set uniformColor when the alpha is already uniform. it's only useful in that case ... and if the alpha was nonuniform then computing whether the color is uniform would require unpremultiplying every pixel */ analysis->uniformColor = deltas == 0; if (analysis->uniformColor) { if (d_first_alpha == 0.0) { /* can't unpremultiply, this is OK */ analysis->r = analysis->g = analysis->b = 0.0; } else { analysis->r = (first & 0xFF)/d_first_alpha; analysis->g = ((first >> 8) & 0xFF)/d_first_alpha; analysis->b = ((first >> 16) & 0xFF)/d_first_alpha; } } } }