How to convert RGB to BGR?
Asked Answered
U

5

1

This is probably easy, but I'm trying to convert from a source which provides colors in RGB strings to an output in BGR strings in Java. I've been busting my brain and time on shifting and Long.decode and Long.toHexString.

Feel free to also throw alpha values in there (RGBA -> ABGR), though I think I can extend the principles.

I can assume that the hex is in the form specified in the long and int decode:

0x HexDigits  
0X HexDigits 
# HexDigits
Ultrasonics answered 14/6, 2010 at 22:57 Comment(0)
A
6

For 24bit colors (8 bits to each of R,G,B):

String rgbSource = getRGBSource(); //your function to get a string version of it
int in = Integer.decode(rgbSource);
int red = (in >> 16) & 0xFF;
int green = (in >> 8) & 0xFF;
int blue = (in >> 0) & 0xFF;
int out = (blue << 16) | (green << 8) | (red << 0);
Amoebaean answered 14/6, 2010 at 23:12 Comment(2)
good answer! This one worked if I switched the color variable names to be in order, red green blue.Ultrasonics
This method also works when adding an optional alpha if the pattern is continued. You can use the following from my answer to auto add an opaque alpha if one is missing: long rgba = (rgbSource.length() < 8 ? Long.decode(rgbSource+ "ff") : Long.decode(rgbSource)); //decodes a number of hex formats and sets alphaUltrasonics
F
2

int abgr = Integer.reverseBytes(rgba);


Including supporting code, with the assumption that it is safe to decide whether alpha needs adding based on the string length (consider "0xFFFFFF".length() for example):

String rgb = getRGB();

//decodes a number of hex formats and sets alpha
int rgba = rgb.length() < 8 ? 
           Long.decode(rgb + "ff").intValue() : 
           Long.decode(rgb       ).intValue();

int abgr = Integer.reverseBytes(rgba);

Here's a one line method:

public static String reverseRGB(String rgba) {
    return String.format("%08X",Integer.reverseBytes(Long.decode(rgba.length() < 8 ? rgba + "ff" : rgba).intValue()));
}
Folk answered 14/6, 2010 at 23:13 Comment(10)
looks appealing, but int in = Integer.decode(preferenceValue); String abgrColor = Integer.toHexString(Integer.reverseBytes(in)); had #00ff0d -> dff0000Ultrasonics
@Ultrasonics that's why I included "a" in the variable names. If you add "ff" on the end using your code, then #00ff0dff becomes ff0dff00Folk
I guess I am confused. I thought that in order to alpha long would be needed because #ffffffff (opaque white) is larger than int max. When I tried this same idea with longs the result was even further off. Were you using unsigned ints?Ultrasonics
@Adam, Java doesn't have unsigned ints, but it does have methods in Integer that work with 32 bits, ignoring the special status of the high bit as a sign bit. The reverseBytes method uses >>> 24 to perform a logical shift right of the high bytes, saving the need to AND it with 0xFF.Folk
@Stephen How do you store the rbga #ffffffff in an int (4 294 967 295 > 2 147 483 647)? Sorry for my ignorance on the issue. Do you convert the int back into a long for Long.toHexString?Ultrasonics
@Ultrasonics both Integer and Long's decode functions require the hex digits portion to represent positive numbers, with a minus sign to indicate negatives, so I recommend using Long's decode function. Then Long.intValue() returns the lower 32 bits, which interpreted as a two's complement signed integer is -1.Folk
@Ultrasonics javadocs on Integer.toHexString say that integer is treated as an unsigned integer, so no need to use Long's, though it wouldn't make any difference. Of more concern is that both toHexString methods only return sufficient hex characters to represent the number. You'd probably be better off with String.format("%08X",abgr);Folk
@Stephen I appreciate all your help with this, but this method still isn't working for me. Note that missing leading zeroes is fine in my case, but I like your format (+1). long number = (rgba .length() < 8 ? Long.decode(rgba + "ff") : Long.decode(rgba )); String abgrColor = Long.toHexString(Integer.reverseBytes((int)number)); Results in #d90d8e -> ffffffffUltrasonics
@Ultrasonics Long.toHexString returns ffffffffff8e0dd9Folk
@Stephen Ah, I see what is happeneing. I was then putting that value into a kml doc where only the first 8 characters were read. Thanks for your help on this!Ultrasonics
U
1

If the input is a 6 character rgb string:

String bgr = rgb.substring(4,6) + rgb.substring(2,4) + rgb.substring(0,2);

If the input is an 8 character rgba string:

String abgr = rgba.substring(6,8) + rgba.substring(4,6) + rgba.substring(2,4) + rgba.substring(0,2);

If the input is an int with 8 bit channels:

String bgr = String.format( "%02X%02X%02X" , rgb & 0x00FF , (rgb>>8) & 0x00FF , (rgb>>16) & 0x00FF );
String abgr = String.format( "%02X%02X%02X%02X" , rgba & 0x00FF , (rgba>>8) & 0x00FF , (rgba>>16) & 0x00FF , (rgba>>24) & 0x00FF );
// or
String bgr = String.format( "%06X" , Integer.reverseBytes( rgb ) >> 8 );
String abgr = String.format( "%08X" , Integer.reverseBytes( rgba ) );
Ultrafilter answered 14/6, 2010 at 23:28 Comment(1)
This answer is also good, but it doesn't have the robustness of using a "decode" function when dealing with "#rrggbb" or "0xrrggbb"Ultrasonics
U
0

Here is how I got it to work, but I really hope there is a better way because this is awful. Please come up with a cleaner, more efficient way to do this, so I can give you rep.

long number = (rgb.length() < 8 ? Long.decode(rgb+ "ff") : Long.decode(rgb)); //decodes a number of hex formats and sets alpha
String abgrColor = (new StringBuilder())
.append((Long.toHexString((number) & 0xFF).length()==2? Long.toHexString((number) & 0xFF): "0"+Long.toHexString((number) & 0xFF)))
.append((Long.toHexString((number>>8) & 0xFF).length()==2? Long.toHexString((number>>8) & 0xFF): "0"+Long.toHexString((number>>8) & 0xFF)))
.append((Long.toHexString((number>>16) & 0xFF).length()==2? Long.toHexString((number>>16) & 0xFF): "0"+Long.toHexString((number>>16) & 0xFF)))
.append((Long.toHexString((number>>24) & 0xFF).length()==2? Long.toHexString((number>>24) & 0xFF): "0"+Long.toHexString((number>>24) & 0xFF)))
.toString();
Ultrasonics answered 14/6, 2010 at 23:14 Comment(0)
P
0

This should work.

public static int swapByte1And3(int inValue) {
        int swap = inValue & 0xFF;
        swap = swap << 16 | (inValue >>> 16 & 0xFF);
        return inValue & 0xFF00FF00 | swap;
    }

    public static int convertBRGtoRBG(int inColor) {
        return swapByte1And3(inColor);
    }

    public static int convertABRGtoRBGA(int inColor) {
        int swap = inColor >>> 24;
        inColor = convertBRGtoRBG(inColor) << 8;
        return inColor | swap;
    }
Ponzo answered 5/9, 2012 at 15:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.