// JP opened flex table

Click to See Complete Forum and Search --> : Affects -


.pcbrainbuster
November 22nd, 2007, 05:37 PM
Hello again,

Is there any function(s) you can use that apply effects on a bitmap? Like blur, distortion, etc.

Thanks.

LoKi_79
November 22nd, 2007, 06:16 PM
Hello again,

Is there any function(s) you can use that apply effects on a bitmap? Like blur, distortion, etc.

Thanks.

blur is easy to do yourself - just apply a mask to each pixel.

so for each pixel you take the average of the surrounding pixels and update the new value to the average.

be careful not to change the original until you have finished, or work from a copy - either way don't change the pixels you are calculating from.

also you will realise how annoying edge effects are when applying filters - you can either 'wrap around' the image, or reuse the edge values..

.pcbrainbuster
November 22nd, 2007, 06:20 PM
Can I have an example? I'm confused :(

Thanks.

LoKi_79
November 22nd, 2007, 06:37 PM
Can I have an example? I'm confused :(

Thanks.

i do have an old app that applies a generic 5x5 matrix to a bitmap - but i wrote it when i started learning so it may not be the best example... i will dig it out tomorrow.

read this first:
http://student.kuleuven.be/~m0216922/CG/filtering.html

.pcbrainbuster
November 23rd, 2007, 04:51 AM
I have no idea what matrixes are but I'll search it up a little later and then have a look at the link.

BTW, is this part of a matrix? -
|x y| = |12 32|

Thanks.

LoKi_79
November 23rd, 2007, 06:21 AM
I have no idea what matrixes are but I'll search it up a little later and then have a look at the link.

BTW, is this part of a matrix? -
|x y| = |12 32|

Thanks.
that is a 1-dimensional matrix if you like (1x2), but most people would call it a 2D vector, or just 2D coordinates - depending on what it was describing...

a 3x3 matrix is:
a1 a2 a3
b1 b2 b3
c1 c2 c3

.pcbrainbuster
November 23rd, 2007, 07:35 AM
Man I couldn't find any tutorials :( Could you point me in the right direction?

Thanks.

Marc G
November 23rd, 2007, 07:49 AM
Checkout http://mathworld.wolfram.com/ for mathematical issues.
And basic matrix stuff see: http://www.math.hmc.edu/calculus/tutorials/matrixalgebra/

.pcbrainbuster
November 23rd, 2007, 04:23 PM
I'm quite confused and put them a little down on the priority list :) I think I'm getting somewhere with the idea of how to blur my images -


COLORREF C1, C2, C3, C4, C5, CResult;
...
case USERSAIDTOBLUR :

C1 = GetPixel(MDC, StartingCursorPos.x, StartingCursorPos.y);
C2 = GetPixel(MDC, StartingCursorPos.x, StartingCursorPos.y + 1);
C3 = GetPixel(MDC, StartingCursorPos.x + 1, StartingCursorPos.y);
C4 = GetPixel(MDC, StartingCursorPos.x, StartingCursorPos.y - 1);
C5 = GetPixel(MDC, StartingCursorPos.x - 1, StartingCursorPos.y);
CResult = (C1 + C2 + C3 + C4 + C5) / 5;

SetPixel(MDC, StartingCursorPos.x, StartingCursorPos.y, CResult);

break;
...


Or something like that :)

I'm obviously am not completely sure what to do or if this will work, what do I do from there?

Thanks.

JamesSchumacher
November 24th, 2007, 11:24 AM
GetPixel and SetPixel used in this manner on every pixel in the bitmap selected into the DC is slow. A better method would be use a DIB bitmap (CreateDIBSection) and do this manually on the bits in the data you receive from CreateDIBSection. The easiest way to do this, is to make sure the DIB is a 32bpp bitmap, and also remember when accessing the bits directly, a COLORREF from the RGB macro gets the blue and red values reversed. So, you will have to write a function to create color values for direct access.

The RGB macro puts them in this order:

Parentheses = ignored value

Byte Index 0 1 2 3
R G B (A)

Direct Access requires them in this order

0 1 2 3
B G R A


typedef unsigned long DirectColorRef;
inline DirectColorRef FromARGB(unsigned char ucAlpha,
unsigned char ucRed,unsigned char ucGreen,unsigned char ucBlue)
{
DirectColorRef clrValue = 0;

clrValue |= static_cast<DirectColorRef>(ucBlue);
clrValue |= ( static_cast<DirectColorRef>(ucGreen) << 8 );
clrValue |= ( static_cast<DirectColorRef>(ucRed) << 16 );
clrValue |= ( static_cast<DirectColorRef>(ucAlpha) << 24 );

return clrValue;
}


Also, even though the alpha value is not ignored, if it's anything other than 0 on a simple setting of a pixel, it's considered black by the video card. (Or by the BitBlt or StretchBlt operation. TransparentBlt as well. Only AlphaBlend and similar things recognize the alpha value.)

As far as implementing algorithms... Whatever you want to do can be done, the fact that algorithms exist already for other routines says they have been written before.

This is code from a library I started awhile ago, however... I have scratched this one in favor of a better one down the line. This is not the whole code for my Gradient function, but this should give you an idea that one function does not have to do it all.


bool VGraphics::Gradient(VBitmap * pBitmap,const VColor & clrStart,const VColor & clrEnd,VGradientMode nMode,VRasterOp nROP)
{
if (nROP >= 0 && nROP <= 5)
{
GradientCall funcTable[6] = { GradientCopy,
GradientAnd, GradientOr, GradientXor, GradientAdd,
GradientSub };

return (*funcTable[nROP])(pBitmap,clrStart,clrEnd,nMode);
}

return false;
}


Notice how I am using function pointers in this functioin. GradientCopy is a function that does a normal assignment of the source to the dest. You can probably figure what the rest do.

I will post the source of GradientCopy to give you an idea, these type of things are possible to achieve in C++. However... This is actually a slow implementation with less memory usage... One of the reasons I decided to scratch this library in favor of my new idea. (The speed of this code would be drastically increased if I were to allocate a temporary buffer and do the calculations for the gradient only once.)


bool GradientCopy(VBitmap * pBitmap,const VColor & clrStart,const VColor & clrEnd,VGradientMode nMode)
{
const VSize nSize = pBitmap->GetSize();
const UInt32 dwScanLineSize = pBitmap->GetScanlineSize();

Byte ucRedDiff,ucGreenDiff,ucBlueDiff;

ucRedDiff = clrEnd.Red - clrStart.Red;
ucGreenDiff = clrEnd.Green - clrStart.Green;
ucBlueDiff = clrEnd.Blue - clrStart.Blue;

Byte * pBuffer = pBitmap->GetPixels();

VPixelFormat nFormat = pBitmap->GetFormat();

if (nFormat == PixelFormat::BGRA_32BPP)
{
VColor * pColors = reinterpret_cast<VColor *>(pBuffer);

UInt32 dwIndex;
VColor vClr;

if (nMode == GradientMode::LeftToRight)
{
double lfTemp;

for (UInt32 y = 0; y < nSize.Height; ++y)
{
dwIndex = (nSize.Height - y - 1) * nSize.Width;

for (UInt32 x = 0; x < nSize.Width; ++x)
{
lfTemp = static_cast<double>(x) / static_cast<double>(nSize.Width);

if (ucRedDiff != 0)
{
vClr.Red = static_cast<Byte>((static_cast<double>(ucRedDiff) * lfTemp) + clrStart.Red);
}
else
{
vClr.Red = clrStart.Red;
}

if (ucGreenDiff != 0)
{
vClr.Green = static_cast<Byte>((static_cast<double>(ucGreenDiff) * lfTemp) + clrStart.Green);
}
else
{
vClr.Green = clrStart.Green;
}

if (ucBlueDiff != 0)
{
vClr.Blue = static_cast<Byte>((static_cast<double>(ucBlueDiff) * lfTemp) + clrStart.Blue);
}
else
{
vClr.Blue = clrStart.Blue;
}

pColors[dwIndex].Data = vClr.Data;
++dwIndex;
}
}
}
else if (nMode == GradientMode::TopToBottom)
{
double lfTemp;

for (UInt32 x = 0; x < nSize.Width; ++x)
{
for (UInt32 y = 0; y < nSize.Height; ++y)
{
dwIndex = ((nSize.Height - y - 1) * nSize.Width) + x;

lfTemp = static_cast<double>(y) / static_cast<double>(nSize.Height);

if (ucRedDiff != 0)
{
vClr.Red = static_cast<Byte>((static_cast<double>(ucRedDiff) * lfTemp) + clrStart.Red);
}
else
{
vClr.Red = clrStart.Red;
}

if (ucGreenDiff != 0)
{
vClr.Green = static_cast<Byte>((static_cast<double>(ucGreenDiff) * lfTemp) + clrStart.Green);
}
else
{
vClr.Green = clrStart.Green;
}

if (ucBlueDiff != 0)
{
vClr.Blue = static_cast<Byte>((static_cast<double>(ucBlueDiff) * lfTemp) + clrStart.Blue);
}
else
{
vClr.Blue = clrStart.Blue;
}

pColors[dwIndex].Data = vClr.Data;
}
}
}
else if (nMode == GradientMode::RightToLeft)
{
double lfTemp;

for (UInt32 y = 0; y < nSize.Height; ++y)
{
dwIndex = (nSize.Height - y - 1) * nSize.Width;

for (UInt32 x = nSize.Width; x > 0; --x)
{
lfTemp = static_cast<double>(nSize.Width - x) / static_cast<double>(nSize.Width);

if (ucRedDiff != 0)
{
vClr.Red = static_cast<Byte>((static_cast<double>(ucRedDiff) * lfTemp) + clrStart.Red);
}
else
{
vClr.Red = clrStart.Red;
}

if (ucGreenDiff != 0)
{
vClr.Green = static_cast<Byte>((static_cast<double>(ucGreenDiff) * lfTemp) + clrStart.Green);
}
else
{
vClr.Green = clrStart.Green;
}

if (ucBlueDiff != 0)
{
vClr.Blue = static_cast<Byte>((static_cast<double>(ucBlueDiff) * lfTemp) + clrStart.Blue);
}
else
{
vClr.Blue = clrStart.Blue;
}

pColors[dwIndex + x - 1].Data = vClr.Data;
}
}
}
else if (nMode == GradientMode::BottomToTop)
{
double lfTemp;

for (UInt32 x = 0; x < nSize.Width; ++x)
{
for (UInt32 y = 0; y < nSize.Height; ++y)
{
dwIndex = (y * nSize.Width) + x;

lfTemp = static_cast<double>(y) / static_cast<double>(nSize.Height);

if (ucRedDiff != 0)
{
vClr.Red = static_cast<Byte>((static_cast<double>(ucRedDiff) * lfTemp) + clrStart.Red);
}
else
{
vClr.Red = clrStart.Red;
}

if (ucGreenDiff != 0)
{
vClr.Green = static_cast<Byte>((static_cast<double>(ucGreenDiff) * lfTemp) + clrStart.Green);
}
else
{
vClr.Green = clrStart.Green;
}

if (ucBlueDiff != 0)
{
vClr.Blue = static_cast<Byte>((static_cast<double>(ucBlueDiff) * lfTemp) + clrStart.Blue);
}
else
{
vClr.Blue = clrStart.Blue;
}

pColors[dwIndex].Data = vClr.Data;
}
}
}

return true;
}
else if (nFormat == PixelFormat::BGR_24BPP)
{
VBGRColor * pPixel;
Byte * pTemp;
VColor vClr;

if (nMode == GradientMode::LeftToRight)
{
double lfTemp;

for (UInt32 y = 0; y < nSize.Height; ++y)
{
pTemp = pBuffer + ((nSize.Height - y - 1) * dwScanLineSize);
pPixel = reinterpret_cast<VBGRColor *>(pTemp);

for (UInt32 x = 0; x < nSize.Width; ++x)
{
lfTemp = static_cast<double>(x) / static_cast<double>(nSize.Width);

if (ucRedDiff != 0)
{
vClr.Red = static_cast<Byte>((static_cast<double>(ucRedDiff) * lfTemp) + clrStart.Red);
}
else
{
vClr.Red = clrStart.Red;
}

if (ucGreenDiff != 0)
{
vClr.Green = static_cast<Byte>((static_cast<double>(ucGreenDiff) * lfTemp) + clrStart.Green);
}
else
{
vClr.Green = clrStart.Green;
}

if (ucBlueDiff != 0)
{
vClr.Blue = static_cast<Byte>((static_cast<double>(ucBlueDiff) * lfTemp) + clrStart.Blue);
}
else
{
vClr.Blue = clrStart.Blue;
}

pPixel->Red = vClr.Red;
pPixel->Green = vClr.Green;
pPixel->Blue = vClr.Blue;
++pPixel;
}
}
}
else if (nMode == GradientMode::TopToBottom)
{
double lfTemp;

for (UInt32 x = 0; x < nSize.Width; ++x)
{
for (UInt32 y = 0; y < nSize.Height; ++y)
{
pTemp = pBuffer + ((nSize.Height - y - 1) * dwScanLineSize) + (x * 3);
pPixel = reinterpret_cast<VBGRColor *>(pTemp);
lfTemp = static_cast<double>(y) / static_cast<double>(nSize.Height);

if (ucRedDiff != 0)
{
vClr.Red = static_cast<Byte>((static_cast<double>(ucRedDiff) * lfTemp) + clrStart.Red);
}
else
{
vClr.Red = clrStart.Red;
}

if (ucGreenDiff != 0)
{
vClr.Green = static_cast<Byte>((static_cast<double>(ucGreenDiff) * lfTemp) + clrStart.Green);
}
else
{
vClr.Green = clrStart.Green;
}

if (ucBlueDiff != 0)
{
vClr.Blue = static_cast<Byte>((static_cast<double>(ucBlueDiff) * lfTemp) + clrStart.Blue);
}
else
{
vClr.Blue = clrStart.Blue;
}

pPixel->Red = vClr.Red;
pPixel->Green = vClr.Green;
pPixel->Blue = vClr.Blue;
}
}
}
else if (nMode == GradientMode::RightToLeft)
{
double lfTemp;

for (UInt32 y = 0; y < nSize.Height; ++y)
{
for (UInt32 x = nSize.Width; x > 0; --x)
{
pTemp = pBuffer + ((nSize.Height - y - 1) * dwScanLineSize) + ((x - 1) * 3);
pPixel = reinterpret_cast<VBGRColor *>(pTemp);
lfTemp = static_cast<double>(nSize.Width - x) / static_cast<double>(nSize.Width);

if (ucRedDiff != 0)
{
vClr.Red = static_cast<Byte>((static_cast<double>(ucRedDiff) * lfTemp) + clrStart.Red);
}
else
{
vClr.Red = clrStart.Red;
}

if (ucGreenDiff != 0)
{
vClr.Green = static_cast<Byte>((static_cast<double>(ucGreenDiff) * lfTemp) + clrStart.Green);
}
else
{
vClr.Green = clrStart.Green;
}

if (ucBlueDiff != 0)
{
vClr.Blue = static_cast<Byte>((static_cast<double>(ucBlueDiff) * lfTemp) + clrStart.Blue);
}
else
{
vClr.Blue = clrStart.Blue;
}

pPixel->Red = vClr.Red;
pPixel->Green = vClr.Green;
pPixel->Blue = vClr.Blue;
}
}
}
else if (nMode == GradientMode::BottomToTop)
{
double lfTemp;

for (UInt32 x = 0; x < nSize.Width; ++x)
{
for (UInt32 y = nSize.Height; y > 0; --y)
{
pTemp = pBuffer + ((nSize.Height - y) * dwScanLineSize) + (x * 3);
pPixel = reinterpret_cast<VBGRColor *>(pTemp);
lfTemp = static_cast<double>(nSize.Height - y) / static_cast<double>(nSize.Height);

if (ucRedDiff != 0)
{
vClr.Red = static_cast<Byte>((static_cast<double>(ucRedDiff) * lfTemp) + clrStart.Red);
}
else
{
vClr.Red = clrStart.Red;
}

if (ucGreenDiff != 0)
{
vClr.Green = static_cast<Byte>((static_cast<double>(ucGreenDiff) * lfTemp) + clrStart.Green);
}
else
{
vClr.Green = clrStart.Green;
}

if (ucBlueDiff != 0)
{
vClr.Blue = static_cast<Byte>((static_cast<double>(ucBlueDiff) * lfTemp) + clrStart.Blue);
}
else
{
vClr.Blue = clrStart.Blue;
}

pPixel->Red = vClr.Red;
pPixel->Green = vClr.Green;
pPixel->Blue = vClr.Blue;
}
}
}
}
}

.pcbrainbuster
November 24th, 2007, 01:24 PM
Oh my god :( I've never seen code like that in my life!

I realize now that reinterpret_cast and static_cast are important and need links to tutorials that will teach me how to work with them, please :)

Also what is the meaning of the operator "|="?

Thanks.

JamesSchumacher
November 24th, 2007, 04:13 PM
Oh my god :( I've never seen code like that in my life!

I realize now that reinterpret_cast and static_cast are important and need links to tutorials that will teach me how to work with them, please :)

Also what is the meaning of the operator "|="?

Thanks.

It's the mathematical bitwise "Or Equals" operator. Imagine a set of 8 bits. (the color value is 32 bits)

2 values.

10101010 binary = 170 decimal
01010101 binary = 85 decimal

'Or' means that if the source is set or the dest is set, then the output is set.

So, the operation on the above values would result in all bits set.

11111111 = 255

Another example...

11000100 = 196
11000111 = 199

What is the output?

11000111 = 199

.pcbrainbuster
November 24th, 2007, 04:27 PM
Again I'm confused :( Sorry to be like that :( I guess I'll try to look it up.

Thanks :).

//JP added flex table