2

I need to check if picture is sRGB or Adobe RGB in my WEBapplication. Is there a way to know exactly what RGB does the picture have?

UPDATE: Tried to Use Color.Context, but it's always null

code

Bitmap img = (Bitmap)image;
var imgPixel = img.GetPixel(0,0);
System.Windows.Media.Color colorOfPixel= System.Windows.Media.Color.FromArgb(imgPixel.A,imgPixel.R, imgPixel.G, imgPixel.B);
var context = colorOfPixel.ColorContext; //ColorContext is null

In System.Windows.Media also found PixelFormat and PixelFormats that can show what exact RGB type an image is. But still I can't find a way to get System.Windows.Media.PixelFormat of an img. How should I do this?

anindis
  • 714
  • 2
  • 11
  • 20
  • 1
    `ColorContext` is `null` because you are creating the color syntetically by specifying the components. To use it, you need to use `BitmapFrame`, which has a `ColorContexts` property (you'll find the right one in index 0). I can't really write an example right now. – Jcl Mar 03 '15 at 06:34
  • i did this BitmapSource bmp = new BitmapImage(uri); BitmapFrame bmf = BitmapFrame.Create(bmp); And ColorContexts are null ( And Format property is always bgr32, although I converted to sRGB and adobe RGB by online converter, and checked photoes that boss gave me as examples – anindis Mar 03 '15 at 07:12
  • Used this answer. ColorContexts[0].colorspace is always RGB: https://social.msdn.microsoft.com/Forums/vstudio/en-US/1142bf27-dab5-4018-924f-15d481906120/how-to-get-the-color-spcae-of-a-bitmapsource?forum=wpf – anindis Mar 03 '15 at 07:28
  • I wrote an example of how to get the color context (and also tested it). Determining if that context is sRGB or AdobeRGB might have a bit more work tho – Jcl Mar 03 '15 at 07:55

3 Answers3

4

You'll need to use a BitmapDecoder to get the frame from there, then check the color context:

BitmapDecoder bitmapDec = BitmapDecoder.Create(
   new Uri("mybitmap.jpg", UriKind.Relative),
   BitmapCreateOptions.None,
   BitmapCacheOption.Default);
BitmapFrame bmpFrame = bitmapDec.Frames[0];
ColorContext context = bmpFrame.ColorContexts[0];

Afterwards, you'd need to process the raw color profile (using context.OpenProfileStream()) to determine which profile it is.

If you want to write the profiles to disk to check them with an hex editor or something, you can use this code:

using(var fileStream = File.Create(@"myprofilename.icc"))
using (var st = context.OpenProfileStream())
{
  st.CopyTo(fileStream);
  fileStream.Flush(true);
  fileStream.Close();
}

Using that method, I've extracted the raw data from both sRGB (link) and AdobeRGB (link) if you want to check them. There are magic strings and IDs at the start if you want to check but I really don't know them or know where to find a table for the common ones (the embedded profiles could be infinite, not limited to AdobeRGB and sRGB).

Also, one image might have more than one color profile.

With this method, if ColorContexts is empty, then the image doesn't have any profile.

Jcl
  • 27,696
  • 5
  • 61
  • 92
  • If the original image has a color profile different than sRGB, the BitmapDecoder must be used with the options `BitmapCreateOptions.PreservePixelFormat` and `BitmapCacheOption.None`, otherwise color conversions don't work correctly. – The Conspiracy Jan 17 '16 at 14:12
1

Color.ColorContext Property MSDN: https://msdn.microsoft.com/en-us/library/System.Windows.Media.Color_properties(v=vs.110).aspx

1

You might use System.Drawing.Image.PropertyItems. The property "PropertyTagICCProfile" (Id=34675=0x8773) is populated with the icc profile of the image, even if it is embedded in image data and not in exif data (or there is no profile embedded, but the image is labeled as AdobeRGB in exif: InteroperabilityIndex="R03").

byte[] iccProfile = null;
try {
    System.Drawing.Bitmap myImage = new Bitmap("Image.jpg");
    iccProfile = myImage.GetPropertyItem(34675).Value;
} catch (Exception) {
    //...
}
ironed
  • 61
  • 5