In Java, extract JPEG from a URL and convert it to binary or hexadecimal, suitable for embedding in an RTF document

I'm trying to write a simple RTF document pretty much from scratch in Java, and I'm trying to embed a JPEG in a document. Here is an example JPEG (a 2x2-pixel JPEG consisting of three white pixels and a black pixel in the upper left, if you are interested) embedded in an RTF document (generated by WordPad that converted JPEG to WMF):

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

I read the RTF specification , and it looks like you can indicate that the image is JPEG, but since WordPad always converts images to WMF, I don't see an example of embedded JPEG. Therefore, I may also need to transcode from JPEG to WMF or something like that.

But basically, I'm looking for how to generate binary or hexadecimal (Spec, p.148: "These images can be in hexadecimal (default) or binary format.") JPEG format with the given file URL.

Thank!


EDIT: I have a stream that works fine, I think, but still don’t understand how to encode it, because whatever I do is not RTF-readable. For example, the above image looks like this:

ffd8ffe00104a464946011106006000ffdb0430211211222222223533333644357677767789b988a877adaabcccc79efdcebcccffdb04312223336336c878ccccccccccccccccccccccccccccccccccccccccccccccccccffc0011802023122021113111ffc401f001511111100000000123456789abffc40b5100213324355440017d123041151221314161351617227114328191a182342b1c11552d1f024336272829a161718191a25262728292a3435363738393a434445464748494a535455565758595a636465666768696a737475767778797a838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae1e2e3e4e5e6e7e8e9eaf1f2f3f4f5f6f7f8f9faffc401f103111111111000000123456789abffc40b51102124434754401277012311452131612415176171132232818144291a1b1c19233352f0156272d1a162434e125f11718191a262728292a35363738393a434445464748494a535455565758595a636465666768696a737475767778797a82838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae2e3e4e5e6e7e8e9eaf2f3f4f5f6f7f8f9faffda0c31021131103f0fdecf09f84f4af178574cd0b42d334fd1744d16d22bd3f4fb0b74b6b5bb78902450c512091c688aaaa8a0500014514507ffd9

This PHP library could do the trick, so I'm trying to port the appropriate part to Java. That's what:

$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;

But I do not know what the Java counterpart is dechex(ord($imageData{$i})). :( I only got to the function Integer.toHexString()that takes care of the part dechex....

Thanks to everyone. :)

+3
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 ( ). 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

EDIT: 0

EDIT: ints > _ <

+2

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

Source: https://habr.com/ru/post/1751088/


All Articles