void GdiPlusAccess::AverageBlur(Gdiplus::BitmapData &data, size_t xRadius, size_t yRadius) { struct ColumnCache { List<DArr<4>> Content; size_t Index = 0; }; Queue<ColumnCache> cache; List<List<DArr<4>>> result; for (size_t x = 0; x < data.Width; ++x) { for (size_t cx = (cache.Count() == 0 ? 0 : x + xRadius); cx < data.Width && cx <= x + xRadius; ++cx) { ColumnCache curCol; curCol.Index = cx; curCol.Content.PushBack(ColorToDArr(GetColor(data, cx, 0)) * static_cast<double>(yRadius + 1)); for (size_t ay = 1; ay <= yRadius; ++ay) { curCol.Content.Last() += ColorToDArr(GetColor(data, cx, (ay >= data.Height ? data.Height - 1 : ay))); } for (size_t cy = 1; cy < data.Height; ++cy) { DArr<4> lpx = curCol.Content.Last(); curCol.Content.PushBack(lpx); DArr<4> &curPx = curCol.Content.Last(); curPx -= ColorToDArr(GetColor(data, cx, (cy < yRadius + 1 ? 0 : cy - yRadius - 1))); curPx += ColorToDArr(GetColor(data, cx, Core::Math::Min(cy + yRadius, static_cast<size_t>(data.Height) - 1))); } cache.PushHead(curCol); } while (cache.PeekTail().Index + xRadius < x) { cache.PopTail(); } result.PushBack(List<DArr<4>>()); List<DArr<4>> &curList = result.Last(); for (size_t y = 0; y < data.Height; ++y) { curList.PushBack(DArr<4>()); DArr<4> &curPx = curList.Last(); cache.ForEachTailToHead([&](const ColumnCache &cc) { size_t repeat = 1; if (cc.Index == 0) { repeat = xRadius + 1 - x; } else if (cc.Index == data.Width - 1) { repeat = x + xRadius + 2 - data.Width; } for (size_t i = 0; i < repeat; ++i) { curPx += cc.Content[static_cast<size_t>(y)]; } return true; }); } } for (size_t x = 0; x < data.Width; ++x) { for (size_t y = 0; y < data.Height; ++y) { GetColor(data, x, y) = DArrToColor(result[x][y] / ((2 * xRadius + 1) * (2 * yRadius + 1))); } } }