4
\$\begingroup\$

I found a Go language code to do RGB to YCbCr conversion from here! I ported it to Java:

private byte[] generateColorBar(int width,int height) {
    final int  COL[][] =
            {
                    { 255, 255, 255 },  // 100% White
                    { 255, 255,   0 },  // Yellow
                    {   0, 255, 255 },  // Cyan
                    {   0, 255,   0 },  // Green
                    { 255,   0, 255 },  // Magenta
                    { 255,   0,   0 },  // Red
                    {   0,   0, 255 },  // Blue
                    {   0,   0,   0 },  // Black
            };

    int columnHeight = height / COL.length;
    byte[] arr = new byte[width*height*3/2];
    int yOffset = 0;
    int uvOffset = width*height;

    for (int j = 0; j < height; j++) {
        for (int i = 0; i < width; i++) {
            int idx = j / columnHeight;
            int R = COL[idx][0];
            int G = COL[idx][1];
            int B = COL[idx][2];
            int yIndex = j*width+i;
            int uvIndex = j*width/2+i;

            int Y = (19595*R + 38470*G + 7471*B + (1<<15)) >> 16;
            int Cb = -11056*R - 21712*G + 32768*B + (257<<15);
            if ((Cb & 0xff000000) == 0) {
                Cb >>= 16;
            } else {
                Cb = 0xffffffff ^ (Cb >> 31);
            }
            int Cr = 32768*R - 27440*G - 5328*B + (257<<15);
            if ((Cr & 0xff000000) == 0) {
                Cr >>= 16;
            } else {
                Cr = 0xffffffff ^ (Cr >> 31);
            }
            arr[yOffset + yIndex] = (byte) Y;
            if (i%2 == 0 && j%2 == 0) {
                arr[uvOffset + uvIndex] = (byte) Cb;
                arr[uvOffset + uvIndex + 1] = (byte) Cr;
            }
        }
    }
    return arr;
}

Please help review it.

The original Go language code is below:

// RGBToYCbCr converts an RGB triple to a Y'CbCr triple.
func RGBToYCbCr(r, g, b uint8) (uint8, uint8, uint8) {
  // The JFIF specification says:
  //  Y' =  0.2990*R + 0.5870*G + 0.1140*B
  //  Cb = -0.1687*R - 0.3313*G + 0.5000*B + 128
  //  Cr =  0.5000*R - 0.4187*G - 0.0813*B + 128
  // https://www.w3.org/Graphics/JPEG/jfif3.pdf says Y but means Y'.

  r1 := int32(r)
  g1 := int32(g)
  b1 := int32(b)

  // yy is in range [0,0xff].
  //
  // Note that 19595 + 38470 + 7471 equals 65536.
  yy := (19595*r1 + 38470*g1 + 7471*b1 + 1<<15) >> 16

  // The bit twiddling below is equivalent to
  //
  // cb := (-11056*r1 - 21712*g1 + 32768*b1 + 257<<15) >> 16
  // if cb < 0 {
  //     cb = 0
  // } else if cb > 0xff {
  //     cb = ^int32(0)
  // }
  //
  // but uses fewer branches and is faster.
  // Note that the uint8 type conversion in the return
  // statement will convert ^int32(0) to 0xff.
  // The code below to compute cr uses a similar pattern.
  //
  // Note that -11056 - 21712 + 32768 equals 0.
  cb := -11056*r1 - 21712*g1 + 32768*b1 + 257<<15
  if uint32(cb)&0xff000000 == 0 {
      cb >>= 16
  } else {
      cb = ^(cb >> 31)
  }

  // Note that 32768 - 27440 - 5328 equals 0.
  cr := 32768*r1 - 27440*g1 - 5328*b1 + 257<<15
  if uint32(cr)&0xff000000 == 0 {
      cr >>= 16
  } else {
      cr = ^(cr >> 31)
  }

  return uint8(yy), uint8(cb), uint8(cr)
}
\$\endgroup\$
  • 1
    \$\begingroup\$ Use this formula instead: int Y = 16 + (((R<<6) + (R<<1) + (G<<7) + G + (B<<4) + (B<<3) + B)>>8); int Cb = 128 + ((-((R<<5) + (R<<2) + (R<<1)) - ((G<<6) + (G<<3) + (G<<1)) + (B<<7) - (B<<4))>>8); int Cr = 128 + (((R<<7) - (R<<4) - ((G<<6) + (G<<5) - (G<<1)) - ((B<<4) + (B<<1)))>>8); \$\endgroup\$ – beetlej May 1 at 1:42
  • 1
    \$\begingroup\$ I see you removed the statement "Not sure if it caused by int overflow in java! I try to change it to long but still not helpful!" and added the statement "The output sounds good for my color bar, please help review if it's good.". Is the java code working as intended? \$\endgroup\$ – Sᴀᴍ Onᴇᴌᴀ May 1 at 17:13
  • \$\begingroup\$ Yes, it works now! \$\endgroup\$ – lucky1928 May 1 at 17:53
  • \$\begingroup\$ is there any reason why you use java? one benefit of java is the OOP and i can't see much objects in your code... \$\endgroup\$ – Martin Frank May 7 at 8:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.