Re: [Lcms-user] Difficulty with cmsTransform in C#
> Does this code actually work for you? Yes is does. Perhaps I should have mentioned that you need at least .Net 4 In 3.5 it's available but does not work... (s. https://social.msdn.microsoft.com/Forums/en-US/be7ad7d6-972f-4a39-ae90-55660d66c561/iccprofildaten-via-colorcontext?forum=wpfde) The second thing that might cause some trouble: some jpeg (of digicams) do not really contain an icc profile, they are just tagged (in exif) to be SRGB or AdobeRGB. E.g. if exif:InteroperabilityIndex contains R03 it's an AdobeRGB image, s http://regex.info/blog/photo-tech/color-spaces-page7 But! I just checked my AdobeRGB images taken with my Nikon or my Canon, and in every case ColorContext did work... > Where does the "StreamToArray" method comes from? The StreamToArray is a simple helper method (I forgot to cite) e.g.: public static Byte[] StreamToArray(Stream input) { if (input is MemoryStream) { return (input as MemoryStream).ToArray(); } else { using (MemoryStream ms = new MemoryStream()) { input.CopyTo(ms); return ms.ToArray(); } } } Edgar > > First of all, when creating a BitmapFrame with PreservePixelFormats the > ColorContext is *always* nill!!! > It does not work for me, with the JPEG files I tried. > > I would *love* for the ColorContext to come across as I would be able to > create an ICC profile from memory, the way to do it. > It is perfect! Except, it does not work. > > In all my testing, so far, I have NOT been able to retrieve a ColorContext > (embedded ICC profile) from a JPEG image. > > Second question... > > > Best / Roger > > > -- > Attend Shape: An AT Tech Expo July 15-16. Meet us at AT Park in San > Francisco, CA to explore cutting-edge tech and listen to tech luminaries > present their vision of the future. This family event has something for > everyone, including kids. Get more information and register today. > http://sdm.link/attshape > ___ > Lcms-user mailing list > Lcms-user@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/lcms-user > -- lakeBits Inh. Edgar Loser Haydnstr. 25 78464 Konstanz Tel 0049 7531 5844154 0 Fax 0049 7531 5844154 9 http://www.colymp.com/ mailto:lo...@colymp.com -- Attend Shape: An AT Tech Expo July 15-16. Meet us at AT Park in San Francisco, CA to explore cutting-edge tech and listen to tech luminaries present their vision of the future. This family event has something for everyone, including kids. Get more information and register today. http://sdm.link/attshape ___ Lcms-user mailing list Lcms-user@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/lcms-user
Re: [Lcms-user] Difficulty with cmsTransform in C#
Edgar, You wrote : > // create lcms inputprofile > IntPtr inputProfileH = IntPtr.Zero; >I f (biFrm.ColorContexts != null) { > byte[] inputProfile = > StreamToArray(biFrm.ColorContexts[0].OpenProfileStream()); > inputProfileH = > Basic.Lcms.NativeMethods.cmsOpenProfileFromMem(inputProfile, > (uint)inputProfile.Length); Does this code actually work for you? First of all, when creating a BitmapFrame with PreservePixelFormats the ColorContext is *always* nill!!! It does not work for me, with the JPEG files I tried. I would *love* for the ColorContext to come across as I would be able to create an ICC profile from memory, the way to do it. It is perfect! Except, it does not work. In all my testing, so far, I have NOT been able to retrieve a ColorContext (embedded ICC profile) from a JPEG image. Second question... Where does the "StreamToArray" method comes from? Best / Roger -- Attend Shape: An AT Tech Expo July 15-16. Meet us at AT Park in San Francisco, CA to explore cutting-edge tech and listen to tech luminaries present their vision of the future. This family event has something for everyone, including kids. Get more information and register today. http://sdm.link/attshape ___ Lcms-user mailing list Lcms-user@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/lcms-user
Re: [Lcms-user] Difficulty with cmsTransform in C#
> If I could develop my application strictly in C, my problems accessing > LittleCMS would be non-existent, > but I need to develop in C# :( Working with C# is not too bad! >[...] > cmsDoTransform(cmsHTRANSFORM Transform, const void * InputBuffer, > void * OutputBuffer, > cmsUInt32Number Size); > > (Not sure what the 'const' keyword in front of the first void * statement > does?) By writing 'const' Marti is telling us, that cmsDoTransform will not touch the data in InputBuffer. I.e. we can either pass a const void* or we can pass a void*. If he would had omit to write 'const' and we would have just a const void* inputBuffer we could not pass this pointer to cmsDoTransform (compiler error)... (s. http://stackoverflow.com/questions/4064286/c-const-keyword-explanation) > [DllImport(lcms2Path, CallingConvention = CallingConvention.Winapi)] > static extern void cmsDoTransform(IntPtr xform, IntPtr inputColors [in], > IntPtr outputColors [out], uint Size); > > So my question becomes how do I pass pointers to the these buffers in my new > declaration? > I read somewhere about the need to use the keyword 'unsafe' but I am not > sure. > Also read about the need to use the attributes [in] and [out] in marshalling > the data. > (The Marshalling of data is a HUGE topic in itself as I found out through my > hours of reading online) > > Ultimately, my goal is is to convert JPEG or TIFF images from one color > space to another through LittleCMS. It's not that difficult... Here is what I'm using (somehow stripped, without error handling, without cleanup...) public static class NativeMethods { [DllImport("lcms2.dll")] public static extern void cmsDoTransform( [In] IntPtr Transform, [In] byte[] InputBuffer, [Out] byte[] OutputBuffer, [In] UInt32 Size); } // We use WPF classes to read binary data of the images: // Namespace: System.Windows.Media.Imaging // Assembly: PresentationCore (in PresentationCore.dll) BitmapDecoder biDec = BitmapDecoder.Create(.) BitmapFrame biFrm = biDec.Frames[0]; PixelFormat inputFormat = biFrm.Format; uint lcmsInputFormat = 0; FormatConvertedBitmap fcb = null; // if we have an input format that we cannot use direktly in lcms // we have to create a temporary bitmap with lcms compatible format and use this instead of biFrm if (inputFormat == PixelFormats.Bgra32) { lcmsInputFormat = 0x44499; // Lcms.Format.TYPE_BGRA_8; } else if (inputFormat == PixelFormats.Bgr24) { lcmsInputFormat = 0x40419; // Lcms.Format.TYPE_BGR_8; } else { inputFormat = PixelFormats.Bgra32; // we enforce Bgra32 format lcmsInputFormat = 0x44499; // Lcms.Format.TYPE_BGRA_8; fcb = new FormatConvertedBitmap(biFrm, inputFormat, null, 0); if (fcb == null) { throw new Exception("Unable to create FormatConvertedBitmap"); } } // create lcms inputprofile IntPtr inputProfileH = IntPtr.Zero; if (biFrm.ColorContexts != null) { byte[] inputProfile = StreamToArray(biFrm.ColorContexts[0].OpenProfileStream()); inputProfileH = Basic.Lcms.NativeMethods.cmsOpenProfileFromMem(inputProfile, (uint)inputProfile.Length); } else { inputProfileH = Basic.Lcms.NativeMethods.cmsCreate_sRGBProfile(); } IntPtr outputProfileH = .; // create your lcms output profile IntPtr lcmsTrafo = NativeMethods.cmsCreateTransform( inputProfileH , lcmsInputFormat , outputProfileH , lcmsInputFormat // output format = input format , YourRenderingIntent , 0); // copy image data to byte[] int stride = biFrm.PixelWidth * inputFormat.BitsPerPixel / 8; Byte[] inputBitmapData = new Byte[stride * biFrm.PixelHeight]; if (fcb == null) { // we copy pixel data from original image biFrm.CopyPixels(inputBitmapData, stride, 0); } else {// we copy pixel data from format converted bitmap fcb.CopyPixels(inputBitmapData, stride, 0); } // I have to copy the whole data, to get a copy of alpha channel (lcms 2.7) Byte[] outputBitmapData = inputBitmapData.Clone() as Byte[]; NativeMethods.cmsDoTransform(lcmsTrafo, inputBitmapData, outputBitmapData, (uint)(biFrm.PixelWidth * biFrm.PixelHeight)); // create a new image, based on outputBitmapData: BitmapSource ccb = BitmapSource.Create( biFrm.PixelWidth, biFrm.PixelHeight , biFrm.DpiX, biFrm.DpiY , inputFormat , null , outputBitmapData , stride); // create e.g. .png file: BitmapEncoder biEnc = new PngBitmapEncoder(); biEnc.Frames.Add(BitmapFrame.Create(ccb)); biEnc.Save(YourOutputStream); -- lakeBits Inh. Edgar Loser Haydnstr. 25 78464 Konstanz Tel 0049 7531 5844154 0 Fax 0049 7531 5844154 9 http://www.colymp.com/ mailto:lo...@colymp.com
Re: [Lcms-user] Difficulty with cmsTransform in C#
If I could develop my application strictly in C, my problems accessing LittleCMS would be non-existent, but I need to develop in C# :( I am seeking help with re-coding the cmsDoTransform declaration. Right now, I use this : [DllImport(@lcmsPath, CallingConvention = CallingConvention.Winapi)] static extern void cmsDoTransform( IntPtr xform, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2), In] double[] inputColors, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3), Out] double[] outputColors, uint Size); In code, I use this : double[] input = { 0.5, 0.5, 0.5, 0 }; double[] output = { 0, 0, 0, 0 }; cmsDoTransform(xform, input, output, 1); As you can see, I pass individual RGB values [in], recovering CMYK values [out]. The cmsCreateTransform looks like this : IntPtr xform = cmsCreateTransform(hSRGB, TYPE_RGB_DBL, hDestination, TYPE_CMYK_DBL, INTENT_RELATIVE_COLORIMETRIC, 0); Works perfect. But now, I need to pass 'pixels' (to convert bitmap images) values instead of individual device values. Obviously, I need to modify the pinvoke declaration to accommodate the difference in data type. I am no C# specialist (maybe someday?) but I read that I may not need very meticulous marshalling of data between my C# and lcms.dll. So I am looking for a way to rewrite the declaration to accommodate more than just 'double'. In C, the original cmsDoTransform function require a Handle to the Transform (another pointer), pointers to an input and output buffers, and the size of the buffer themselves : cmsDoTransform(cmsHTRANSFORM Transform, const void * InputBuffer, void * OutputBuffer, cmsUInt32Number Size); (Not sure what the 'const' keyword in front of the first void * statement does?) So my first awkward/intuitive shot at rewriting the function in C# call looks like this : [DllImport(lcms2Path, CallingConvention = CallingConvention.Winapi)] static extern void cmsDoTransform(IntPtr xform, IntPtr inputColors [in], IntPtr outputColors [out], uint Size); I have not tried running this code yet but I have been reading quite a bit about pointers and how they have a fixed size, no matter the type of data they point to. So my question becomes how do I pass pointers to the these buffers in my new declaration? I read somewhere about the need to use the keyword 'unsafe' but I am not sure. Also read about the need to use the attributes [in] and [out] in marshalling the data. (The Marshalling of data is a HUGE topic in itself as I found out through my hours of reading online) Ultimately, my goal is is to convert JPEG or TIFF images from one color space to another through LittleCMS. Thank you so much in advance for your kind help. / Roger Breton -- Attend Shape: An AT Tech Expo July 15-16. Meet us at AT Park in San Francisco, CA to explore cutting-edge tech and listen to tech luminaries present their vision of the future. This family event has something for everyone, including kids. Get more information and register today. http://sdm.link/attshape ___ Lcms-user mailing list Lcms-user@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/lcms-user
Re: [Lcms-user] Difficulty with cmsTransform in C#
Did you declare input[] and output[] as volatile? (s. https://msdn.microsoft.com/de-de/library/x13ttww7.aspx) Edgar Am 16.06.2016 um 21:25 schrieb Roger Breton: > Tengo una pequena problema... > > I need to convert 400 RGB values to Lab using a monitor profile. > > I use the following C# code : > > string Source = "Monitor.icm"; > IntPtr hSource = cmsOpenProfileFromFile(Source, "r"); > > xform = cmsCreateTransform(hSource, TYPE_RGB_DBL, hLab2, TYPE_Lab_DBL, > INTENT_ABSOLUTE_COLORIMETRIC, 0); > > for (int i = 0; i < 400; i++) > { > input[0] = R[i]; > input[1] = G[i]; > input[2] = B[i]; > >cmsDoTransform(xform, input, output, 1); > >L = output[0]; >a = output[1]; >b = output[2]; > } > > First time through the loop I get valid Lab results. > But subsequent passage through the loop always return the same Lab values? > The input[] values do change as expected. > > When I use this code outside of a loop, it works perfect. > > / Roger Breton > > > -- > What NetFlow Analyzer can do for you? Monitors network bandwidth and traffic > patterns at an interface-level. Reveals which users, apps, and protocols are > consuming the most bandwidth. Provides multi-vendor support for NetFlow, > J-Flow, sFlow and other flows. Make informed decisions using capacity planning > reports. http://sdm.link/zohomanageengine > ___ > Lcms-user mailing list > Lcms-user@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/lcms-user > -- lakeBits Inh. Edgar Loser Haydnstr. 25 78464 Konstanz Tel 0049 7531 5844154 0 Fax 0049 7531 5844154 9 http://www.colymp.com/ mailto:lo...@colymp.com -- What NetFlow Analyzer can do for you? Monitors network bandwidth and traffic patterns at an interface-level. Reveals which users, apps, and protocols are consuming the most bandwidth. Provides multi-vendor support for NetFlow, J-Flow, sFlow and other flows. Make informed decisions using capacity planning reports. http://sdm.link/zohomanageengine ___ Lcms-user mailing list Lcms-user@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/lcms-user
[Lcms-user] Difficulty with cmsTransform in C#
Tengo una pequena problema... I need to convert 400 RGB values to Lab using a monitor profile. I use the following C# code : string Source = "Monitor.icm"; IntPtr hSource = cmsOpenProfileFromFile(Source, "r"); xform = cmsCreateTransform(hSource, TYPE_RGB_DBL, hLab2, TYPE_Lab_DBL, INTENT_ABSOLUTE_COLORIMETRIC, 0); for (int i = 0; i < 400; i++) { input[0] = R[i]; input[1] = G[i]; input[2] = B[i]; cmsDoTransform(xform, input, output, 1); L = output[0]; a = output[1]; b = output[2]; } First time through the loop I get valid Lab results. But subsequent passage through the loop always return the same Lab values? The input[] values do change as expected. When I use this code outside of a loop, it works perfect. / Roger Breton -- What NetFlow Analyzer can do for you? Monitors network bandwidth and traffic patterns at an interface-level. Reveals which users, apps, and protocols are consuming the most bandwidth. Provides multi-vendor support for NetFlow, J-Flow, sFlow and other flows. Make informed decisions using capacity planning reports. http://sdm.link/zohomanageengine ___ Lcms-user mailing list Lcms-user@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/lcms-user