В Java извлеките JPEG из URL и преобразуйте его в двоичную или шестнадцатеричную форму, подходящую для встраивания в документ RTF - PullRequest
3 голосов
/ 22 июня 2010

Я пытаюсь написать простой RTF-документ практически с нуля на Java, и я пытаюсь встраивать JPEG-документы в документ.Вот пример JPEG (2x2-пиксельный JPEG, состоящий из трех белых пикселей и черного пикселя в верхнем левом углу, если вам интересно), встроенный в документ RTF (созданный WordPad, который преобразовал JPEG в WMF):

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

Я читал спецификацию RTF , и похоже, что вы можете указать, что изображение является JPEG, но поскольку WordPad всегда конвертирует изображения в WMF, я могу 'См. пример встроенного JPEG.Так что мне может также понадобиться перекодировать из JPEG в WMF или что-то в этом роде ...

Но в основном я ищу способ генерирования двоичного или шестнадцатеричного числа (Spec, стр.148: «Эти картинкиможет быть в шестнадцатеричном (по умолчанию) или двоичном формате. ") формате JPEG с указанным URL-адресом файла.

Спасибо!


РЕДАКТИРОВАТЬ: У меня естьЯ думаю, что с потоковыми вещами все в порядке, но я все еще не понимаю, как именно их кодировать, потому что, что бы я ни делал, он не читается в формате 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 части ....

Спасибо всем.:)

Ответы [ 2 ]

2 голосов
/ 22 июня 2010

Учитывая 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 шестнадцатеричных цифр (что удваивает размер изображения без видимой причины).Все это хранится в сырой 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

РЕДАКТИРОВАТЬ: Обновлен пример кода для площадок 0 в шестнадцатеричных байтах

РЕДАКТИРОВАТЬ: отрицательные байты логически смещались вправо при преобразовании вцелые числа> _ <</p>

0 голосов
/ 16 августа 2013

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());}

Этот код принимает представление в одну строку, а результат сохраняется в файле.

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;
          }
        }
      }
    }
...