简体   繁体   English

在Java中分配32位浮点数到4个整数(RGBA)上

[英]Distribute 32bit float over 4 integers (RGBA) in java

1. Consider a 32bit java float sample in (0.0f .. 1.0f) and four 32bit java integers r, g, b, a each in (0 .. 255) in a vector called RGBA . 1.考虑一个(0.0f .. 1.0f)中的32位Java浮点sample和一个称为RGBA的向量中的四个32位Java整数r, g, b, a每个均在(0 .. 255)中。

2. The sample variable contains normalized measurement data that I wish to present in an ImageIcon in the form of a heat map. 2. sample变量包含我希望以热图形式显示在ImageIcon中的标准化测量数据。 The target for the final RGBA values is an integer vector that later is passed as pixel data to a java BufferdImage . 最终RGBA值的目标是一个整数向量,该整数向量随后作为像素数据传递到java BufferdImage

3. The constraints are that when sample==0.0f then RGBA==[0,0,0,255] with uniform distribution so that sample==1.0f represents RGBA==[255,0,0,255] and with sample==0.5f is represented by RGBA==[255,255,255,255] . 3.约束条件是,当sample==0.0f RGBA==[0,0,0,255]具有均匀分布,因此sample==1.0f表示RGBA==[255,0,0,255]sample==0.5fRGBA==[255,255,255,255] The alpha channel is always 255. Alpha通道始终为255。

4. So far I have used a static method by dividing the colors into three separate sections RGB while A remain static at 255. Like so 4.到目前为止,我已经使用静态方法将颜色分为三个独立的部分RGB,而A保持为255。

/* BLUE */
if ( sample <= 0.340000f ){
    localSample = (sample/(0.340000f/255.000000f));
    sourceLinearData[localIndex] = 0; // R
    sourceLinearData[localIndex+1] = 0; // G
    sourceLinearData[localIndex+2] = Math.round(localSample); // B
}

5. My questions: A) Are there any suitable java api's/libraries that would help me do this? 5.我的问题:A)是否有任何合适的Java api /库可以帮助我做到这一点? B) If not then I ask for suggestions to a solution. B)如果没有,我要求提出解决方案的建议。

6. Thoughts: Since each of the R, G, B, A are in (0 .. 255) I assume I can use bytes instead of integers and then possibly shift these bytes into one variable and then extract the float that way. 6.想法:由于R,G,B,A中的每一个都在(0 .. 255)中,因此我假设我可以使用字节而不是整数,然后可以将这些字节移入一个变量,然后以这种方式提取浮点数。 Though I have not had any success with this method so far. 尽管到目前为止,这种方法我还没有取得任何成功。

7. EDIT: Adding example heat map 7.编辑:添加示例热图

热点图示例

SOLVED: So, like many other things in software development, this question too holds more than a single answer. 已解决:因此,就像软件开发中的许多其他事情一样,这个问题也不仅仅是一个答案。 In my case I wanted the most direct route with the least amount of additional work. 以我为例,我想要的是最直接的路线,最少的额外工作量。 Because of that I decided to go with the answer given by @haraldK. 因此,我决定采用@haraldK给出的答案。 This said though, if you are looking for a formal solution with more control, precision and flexibility, the answer provided by @SashaSalauyou is the more correct one. 这就是说,但是,如果您正在寻找一种具有更多控制,精度和灵活性的正式解决方案,那么@SashaSalauyou提供的答案将是更正确的解决方案。

To elaborate on my comment above. 在上面详细阐述我的评论。 This doesn't give exactly the colors in the map above, but it is pretty close, and extremely simple: 上面的地图并没有给出确切的颜色,但是非常接近,而且非常简单:

float sample = ...; // [0...1]
float hue = (1 - sample) * .75f; // limit hue to [0...0.75] to avoid color "loop"
int rgb = Color.getHSBColor(hue, 1, 1).getRGB(); 

If you want darker tints in "edges" of the scale, you could use a sine function to compute the brightness, for example: 如果要在刻度的“边缘”上使用较深的色彩,可以使用正弦函数来计算亮度,例如:

float hue = (1 - sample) * .75f;
float brightness = .5f + (float) Math.sin(Math.PI * sample) / 2;
int rgb = Color.getHSBColor(hue, 1, brightness).getRGB();

I suggest some kind of interpolation in a path that value from 0 to 1 performs in 3D color space: 我建议在3D颜色空间中执行从0到1的值的路径中的某种插值:

// black: c = 0.0
// blue:  c = 0.3 
// white: c = 0.5
// red:   c = 1.0
// add more color mappings if needed, keeping c[] sorted

static float[] c = {0.0, 0.3, 0.5, 1.0};
static int[] r =   {  0,   0, 255, 255}; // red components
static int[] g =   {  0,   0, 255,   0}; // green components
static int[] b =   {  0, 255, 255,   0}; // blue components

public int[] getColor(float f) {
    int i = 0;
    while (c[i] < f) 
       i++;
    if (i == 0) 
       return new int[] {r[0], g[0], b[0]};

    // interpolate
    float k = (f - c[i-1]) / (c[i] - c[i-1]);
    return new int[] {
         Math.round((r[i] - r[i-1]) * k + r[i-1]),
         Math.round((g[i] - g[i-1]) * k + g[i-1]),
         Math.round((b[i] - b[i-1]) * k + b[i-1])
         }
    }

}

Lerp should do the trick: 勒普应该做到这一点:

public static void main(String[] args) {
    float value = 0.5f;

    float[] red = new float[] {1.0f, 0, 0};
    float[] white = new float[] {1.0f, 1.0f, 1.0f};
    float[] black = new float[] {0, 0, 0};

    if (value <= 0.5f) {
        float gradientValue = value * 2;
        int[] color = new int[] {(int) (lerp(white[0], black[0], gradientValue) * 255), (int) (lerp(white[1], black[1], gradientValue) * 255), 
                (int) (lerp(white[2], black[2], gradientValue) * 255), 255};
    } else if (value > 0.5f) {
        float gradientValue = (value + 1) / 2.0f;
        int[] color = new int[] {(int) (lerp(white[0], red[0], gradientValue) * 255), (int) (lerp(white[1], red[1], gradientValue) * 255), 
                (int) (lerp(white[2], red[2], gradientValue) * 255), 255};
    }
}

public static float lerp(float v0, float v1, float t) {
      return (1-t)*v0 + t*v1;
}

(the order of the lerp arguments might be different, I haven't tested) (lerp参数的顺序可能有所不同,我尚未测试)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM