I have CMYK color values ( 0, 0.58 ,1 ,0 ) . Now I have to convert to its Integer equivalent using C# . I think it is possible using Bitwise operator but not sure .
Kindly assist me how can achieve same .
Thanks,
Pawan
Try this:
float c = 0.0;
float y = 0.58;
float m = 1.0;
float k = 0.0;
uint intColor = (uint)(c * 255) << 24;
intColor += (uint)(y * 255) << 16;
intColor += (uint)(m * 255) << 8;
intColor += (uint)(k * 255) << 0;
Here intColor will be a 32-bit unsigned integer, containing the byte value of the C, Y, M and K components of the color, respectively. To convert back to the components from the integer, simply invert all the operations and their order:
float c = ((intColor & 0xFF000000) >> 24) / 255.0f;
float y = ((intColor & 0x00FF0000) >> 16) / 255.0f;
float m = ((intColor & 0x0000FF00) >> 8) / 255.0f;
float k = ((intColor & 0x000000FF) >> 0) / 255.0f;
Related
Why is the first piece of code much slower than the second?
public long Gen(int mod)
{
long a, b = 0x7fffffffffffffff - mod;
do
{
a = (long)(Gen() >> 1);
} while (a > b);
return a % mod;
}
public long Gen(int mod)
{
long a, b = 0x7fffffffffffffff - mod;
do
{
a = (long)(Gen() >> 1);
} while (a > b);
return a % 12345;
}
The gen function is a 64 bit unsigned PRNG (see below).
The problem is that the first piece of code is so much slower, that using a variable to calculate the modulus basically adds 3x the amount of time it takes to calculate just the random numbers! To add to the mystery, when you remove the loop, and calculate the modulus using a variable, the speed is similar to the second piece of code.
Something weird is going on around here, because you can't tell me that a modulus using a variable is several times as slow as this:
public ulong Gen()
{
counter = (counter + 1) & 3;
if (counter == 0)
{
state[0]++;
ulong x0 = state[0];
ulong x1 = state[1];
ulong x2 = state[2];
ulong x3 = state[3];
for (int i = 0; i < 2; i++)
{
x0 += x1; x1 ^= ((x0 << 32) | (x0 >> (64 - 32)));
x1 += x0; x0 ^= ((x1 << 32) | (x1 >> (64 - 32)));
x2 += x3; x3 ^= ((x2 << 32) | (x2 >> (64 - 32)));
x3 += x2; x2 ^= ((x3 << 32) | (x3 >> (64 - 32)));
x0 += x2; x2 ^= ((x0 << 27) | (x0 >> (64 - 27)));
x2 += x0; x0 ^= ((x2 << 27) | (x2 >> (64 - 27)));
x1 += x3; x3 ^= ((x1 << 27) | (x1 >> (64 - 27)));
x3 += x1; x1 ^= ((x3 << 27) | (x3 >> (64 - 27)));
x0 += x3; x3 ^= ((x0 << 11) | (x0 >> (64 - 11)));
x3 += x0; x0 ^= ((x3 << 11) | (x3 >> (64 - 11)));
x1 += x2; x2 ^= ((x1 << 11) | (x1 >> (64 - 11)));
x2 += x1; x1 ^= ((x2 << 11) | (x2 >> (64 - 11)));
}
block[0] = x0;
block[1] = x1;
block[2] = x2;
block[3] = x3;
}
return block[counter];
}
Minimal reproducible version as requested:
using System;
using System.Diagnostics;
class Program
{
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
Arx rng = new Arx();
long a = 0;
// constant = fast
sw.Start();
for (int i = 0; i < 10000000; i++)
{
a += rng.GenConstant(123);
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
Console.WriteLine("{0:x16}", a);
sw.Reset();
// no loop = fast
sw.Start();
for (int i = 0; i < 10000000; i++)
{
a += rng.GenNoLoop(123);
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
Console.WriteLine("{0:x16}", a);
sw.Reset();
// modulus variable = slow
sw.Start();
for (int i = 0; i < 10000000; i++)
{
a += rng.GenVariable(123);
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
Console.WriteLine("{0:x16}", a);
sw.Reset();
}
}
class Arx
{
static public ulong[] state = new ulong[4];
static public ulong[] outBlock = new ulong[4];
static int counter = -1;
public Arx(ulong seed = 0)
{
if (seed == 0)
state[1] = (ulong)DateTime.UtcNow.Ticks;
else
state[1] = seed;
}
public ulong Gen()
{
counter = (counter + 1) & 3;
if (counter == 0)
{
state[0]++;
ulong x0 = state[0];
ulong x1 = state[1];
ulong x2 = state[2];
ulong x3 = state[3];
for (int i = 0; i < 2; i++)
{
x0 += x1; x1 ^= ((x0 << 32) | (x0 >> (64 - 32)));
x1 += x0; x0 ^= ((x1 << 32) | (x1 >> (64 - 32)));
x2 += x3; x3 ^= ((x2 << 32) | (x2 >> (64 - 32)));
x3 += x2; x2 ^= ((x3 << 32) | (x3 >> (64 - 32)));
x0 += x2; x2 ^= ((x0 << 27) | (x0 >> (64 - 27)));
x2 += x0; x0 ^= ((x2 << 27) | (x2 >> (64 - 27)));
x1 += x3; x3 ^= ((x1 << 27) | (x1 >> (64 - 27)));
x3 += x1; x1 ^= ((x3 << 27) | (x3 >> (64 - 27)));
x0 += x3; x3 ^= ((x0 << 11) | (x0 >> (64 - 11)));
x3 += x0; x0 ^= ((x3 << 11) | (x3 >> (64 - 11)));
x1 += x2; x2 ^= ((x1 << 11) | (x1 >> (64 - 11)));
x2 += x1; x1 ^= ((x2 << 11) | (x2 >> (64 - 11)));
}
outBlock[0] = x0;
outBlock[1] = x1;
outBlock[2] = x2;
outBlock[3] = x3;
}
return outBlock[counter];
}
public long GenConstant(int mod)
{
long a, b = 0x7fffffffffffffff - mod;
do
{
a = (long)(Gen() >> 1);
} while (a > b);
return a % 12345;
}
public long GenVariable(int mod)
{
long a, b = 0x7fffffffffffffff - mod;
do
{
a = (long)(Gen() >> 1);
} while (a > b);
return a % mod;
}
public long GenNoLoop(int mod)
{
long a = (long)(Gen() >> 1);
return a % mod;
}
}
This is an optimizer issue.
First no doubt that using a variable is slower than using a constant because loading a variable needs more time.
But when you remove the loop part, the methods become simple and the optimizer makes them inline. And notice when the method is inline the expression a % mod from rng.GenNoLoop(123) can be recognized as constant. So they are identical now.
To restore the unoptimized state, you need pass a real variable to GenNoLoop.
static int mod = 123;
static void Main(string[] args)
{
rng.GenNoLoop(mod);
}
Another choice is force the method no inline
[MethodImpl(MethodImplOptions.NoInlining)]
public long GenNoLoop(int mod)
I used this code to test the speed of the two methods:
void Main()
{
Stopwatch sw = new Stopwatch();
var ts1 = TimeSpan.Zero;
var ts2 = TimeSpan.Zero;
Arx rng = new Arx();
for (var x = 0; x < 1000; x++)
{
long a = 0;
sw.Start();
for (int i = 0; i < 100000; i++)
{
a += rng.GenVariable(123);
}
sw.Stop();
ts1 += sw.Elapsed;
sw.Reset();
a = 0;
sw.Start();
for (int i = 0; i < 100000; i++)
{
a += rng.GenConstant(123);
}
sw.Stop();
ts2 += sw.Elapsed;
sw.Reset();
}
ts1.TotalMilliseconds.Dump();
ts2.TotalMilliseconds.Dump();
}
I got 2890.5391 & 2805.8824 milliseconds out respectively. The variable version is only 3% slower. There's not a big difference.
I am trying to convert a byte (6-bit RGB) into an appropriate System.Drawing.Color structure. My byte looks like this:
UNUSED
---------------------------------
| 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 |
---------------------------------
R1 R2 G1 G2 B1 B2
So given this:
byte color = 51;
How do I convert this into the closest color match that I can pass into Color.FromArgb? I know there is probably some math formula involved in this, but I don't know what it is. I also need to go the other way around. I would need to convert a Color into a 6-bit byte. Please point me in the right direction for this.
You would just need to multiply your RGB values by 64.
int r = color >> 4;
int g = (color >> 2) & 0x3;
int b = color & 0x3;
Color frameworkColor = Color.FromArgb(r * 64, g * 64, b * 64);
And likewise, to go back to your 6-bit color:
int r = frameworkColor.R / 64;
int g = frameworkColor.G / 64;
int b = frameworkColor.B / 64;
int color = (r << 4) | (g << 2) | b;
You would isloate the components:
int r = color >> 4;
int g = (color >> 2) & 3
int b = color & 3;
Then you can scale the 0..3 values to the 0..255 range by multiplying by 85:
Color c = Color.FromArgb(255, r * 85, g * 85, b * 85);
To go the other way you divide by 85 and put them together in a byte:
int r = c.R / 85;
int g = c.G / 85;
int b = c.B / 85;
byte color = (byte)((r << 4) + (g << 2) + b);
I would multiply by 85 rather than 64 so that 00 is mapped to 0 while 11 is mapped to 255.
Color.FromArgb(255, 85 * ((color >> 4) & 3), 85 * ((color >> 2) & 3), 85 * (color & 3))
I have byte array with yuv420 data.
byte[] yuv420;//yuv data
How can I convert this to an Image<Bgr, byte>?
I found a math formula to convert to RGB and then to Image<Bgr, byte> but it is very slow. Is there a way to convert it faster?
There is a class in Emgu for converting
COLOR_CONVERSION(enum CV_YUV2RGB Convert YUV color to RGB)
but I can not understand how use this class. Can anyone help?
static Bitmap ConvertYUV2RGB(byte[] yuvFrame, byte[] rgbFrame, int width, int height)
{
int uIndex = width * height;
int vIndex = uIndex + ((width * height) >> 2);
int gIndex = width * height;
int bIndex = gIndex * 2;
int temp = 0;
//图片为pic1,RGB颜色的二进制数据转换得的int r,g,b;
Bitmap bm = new Bitmap(width, height);
int r = 0;
int g = 0;
int b = 0;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
// R分量
temp = (int)(yuvFrame[y * width + x] + (yuvFrame[vIndex + (y / 2) * (width / 2) + x / 2] - 128) * YUV2RGB_CONVERT_MATRIX[0, 2]);
rgbFrame[y * width + x] = (byte)(temp < 0 ? 0 : (temp > 255 ? 255 : temp));
// G分量
temp = (int)(yuvFrame[y * width + x] + (yuvFrame[uIndex + (y / 2) * (width / 2) + x / 2] - 128) * YUV2RGB_CONVERT_MATRIX[1, 1] + (yuvFrame[vIndex + (y / 2) * (width / 2) + x / 2] - 128) * YUV2RGB_CONVERT_MATRIX[1, 2]);
rgbFrame[gIndex + y * width + x] = (byte)(temp < 0 ? 0 : (temp > 255 ? 255 : temp));
// B分量
temp = (int)(yuvFrame[y * width + x] + (yuvFrame[uIndex + (y / 2) * (width / 2) + x / 2] - 128) * YUV2RGB_CONVERT_MATRIX[2, 1]);
rgbFrame[bIndex + y * width + x] = (byte)(temp < 0 ? 0 : (temp > 255 ? 255 : temp));
Color c = Color.FromArgb(rgbFrame[y * width + x], rgbFrame[gIndex + y * width + x], rgbFrame[bIndex + y * width + x]);
bm.SetPixel(x, y, c);
}
}
return bm;
}
static double[,] YUV2RGB_CONVERT_MATRIX = new double[3, 3] { { 1, 0, 1.4022 }, { 1, -0.3456, -0.7145 }, { 1, 1.771, 0 } };
static byte clamp(float input)
{
if (input < 0) input = 0;
if (input > 255) input = 255;
return (byte)Math.Abs(input);
}
You are in luck because i solved exactly this issue before. There are some links in the code for more info.
In general always try to use pointers when doing image processing and avoid calling functions in nested loops. In my code the size comparison is by far the slowest part but unfortunately it is needed (try switching it off using the pre-processor switch).
I have to say though that in the end i never used this function because it was just too slow, i opted to implement it in c++ and call it from c# using p invoke.
private static unsafe void YUV2RGBManaged(byte[] YUVData, byte[] RGBData, int width, int height)
{
//returned pixel format is 2yuv - i.e. luminance, y, is represented for every pixel and the u and v are alternated
//like this (where Cb = u , Cr = y)
//Y0 Cb Y1 Cr Y2 Cb Y3
/*http://msdn.microsoft.com/en-us/library/ms893078.aspx
*
* C = Y - 16
D = U - 128
E = V - 128
R = clip(( 298 * C + 409 * E + 128) >> 8)
G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8)
B = clip(( 298 * C + 516 * D + 128) >> 8)
* here are a whole bunch more formats for doing this...
* http://stackoverflow.com/questions/3943779/converting-to-yuv-ycbcr-colour-space-many-versions
*/
fixed(byte* pRGBs = RGBData, pYUVs = YUVData)
{
for (int r = 0; r < height; r++)
{
byte* pRGB = pRGBs + r * width * 3;
byte* pYUV = pYUVs + r * width * 2;
//process two pixels at a time
for (int c = 0; c < width; c += 2)
{
int C1 = pYUV[1] - 16;
int C2 = pYUV[3] - 16;
int D = pYUV[2] - 128;
int E = pYUV[0] - 128;
int R1 = (298 * C1 + 409 * E + 128) >> 8;
int G1 = (298 * C1 - 100 * D - 208 * E + 128) >> 8;
int B1 = (298 * C1 + 516 * D + 128) >> 8;
int R2 = (298 * C2 + 409 * E + 128) >> 8;
int G2 = (298 * C2 - 100 * D - 208 * E + 128) >> 8;
int B2 = (298 * C2 + 516 * D + 128) >> 8;
#if true
//check for overflow
//unsurprisingly this takes the bulk of the time.
pRGB[0] = (byte)(R1 < 0 ? 0 : R1 > 255 ? 255 : R1);
pRGB[1] = (byte)(G1 < 0 ? 0 : G1 > 255 ? 255 : G1);
pRGB[2] = (byte)(B1 < 0 ? 0 : B1 > 255 ? 255 : B1);
pRGB[3] = (byte)(R2 < 0 ? 0 : R2 > 255 ? 255 : R2);
pRGB[4] = (byte)(G2 < 0 ? 0 : G2 > 255 ? 255 : G2);
pRGB[5] = (byte)(B2 < 0 ? 0 : B2 > 255 ? 255 : B2);
#else
pRGB[0] = (byte)(R1);
pRGB[1] = (byte)(G1);
pRGB[2] = (byte)(B1);
pRGB[3] = (byte)(R2);
pRGB[4] = (byte)(G2);
pRGB[5] = (byte)(B2);
#endif
pRGB += 6;
pYUV += 4;
}
}
}
}
and incase you decide to implement this in c++
void YUV2RGB(void *yuvDataIn,void *rgbDataOut, int w, int h, int outNCh)
{
const int ch2 = 2 * outNCh;
unsigned char* pRGBs = (unsigned char*)rgbDataOut;
unsigned char* pYUVs = (unsigned char*)yuvDataIn;
for (int r = 0; r < h; r++)
{
unsigned char* pRGB = pRGBs + r * w * outNCh;
unsigned char* pYUV = pYUVs + r * w * 2;
//process two pixels at a time
for (int c = 0; c < w; c += 2)
{
int C1 = pYUV[1] - 16;
int C2 = pYUV[3] - 16;
int D = pYUV[2] - 128;
int E = pYUV[0] - 128;
int R1 = (298 * C1 + 409 * E + 128) >> 8;
int G1 = (298 * C1 - 100 * D - 208 * E + 128) >> 8;
int B1 = (298 * C1 + 516 * D + 128) >> 8;
int R2 = (298 * C2 + 409 * E + 128) >> 8;
int G2 = (298 * C2 - 100 * D - 208 * E + 128) >> 8;
int B2 = (298 * C2 + 516 * D + 128) >> 8;
//unsurprisingly this takes the bulk of the time.
pRGB[0] = (unsigned char)(R1 < 0 ? 0 : R1 > 255 ? 255 : R1);
pRGB[1] = (unsigned char)(G1 < 0 ? 0 : G1 > 255 ? 255 : G1);
pRGB[2] = (unsigned char)(B1 < 0 ? 0 : B1 > 255 ? 255 : B1);
pRGB[3] = (unsigned char)(R2 < 0 ? 0 : R2 > 255 ? 255 : R2);
pRGB[4] = (unsigned char)(G2 < 0 ? 0 : G2 > 255 ? 255 : G2);
pRGB[5] = (unsigned char)(B2 < 0 ? 0 : B2 > 255 ? 255 : B2);
pRGB += ch2;
pYUV += 4;
}
}
}
The biggest offender in that code is the use of Bitmap.SetPixel; it is very slow to do this on every inner loop iteration. Instead, use a byte array to store your RGB values and once it is filled, copy it into a bitmap as a single step.
Secondly, understand that y, u and v are bytes, and so can only have 256 possible values. It is therefore perfectly feasible to build lookup tables for r, g and b, so you don't have to perform any computations in your inner loop.
Finally, if you really want performance you'll have to write this in C++ using pointer arithmetic and compile with all optimizations on. This loop is also a very good candidate for a parallel for since every iteration operates on independent data. It is also possible to optimize this further with SSE intrinsics, converting several pixels per instruction.
Hopefully this should get you started.
I just found an old piece of code which might help you. YUV conversion using OpenCVSharp
(disclaimer: i removed some unnecessary code and haven't tested this!)
IplImage yuvImage = new IplImage(w, h, BitDepth.U8, 3);
IplImage rgbImage = new IplImage(w, h, BitDepth.U8, 3);
Cv.CvtColor(yuvImage, rgbImage, ColorConversion.CrCbToBgr);
to answer your other question - to converting byte[] to a Bitmap use this
int w= 100;
int h = 200;
int ch = 3;
byte[] imageData = new byte[w*h*ch]; //you image data here
Bitmap bitmap = new Bitmap(w,h,PixelFormat.Format24bppRgb);
BitmapData bmData = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
IntPtr pNative = bmData.Scan0;
Marshal.Copy(imageData,0,pNative,w*h*ch);
bitmap.UnlockBits(bmData);
One faster mode. Two mutiplication and two add less per pixel:
private static unsafe void YUV2RGBManaged(byte[] YUVData, byte[] RGBData, int width, int height)
{
//returned pixel format is 2yuv - i.e. luminance, y, is represented for every pixel and the u and v are alternated
//like this (where Cb = u , Cr = y)
//Y0 Cb Y1 Cr Y2 Cb Y3
/*http://msdn.microsoft.com/en-us/library/ms893078.aspx
*
C = 298 * (Y - 16) + 128
D = U - 128
E = V - 128
R = clip(( C + 409 * E) >> 8)
G = clip(( C - 100 * D - 208 * E) >> 8)
B = clip(( C + 516 * D ) >> 8)
* here are a whole bunch more formats for doing this...
* http://stackoverflow.com/questions/3943779/converting-to-yuv-ycbcr-colour-space-many-versions
*/
fixed(byte* pRGBs = RGBData, pYUVs = YUVData)
{
for (int r = 0; r < height; r++)
{
byte* pRGB = pRGBs + r * width * 3;
byte* pYUV = pYUVs + r * width * 2;
//process two pixels at a time
for (int c = 0; c < width; c += 2)
{
int C1 = 298 * (pYUV[1] - 16) + 128;
int C2 = 298 * (pYUV[3] - 16) + 128;
int D = pYUV[2] - 128;
int E = pYUV[0] - 128;
int R1 = (C1 + 409 * E) >> 8;
int G1 = (C1 - 100 * D - 208 * E) >> 8;
int B1 = (C1 + 516 * D) >> 8;
int R2 = (C2 + 409 * E) >> 8;
int G2 = (C2 - 100 * D - 208 * E) >> 8;
int B2 = (298 * C2 + 516 * D) >> 8;
//check for overflow
//unsurprisingly this takes the bulk of the time.
pRGB[0] = (byte)(R1 < 0 ? 0 : R1 > 255 ? 255 : R1);
pRGB[1] = (byte)(G1 < 0 ? 0 : G1 > 255 ? 255 : G1);
pRGB[2] = (byte)(B1 < 0 ? 0 : B1 > 255 ? 255 : B1);
pRGB[3] = (byte)(R2 < 0 ? 0 : R2 > 255 ? 255 : R2);
pRGB[4] = (byte)(G2 < 0 ? 0 : G2 > 255 ? 255 : G2);
pRGB[5] = (byte)(B2 < 0 ? 0 : B2 > 255 ? 255 : B2);
pRGB += 6;
pYUV += 4;
}
}
}
}
I see this hakmem algorithm:
int pop(unsigned x) {
unsigned n;
n = (x >> 1) & 0x77777777;
x = x - n;
n = (n >> 1) & 0x77777777;
x = x - n;
n = (n >> 1) & 0x77777777;
x = x - n;
x = (x + (x >> 4)) & 0x0F0F0F0F;
x = x * 0x01010101;
return x >> 24;
}
Is possible change it for a long of 64 bits?
You are calculating what is known as the "Hamming weight", which for integers means the number of binary "1" bits in the number. For binary numbers, this is also known as the "population count".
There are several ways to implement this for 64 bits.
Please see the Wiki page for details.
Here's an implementation stolen from here:
public int Pop(ulong w)
{
w -= (w >> 1) & 0x5555555555555555UL;
w = (w & 0x3333333333333333UL) + ((w >> 2) & 0x3333333333333333UL);
w = (w + (w >> 4)) & 0x0f0f0f0f0f0f0f0fUL;
return (int)((w * 0x0101010101010101UL) >> 56);
}
Hi sorry for being annoying by rephrasing my question but I am just on the point of discovering my answer.
I have an array of int composed of RGB values, I need to decompose that int array into a byte array, but it should be in BGR order.
The array of int composed of RGB values is being created like so:
pix[index++] = (255 << 24) | (red << 16) | blue;
C# code
// convert integer array representing [argb] values to byte array representing [bgr] values
private byte[] convertArray(int[] array)
{
byte[] newarray = new byte[array.Length * 3];
for (int i = 0; i < array.Length; i++)
{
newarray[i * 3] = (byte)array[i];
newarray[i * 3 + 1] = (byte)(array[i] >> 8);
newarray[i * 3 + 2] = (byte)(array[i] >> 16);
}
return newarray;
}
#define N something
unsigned char bytes[N*3];
unsigned int ints[N];
for(int i=0; i<N; i++) {
bytes[i*3] = ints[i]; // Blue
bytes[i*3+1] = ints[i] >> 8; // Green
bytes[i*3+2] = ints[i] >> 16; // Red
}
Using Linq:
pix.SelectMany(i => new byte[] {
(byte)(i >> 0),
(byte)(i >> 8),
(byte)(i >> 16),
}).ToArray();
Or
return (from i in pix
from x in new[] { 0, 8, 16 }
select (byte)(i >> x)
).ToArray();
Try to use Buffer Class
byte[] bytes = new byte[ints.Length*4];
Buffer.BlockCopy(ints, 0, bytes, 0, ints.Length * 4);
r = (pix[index] >> 16) & 0xFF
the rest is similar, just change 16 to 8 or 24.