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

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

新規登録して質問してみよう
ただいま回答率
85.48%
C#

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

Q&A

解決済

2回答

4665閲覧

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

nomurax

総合スコア32

C#

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

0グッド

0クリップ

投稿2017/12/05 08:44

編集2017/12/05 09:11

###前提・実現したいこと
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を左にする」を左右を反転すると読むと

63→1100011-LSBを左にする→1100011 60→1100000-LSBを左にする→0000011 20→100000-LSBを左にする→000001

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

###発生している問題

11000110 00001100 0001

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

###試したこと
次に、「LSBを左にする」をLSBのみを左に移動すると読むと

63→1100011-LSBを左にする→1110001 60→1100000-LSBを左にする→0110000 20→100000-LSBを左にする→010000

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

###発生している問題

11100010 11000001 0000

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

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

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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/12/05 09:03

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

回答2

0

ベストアンサー

本回答は間違いでした!
参照ページをよくみると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桁で表すことにすると、

text

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

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

投稿2017/12/05 09:13

編集2017/12/05 09:58
KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KSwordOfHaste

2017/12/05 09:35

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

2017/12/05 09:43

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

2017/12/05 09: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 まだなにか足りないでしょうか?
nomurax

2017/12/05 09:50

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

2017/12/05 09:51

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

2017/12/05 09:54

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

2017/12/05 10:17

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

2017/12/05 10: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 さらっとみてすぐわかるようなものではなく理解しようとするならじっくり読み込まないといけないので自分に言えるヒントはこのあたりまでです。重ね重ね中途半端な回答してしまいすみませんでした。
KSwordOfHaste

2017/12/05 10:29

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

2017/12/05 14:08

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

0

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

投稿2017/12/05 09:03

編集2017/12/05 09:16
daive

総合スコア2028

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nomurax

2017/12/05 09: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 には合致しそうにないです…。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問