RGB到CIELAB色彩转换器的问题出在哪里

问题描述

package com.dendeberia;

import java.awt.*;
import java.awt.color.ColorSpace;

public class ColorService {

    //Array that represents the available brush color values
    //The three first values - RGB
    //The three last values - CIELAB
    private static final float[][] PROJECTGALAXYCOLORBRUSH = {
        {204,204,(float) 82.0457816743455,(float) 0.00444629164148,(float)-0.0087972292033944},{0,0},{68,68,(float)28.8519023984,(float)0.0020339950922155,(float)-0.0040243696247777},136,(float)14.2738172334721,(float)49.6367882123441,(float)-67.6039440409195},(float)37.3402961144031,(float)42.3723762076028,(float)-70.3408856896172},(float)49.017553063054,(float)-54.016526105245,(float)52.1340895507155},(float)72.7811549405922,(float)-62.2321453672768,(float)55.0872382088958},(float)51.1356589056541,(float)-30.1340711239506,(float)-8.86112163355215},(float)75.3107048081516,(float)-35.6225911879833,(float)-10.7130452502874},{136,(float)27.3919538133614,(float)50.208793415402,(float)40.4309077462604},{204,(float)48.7464456160487,(float)53.6620511975798,(float)30.2021140378087},(float)31.8337886733411,(float)61.5811794803788,(float)-38.1335558077085},(float)53.3101338039571,(float)69.1649884797985,(float)-43.7805478031053},(float)56.7034107567544,(float)0.0032970369763796,(float)-0.0065233665066833}
    };

    private static float getDeltaE(double L1,double a1,double b1,double L2,double a2,double b2){
        float Lmean = (float) ((L1 + L2) / 2.0);
        float C1 = (float) Math.sqrt(a1*a1 + b1*b1);
        float C2 = (float) Math.sqrt(a2*a2 + b2*b2);
        float Cmean = (float) ((C1 + C2) / 2.0);

        float G = (float) (( 1 - Math.sqrt( Math.pow(Cmean,7) / (Math.pow(Cmean,7) + Math.pow(25,7)) ) ) / 2);
        float a1prime = (float) (a1 * (1 + G));
        float a2prime = (float) (a2 * (1 + G));

        float C1prime = (float) Math.sqrt(a1prime*a1prime + b1*b1);
        float C2prime = (float) Math.sqrt(a2prime*a2prime + b2*b2);
        float Cmeanprime = (C1prime + C2prime) / 2;

        float h1prime = (float) (Math.atan2(b1,a1prime) + 2*Math.PI * (Math.atan2(b1,a1prime)<0 ? 1 : 0));
        float h2prime = (float) (Math.atan2(b2,a2prime) + 2*Math.PI * (Math.atan2(b2,a2prime)<0 ? 1 : 0));
        float Hmeanprime = (Math.abs(h1prime - h2prime) > Math.PI) ? (float) ((h1prime + h2prime + 2 * Math.PI) / 2) : (h1prime + h2prime) / 2;

        float T = (float) (1.0 - 0.17 * Math.cos(Hmeanprime - Math.PI/6.0) + 0.24 * Math.cos(2*Hmeanprime) + 0.32 * Math.cos(3*Hmeanprime + Math.PI/30) - 0.2 * Math.cos(4*Hmeanprime - 21*Math.PI/60));

        float deltahprime = (Math.abs(h1prime - h2prime) <= Math.PI) ? h2prime - h1prime : (float) ((h2prime <= h1prime) ? h2prime - h1prime + 2 * Math.PI : h2prime - h1prime - 2 * Math.PI);

        float deltaLprime = (float) (L2 - L1);
        float deltaCprime = C2prime - C1prime;
        float deltaHprime = (float) (2.0 * Math.sqrt(C1prime*C2prime) * Math.sin(deltahprime / 2.0));
        float SL = (float) (1.0 + ( (0.015*(Lmean - 50)*(Lmean - 50)) / (Math.sqrt( 20 + (Lmean - 50)*(Lmean - 50) )) ));
        float SC = (float) (1.0 + 0.045 * Cmeanprime);
        float SH = (float) (1.0 + 0.015 * Cmeanprime * T);

        float deltaTheta = (float) ((30 * Math.PI / 180) * Math.exp(-((180/Math.PI*Hmeanprime-275)/25)*((180/Math.PI*Hmeanprime-275)/25)));
        float RC = (float) (2 * Math.sqrt(Math.pow(Cmeanprime,7) / (Math.pow(Cmeanprime,7))));
        float RT = (float) (-RC * Math.sin(2 * deltaTheta));

        float KL = 1;
        float KC = 1;
        float KH = 1;

        float deltaE = (float) Math.sqrt(
                ((deltaLprime/(KL*SL)) * (deltaLprime/(KL*SL))) +
                        ((deltaCprime/(KC*SC)) * (deltaCprime/(KC*SC))) +
                        ((deltaHprime/(KH*SH)) * (deltaHprime/(KH*SH))) +
                        (RT * (deltaCprime/(KC*SC)) * (deltaHprime/(KH*SH)))
        );

        return deltaE;
    }

    private static float[] getLabFromRGB(int red,int green,int blue){
        float xyz[] = getXYZFromRGB(new int[]{red,green,blue});

        float X = xyz[0];
        float Y = xyz[1];
        float Z = xyz[2];

        float tempX = (float) (X / 95.047);
        float tempY= (float) (Y / 100.000);
        float tempZ = (float) (Z / 108.883);

        if ( tempX > 0.008856 ){
            tempX = (float) Math.pow(tempX,0.3333333333333333);
        } else {
            tempX = (float) (( 7.787 * tempX ) + ( 16 / 116 ));
        }

        if ( tempY > 0.008856 ) {
            tempY = (float) Math.pow(tempY,0.3333333333333333);
        } else {
            tempY = (float) (( 7.787 * tempY ) + ( 16 / 116 ));
        }

        if ( tempZ > 0.008856 ){
            tempZ = (float) Math.pow(tempZ,0.3333333333333333);
        } else {
            tempZ = (float) (( 7.787 * tempZ ) + ( 16 / 116 ));
        }

        float L = ( 116 * tempY ) - 16;
        float a = 500 * ( tempX - tempY );
        float b = 200 * ( tempY - tempZ );

        return new float[]{L,a,b};
    }

    private static float[] getXYZFromRGB(int[] rgb){

        int sR = rgb[0];
        int sG = rgb[1];
        int sB = rgb[2];

        float tempR = ( sR / 255 );
        float tempG = ( sG / 255 );
        float tempB = ( sB / 255 );

        if ( tempR > 0.04045 ){
            tempR = (float) Math.pow(( ( tempR + 0.055 ) / 1.055 ),2.4);
        } else {
            tempR /= 12.92;
        }

        if(tempG > 0.04045){
            tempG = (float) Math.pow(( ( tempG + 0.055 ) / 1.055 ),2.4);
        } else {
            tempG /= 12.92;
        }

        if(tempB > 0.04045){
            tempB = (float) Math.pow(( ( tempB + 0.055 ) / 1.055 ),2.4);
        } else {
            tempB /= 12.92;
        }

        tempR *= 100;
        tempG *= 100;
        tempB *= 100;

        float X = (float) (tempR * 0.4124 + tempG * 0.3576 + tempB * 0.1805);
        float Y = (float) (tempR * 0.2126 + tempG * 0.7152 + tempB * 0.0722);
        float Z = (float) (tempR * 0.0193 + tempG * 0.1192 + tempB * 0.9505);

        return new float[]{X,Y,Z};
    }

    public static Color getMoreSimilarColor(Color color){

        int red = color.getRed();
        int green = color.getGreen();
        int blue = color.getBlue();

        float[] labFromRGB = getLabFromRGB(red,blue);

        float[] deltaEForEveryColor = new float[PROJECTGALAXYCOLORBRUSH.length];

        for(int i = 0; i < PROJECTGALAXYCOLORBRUSH.length; i++){
            float[] temp = PROJECTGALAXYCOLORBRUSH[i];

            float deltaE = getDeltaE(labFromRGB[0],labFromRGB[1],labFromRGB[2],temp[3],temp[4],temp[5]);

            deltaEForEveryColor[i] = deltaE;

        }

        float minDeltaE = deltaEForEveryColor[0];
        float minDeltaERGB[] = {PROJECTGALAXYCOLORBRUSH[0][0],PROJECTGALAXYCOLORBRUSH[0][1],PROJECTGALAXYCOLORBRUSH[0][2]};

        for(int i = 1; i < deltaEForEveryColor.length; i++){
            if(deltaEForEveryColor[i] < minDeltaE){
                minDeltaE = deltaEForEveryColor[i];

                minDeltaERGB[0] = PROJECTGALAXYCOLORBRUSH[i][0];
                minDeltaERGB[1] = PROJECTGALAXYCOLORBRUSH[i][1];
                minDeltaERGB[2] = PROJECTGALAXYCOLORBRUSH[i][2];
            }
        }

        return new Color(minDeltaERGB[0] / 255,minDeltaERGB[1] / 255,minDeltaERGB[2] / 255);
    }

}

此代码获取颜色实例,并且必须从数组中返回最相似的颜色。它的工作原理是:

  • 获取参数color的CIELAB值
  • 找到每个数组颜色的deltaE值
  • 返回代表较小deltaE值的RGB

但是它不起作用。在大多数情况下,它返回黑色(0、0、0)。还有一个问题-对于许多不同的颜色,deltaE是相同的。 getDeltaE() getLabFromRGB() getXYZFromRGB()只是数学公式的实现。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...