0

I have some C# code that is doing key-color replacement based on hue. On my local machine, it's executing perfectly. However when I push it up to the server it replaces "some" but not all of the colors. It's like it's just deciding not to run part of the code.

The images are lossless PNGs - they are intact on the server. Is this some kind of threading issue? My code is not threaded here (beyond what the webserver does), but has anyone ever seen anything similar happen?

It might also help if I mention that this code is compiled in a separate library project and then referenced from an MVC3 application.

Thanks, and here is the code sample:

private void _ReplaceImageColor(Image img, Color baseColor, Color newColor)
{
    Bitmap bmp = (Bitmap)img;
    double baseHue = baseColor.GetHue();
    for (int x = 0; x < bmp.Width; x++)
    {
        for (int y = 0; y < bmp.Height; y++)
        {
            double pixelHue, pixelSat, pixelVal;
            ColorProcessor.ColorToHSV(bmp.GetPixel(x, y), out pixelHue, out pixelSat, out pixelVal);
            if (pixelHue == baseHue)
            {
                Color setColor = ColorProcessor.ColorFromHSV(newColor.GetHue(), pixelSat, pixelVal);
                bmp.SetPixel(x, y, setColor);
            }
        }
    }
}

Here's the methods from ColorProcessor since people asked...

public static void ColorToHSV(Color color, out double hue, out double saturation, out double value)
{
    int max = Math.Max(color.R, Math.Max(color.G, color.B));
    int min = Math.Min(color.R, Math.Min(color.G, color.B));

    hue = color.GetHue();
    saturation = (max == 0) ? 0 : 1d - (1d * min / max);
    value = max / 255d;
}

public static Color ColorFromHSV(double hue, double saturation, double value)
{
    int hi = Convert.ToInt32(Math.Floor(hue / 60)) % 6;
    double f = hue / 60 - Math.Floor(hue / 60);

    value = value * 255;
    int v = Convert.ToInt32(Math.Max(value, 0));
    int p = Convert.ToInt32(Math.Max(value * (1 - saturation), 0));
    int q = Convert.ToInt32(Math.Max(value * (1 - f * saturation), 0));
    int t = Convert.ToInt32(Math.Max(value * (1 - (1 - f) * saturation), 0));

    if (hi == 0)
        return Color.FromArgb(255, v, t, p);
    else if (hi == 1)
        return Color.FromArgb(255, q, v, p);
    else if (hi == 2)
        return Color.FromArgb(255, p, v, t);
    else if (hi == 3)
        return Color.FromArgb(255, p, q, v);
    else if (hi == 4)
        return Color.FromArgb(255, t, p, v);
    else
        return Color.FromArgb(255, v, p, q);
}
Charles
  • 50,943
  • 13
  • 104
  • 142
jocull
  • 20,008
  • 22
  • 105
  • 149
  • 2
    What is `ColorProcessor` from? – Scott Chamberlain May 29 '12 at 22:32
  • You need to do some more investigation first. Can you create a test of data to use on both and narrow it down a single datum that fails. Then investigate for exceptions in the code? – Preet Sangha May 29 '12 at 22:34
  • 3
    I think this is worth mentioning here: read the `Caution` box in this link to the `System.Drawing` namespace on MSDN: http://msdn.microsoft.com/en-us/library/xs6ftd89 – BeemerGuy May 29 '12 at 22:34
  • Sorry, `ColorProcessor` is another class I have to manage a bunch of other color tasks for this project. If you need code from there I will post it. Here I am just converting RGB to HSV values for color matching based on hue. – jocull May 29 '12 at 22:36
  • Thanks Beemer, it's not a .NET service, it's just an MVC3 application. I've done this dozens of times, but this is the first time anything weird has happened. Preet - Everything is working fine except for on the server some of the key coloring is skipped. It happens the same way every time. – jocull May 29 '12 at 22:38
  • @jocull that warning **explicitly applies** to web applications, such as MVC3... " or ASP.NET service " – Marc Gravell May 29 '12 at 22:40
  • @Marc - Sorry. Did not know a "service" was the same as an "application" here. They're different other places. – jocull May 29 '12 at 22:43
  • Is there anything that could happen when building in release mode? I just had this happen when I rebuilt locally... but I don't understand why. The code is the same. – jocull May 30 '12 at 00:29

1 Answers1

1

You might want to check very carefully that your dll references are the same on the server as on the dev machine. Hanselman had an article on that very thing recently: Confirm Your Expectations and Version Numbers in Production Environments

Also, since it is behaving differently on debug versus release mode check that it is using the same bitness in the build to eliminate that potential variation (e.g. x86) which can manifest on floating point numbers.

Turnkey
  • 9,266
  • 3
  • 27
  • 36
  • The versions all seem the same now, but this just happened on my local machine when building in release mode... what does that mean? – jocull May 30 '12 at 00:29
  • That sounds like a Heisenbug, where it behaves differently depending on the environment. Those are very hard to troubleshoot. Make sure you are nailing down the bitness in the build to eliminate that potential variation (e.g. x86). Also check out this: http://stackoverflow.com/questions/4787082/code-is-behaving-differently-in-release-vs-debug-mode – Turnkey May 30 '12 at 00:43
  • Hell! I bet you are right. This is dealing with doubles (HSV) and I should've known that the floating points would get to me... I will look into that. – jocull May 30 '12 at 03:45
  • That was the issue, thank you. The .NET compiler should just throw a warning when using `==` on floating points... – jocull May 30 '12 at 04:05
  • No problem, glad you got that difficult one solved. I'll amend the answer to include the other details from the comments. – Turnkey May 30 '12 at 12:57