Problem extracting full palette from 8bit image
-
I've been using CastorTiu's amazing IconLib in my application. http://www.codeproject.com/cs/library/IconLib.asp He has a function in the library that adds an image to an icon. It can add images of many different bit types and they all work fine except for 8bit images. When 8 bit images go through this code which reproduces a full palette the for loop iterates 256 times and this causes the program to go unresponsive for too long... It does eventually finish but only after nearly freezing the program for a few seconds. I was wondering if anyone knew of an alternative for creating a full palette that isn't so intensive on the system. Here is the function that causes the delays with 8bit images but not 4bit [16 iterations] or 32 bit [skips loop altogether]
public static RGBQUAD[] RGBQUADFromColorArray(Bitmap bmp) { // Some programs as Axialis have problems with a reduced palette, so lets create a full palette int bits = Tools.BitsFromPixelFormat(bmp.PixelFormat); RGBQUAD[] rgbArray = new RGBQUAD[bits <= 8 ? (1 << bits) : 0]; for(int i=0; i < bmp.Palette.Entries.Length; i++) { rgbArray[i].rgbRed = bmp.Palette.Entries[i].R; rgbArray[i].rgbGreen= bmp.Palette.Entries[i].G; rgbArray[i].rgbBlue = bmp.Palette.Entries[i].B; } return rgbArray; }
-
I've been using CastorTiu's amazing IconLib in my application. http://www.codeproject.com/cs/library/IconLib.asp He has a function in the library that adds an image to an icon. It can add images of many different bit types and they all work fine except for 8bit images. When 8 bit images go through this code which reproduces a full palette the for loop iterates 256 times and this causes the program to go unresponsive for too long... It does eventually finish but only after nearly freezing the program for a few seconds. I was wondering if anyone knew of an alternative for creating a full palette that isn't so intensive on the system. Here is the function that causes the delays with 8bit images but not 4bit [16 iterations] or 32 bit [skips loop altogether]
public static RGBQUAD[] RGBQUADFromColorArray(Bitmap bmp) { // Some programs as Axialis have problems with a reduced palette, so lets create a full palette int bits = Tools.BitsFromPixelFormat(bmp.PixelFormat); RGBQUAD[] rgbArray = new RGBQUAD[bits <= 8 ? (1 << bits) : 0]; for(int i=0; i < bmp.Palette.Entries.Length; i++) { rgbArray[i].rgbRed = bmp.Palette.Entries[i].R; rgbArray[i].rgbGreen= bmp.Palette.Entries[i].G; rgbArray[i].rgbBlue = bmp.Palette.Entries[i].B; } return rgbArray; }
Hmm that loop should take under a millisecond if bmp.Palette.Entries.Length is 256. Are you positive that's where time is being consumed (on the thread executing the loop)? Mark
"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder
-
Hmm that loop should take under a millisecond if bmp.Palette.Entries.Length is 256. Are you positive that's where time is being consumed (on the thread executing the loop)? Mark
"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder
Positive... I stepped through the entire thing and the slowdowns happen during the iterations of the loop. Happens in my program and just to make sure it wasn't something I did, I loaded up the IconLib project itself and passed it an 8bit image and had the same problem.
-
Positive... I stepped through the entire thing and the slowdowns happen during the iterations of the loop. Happens in my program and just to make sure it wasn't something I did, I loaded up the IconLib project itself and passed it an 8bit image and had the same problem.
This sounds kinda strange... Copying 1 byte from one location to another 768 times shouldn't take long (unless you have a REALLY slow machine. I'm pretty sure the original PC at 4.77 MHz could do it in under a millisecond :) If you break execution when it stalls is it really in the loop or is it maybe in the Tools.BitsFromPixelFormat(bmp.PixelFormat) call. Mark
"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder
-
This sounds kinda strange... Copying 1 byte from one location to another 768 times shouldn't take long (unless you have a REALLY slow machine. I'm pretty sure the original PC at 4.77 MHz could do it in under a millisecond :) If you break execution when it stalls is it really in the loop or is it maybe in the Tools.BitsFromPixelFormat(bmp.PixelFormat) call. Mark
"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder
Machine can more than handle this that's why I posted the question because it's so strange... Yes it does stall during the loop not during the bitsfrompixel Bits from pixel is just a simply switch anyway
public static int BitsFromPixelFormat(PixelFormat pixelFormat) { switch (pixelFormat) { case PixelFormat.Format1bppIndexed: return 1; case PixelFormat.Format4bppIndexed: return 4; case PixelFormat.Format8bppIndexed: return 8; ... etc.
-
Machine can more than handle this that's why I posted the question because it's so strange... Yes it does stall during the loop not during the bitsfrompixel Bits from pixel is just a simply switch anyway
public static int BitsFromPixelFormat(PixelFormat pixelFormat) { switch (pixelFormat) { case PixelFormat.Format1bppIndexed: return 1; case PixelFormat.Format4bppIndexed: return 4; case PixelFormat.Format8bppIndexed: return 8; ... etc.
Here's a picture of my actual breakpoints... http://wwwp.mirror.waffleimages.com/files/13/13e214fd705683442d70081bb7c901230aac708a.png With the wya they are setup in the picture it takes a while to manually step through 256times but it reaches the end eventually and all is fine... But only because it took some time to do manually. If I remove the breakpoints on
i < bmp.Palette.Entries.Length;
andi++;
the stall happens directly betweenint i=0;
andreturn rgbArray;
There isn't any further question in my mind that something is going wrong during that palette copying inside that loop. But the real question is why? This machine is a beast and the rest of the code is fine just for somereason 256 iterations ofrgbArray[i].rgbRed = bmp.Palette.Entries[i].R; rgbArray[i].rgbGreen= bmp.Palette.Entries[i].G; rgbArray[i].rgbBlue = bmp.Palette.Entries[i].B;
stalls the program for 30 seconds or so. -
Machine can more than handle this that's why I posted the question because it's so strange... Yes it does stall during the loop not during the bitsfrompixel Bits from pixel is just a simply switch anyway
public static int BitsFromPixelFormat(PixelFormat pixelFormat) { switch (pixelFormat) { case PixelFormat.Format1bppIndexed: return 1; case PixelFormat.Format4bppIndexed: return 4; case PixelFormat.Format8bppIndexed: return 8; ... etc.
Hmmm... Is this managed C++? If so, does optimizing the loop help any?
public static RGBQUAD[] RGBQUADFromColorArray(Bitmap bmp)
{
// Some programs as Axialis have problems with a reduced palette, so lets create a full palette
int bits = Tools.BitsFromPixelFormat(bmp.PixelFormat);if (bits <= 8)
{
RGBQUAD[] rgbArray = new RGBQUAD[1 << bits];ColorPalette ^palette = bmp.Palette; array<Color>^palcolors = palette->Entries; for(int i=0; i < palcolors->Length; i++) { rgbArray\[i\].rgbRed = palcolors\[i\].R; rgbArray\[i\].rgbGreen= palcolors\[i\].G; rgbArray\[i\].rgbBlue = palcolors\[i\].B; } return rgbArray;
}
return 0;
}"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder
-
Here's a picture of my actual breakpoints... http://wwwp.mirror.waffleimages.com/files/13/13e214fd705683442d70081bb7c901230aac708a.png With the wya they are setup in the picture it takes a while to manually step through 256times but it reaches the end eventually and all is fine... But only because it took some time to do manually. If I remove the breakpoints on
i < bmp.Palette.Entries.Length;
andi++;
the stall happens directly betweenint i=0;
andreturn rgbArray;
There isn't any further question in my mind that something is going wrong during that palette copying inside that loop. But the real question is why? This machine is a beast and the rest of the code is fine just for somereason 256 iterations ofrgbArray[i].rgbRed = bmp.Palette.Entries[i].R; rgbArray[i].rgbGreen= bmp.Palette.Entries[i].G; rgbArray[i].rgbBlue = bmp.Palette.Entries[i].B;
stalls the program for 30 seconds or so.I'm wondering if it's reallocating/recreating a new palette every time the Palette property is accessed. Maybe the optimized loop I posted below will help :) Mark
"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder
-
Hmmm... Is this managed C++? If so, does optimizing the loop help any?
public static RGBQUAD[] RGBQUADFromColorArray(Bitmap bmp)
{
// Some programs as Axialis have problems with a reduced palette, so lets create a full palette
int bits = Tools.BitsFromPixelFormat(bmp.PixelFormat);if (bits <= 8)
{
RGBQUAD[] rgbArray = new RGBQUAD[1 << bits];ColorPalette ^palette = bmp.Palette; array<Color>^palcolors = palette->Entries; for(int i=0; i < palcolors->Length; i++) { rgbArray\[i\].rgbRed = palcolors\[i\].R; rgbArray\[i\].rgbGreen= palcolors\[i\].G; rgbArray\[i\].rgbBlue = palcolors\[i\].B; } return rgbArray;
}
return 0;
}"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder
-
You should be able to do the same thing. The point is, pull the Palette and Palette.Entries property accesses OUT of the loop and loop through the entries array only. Sorry I don't know the syntax - it should be simple for you I would think :) Mark
"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder
-
I'll take a WILD stab at the C# syntax LOL...
public static RGBQUAD[] RGBQUADFromColorArray(Bitmap bmp)
{
// Some programs as Axialis have problems with a reduced palette, so lets create a full palette
int bits = Tools.BitsFromPixelFormat(bmp.PixelFormat);if (bits <= 8)
{
RGBQUAD[] rgbArray = new RGBQUAD[1 << bits];ColorPalette palette = bmp.Palette; Color\[\] palcolors = palette.Entries; for(int i=0; i < palcolors.Length; i++) { rgbArray\[i\].rgbRed = palcolors\[i\].R; rgbArray\[i\].rgbGreen= palcolors\[i\].G; rgbArray\[i\].rgbBlue = palcolors\[i\].B; } return rgbArray;
}
return 0;
}"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder
-
You should be able to do the same thing. The point is, pull the Palette and Palette.Entries property accesses OUT of the loop and loop through the entries array only. Sorry I don't know the syntax - it should be simple for you I would think :) Mark
"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder
-
I'll take a WILD stab at the C# syntax LOL...
public static RGBQUAD[] RGBQUADFromColorArray(Bitmap bmp)
{
// Some programs as Axialis have problems with a reduced palette, so lets create a full palette
int bits = Tools.BitsFromPixelFormat(bmp.PixelFormat);if (bits <= 8)
{
RGBQUAD[] rgbArray = new RGBQUAD[1 << bits];ColorPalette palette = bmp.Palette; Color\[\] palcolors = palette.Entries; for(int i=0; i < palcolors.Length; i++) { rgbArray\[i\].rgbRed = palcolors\[i\].R; rgbArray\[i\].rgbGreen= palcolors\[i\].G; rgbArray\[i\].rgbBlue = palcolors\[i\].B; } return rgbArray;
}
return 0;
}"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder
-
Wow that worked... You're a lifesaver and a genius. I wouldn't have thought that could fix it either but I was willing to try anything, so thanks for suggesting what I thought didn't matter. :D
Cool! I had no idea using the properties in the loop would be that slow! Good to know! :) Mark
"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder