image conversion - c#

I need to convert a RGB (jpg) grayscale CMYK using only to black channel (K).
I'm trying to do this with imageglue, but the result is not what i'm looking for since it converts the grays using the C,M and Y channel and leaves the black channel to 0%.
What I need is if anyone has experience in using any other library/api in .net that could work?

I would start by looking at the ColorConvertedBitmap class in WPF. Here is a link to the docs and a basic example:
http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.colorconvertedbitmap(VS.85).aspx

Have you triedAForge.Net?
There is also ImageMagick, a c++ framework for image processing, with a .net wrapper (google for MagickNet)

Her is RGB to/from CMYK question which is related this one:
How is 1-bit bitmap data converted to 8bit (24bpp)?

I found The bitmap transform classes useful when trying to do some image format conversions but ... CYMK is one of the most complicated conversions you can tackle because there is more than one way to represent some colours. In particular equal CYM percentages give you shades of grey which are equivalent to the same percentage of K. Printers often use undercolour removal/transformation which normalises CYMK so that the a large common percentage is taken from CYM and transfered to the K. This is suppose to give purer blacks and grey tones. So even if you have a greyscale image represented using nothing but CYM with a zero black channel it could still print using nothing but K when you get it to a printer using undercolour removal.

Related

Subsampling compression detection

I have a new requirement within my application. All images needs to be in RGB format (no CMYK) and the subsampling should be deactivated. I have managed to check the CMYK check, but struggling with the subsampling requirement.
Now I have to implement a method like this:
private bool IsSubsamplingActivated(byte[] imageContent)
{
// code goes here
}
Unfortunately I really don't know how to solve that issue :-(
Could you guys give me a hint how to solve this? External library? Some dotNET classes?
1) A color JPEG is almost always in YCbCr format.
2) If you want to check to see if the image uses subsampling, you need to scan for an SOF marker (there are several types). The sampling values are in that market. If the X sampling values for all scans are the same and the y sampling values are all the same, there is no sub sampling.

Writing a HLSL shader for rescaling floating point textures

When using HalfSingle/Single format for my Texture2D, XNA complains that sampling must be set to PointClamp, and this makes my texture look jagged. I am actually using this to pass depth data to the shader, so I am trying to get a better dynamic range than simply using RGBA grayscale values.
If I use Color or Bgra, then I basically only have 255 levels. If I encode the depth values as color pixels, then I can enable antialiasing, but then it doesn't work correcly because the sampler treats each byte/nibble separately when lerping.
Question:
Is there a way to tell HLSL to sample my floating point texture using anti-aliasing filters, or do I need to write the shader myself?
It turns out there are two ways to solve this:
Pack .NET 32-bit floats into a RGBA using my own conversion methods, or
Use SurfaceFormat.Rg32 to pack two 16-bit floats into RGBA (this format supports texture filtering).
I went for the first method.

16bit greyscale image to heatmap

I'm working on a scientific imaging software for my university, and I've encountered a major problem. Scientific camera (Apogee Alta U57) at my lab provides images as 16bpp array - it's 0-65535 values per pixel! We want to keep this range, but in fact we can't display them on monitor (0-255 grayscale range). So I found a way to resolve this problem - simply to make use of colors, and to display whole image as a heatmap (from black, blue, through green and red, to pure white).
I mean something like this - Example heatmap image I want to achieve
My only question is: How to efficiently convert 16bpp array of pixel values to complete heatmap bitmap in c#? Are there any libraries for doing that? If not, how do I achieve that using .NET resources?
My idea was to create function that maps 65536 values into (255 R, 255G, 255B), but it's a tough job - especially without using HSV model.
I would be much obliged for any help provided!
Your question consist of several parts:
reading in the 16 bit pixel data values
mapping them to 24 bit rgb colors
writing them out to an image file
I'll skip part one and three and give you a few ideas about part 2.
It is in fact harder than it seems. A unique mapping that doesn't lose any information is simple, in fact trivial, just a little bit shifting will do.
But you also want the result to work visually, meaning not so much is should be visually appealing but should make sense to a human eye. so we need a mapping that has a credible yet large enough gradient.
For this you should experiment a little. I suggest to make use of the LinearGradientBrush, as I show here. Have a look at the interpolateColors function! It uses only 6 colors in the example, way to few for your case!
You should pick many more; you may need to go through the color space in a spiral..
The trick for you will be to choose both nice and enough stop colors to create a 64k large set of unique colors, best going from blueish to reddish..
You will need to test the result for uniqueness; in fact you may want to create a pair of Dictionary and Dictionary for the mappings..

Color Image Quantization in .NET

I want to reduce the number of unique colors of a bitmap in c#.
The reason I want to do this is that an image which is initially created with three color but due to many factors (including compression) has now more than three colors (i.e neighbour pixels has affected each other)
Any idea of how to do that?
The solution maybe something to convert the whole bitmap from RGB to Indexed color system or some function that can be applied to a single pixel.
Any GDI+ or Emgu (opencv) solutions are good for me.
Check out nQuant at http://nquant.codeplex.com. This yields much higher quality than the code in the MSDN article that Magnus references. It also takes the Alpha layer into consideration while the msdn article only evaluates RGB. Source code is available and there is an accompanying blog post that discusses the code and algorithm in detail.
There is an article on msdn called Optimizing Color Quantization for ASP.NET Images that might help you, it has good example code.
I've just stumbled upon this question and though it is quite an old one maybe it still can be useful to mention that last year I made my Drawing Libraries public (NuGet), which happens to support quantization, too.
Note: As the question contains the GDI+ tag the examples below go for the Bitmap type but the library supports completely managed bitmap data manipulation as well, which supports all pixel formats on every platform (see BitmapDataFactory and BitmapDataExtensions classes).
If you have a Bitmap instance, quantization is as simple as follows:
using System.Drawing;
using System.Drawing.Imaging;
using KGySoft.Drawing;
using KGySoft.Drawing.Imaging;
// [...]
IQuantizer quantizer = PredefinedColorsQuantizer.FromCustomPalette(myColors, backColor);
// getting a quantized clone of a Bitmap with arbitrary PixelFormat:
Bitmap quantizedBitmap = originalBitmap.ConvertPixelFormat(PixelFormat.Format8bppIndexed,
quantizer);
// or, you can quantize a Bitmap in-place (which does not change PixelFormat):
originalBitmap.Quantize(quantizer);
Original bitmap:
Quantized bitmap using a custom 8 colors palette and silver background (which appears white with this palette):
In the example above I used the FromCustomPalette method but there are many other predefined quantizers available in the PredefinedColorsQuantizer and OptimizedPaletteQuantizer classes (see the members for image and code examples).
And since reducing colors may severely affect the quality of the result you might want to use dithering with the quantization:
IQuantizer quantizer = PredefinedColorsQuantizer.FromCustomPalette(myColors, backColor);
IDitherer = OrderedDitherer.Bayer8x8;
// ConvertPixelFormat can be used also with a ditherer
Bitmap quantizedBitmap = originalBitmap.ConvertPixelFormat(PixelFormat.Format8bppIndexed,
quantizer, ditherer);
// Or use the Dither extension method to change the Bitmap in-place
originalBitmap.Dither(quantizer, ditherer);
The difference is quite significant, even though the same colors are used:
You will find a lot of image examples in the description of the OrderedDitherer, ErrorDiffusionDitherer, RandomNoiseDitherer and InterleavedGradientNoiseDitherer classes.
To try the possible built-in quantizers and ditherers in an application you can use my Imaging Tools app. In the link you can find also its source, which provides a bit more advanced examples with cancellable async conversions with progress tracking, etc.

Convert BitmapImage to grayscale, and keep alpha channel

I'm having an issue with converting a BitmapImage (WPF) to grayscale, whilst keeping the alpha channel. The source image is a PNG.
The MSDN article here works fine, but it removes the alpha channel.
Is there any quick and effective way of converting a BitmapImage to a grayscale?
You should have a look at image transformation using matrices.
In particular, this article describes how to convert a bitmap to grayscale using a ColorMatrix. (It is written in VB.NET, but it should be easy enough to translate to C#).
I haven't tested if it works with the alpha channel, but I'd say it's worth a try, and it definitely is a quick and effective way of modifying bitmaps.
It really depends upon what your source PixelFormat is. Assuming your source is PixelFormats.Bgra32 and that you want to go to grayscale, you might consider using a target pixel format of PixelFormats.Gray16. However, Gray16 doesn't support alpha. It just has 65,535 graduations between black and white, inclusive.
You have a few options. One is to stay with Bgra32 and just set the blue, green and red channels to the same value. That way you can keep the alpha channel. This may be wasteful if you don't require an 8-bit alpha channel (for differing levels of alpha per pixel).
Another option is to use an indexed pixel format such as PixelFormats.Indexed8 and create a palette that contains the gray colours you need and alpha values. If you don't need to blend alpha, you could make the palette colour at position zero be completely transparent (an alpha of zero) and then progress solid black in index 1 through to white in 255.
if relying on API calls fails. You can always try the 'do it yourself' approach: Just get access to the RGBA bytes of the picture, and for every RGBA replace it with MMMA, where M = (R+G+B)/3;
If you want it more perfect, you should add weights to the contribution of the RGB components. I believe your eye is more receptive for green, and as such that value should weigh more.
While not exactly quick and easy, a ShaderEffect would do the job and perform quite well. I've done it myself, and it works great. This article references how to do it and has source associated. I've not used his source, so I can't vouch for it. If you run into problems, ask, and I may be able to post some of my code.
Not every day you get to use HLSL in your LOB app. :)

Categories