質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

91.36%

  • C#

    4777questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

16進数を2進数にして、各バイトのLSBを左にして1本のビット列にするとは?

解決済

回答 2

投稿 2017/12/05 17:44 ・編集 2017/12/05 18:11

  • 評価
  • クリップ 0
  • VIEW 117

nomurax

score 6

前提・実現したいこと

16進数と、2進数の変換について教えてください。

63 60 20 19 fc c7 01 18 70 4a 20 5b 81 ac 08 c5 6a ca 24 00
という16進数を2進数にして、各バイトのLSB(Least significant bit:最下位ビット)を左にして1本のビット列にした結果が、次のようになっています。

11000110 00011111 11110011 00000011 00000000 00100010 00000110
01000111 11111100 00100001 00000001 00000000 01100100 00010100
10110001 10000010 10001100 01111111 11100001 00010100 10000110
00100001 10010110 11000000 01001100 10010000 00010111 00000010
01101100 11000111 11111100 00101010 11011100 01111010 11011100
00001110 01011010 01110001 11001010 01000000 00000000


この変換ルールを読み解きたいので、お知恵をお貸しください。

試したこと

前から考えると、「LSBを左にする」を左右を反転すると読むと

631100011-LSBを左にする→1100011
601100000-LSBを左にする→0000011
20100000-LSBを左にする→000001


です。見やすいように区切りを8桁ごとにいれると、次のようになります。

発生している問題

11000110 00001100 0001


この3つの16進数を2進数に変換しただけで、もう数字が違っています。

試したこと

次に、「LSBを左にする」をLSBのみを左に移動すると読むと

631100011-LSBを左にする→1110001
601100000-LSBを左にする→0110000
20100000-LSBを左にする→010000


です。見やすいように区切りを8桁ごとにいれると、次のようになります。

発生している問題

11100010 11000001 0000


これはぜんぜん違うみたいです。

どのように考えたら、上の結果を導けるのか、ご指導いただければ幸いです。
この数字列は、
http://blog.livedoor.jp/cperl/archives/22023950.html
を参考にしています。

Windows10, 64bit, Visual Studio 2017 Communityです。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • SurferOnWww

    2017/12/05 18:03

    C# のタグが付いてますが C# とどういう関係があるのでしょうか? #そもそも 63→1100011, 60→1100000, 20→100000 からして違うような気がしますけど、どうでしょう?

    キャンセル

回答 2

checkベストアンサー

+2

本回答は間違いでした!
参照ページをよくみるとzlib(すみません、最初ハフマンコードって書きましたがそれより前に多分zlibで圧縮したもの)ですね!
下記回答は全然違ってます。大変失礼しました。


16進数を2進数にして、各バイトのLSBを左にして1本のビット列にするとは?

参照されているページにはそうは書いてません。「各バイトのLSBを左にして一本のビット列にしたもの。」と書いてあります。

つまり「各バイトの」であり「16進数を2進数に」とは書いてません。うーん、この微妙な違いがわかるでしょうか?なにがまずいかと言えば「16進数」と言われても「何ケタの16進数なのか?」というのがわかりませんがこのページで話題にしているのはあきらかに特定のビット数幅での処理です。「各バイトの」と言われれば「あぁ、8bitごとに何かするんだな」ということがわかります。

各バイトのLSBを左にして一本のビット列にしたもの。

は「1バイトずつ先頭から取り出し(通常はMSBを左(先)にLSBを右(後)に並べるが)それを逆順に並べる」と解釈すべきです。また変換は8bitごとに(どのビットも落とさずに全て変換対象にする)ので上位の0を省略してはいけません。1バイトの内容を16進数を0xで始めた2桁, 2進数を0bで始まる8桁で表すことにすると、

0x63 => 0b01100011 =>左右反転は=> 0x11000110 です。
        (A)


(A)を先頭の0のビットを省略し0b1100011と解釈してはいけません。質問者さんは先頭の0を「いらないビット」と解釈してしまったため混乱しているのだと思います。

投稿 2017/12/05 18:13

編集 2017/12/05 18:58

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/05 18:35

    自分にはこのページを書いた人がDEFLATE部分の16進表記(こちらが実際のファイルの中身と思われる)からどうやってすぐ次のビットの羅列に変換したのかさっぱりわかりませんでした。PNGの仕様を見た方が早い気がしました・・・
    変な回答してしまいごめんなさい。

    キャンセル

  • 2017/12/05 18:43

    ちゃんと理解してませんが、おそらく63 60...というバイト列に対してzlib圧縮データをデコードした結果のビット列が2進数のところに書いてあるような予感がします。このページの著者さんはzlibを展開するところは「DEFLATEデータって書いてあるから察してもらえるだろう」と考えたのかも知れません。
    この部分がzlib圧縮されているのは(一次情報源でなくてすみませんが)
    http://darkcrowcorvus.hatenablog.jp/entry/2017/02/12/235044
    をみてそう思いました。

    キャンセル

  • 2017/12/05 18:45

    コメントありがとうございます。おっしゃるとおり、文章を解釈できていないと感じています。
    なぜ「各バイトの」で8ビットごとにとわかるんでしょう…?
    ~勉強しました。~
    そうか、1バイト=8ビットだからですね。なるほど。
    次の疑問。この場合、2ケタごとの63とか60とかが8ビットなのでしょうか。acも8ビット?
    とりあえず2進数の8桁にしてみます。

    前から考えます。「LSBを左にする」を左右を反転すると読むとので、
    0x63→0b01100011-LSBを左にする→0b11000110
    0x60→0b01100000-LSBを左にする→0b00000110
    0x20→0b00100000-LSBを左にする→0b00000100
    です。もともと8桁単位なので見やすいように区切りをいれてつなげると、次のようになります。

    11000110 00000110 00000100

    最初のひとつは合致しましたが、2個目も3個目もだめです。
    11000110 00011111 11110011 00000011 00000000 00100010 00000110
    まだなにか足りないでしょうか?

    キャンセル

  • 2017/12/05 18:50

    はい。さらにコメントありがとうございます。
    11月25日からずっとpngを読もうとしていて、現在、DEFLATEを分離するところまではたどりつきました。だいぶpngの仕様書関係のページを読んだのですが、どうもいまいちぴんと来なくて、この5日ほどつまっています。それでヘルプを出した次第です。

    キャンセル

  • 2017/12/05 18:51

    さらにさらにコメントありがとうございます。
    ハフマンコードでビット圧縮…。むむむ。
    ぜんぜん読み解けてなくて申しわけないです…。

    キャンセル

  • 2017/12/05 18:54

    ハフマンコードはまだ気にしなくていいと思います。問題はzlib圧縮だと思います。

    zlib圧縮したものが63 60...という16進数のデータバイトと思うのですが上にコメントしたようにこれをzlib圧縮データの解凍処理をほどこしてそれを2進数のビット列に並べたのが
    11000110 00011111...
    というデータなのだと想像します。最初のバイト0x63はビット列を逆順にすれば
    11000110となり合致しますが、次のバイト0x60はどうやっても0001111にはなりません。
    だからこれは63 60..を単純にビット順を反転しただけのものではないと思いました。
    少なくともこれを理解するにはzlibの圧縮・解凍アルゴリズムを把握しないと無理と思います。

    キャンセル

  • 2017/12/05 19:17

    さらにさらにコメントありがとうございます。
    なるほど。
    このご示唆いただいたページは5/6はすでに読んでいたのですが、1/6-4/6を読んでみました。こちらは初めて。それでおっしゃるとおり、zlibの理解が必要そうです。
    ざっくりは理解できたのですが、具体的なコードで検討するところには至らず、だいぶ時間がかかりそうな予感です。
    このhttp://darkcrowcorvus.hatenablog.jp/entry/2017/02/12/235044にはサンプルコードもあるのですがC++で読めず…。
    わたしはC#を使っているので…。
    まだ道のり遠そうです。
    ありがとうございます。

    キャンセル

  • 2017/12/05 19:26 編集

    質問者さんが読みかねている63 60の直前のバイトをみたところ

    18 …CMFバイト
    57 …FLGバイト

    CMF:0x18=>0001=>CINFO 1000=>CM

    1000 CM compression method=>8はdeflateアルゴリズムをあらわす
    0001 CINFO compression info=>deflateではwindow size=2^(1+8)=512 byte

    FLG: 0x57
    17 = FCHECK (check bits for CMF and FLG: よくわからんです。チェックサムっぽいやつかも
    0 = FDICT (preset dictionary)
    1 = FLEVEL (compression level: compressor used fast algorithm)
    こんな感じの仕様になっているようで512byteをウィンドウサイズとしてdeflateアルゴリズムでの圧縮で圧縮レベル1で初期辞書なしみたいな感じでした。

    deflateアルゴリズムの詳細は日本語ページ(下記)がありました。
    http://www.futomi.com/lecture/japanese/rfc1951.html
    さらっとみてすぐわかるようなものではなく理解しようとするならじっくり読み込まないといけないので自分に言えるヒントはこのあたりまでです。重ね重ね中途半端な回答してしまいすみませんでした。

    キャンセル

  • 2017/12/05 19:29

    うう・・・間違いなのにBAにしてはまずいと思うのですが・・・
    チャンス(他のよいコメントがつくなどしたら)遠慮なくBA外してください!

    キャンセル

  • 2017/12/05 23:08

    まあ質問も悪かったというか、当たっていた壁がなにかわかった、ということがわたしにとっては大きかったのです。ですから感謝です。

    キャンセル

0

1.リトルエンディアン、ビッグエンディアンについて、調べていないだけでしょうねぇ。
x86 / x64 はどちらでしょうか?調べてみてください。
⇒検索ワード:バイトオーダー、リトルエンディアン、ビッグエンディアンなど
2.C# とだけあっても、回答者には、環境が不明です。
OS、開発環境等について、書込みしてください。
3.LSB / MSB についても、左:MSB 、右:LSB や、左:LSB、右:MSB の資料があったりします。注意してください。

投稿 2017/12/05 18:03

編集 2017/12/05 18:16

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/05 18:21

    早速ありがとうございます。
    63 60 20 19 fc c7 01 18 70 4a 20 5b 81 ac 08 c5 6a ca 24 00
    をリトルエンディアンに変換すると、
    00 24 CA 6A C5 08 AC 81 5B 20 4A 70 18 01 C7 FC 19 20 60 63

    先頭の00はどうやっても0なのでとりあえず措くとして、

    24→100100-LSBを左にする→001001
    CA→11001010-LSBを左にする→01010011
    6A→1101010-LSBを左にする→0101011

    どれを選んでも、
    11000110 00011111 11110011 00000011 00000000 00100010 00000110
    には合致しそうにないです…。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

ただいまの回答率

91.36%

関連した質問

同じタグがついた質問を見る

  • C#

    4777questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。