Determine if a base64 string or a buffer contains JPEG or PNG without metadata? Possible?

前端 未结 2 1380
庸人自扰
庸人自扰 2021-01-14 17:14

Is there any way to do this using node, whether natively or with a plugin?

What I\'m trying to accomplish is to choose loseless or lossy image compression depending

相关标签:
2条回答
  • 2021-01-14 17:21

    The first eight bytes of a PNG file always contain the following values - see PNG Specification:

    (decimal)              137  80  78  71  13  10  26  10
    (hexadecimal)           89  50  4e  47  0d  0a  1a  0a
    (ASCII C notation)    \211   P   N   G  \r  \n \032 \n
    

    So, if I take 8 bytes from the start of any PNG file and base64 encode it as follows, I get:

    head -c8 test.png | base64
    iVBORw0KGgo=
    

    The first 2 bytes of every JPEG file contain ff d8 in hex - see Wikipedia entry for JPEG. So if I take any JPEG file and base64 encode the first two bytes as follows, I get:

    head -c2 test.jpg | base64
    /9g=
    

    So my suggestion would be to look at the first few (10 for PNG and 2 for JPEG, always excluding the =) characters of your base64-encoded file and see if they match what I am suggesting and then use that as the determinant - be sure to output error messages if your string matches neither in case the test is not sufficiently thorough for some reason!


    Why 10 characters for PNG? Because the guaranteed signature is 8 bytes, i.e. 64 bits and base64 splits into 6 bits at a time to generate a character, so the first 10 characters are the first 60 bits. The 11th character will vary depending on what follows the signature.

    Same logic for JPEG... 2 bytes is 16 bits, which means 2 characters each corresponding to 6 bits are guaranteed. The 3rd character will vary depending on what follows the 2-byte SOI marker.

    0 讨论(0)
  • 2021-01-14 17:34

    @MarkSetchell's answer above is correct in theory. However, in practice, it doesn't work for JPGs!

    It is true that head -c2 test.jpg | base64 produces /9g

    However

    head -c3 test.jpg | base64`
    /9j/
    

    So, if you want to "Determine if a base64 string or a buffer contains JPEG" you need to test that it starts with /9j not /9g!

    0 讨论(0)
提交回复
热议问题