forked from sysprog21/mado
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1b140a1
commit e256088
Showing
5 changed files
with
198 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"files.associations": { | ||
"apps_animation.h": "c", | ||
"cstdlib": "c", | ||
"apps_multi.h": "c" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
// horizontal pass | ||
for (auto y = 0u; y < h; ++y) | ||
{ | ||
auto row = data.getLinePointer (static_cast<int> (y)); | ||
|
||
// clear everything | ||
stackSum = sumIn = sumOut = queueIndex = 0; | ||
|
||
// Pre-fill the left half of the queue with the leftmost pixel value | ||
for (auto i = 0u; i <= radius; ++i) | ||
{ | ||
queue[i] = row[0]; | ||
|
||
// these init left side AND middle of the stack | ||
sumOut += row[0]; | ||
stackSum += row[0] * (i + 1); | ||
} | ||
|
||
// Fill the right half of the queue with the actual pixel values | ||
// zero is the center pixel here, it's added to the sum radius + 1 times | ||
for (auto i = 1u; i <= radius; ++i) | ||
{ | ||
// edge case where queue is bigger than image width! | ||
// for example vertical test where width = 1 | ||
auto value = (i <= w - 1) ? row[i] : row[w - 1]; | ||
|
||
queue[radius + i] = value; // look ma, no bounds checkin' | ||
sumIn += value; | ||
stackSum += value * (radius + 1 - i); | ||
} | ||
|
||
for (auto x = 0u; x < w; ++x) | ||
{ | ||
// calculate the blurred value from the stack | ||
row[x] = static_cast<unsigned char> (stackSum / sizeOfStack); | ||
|
||
// remove the outgoing sum from the stack | ||
stackSum -= sumOut; | ||
|
||
// remove the leftmost value from sumOut | ||
sumOut -= queue[queueIndex]; | ||
|
||
// Conveniently, after advancing the index of a circular buffer | ||
// the old "start" (aka queueIndex) will be the new "end", | ||
// This means we can just replace it with the incoming pixel value | ||
// if we hit the right edge, use the rightmost pixel value | ||
auto nextIndex = x + radius + 1; | ||
if (nextIndex < w) | ||
queue[queueIndex] = row[nextIndex]; | ||
else | ||
queue[queueIndex] = row[w - 1]; | ||
|
||
// Also add the new incoming value to the sumIn | ||
sumIn += queue[queueIndex]; | ||
|
||
// Advance the queue index by 1 position | ||
// the new incoming element is now the "last" in the queue | ||
if (++queueIndex == queue.size()) | ||
queueIndex = 0; | ||
|
||
// Put into place the next incoming sums | ||
stackSum += sumIn; | ||
|
||
// Add the current center pixel to sumOut | ||
auto middleIndex = (queueIndex + radius) % queue.size(); | ||
sumOut += queue[middleIndex]; | ||
|
||
// *remove* the new center pixel from sumIn | ||
sumIn -= queue[middleIndex]; | ||
} | ||
} | ||
|
||
// vertical pass, loop around each column | ||
// pretty much identical to the horizontal pass | ||
// except the pixel access is vertical instead of horizontal | ||
// hey, it's a naive implementation! prob better for perf this way too | ||
for (auto x = 0u; x < w; ++x) | ||
{ | ||
// clear everything | ||
stackSum = sumIn = sumOut = queueIndex = 0; | ||
|
||
// Pre-fill the left half of the queue with the topmost pixel value | ||
auto topMostPixel = data.getLinePointer (0) + (unsigned int) data.pixelStride * x; | ||
for (auto i = 0u; i <= radius; ++i) | ||
{ | ||
queue[i] = topMostPixel[0]; | ||
|
||
// these init left side + middle of the stack | ||
sumOut += queue[i]; | ||
stackSum += queue[i] * (i + 1); | ||
} | ||
|
||
// Fill the right half of the queue (excluding center!) with actual pixel values | ||
// zero is the topmost/center pixel here (it was added to the sum (radius + 1) times above) | ||
for (auto i = 1u; i <= radius; ++i) | ||
{ | ||
if (i <= h - 1) | ||
{ | ||
auto pixel = data.getLinePointer (i) + (unsigned int) data.pixelStride * x; | ||
queue[radius + i] = pixel[0]; | ||
} | ||
// edge case where queue is bigger than image height! | ||
// for example where width = 1 | ||
else | ||
{ | ||
auto pixel = data.getLinePointer ((h - 1)) + (unsigned int) data.pixelStride * x; | ||
queue[radius + i] = pixel[0]; | ||
} | ||
|
||
sumIn += queue[radius + i]; | ||
stackSum += queue[radius + i] * (radius + 1 - i); | ||
} | ||
|
||
for (auto y = 0u; y < h; ++y) | ||
{ | ||
// calculate the blurred value from the stack | ||
auto blurredValue = stackSum / sizeOfStack; | ||
jassert (blurredValue <= 255); | ||
auto blurredPixel = data.getLinePointer (static_cast<int> (y)) + (unsigned int) data.pixelStride * x; | ||
blurredPixel[0] = static_cast<unsigned char> (blurredValue); | ||
|
||
// remove outgoing sum from the stack | ||
stackSum -= sumOut; | ||
|
||
// start crafting the next sumOut by removing the leftmost value from sumOut | ||
sumOut -= queue[queueIndex]; | ||
|
||
// Replace the leftmost value with the incoming value | ||
if (y + radius + 1 < h) | ||
queue[queueIndex] = *data.getPixelPointer (static_cast<int> (x), static_cast<int> (y + radius + 1)); | ||
else | ||
queue[queueIndex] = *data.getPixelPointer (static_cast<int> (x), static_cast<int> (h - 1)); | ||
|
||
// Add the incoming value to the sumIn | ||
sumIn += queue[queueIndex]; | ||
|
||
// Advance the queue index by 1 position | ||
if (++queueIndex == queue.size()) queueIndex = 0; | ||
|
||
// Put into place the next incoming sums | ||
stackSum += sumIn; | ||
|
||
// Before we move the queue/kernel, add the current center pixel to sumOut | ||
auto middleIndex = (queueIndex + radius) % queue.size(); | ||
sumOut += queue[middleIndex]; | ||
|
||
// *remove* the new center pixel (only after the window shifts) | ||
sumIn -= queue[middleIndex]; | ||
} | ||
} |