3

私はJavaでほとんどゼロから単純なRTFドキュメントを書き込もうとしており、ドキュメントにJPEGを埋め込もうとしています。RTFドキュメント(JPEGをWMFに変換したワードパッドによって生成された)に埋め込まれたJPEG(3つの白いピクセルと左上の黒いピクセルで構成される2x2ピクセルのJPEG)の例を次に示します。

{\pict\wmetafile8\picw53\pich53\picwgoal30\pichgoal30 
0100090000036e00000000004500000000000400000003010800050000000b0200000000050000
000c0202000200030000001e000400000007010400040000000701040045000000410b2000cc00
020002000000000002000200000000002800000002000000020000000100040000000000000000
000000000000000000000000000000000000000000ffffff00fefefe0000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000
0000001202af0801010000040000002701ffff030000000000
}

RTF仕様を読んでいて、画像がJPEGであることを指定できるようですが、ワードパッドは常に画像をWMFに変換するため、埋め込まれたJPEGの例を見ることができません。そのため、JPEGからWMFなどにトランスコードする必要が生じる可能性もあります。

しかし、基本的には、ファイルURLを指定してJPEGの2進数または16進数(仕様、p.148:「これらの画像は16進数(デフォルト)または2進数形式にすることができます。」)形式を生成する方法を探しています。

ありがとう!


編集:私はストリームのものがうまく機能していると思いますが、それでもそれをエンコードする方法を正確に理解していません。なぜなら、私が何をしていても、RTFで読み取れないからです。たとえば、上の画像は代わりに次のように表示されます。

ffd8ffe00104a464946011106006000ffdb0430211211222222223533333644357677767789b988a877adaabcccc79efdcebcccffdb04312223336336c878ccccccccccccccccccccccccccccccccccccccccccccccccccffc0011802023122021113111ffc401f001511111100000000123456789abffc40b5100213324355440017d123041151221314161351617227114328191a182342b1c11552d1f024336272829a161718191a25262728292a3435363738393a434445464748494a535455565758595a636465666768696a737475767778797a838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae1e2e3e4e5e6e7e8e9eaf1f2f3f4f5f6f7f8f9faffc401f103111111111000000123456789abffc40b51102124434754401277012311452131612415176171132232818144291a1b1c19233352f0156272d1a162434e125f11718191a262728292a35363738393a434445464748494a535455565758595a636465666768696a737475767778797a82838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae2e3e4e5e6e7e8e9eaf2f3f4f5f6f7f8f9faffda0c31021131103f0fdecf09f84f4af178574cd0b42d334fd1744d16d22bd3f4fb0b74b6b5bb78902450c512091c688aaaa8a0500014514507ffd9

このPHPライブラリでうまくいくので、関連する部分をJavaに移植しようとしています。これがあります:

$imageData = file_get_contents($this->_file);
$size = filesize($this->_file);

$hexString = '';

for ($i = 0; $i < $size; $i++) {
    $hex = dechex(ord($imageData{$i}));

    if (strlen($hex) == 1) {
        $hex = '0' . $hex;
    }

    $hexString .= $hex;
}

return $hexString;

しかし、Javaの類似物が何であるかはわかりませんdechex(ord($imageData{$i}))。:(私はInteger.toHexString()その部分を処理する関数までしか得られませんでしたdechex...。

皆さんありがとう。:)

4

2 に答える 2

2

任意のファイルのファイルURLを指定すると、(簡潔にするために例外処理を省略して)実行することで対応するバイトを取得できます。

int BUF_SIZE = 512;
URL fileURL = new URL("http://www.somewhere.com/someurl.jpg");
InputStream inputStream = fileURL.openStream();
byte [] smallBuffer = new byte[BUF_SIZE];
ByteArrayOutputStream largeBuffer = new ByteArrayOutputStream();
int numRead = BUF_SIZE;
while(numRead == BUF_SIZE) {
    numRead = inputStream.read(smallBuffer,0,BUF_SIZE);
    if(numRead > 0) {
        largeBuffer.write(smallBuffer,0,BUF_SIZE);
    }
}
byte [] bytes = largeBuffer.toByteArray();

私は今あなたのPHPスニペットを見ていて、RTFが奇妙な仕様であることに気づいています!画像の各バイトは2桁の16進数としてエンコードされているようです(これは明らかな理由もなく画像のサイズを2倍にします)。すべてが生のASCIIエンコーディングで保存されます。だから、あなたはしたいと思うでしょう...

StringBuilder hexStringBuilder = new StringBuilder(bytes.length * 2);
for(byte imageByte : bytes) {
    String hexByteString = Integer.toHexString(0x000000FF & (int)imageByte);
    if(hexByteString .size() == 1) {
        hexByteString = "0" + hexByteString ;
    }
    hexStringBuilder.append(hexByteString);
}
String hexString = hexStringBuilder.toString();
byte [] hexBytes = hexString.getBytes("UTF-8"); //Could also use US-ASCII

編集:コードサンプルを更新して、16進バイトの0を埋めるようにしました

編集:ints> _ <に変換すると、負のバイトが論理的に右シフトされていました

于 2010-06-22T02:01:45.477 に答える
0

https://joseluisbz.wordpress.com/2013/07/26/exploring-a-wmf-file-0x000900/

多分これを助ける:

        String HexRTFBytes = "Representations text of bytes from Image RTF File";
        String Destiny = "The path of the output File";
        FileOutputStream wmf;
        try {
          wmf = new FileOutputStream(Destiny);
          HexRTFBytes = HexRTFBytes.replaceAll("\n", ""); //Erase New Lines
          HexRTFBytes = HexRTFBytes.replaceAll(" ", ""); //Erase Blank spaces
          int NumBytesWrite = HexRTFBytes.length();
          int WMFBytes = NumBytesWrite/2;//One byte is represented by 2 characters
          byte[] ByteWrite = new byte[WMFBytes];
          for (int i = 0; i < WMFBytes; i++){
            se = HexRTFBytes.substring(i*2,i*2+2);
            int Entero = Integer.parseInt(se,16);
            ByteWrite[i] = (byte)Entero;
          }
          wmf.write(ByteWrite);
          wmf.close();
        }
        catch (FileNotFoundException fnfe)
        {System.out.println(fnfe.toString());}
        catch (NumberFormatException fnfe)
        {System.out.println(fnfe.toString());}
        catch (EOFException eofe)
        {System.out.println(eofe.toString());}
        catch (IOException ioe)
        {System.out.println(ioe.toString());}

このコードは 1 つの文字列で表現を取り、結果はファイルに保存されます。

https://joseluisbz.wordpress.com/2011/06/22/script-de-clases-rtf-para-jsp-y-php/

画像ファイルの表現を取得したい場合は、これを使用できます。

    private void ByteStreamImageString(byte[] ByteStream) {
      this.Format = 0;
      this.High = 0;
      this.Wide = 0;
      this.HexImageString = "Error";
      if (ByteStream[0]== (byte)137 && ByteStream[1]== (byte)80 && ByteStream[2]== (byte)78){
        this.Format = PNG; //PNG
        this.High = this.Byte2PosInt(ByteStream[22],ByteStream[23]);
        this.Wide = this.Byte2PosInt(ByteStream[18],ByteStream[19]);
      }
      if (ByteStream[0]== (byte)255 && ByteStream[1]== (byte)216
          && ByteStream[2]== (byte)255 && ByteStream[3]== (byte)224){
        this.Format = JPG; //JPG
        int PosJPG = 2;
        while (PosJPG < ByteStream.length){
          String M = String.format("%02X%02X", ByteStream[PosJPG+0],ByteStream[PosJPG+1]);
          if (M.equals("FFC0") || M.equals("FFC1") || M.equals("FFC2") || M.equals("FFC3")){
            this.High = this.Byte2PosInt(ByteStream[PosJPG+5],ByteStream[PosJPG+6]);
            this.Wide = this.Byte2PosInt(ByteStream[PosJPG+7],ByteStream[PosJPG+8]);
          }
          if (M.equals("FFDA")) {
            break;
          }
          PosJPG = PosJPG+2+this.Byte2PosInt(ByteStream[PosJPG+2],ByteStream[PosJPG+3]);
        }
      }
      if (this.Format > 0) {
        this.HexImageString = "";
        int Salto = 0;
        for (int i=0;i < ByteStream.length; i++){
          Salto++;
          this.HexImageString += String.format("%02x", ByteStream[i]);
          if (Salto==64){
            this.HexImageString += "\n"; //To make readable
            Salto = 0;
          }
        }
      }
    }
于 2013-08-16T04:08:25.973 に答える