 |
|
 |
There's any possibility to give to the input image an inner shadow?
Where should I change the code you wrote?
Regards.
|
|
|
|
 |
|
 |
There's no option for inner shadows.
To do that in the code, you would have to create a layer, paint it black and cut out the piece inside that black region. Blur that layer. Cut out the same region of the input image and simply put the input image above the shadow layer. Move the shadow layer a bit to the right and to the bottom. I think it's better to start with the code of The Aqualizer or maybe learn GIMP Also take a look at the GPaint article.
|
|
|
|
 |
|
 |
Hi
Thanks your for your good control.
Can you find the edges of an image and create a shade for it,for example shade a flower or egg outside a Regtangle like the shades that we see for them in natural world?
Thanks again.
|
|
|
|
 |
|
 |
Do one of the parameters for Shadow allow a transparent background to be set? If so what values should be used?
Thanks.
|
|
|
|
 |
|
 |
Hello,
take a look at the messages for my other cool program :
http://www.codeproject.com/cs/media/aqualize.asp
Someone has posted the code in the messages to set the background transparent and to save the bitmap as a PNG.
|
|
|
|
 |
|
 |
Thanks I'm looking at that. Something else I tried to do with Shadow but couldn't get working was turning it into a .NET standalone class. I'd love to be able to create an instance of the Shadow class and then be able to call it with similar parameters to what you use via the command console and pass an Image to it and get one back with a shadow attached. Would that be hard to do? With all of the dependencies on your FastBitmap type I couldn't even pull out some of the classes and roll it into a new Shadow class.
Rick
|
|
|
|
 |
|
 |
I'm going to take a look at it.
|
|
|
|
 |
|
|
 |
|
 |
You can download shadow.cs in a zip-file here:
http://home.tiscali.be/zoetrope/shadowizer/index.htm
It contains all classes you need. There is one class "Shadowizer" which contains the logic to add shadows. The main function demonstrates how to use it. You have to save them as PNG because it now saves bitmaps in 32-bit. You could put all classes in a separate DLL. Only FastBitmap and Shadowizer would have to be public. Some code differs from shadow in this article. The blur function now uses a sigmoid function instead of a gaussian function.
|
|
|
|
 |
|
 |
That is sensational! It works great!! Could you add a small tweak?
If I am using it as a class its more likely I am going to need the result as an Image and not necessarily saved as a file. With this line:
FastBitmap bmp = s.AddShadow(image);
This returns an image of type FastBitmap. Could it have an overload to return a System.Drawing.Image? Then I could use standard uses of that type including assigning it to a Picturebox.
Also any ideas how performance can be improved? If I use the class against a 343x475 sized jpg, it takes 19-20 seconds to add the shadow which seems fairly long. What takes up the bulk of the time? I remeber in your original article on Shadow that you planned it as a bulk shadowing tool which might take a while if the shadowing time is lengthy. If it makes any difference I am trying this using the .NET Framework 2.0 under Visual Studio 2005.
Also how hard is it to remove the dependency for using unsafe code? Your GetPixel and SetPixel functions seem to be the onlythings marked as unsafe and I was wondering why the native Image GetPixel and SetPixel functions couldn't be used, are they not flexible enough for your image processing?
Thanks so much for doing this, its a very powerful and useful class!! If I use this in some of my personal utilities, how should I credit you in the code? (If thats OK)
Rick
Rick
|
|
|
|
 |
|
 |
Hello,
1. download http://home.tiscali.be/zoetrope/shadowizer/index.htm again. It contains a bug fix: the background wasn't painted. Now you can set the BackColor to Color.Transparent or Color.Red or whatever. In the code you have, the backcolor will always be transparent.
2. FastBitmap contains a Bitmap property and a Bitmap is an Image. But I'm going to take a look at it. I pass and return FastBitmaps to avoid having to make a temporary copy of the image but maybe that's unnecessary. It won't be for today. I don't have time.
3. Performance: Standard GetPixel() and SetPixel() are SLOOOOWWWWW (same as Win32 calls: also very slow). So, I use pointers. The code you have is, I think, already faster than the code in the codeproject article because I think it uses GetPixelInt32(): no need to allocate a structure. The bulk time is .NET itself. Removing unsafe code would make it even slower. Probably not what you want!
4. Credits: something like this maybe:
Portions written by SFJOIBSUTUFZBFSU.
http://home.tiscali.be/zoetrope
(Or "Based on code written by" or something like that.)
In case the link becomes dead in the future, you can remove it. If you don't want to provide a link at all, well ok.
Now I have to go.
|
|
|
|
 |
|
 |
Hi I wanted to check in and see if you were able to look at passing back an Image type instead of a FastBitMap as the result of calling the Shadowizer class.
Out of curiosity, how long is it taking you to add a shadow to an image? I'm curious if it works fastre for you then me since I had been seeing the 20 second per image shadow processingg time.
Thanks a lot,
Rick
|
|
|
|
 |
|
 |
I have improvement for Blur() function. It speeds thing for ~5 times.
Does anybody need it?
SY-
Kosta.
|
|
|
|
 |
|
 |
Can you tell us what you did to improve the speed?
|
|
|
|
 |
|
 |
1. I added 4 arrays and 2 methods to class FastBitmap:
---------------------------
class FastBitmap : IDisposable, ICloneable {
internal Bitmap _bitmap;
internal byte[,] src_red;
internal byte[,] src_green;
internal byte[,] src_blue;
internal byte[,] src_alfa;
<...>
unsafe public void ReadBytes() {
src_red = new byte[_bitmap.Width, _bitmap.Height];
src_green = new byte[_bitmap.Width, _bitmap.Height];
src_blue = new byte[_bitmap.Width, _bitmap.Height];
src_alfa = new byte[_bitmap.Width, _bitmap.Height];
Byte* b = (Byte*)_bitmapData.Scan0;
if (_bitmapData.PixelFormat == PixelFormat.Format32bppArgb) {
for (Int32 i=0; i<_bitmap.Height; i++) {
for (Int32 k=0; k<_bitmap.Width; k++) {
src_blue[k,i] = *b;
b++;
src_green[k,i] = *b;
b++;
src_red[k,i] = *b;
b++;
src_alfa[k,i] = *b;
b++;
}
}
}
if (_bitmapData.PixelFormat == PixelFormat.Format24bppRgb) {
for (Int32 i=0; i<_bitmap.Height; i++) {
for (Int32 k=0; k<_bitmap.Width; k++) {
src_blue[k,i] = *b;
b++;
src_green[k,i] = *b;
b++;
src_red[k,i] = *b;
b++;
src_alfa[k,i] = 0;
}
}
}
}
unsafe public void WriteBytes() {
Byte* b = (Byte*)_bitmapData.Scan0;
if (_bitmapData.PixelFormat == PixelFormat.Format32bppArgb) {
for (Int32 i=0; i<_bitmap.Height; i++) {
for (Int32 k=0; k<_bitmap.Width; k++) {
*b = src_blue[k,i];
b++;
*b = src_green[k,i];
b++;
*b = src_red[k,i];
b++;
*b = src_alfa[k,i];
b++;
}
}
}
if (_bitmapData.PixelFormat == PixelFormat.Format24bppRgb) {
for (Int32 i=0; i<_bitmap.Height; i++) {
for (Int32 k=0; k<_bitmap.Width; k++) {
*b = src_blue[k,i];
b++;
*b = src_green[k,i];
b++;
*b = src_red[k,i];
b++;
}
}
}
}
<...>
}
----------------------------
This was done because GetPixel and SetPixel methods do more operations to access data than just array access.
Here I saved 2 additions, 2 multiplications and two function calls for each call for pixel color. Given number of calls, it saves ~20% of time.
2. The biggest gain went from avoiding calls for _bitmap.Width and _bitmap.Height. For some reason, they are very slow.
3. Then, I moved calculation of alfa weight for each color outside the blur loop. This also gave substantial savings.
4. Then, i unified types (all Single - that saved ~10%).
Final version for Blur() function:
---------------------------------
public void Blur(Int32 horz, Int32 vert) {
Single weightsum;
Single[] weights;
FastBitmap t = (FastBitmap)_bitmap.Clone();
_bitmap.Lock();
t.Lock();
Int32 bmW = _bitmap.Width;
Int32 bmH = _bitmap.Height;
Int32 hr2 = horz * 2 + 1;
Int32 vr2 = vert * 2 + 1;
// horizontal blur
weights = new Single[hr2];
for (Int32 i = 0; i < hr2; i++) {
Single y = Gauss(-horz + i, 0, horz);
weights[i] = y;
}
// speed up code from KCherry on 10/13/2005:
Single[,] src_red = new Single[bmW, bmH];
Single[,] src_green = new Single[bmW, bmH];
Single[,] src_blue = new Single[bmW, bmH];
_bitmap.ReadBytes();
// now calculate intermediate multipliers:
for (Int32 row = 0; row < bmH; row++) {
for (Int32 col = 0; col < bmW; col++) {
src_red[col, row] = _bitmap.src_red[col, row] * _bitmap.src_alfa[col, row] / (Single)255.0;
src_green[col, row] = _bitmap.src_green[col, row] * _bitmap.src_alfa[col, row] / (Single)255.0;
src_blue[col, row] = _bitmap.src_blue[col, row] * _bitmap.src_alfa[col, row] / (Single)255.0;
}
}
t.src_red = new byte[bmW, bmH];
t.src_green = new byte[bmW, bmH];
t.src_blue = new byte[bmW, bmH];
t.src_alfa = new byte[bmW, bmH];
for (Int32 row = 0; row < bmH; row++) {
for (Int32 col = 0; col < bmW; col++) {
Single r = 0;
Single g = 0;
Single b = 0;
Single a = 0;
weightsum = 0;
for (Int32 i = 0; i < hr2; i++) {
Int32 x = col - horz + i;
if (x < 0) {
i += -x;
x = 0;
}
if (x > bmW - 1)
break;
/* Color c = _bitmap.GetPixel(x, row);
r += c.R * weights[i] / 255.0 * c.A;
g += c.G * weights[i] / 255.0 * c.A;
b += c.B * weights[i] / 255.0 * c.A;
a += c.A * weights[i];
*/
r += src_red[x, row] * weights[i];
g += src_green[x, row] * weights[i];
b += src_blue[x, row] * weights[i];
a += _bitmap.src_alfa[x, row] * weights[i];
weightsum += weights[i];
}
r /= weightsum;
g /= weightsum;
b /= weightsum;
a /= weightsum;
Byte br = (Byte)Math.Round(r);
Byte bg = (Byte)Math.Round(g);
Byte bb = (Byte)Math.Round(b);
Byte ba = (Byte)Math.Round(a);
if (br > 255) br = 255;
if (bg > 255) bg = 255;
if (bb > 255) bb = 255;
if (ba > 255) ba = 255;
//t.SetPixel(col, row, Color.FromArgb(ba, br, bg, bb));
t.src_alfa[col, row] = ba;
t.src_red[col, row] = br;
t.src_green[col, row] = bg;
t.src_blue[col, row] = bb;
}
}
// vertical blur
// now calculate intermediate multipliers:
for (Int32 row = 0; row < bmH; row++) {
for (Int32 col = 0; col < bmW; col++) {
src_red[col, row] = t.src_red[col, row] * t.src_alfa[col, row] / (Single)255.0;
src_green[col, row] = t.src_green[col, row] * t.src_alfa[col, row] / (Single)255.0;
src_blue[col, row] = t.src_blue[col, row] * t.src_alfa[col, row] / (Single)255.0;
}
}
weights = new Single[vr2];
for (Int32 i = 0; i < vr2; i++) {
Single y = Gauss(-vert + i, 0, vert);
weights[i] = y;
}
for (Int32 col = 0; col < bmW; col++) {
for (Int32 row = 0; row < bmH; row++) {
Single r = 0;
Single g = 0;
Single b = 0;
Single a = 0;
weightsum = 0;
for (Int32 i = 0; i < vr2; i++) {
Int32 y = row - vert + i;
if (y < 0) {
i += -y;
y = 0;
}
if (y > bmH - 1)
break;
/* Color c = t.GetPixel(col, y);
r += c.R * weights[i] / 255.0 * c.A;
g += c.G * weights[i] / 255.0 * c.A;
b += c.B * weights[i] / 255.0 * c.A;
a += c.A * weights[i];
*/
r += src_red[col, y] * weights[i];
g += src_green[col, y] * weights[i];
b += src_blue[col, y] * weights[i];
a += t.src_alfa[col, y] * weights[i];
weightsum += weights[i];
}
r /= weightsum;
g /= weightsum;
b /= weightsum;
a /= weightsum;
Byte br = (Byte)Math.Round(r);
Byte bg = (Byte)Math.Round(g);
Byte bb = (Byte)Math.Round(b);
Byte ba = (Byte)Math.Round(a);
if (br > 255) br = 255;
if (bg > 255) bg = 255;
if (bb > 255) bb = 255;
if (ba > 255) ba = 255;
_bitmap.src_alfa[col, row] = ba;
_bitmap.src_red[col, row] = br;
_bitmap.src_green[col, row] = bg;
_bitmap.src_blue[col, row] = bb;
//_bitmap.SetPixel(col, row, Color.FromArgb(ba, br, bg, bb));
}
}
_bitmap.WriteBytes();
t.Dispose(); // will unlock
_bitmap.Unlock();
}
---------------------------------
The further improvement will come if Signle would be changed to Int32. I'll finish that sometime soon
But it is still slower than photoshop.
I'm sure they use different algorithm, but I don't have much time to think about it.
Anybody get better ideas?
SY-
Kosta.
|
|
|
|
 |
|
 |
Oh, sh.., it was so nice laid out, and posting removed all formatting. Grrr...
Sorry.
|
|
|
|
 |
|
 |
Oh, sh.., it was so nice laid out, and posting removed all formatting. Grrr...
Sorry.
SY-
Kosta.
|
|
|
|
 |
|
 |
I was working on a new program based on the Shadow code when I noticed something: the Blur Filter is VERY slow. Applying a blur to an image should happen in no time, but it takes seconds on my computer.
Instead of doing a GetPixel(), I tried a GetPixelInt32(), a method which returns the color as a Int32 instead of a Color structure. Performance was better but still way too slow. I discovered the problem is the floating point stuff. But I can't remove it, I need those operations. Sigh.
Conclusion: I would write a new utility in good old (non-.NET) C++. But then I would have to write anti-aliasing code for lines and circles etc. or I would have to use a third-party library. Sigh again.
BTW, you can find an explanation of the Blur Filter on my site http://home.tiscali.be/zoetrope.
|
|
|
|
 |
|
 |
Just a thought, a single shot in the dark. Rather than using floating point, can you use fixed point math? That's an optimisation we often used in Assembly language for games development. I will look at the code and see if I can offer anything on this.
Nursey
|
|
|
|
 |
|
 |
Not only Blur, I found following slow functions (800 * 600 image and based on demo source code):
1) LayeredImage constructor
2) Layer bg = image.Layers.Add(); bg.Clear(bkcolor);
3) Layer shadow = image.Layers.Add(width + shadowwidth, height + shadowwidth);
4) shadow.Blur(shadowwidth, shadowwidth);
WWW: http://hardywang.1accesshost.com
ICQ: 3359839
yours Hardy
|
|
|
|
 |
|
 |
First. Very nice utillity. Especially the batch part.
If however one only needs a dropshadow for at few items, the following CSS class will do this on the fly:
.Shadow
{
filter: progid:dximagetransform.microsoft.dropshadow(offx=2, offy=2, color= 'gray' , positive= 'true' );
}
Notice! Is a windows thing.
Peter Steen Nielsen
|
|
|
|
 |
|
 |
This is also an IE only thing
|
|
|
|
 |
|
 |
Would be nice if you could walk through some of the code in article.
|
|
|
|
 |
|
|
 |
|
 |
Sorry if that came over as not appreciating the work thats been done. It does look wicked
|
|
|
|
 |