web-dev-qa-db-ja.com

RGBカラーを最も一致する8ビットカラーに変換するにはどうすればよいですか?

ビデオに表示される上位16色にインデックスを付けるアプリケーションがあります。

ユーザーが色を選択できる別のアプリケーションを作成しようとしていますが、アプリケーションはこの色が表示されるすべてのビデオを検索します。

問題は、ビデオごとに16色しかインデックス付けしないため、ユーザーがRGBカラーを選択することです。この色がインデックスに登録される可能性は非常に低いため、ほとんどの場合、アプリケーションは結果を返しません。

私はこの作品を作る方法を考えました-ビデオに現れる色にインデックスを付けて、それらを最も近い8ビットの色に変換することができました。

次に、ユーザーがRGBカラーを選択すると、ユーザーの選択を同じ8ビットの最も近いカラーに変換できます。

このように私はいつもマッチを持っているでしょう。

私が今抱えている唯一の大きな問題は、RGBカラーを最も近い8ビットカラーに変換する方法です。

13
bodacydo

Webセーフパレットに変換するには、各r、g、bコンポーネントの範囲を0〜255から0〜5に変換し、それらを組み合わせる必要があります。

color = (r*6/256)*36 + (g*6/256)*6 + (b*6/256)
9
Mark Ransom

あなたがする必要があるのは、RGBをHSB(色相飽和輝度)値に変換することです。 HSBはRGBと同じように3バイトですが、違いは、HSB値をRGBよりもはるかに簡単に比較できることです。

次のステップは、「重要な」重み付けを決定することです。たとえば、気になるのが彩度や明るさではなく「色/色相」だけの場合は、SバイトとBバイトを破棄して、カラーバイトだけを使用できます。

それが私で、8ビットに制限されている場合、4ビットの色情報(16の異なる色)、3ビットの彩度(8つの異なる値)、および1ビットの明るさ情報(明るいまたは暗い)を使用します。

この記事では、JavaでHSBを実行する方法について説明します。

http://Java.sys-con.com/node/43559

この記事のソースコードには、JavaのRGBからHSBへのコンバーターが含まれています。

6
Tyler Durden

1つの可能性は、24ビットカラーを8ビットカラースペースに単純に縮小することです。 cHaoが言及しているように、8ビット数にはRRRGGGBBを使用できます。次に、各色成分は、次のような単純なスケーリングアルゴリズムによって計算できます。

byte red = (originalColor.red * 8) / 256;
byte green = (originalColor.green * 8) / 256;
byte blue = (originalColor.blue * 4) / 256;

8、4、および254は、各色成分で可能な値の数です。元の24ビットカラーでは、赤、緑、青はすべて256の可能な値を持つことができるため、これがスケーリング式の除数です。 8ビットカラーの例では、赤と緑はそれぞれ3ビット(8つの可能な値)であり、青は2ビット(4つの可能な値)です。

これらの3つのコンポーネントを取得したら、それらをいくつかの単純なビットシフト演算と組み合わせることができます。

byte eightBitColor = (red << 5) | (green << 2) | blue;

次に、これらの8ビットカラーを簡単に比較できます。解像度が大幅に低下すると、役立つ場合があります。

または、タイラーが提案したようなことをして、最初にHSBまたはHSVに変換し、色相のみを比較することもできます(明るさと彩度の情報が必要かどうかによって異なります)。目標によっては、それが実際にはより理想的な解決策になる場合があります。

編集:Mark Ransomによって指摘された欠点を修正するために、スケーリングアルゴリズムを変更しました。

2
Michael Calvin

これは非常に便利なPython数年前に見つけたスクリプトです。すべてのクレジットはMicah Elliottにあります。

使い方:

  1. コード全体をコピーして、目的の名前で.pyファイルを作成します。
  2. プログラムは(Hex-> RGB)と(RGB-> Hex)を変換できます
  3. 次のような引数とともにプログラムを実行します。python file.py 9CE445で最も近い8ビットのカラー値を取得し、python file.py 204で正確な16進値を取得します。

    """ Convert values between RGB hex codes and xterm-256 color codes.
    Nice long listing of all 256 colors and their codes. Useful for
    developing console color themes, or even script output schemes.
    Resources:
    * http://en.wikipedia.org/wiki/8-bit_color
    * http://en.wikipedia.org/wiki/ANSI_escape_code
    * /usr/share/X11/rgb.txt
    I'm not sure where this script was inspired from. I think I must have
    written it from scratch, though it's been several years now.
    """
    
    __author__    = 'Micah Elliott http://MicahElliott.com'
    __version__   = '0.1'
    __copyright__ = 'Copyright (C) 2011 Micah Elliott.  All rights reserved.'
    __license__   = 'WTFPL http://sam.zoy.org/wtfpl/'
    
    #---------------------------------------------------------------------
    
    import sys, re
    
    CLUT = [  # color look-up table
    #    8-bit, RGB hex
    
        # Primary 3-bit (8 colors). Unique representation!
        ('00',  '000000'),
        ('01',  '800000'),
        ('02',  '008000'),
        ('03',  '808000'),
        ('04',  '000080'),
        ('05',  '800080'),
        ('06',  '008080'),
        ('07',  'c0c0c0'),
    
        # Equivalent "bright" versions of original 8 colors.
        ('08',  '808080'),
        ('09',  'ff0000'),
        ('10',  '00ff00'),
        ('11',  'ffff00'),
        ('12',  '0000ff'),
        ('13',  'ff00ff'),
        ('14',  '00ffff'),
        ('15',  'ffffff'),
    
        # Strictly ascending.
        ('16',  '000000'),
        ('17',  '00005f'),
        ('18',  '000087'),
        ('19',  '0000af'),
        ('20',  '0000d7'),
        ('21',  '0000ff'),
        ('22',  '005f00'),
        ('23',  '005f5f'),
        ('24',  '005f87'),
        ('25',  '005faf'),
        ('26',  '005fd7'),
        ('27',  '005fff'),
        ('28',  '008700'),
        ('29',  '00875f'),
        ('30',  '008787'),
        ('31',  '0087af'),
        ('32',  '0087d7'),
        ('33',  '0087ff'),
        ('34',  '00af00'),
        ('35',  '00af5f'),
        ('36',  '00af87'),
        ('37',  '00afaf'),
        ('38',  '00afd7'),
        ('39',  '00afff'),
        ('40',  '00d700'),
        ('41',  '00d75f'),
        ('42',  '00d787'),
        ('43',  '00d7af'),
        ('44',  '00d7d7'),
        ('45',  '00d7ff'),
        ('46',  '00ff00'),
        ('47',  '00ff5f'),
        ('48',  '00ff87'),
        ('49',  '00ffaf'),
        ('50',  '00ffd7'),
        ('51',  '00ffff'),
        ('52',  '5f0000'),
        ('53',  '5f005f'),
        ('54',  '5f0087'),
        ('55',  '5f00af'),
        ('56',  '5f00d7'),
        ('57',  '5f00ff'),
        ('58',  '5f5f00'),
        ('59',  '5f5f5f'),
        ('60',  '5f5f87'),
        ('61',  '5f5faf'),
        ('62',  '5f5fd7'),
        ('63',  '5f5fff'),
        ('64',  '5f8700'),
        ('65',  '5f875f'),
        ('66',  '5f8787'),
        ('67',  '5f87af'),
        ('68',  '5f87d7'),
        ('69',  '5f87ff'),
        ('70',  '5faf00'),
        ('71',  '5faf5f'),
        ('72',  '5faf87'),
        ('73',  '5fafaf'),
        ('74',  '5fafd7'),
        ('75',  '5fafff'),
        ('76',  '5fd700'),
        ('77',  '5fd75f'),
        ('78',  '5fd787'),
        ('79',  '5fd7af'),
        ('80',  '5fd7d7'),
        ('81',  '5fd7ff'),
        ('82',  '5fff00'),
        ('83',  '5fff5f'),
        ('84',  '5fff87'),
        ('85',  '5fffaf'),
        ('86',  '5fffd7'),
        ('87',  '5fffff'),
        ('88',  '870000'),
        ('89',  '87005f'),
        ('90',  '870087'),
        ('91',  '8700af'),
        ('92',  '8700d7'),
        ('93',  '8700ff'),
        ('94',  '875f00'),
        ('95',  '875f5f'),
        ('96',  '875f87'),
        ('97',  '875faf'),
        ('98',  '875fd7'),
        ('99',  '875fff'),
        ('100', '878700'),
        ('101', '87875f'),
        ('102', '878787'),
        ('103', '8787af'),
        ('104', '8787d7'),
        ('105', '8787ff'),
        ('106', '87af00'),
        ('107', '87af5f'),
        ('108', '87af87'),
        ('109', '87afaf'),
        ('110', '87afd7'),
        ('111', '87afff'),
        ('112', '87d700'),
        ('113', '87d75f'),
        ('114', '87d787'),
        ('115', '87d7af'),
        ('116', '87d7d7'),
        ('117', '87d7ff'),
        ('118', '87ff00'),
        ('119', '87ff5f'),
        ('120', '87ff87'),
        ('121', '87ffaf'),
        ('122', '87ffd7'),
        ('123', '87ffff'),
        ('124', 'af0000'),
        ('125', 'af005f'),
        ('126', 'af0087'),
        ('127', 'af00af'),
        ('128', 'af00d7'),
        ('129', 'af00ff'),
        ('130', 'af5f00'),
        ('131', 'af5f5f'),
        ('132', 'af5f87'),
        ('133', 'af5faf'),
        ('134', 'af5fd7'),
        ('135', 'af5fff'),
        ('136', 'af8700'),
        ('137', 'af875f'),
        ('138', 'af8787'),
        ('139', 'af87af'),
        ('140', 'af87d7'),
        ('141', 'af87ff'),
        ('142', 'afaf00'),
        ('143', 'afaf5f'),
        ('144', 'afaf87'),
        ('145', 'afafaf'),
        ('146', 'afafd7'),
        ('147', 'afafff'),
        ('148', 'afd700'),
        ('149', 'afd75f'),
        ('150', 'afd787'),
        ('151', 'afd7af'),
        ('152', 'afd7d7'),
        ('153', 'afd7ff'),
        ('154', 'afff00'),
        ('155', 'afff5f'),
        ('156', 'afff87'),
        ('157', 'afffaf'),
        ('158', 'afffd7'),
        ('159', 'afffff'),
        ('160', 'd70000'),
        ('161', 'd7005f'),
        ('162', 'd70087'),
        ('163', 'd700af'),
        ('164', 'd700d7'),
        ('165', 'd700ff'),
        ('166', 'd75f00'),
        ('167', 'd75f5f'),
        ('168', 'd75f87'),
        ('169', 'd75faf'),
        ('170', 'd75fd7'),
        ('171', 'd75fff'),
        ('172', 'd78700'),
        ('173', 'd7875f'),
        ('174', 'd78787'),
        ('175', 'd787af'),
        ('176', 'd787d7'),
        ('177', 'd787ff'),
        ('178', 'd7af00'),
        ('179', 'd7af5f'),
        ('180', 'd7af87'),
        ('181', 'd7afaf'),
        ('182', 'd7afd7'),
        ('183', 'd7afff'),
        ('184', 'd7d700'),
        ('185', 'd7d75f'),
        ('186', 'd7d787'),
        ('187', 'd7d7af'),
        ('188', 'd7d7d7'),
        ('189', 'd7d7ff'),
        ('190', 'd7ff00'),
        ('191', 'd7ff5f'),
        ('192', 'd7ff87'),
        ('193', 'd7ffaf'),
        ('194', 'd7ffd7'),
        ('195', 'd7ffff'),
        ('196', 'ff0000'),
        ('197', 'ff005f'),
        ('198', 'ff0087'),
        ('199', 'ff00af'),
        ('200', 'ff00d7'),
        ('201', 'ff00ff'),
        ('202', 'ff5f00'),
        ('203', 'ff5f5f'),
        ('204', 'ff5f87'),
        ('205', 'ff5faf'),
        ('206', 'ff5fd7'),
        ('207', 'ff5fff'),
        ('208', 'ff8700'),
        ('209', 'ff875f'),
        ('210', 'ff8787'),
        ('211', 'ff87af'),
        ('212', 'ff87d7'),
        ('213', 'ff87ff'),
        ('214', 'ffaf00'),
        ('215', 'ffaf5f'),
        ('216', 'ffaf87'),
        ('217', 'ffafaf'),
        ('218', 'ffafd7'),
        ('219', 'ffafff'),
        ('220', 'ffd700'),
        ('221', 'ffd75f'),
        ('222', 'ffd787'),
        ('223', 'ffd7af'),
        ('224', 'ffd7d7'),
        ('225', 'ffd7ff'),
        ('226', 'ffff00'),
        ('227', 'ffff5f'),
        ('228', 'ffff87'),
        ('229', 'ffffaf'),
        ('230', 'ffffd7'),
        ('231', 'ffffff'),
    
        # Gray-scale range.
        ('232', '080808'),
        ('233', '121212'),
        ('234', '1c1c1c'),
        ('235', '262626'),
        ('236', '303030'),
        ('237', '3a3a3a'),
        ('238', '444444'),
        ('239', '4e4e4e'),
        ('240', '585858'),
        ('241', '626262'),
        ('242', '6c6c6c'),
        ('243', '767676'),
        ('244', '808080'),
        ('245', '8a8a8a'),
        ('246', '949494'),
        ('247', '9e9e9e'),
        ('248', 'a8a8a8'),
        ('249', 'b2b2b2'),
        ('250', 'bcbcbc'),
        ('251', 'c6c6c6'),
        ('252', 'd0d0d0'),
        ('253', 'dadada'),
        ('254', 'e4e4e4'),
        ('255', 'eeeeee'),
    ]
    
    def _str2hex(hexstr):
        return int(hexstr, 16)
    
    def _strip_hash(rgb):
        # Strip leading `#` if exists.
        if rgb.startswith('#'):
            rgb = rgb.lstrip('#')
        return rgb
    
    def _create_dicts():
        short2rgb_dict = dict(CLUT)
        rgb2short_dict = {}
        for k, v in short2rgb_dict.items():
            rgb2short_dict[v] = k
        return rgb2short_dict, short2rgb_dict
    
    def short2rgb(short):
        return SHORT2RGB_DICT[short]
    
    def print_all():
        """ Print all 256 xterm color codes.
        """
        for short, rgb in CLUT:
            sys.stdout.write('\033[48;5;%sm%s:%s' % (short, short, rgb))
            sys.stdout.write("\033[0m  ")
            sys.stdout.write('\033[38;5;%sm%s:%s' % (short, short, rgb))
            sys.stdout.write("\033[0m\n")
        print ("Printed all codes.")
        print ("You can translate a hex or 0-255 code by providing an argument.")
    
    def rgb2short(rgb):
        """ Find the closest xterm-256 approximation to the given RGB value.
        @param rgb: Hex code representing an RGB value, eg, 'abcdef'
        @returns: String between 0 and 255, compatible with xterm.
        >>> rgb2short('123456')
        ('23', '005f5f')
        >>> rgb2short('ffffff')
        ('231', 'ffffff')
        >>> rgb2short('0DADD6') # vimeo logo
        ('38', '00afd7')
        >>> rgb2short('3D3D3D')
        ('237', '3a3a3a')
        >>> rgb2short('070707')
        ('232', '080808')
        """
        rgb = _strip_hash(rgb)
        # Break 6-char RGB code into 3 integer vals.
        parts = [ int(h, 16) for h in re.split(r'(..)(..)(..)', rgb)[1:4] ]
    
        incs = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff]
    
        if parts[0] == parts[1] == parts[2]:
            gs_incs = range(0x08, 0xee, 10)
            incs = sorted(incs + gs_incs + [0xee,])
    
        res = []
        for part in parts:
            i = 0
            while i < len(incs)-1:
                s, b = incs[i], incs[i+1]  # smaller, bigger
                if s <= part <= b:
                    s1 = abs(s - part)
                    b1 = abs(b - part)
                    if s1 < b1: closest = s
                    else: closest = b
                    res.append(closest)
                    break
                i += 1
        #print '***', res
        res = ''.join([ ('%02.x' % i) for i in res ])
        equiv = RGB2SHORT_DICT[ res ]
        #print '***', res, equiv
        return equiv, res
    
    RGB2SHORT_DICT, SHORT2RGB_DICT = _create_dicts()
    
    #---------------------------------------------------------------------
    
    if __name__ == '__main__':
        import doctest
        doctest.testmod()
        if len(sys.argv) == 1:
            print_all()
            raise SystemExit
        arg = sys.argv[1]
        if len(arg) < 4 and int(arg) < 256:
            rgb = short2rgb(arg)
            sys.stdout.write('xterm color \033[38;5;%sm%s\033[0m -> RGB exact \033[38;5;%sm%s\033[0m' % (arg, arg, arg, rgb))
            sys.stdout.write("\033[0m\n")
        else:
            short, rgb = rgb2short(arg)
            sys.stdout.write('RGB %s -> xterm color approx \033[38;5;%sm%s (%s)' % (arg, short, short, rgb))
            sys.stdout.write("\033[0m\n")
    
0
asreerama

フロイド-スタインバーグディザリング に精通していますか?これは、高次の色を低次の色に変換するために使用されます。 24ビットRGBから3ビット(8色)RGB、またはGIF変換用にRGB画像を8ビット(256色)に制限します。

このアルゴリズムは、リンクされたウィキペディアのページで説明されています。

0
David Pointer

24bpp画像を8bpp画像に変換する場合は、次のアルゴリズムを試してください。

for y = 0 to ImageHeight - 1
   for x = 0 to ImageWidth - 1
      GetPixel(x,y,red,grn,blu)
      {read RGB data from 24bpp file}
      d0 = red^2 + grn^2 + blu^2
      ColorIndex = 0
      for cl = 0 to 255
         GetPaletteData(p_red,p_gre,p_blu)
         {read RGB data from 8bpp palette}
         d = (red - p_red)^2 + (grn - p_grn)^2 + (blu - p_blu)^2
         if d0 >= d then
            ColorIndex = cl
            d0 = d
         end if
      next cl
        {use ColorIndex to create your 8bpp file}
     next x
   next y

このステップの前に、ウィキペディアまたは他のソースから8bppファイルについてもっと読んでください。

幸運を!

0
Mircea Melinte