"zlib: inflate error = -3 (data error)" with custom png implementation - algorithm

I'm implementing a PNG encoder in VHDL for learning purposes. It works with image sizes from 1x1 to 4x4. At the image size of 5x5 there is a behaviour I can't understand:
When encoding raw data with values 0...24, the encoding works. However, when using raw data with values 255...231, it generates a broken image.
Input values 0...24:
> hexdump -C png_encoder/gen/test_img_no_compression_5x5.png
00000000 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 |.PNG........IHDR|
00000010 00 00 00 05 00 00 00 05 08 00 00 00 00 a8 04 79 |...............y|
00000020 39 00 00 00 4c 49 44 41 54 78 01 00 04 00 fb ff |9...LIDATx......|
00000030 00 00 01 02 00 04 00 fb ff 03 04 00 05 00 04 00 |................|
00000040 fb ff 06 07 08 09 00 04 00 fb ff 00 0a 0b 0c 00 |................|
00000050 04 00 fb ff 0d 0e 00 0f 00 04 00 fb ff 10 11 12 |................|
00000060 13 00 04 00 fb ff 00 14 15 16 01 02 00 fd ff 17 |................|
00000070 18 0b a4 01 2d d5 1f a2 6d 00 00 00 00 49 45 4e |....-...m....IEN|
00000080 44 ae 42 60 82 |D.B`.|
00000085
> pngcheck -vv png_encoder/gen/test_img_no_compression_5x5.png
File: png_encoder/gen/test_img_no_compression_5x5.png (133 bytes)
chunk IHDR at offset 0x0000c, length 13
5 x 5 image, 8-bit grayscale, non-interlaced
chunk IDAT at offset 0x00025, length 76
zlib: deflated, 32K window, superfast compression
row filters (0 none, 1 sub, 2 up, 3 avg, 4 paeth):
0 0 0 0 0 (5 out of 5)
chunk IEND at offset 0x0007d, length 0
No errors detected in png_encoder/gen/test_img_no_compression_5x5.png (3 chunks, -432.0% compression).
Input values 255...231:
> hexdump -C png_encoder/gen/test_img_no_compression_5x5.png
00000000 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 |.PNG........IHDR|
00000010 00 00 00 05 00 00 00 05 08 00 00 00 00 a8 04 79 |...............y|
00000020 39 00 00 00 4c 49 44 41 54 78 01 00 04 00 fb ff |9...LIDATx......|
00000030 00 ff fe fd 00 04 00 fb ff fc fb 00 fa 00 04 00 |................|
00000040 fb ff f9 f8 f7 f6 00 04 00 fb ff 00 f5 f4 f3 00 |................|
00000050 04 00 fb ff f2 f1 00 f0 00 04 00 fb ff ef ee ed |................|
00000060 ec 00 04 00 fb ff 00 eb ea e9 01 02 00 fd ff e8 |................|
00000070 e7 6a 21 17 bc 9a 17 87 e7 00 00 00 00 49 45 4e |.j!..........IEN|
00000080 44 ae 42 60 82 |D.B`.|
00000085
> pngcheck -vv png_encoder/gen/test_img_no_compression_5x5.png
File: png_encoder/gen/test_img_no_compression_5x5.png (133 bytes)
chunk IHDR at offset 0x0000c, length 13
5 x 5 image, 8-bit grayscale, non-interlaced
chunk IDAT at offset 0x00025, length 76
zlib: deflated, 32K window, superfast compression
row filters (0 none, 1 sub, 2 up, 3 avg, 4 paeth):
zlib: inflate error = -3 (data error)
(0 out of 5)
ERRORS DETECTED in png_encoder/gen/test_img_no_compression_5x5.png
How to interpret the error message zlib: inflate error = -3 (data error)?
I read https://www.zlib.net/zlib_how.html, but didn't find more specific information. My first guess was the row filters are incorrect, but since both files are structured the same, this is unlikely. Is there something wrong with the ADLER32 calculation in the second case (possibly some overflow)?

It was an overflow in the ADLER32 checksum calculation. Specifically, there were two 16 bit numbers added and truncated before applying the modulo with 65521. Unfortunately my ADLER32 unittest didn't catch it, yet.
However, the error message was shown several times during the implementation and I was always not sure about the cause. If anybody could elaborate the error message or explain how to get a better error message, I would be glad to hear it.

Related

mifare 4k classic write does not work as expected

I want to write to a mifare classic 4k, using the following APDU command (UPDATE BINARY):
APDU = {FF D6 00 20 10 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0Fh}
It seems fine as a get a 90 00 result...
but when i read the card back I always got the following (even with different data...):
sector: 8 (block 32), auth OK
032: D5 41 00 EA 00 FF 13 3E 86 6A 00 00 00 00 69 FF
033: D5 41 00 EA 00 FF 13 3E 86 6A 00 00 00 00 69 FF
034: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
035: 00 00 00 00 00 00 FF 07 80 69 FF FF FF FF FF FF
where does this string D5 41 00 EA 00 FF 13 3E 86 6A 00 00 00 00 69 FF come from?
Note that i didn't change any setting on the card and was properly authenticated. It was a blank card and i didn't touch the trailer.
I m using a ACR122 reader (this command comes direct from the documentation of the reader...)
Ok i found my problem, i was setting the wrong size for the cbSendLength parameter in SCardTransmit.
Now i set the correct one (the whole size of the APDU command: 21) and it works fine.
Sorry.

How to extract bitmap images from .slide file generated by a CytoVision Platform

I am working with neural network to classify images.
I have some files generated by a CytoVision Platform. I would like to use the images in those files but I need to extract them somehow.
These .slide files contain several images of apparently 16kb each one.
I have developed a program in C that I am currently running on linux to extract each 16kb in files. I should build a header in order to use those images.
I don't know which format they have.
If I look at the entire file as a bitmap with FileAlyzer I can see this:
File as a bitmap
This link should allow anyone to download an example file:
https://ufile.io/2ibdq
This is what it seems to be one image header:
42 4D 31 00 00 00 00 00 40 8F 40 05 00 9E 5F 98 D7 47 60 A1 40 01 04 4D 65 74 31 00 00 00 00 00 40 8F 40 05 00 64 31 2E 29 B5 46 DC 40 01 04 4D 65 74 32 00 00 00 00 00 40 8F 40 05 00 87 7D 26 70 88 C0 C5 40 01 04 4D 65 74 33 00 00 00 00 00 40 8F 40 05 00 C8 97 53 05 BB 0D 0F 41 01 04 54 65 78 31 00 00 00 00 00 00 D0 40 05 00 00 00 00 00 00 40 5C 40 07 04 54 65 78 32 00 00 00 00 00 00 D0 40 05 00 00 00 00 00 00 00 44 40 07 04 54 65 78 33 00 00 00 00 00 00 D0 40 05 00 00 00 00 00 00 90 76 40 07 04 54 65 78 34 00 00 00 00 00 00 D0 40 05 00 00 00 00 00 00 F4 CD 40 07 0A 43 68 72 6F 6D 73 41 72 65 61 00 00 00 00 00 4C BD 40 05 00 F3 76 84 D3 82 85 74 40 07 08 42 6F 75 6E 64 61 72 79 00 00 00 00 00 88 B3 40 05 00 D9 CE F7 53 E3 AD 7E 40 07 04 41 72 65 61 00 00 00 00 00 88 B3 40 05 00 20 EF 55 2B 13 0B 85 40 07 07 4F 62 6A 65 63 74 73 00 00 00 00 00 00 69 40 05 00 00 00 00 00 00 00 18 40 03 04 43 69 72 63 00 00 00 00 00 40 8F 40 05 00 9D E5 51 0E 5C 34 65 40 03 03 42 47 52 00 00 00 00 00 40 8F 40 05 00 7D 0C CE C7 E0 AC 86 40 03 04 54 65 78 35 00 00 00 00 00 00 D0 40 05 00 00 00 00 00 00 00 53 40 07 04 41 52 41 54 00 00 00 00 00 40 8F 40 05 00 86 89 F7 23 A7 79 7E 40 07 05 43 6C 61 73 73 00 00 00 00 00 00 F0 3F 05 00 00 00 00 00 00 00 F0 BF 00 01 00 00 00 01 00 00 00
With notepad++ I can see the previous hex like this:
BM1 #? ??G`?Met1 #? d1.)??Met2 #? ?&p?bMet3 #? ?S?ATex1 ? #\#Tex2 ? D#Tex3 ? ?#Tex4 ? ??
ChromsArea L? ???t#Boundary ?# ???~#Area ?# ?bObjects i# #Circ #? ?Q\4e#BGR #? }??#Tex5 ? S#ARAT #? Ð??~#Class ?? ?? #
Hope someone can give me an idea about the format of the images and what info I can extract from the header.

DEBUG DOS program to view memory

I have just started studying X86 Assembly Language.
My doubt -
When I am using the DOS DEBUG program to look at memory location, I am getting slightly different values on examining the same memory location using two different segment:offset addresses. I.e.-
Aren't D 40[0]:17 and D 41[0]:7 supposed to give exactly same output? since both of them give same address on adding segment + offset = 400+17 = 410+7 = 417H
The results which I get - (notice they are slightly different)
-D 40:17
0040:0010 00-00 00 1E 00 1E 00 0D 1C .........
0040:0020 44 20 20 39 34 05 34 05-3A 27 39 0A 0D 1C 44 20 D 94.4.:'9...D
0040:0030 20 39 34 05 30 0B 3A 27-31 02 37 08 0D 1C 00 00 94.0.:'1.7.....
0040:0040 93 00 C3 00 00 00 00 00-00 03 50 00 00 10 00 00 ..........P.....
0040:0050 00 18 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0040:0060 0F 0C 00 D4 03 29 30 00-00 00 00 00 91 DA 10 00 .....)0.........
0040:0070 00 00 00 00 00 00 08 00-14 14 14 14 01 01 01 01 ................
0040:0080 1E 00 3E 00 18 10 00 60-F9 11 0B 00 50 01 00 00 ..>....`....P...
0040:0090 00 00 00 00 00 00 10 .......
-D 41:7
0041:0000 00-00 00 2C 00 2C 00 44 20 ...,.,.D
0041:0010 20 39 34 05 31 02 3A 27-37 08 0D 1C 0D 1C 44 20 94.1.:'7.....D
0041:0020 20 39 34 05 30 0B 3A 27-31 02 37 08 0D 1C 00 00 94.0.:'1.7.....
0041:0030 08 00 C3 00 00 00 00 00-00 03 50 00 00 10 00 00 ..........P.....
0041:0040 00 18 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0041:0050 0F 0C 00 D4 03 29 30 00-00 00 00 00 1C DB 10 00 .....)0.........
0041:0060 00 00 00 00 00 00 08 00-14 14 14 14 01 01 01 01 ................
0041:0070 1E 00 3E 00 18 10 00 60-F9 11 0B 00 50 01 00 00 ..>....`....P...
0041:0080 00 00 00 00 00 00 10 .......
You are looking at the BIOS data area, whose contents changes over time since it contains things like the state of shift/control/alt keys, the read/write positions of the keyboard buffer and the timer.

Trying to extract pixel values from a given PNG image

Trying to understand PNG format.
Consider this PNG Image:
The Image is taken from here
In Hex Editor , it looks like this:
89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52 00 00 00 80 00 00 00 44 08 02 00 00 00
C6 25 AA 3E 00 00 00 C2 49 44 41 54 78 5E ED D4 81 06 C3 30 14 40 D1 B7 34 DD FF FF 6F
B3 74 56 EA 89 12 6C 28 73 E2 AA 34 49 03 87 D6 FE D8 7B 89 BB 52 8D 3B 87 FE 01 00 80
00 00 10 00 00 02 00 40 00 00 08 00 00 01 00 20 00 00 04 00 80 00 00 10 00 00 02 00 40
00 00 08 00 00 01 00 20 00 00 00 D4 5E 6A 64 4B 94 F5 98 7C D1 F4 92 5C 5C 3E CF 9C 3F
73 71 58 5F AF 8B 79 5B EE 96 B6 47 EB F1 EA D1 CE B6 E3 75 3B E6 B9 95 8D C7 CE 03 39
C9 AF C6 33 93 7B 66 37 CF AB BF F9 C9 2F 08 80 00 00 10 00 00 02 00 40 00 00 08 00 00
01 00 20 00 00 04 00 80 00 00 10 00 00 02 00 40 00 00 08 00 00 01 00 20 00 00 8C 37 DB
68 03 20 FB ED 96 65 00 00 00 00 49 45 4E 44 AE 42 60 82
Equivalent characters:
‰PNG........IHDR...€...D.....Æ%ª>...ÂIDATx^íÔ..Ã0.#Ñ·4Ýÿÿo³tVê‰.l(sâª4I.‡ÖþØ{‰
»R.;‡þ..€.......#....... ....€.......#....... ...Ô^jdK”õ˜|Ñô’\\>Ïœ?sqX_¯
‹y[î–¶GëñêÑζãu;湕.ÇÎ.9ɯÆ3“{f7Ï«¿ùÉ/.€.......#....... ....€.......#....... ..Œ7Ûh.
ûí–e....IEND®B`‚
The same is shown in following Screenshot of the HEX Editor:
I am trying to reverse engineer this image to extract the header part and the RGB pixel values. I read about the PNG and also here , and so far I have noted the following about this Image:
The IHDR chunk must appear FIRST. It contains:
Width: 4 bytes
Height: 4 bytes
Bit depth: 1 byte
Color type: 1 byte
Compression method: 1 byte
Filter method: 1 byte
Interlace method: 1 byte
Below I am starting reading the HEX Data in sequence:
1- First 8-bytes: This is the 8-Byte signature
89 50 4E 47 0D 0A 1A 0A
Equivalently this is : %PNG as can be seen in HEX Editor
A valid PNG image must contain an IHDR chunk, one or more IDAT chunks, and an IEND chunk.
2- Chunk: Length
00 00 00 0D
3-Chunk: Chunk Type
49 48 44 52
Which is IHDR.
http://www.w3.org/TR/PNG-Chunks.html
4- Chunk: Width of the Image (in Decimal 128)
00 00 00 80
5- Chunk: Height of the image (in Decimal 68)
00 00 00 44
6- Chunk: BIT DEPTH (1 byte )
08
7- Chunk: Color Type
02
8- Compression method
00
9- Filter method:
00
10- Interlace method:
00
11- What is the following data?
C6 25 AA 3E 00 00 00 C2
12-- IDAT
49 44 41 54
13- What is this data (after IDAT):
78 5E ED D4 81 06 C3 30 14 40 D1 B7 34 DD FF FF 6F B3 74 56 EA 89 12 6C 28 73 E2 AA 34 49 03 87 D6 FE D8 7B 89 BB 52 8D 3B 87 FE 01 00 80 00 00 10 00 00 02 00 40 00 00 08 00 00 01 00 20 00 00 04 00 80 00 00 10 00 00 02 00 40 00 00 08 00 00 01 00 20 00 00 00 D4 5E 6A 64 4B 94 F5 98 7C D1 F4 92 5C 5C 3E CF 9C 3F 73 71 58 5F AF 8B 79 5B EE 96 B6 47 EB F1 EA D1 CE B6 E3 75 3B E6 B9 95 8D C7 CE 03 39 C9 AF C6 33 93 7B 66 37 CF AB BF F9 C9 2F 08 80 00 00 10 00 00 02 00 40 00 00 08 00 00 01 00 20 00 00 04 00 80 00 00 10 00 00 02 00 40 00 00 08 00 00 01 00 20 00 00 8C 37 DB 68 03 20 FB ED 96 65 00 00 00 00
14- IEND:
49 45 4E 44
15- Last 4 bytes
AE 42 60 82
What are these ?
Can some help me understand, points 11, 13 and 15 above? And where are the Pixel values? The Image is having (128 x 68 pixels)
Purpose of knowing these details:
Once I know these details, I will generate my own 16 bit PNG image. I already have pixel values, so my job would be to introduce headers etc.
I dont know if there is software that can perform this job.
UPDATE
I understand now because of compression, I would not be able to locate the pixel values.
I got the idea that I can write a file in OpenCV and save it as png. Well now my direct question is: I have a binary file having gray-scale 16 bit-pixel values. Can I write this in OpenCV as 16 bit PNG ?
Although it might be interesting to learn about what PNG Images actually are, and how the image is actually represented in the file, you don't need to know this to generate a PNG file.
Note that PNG uses lossless compression, which means you won't get two bytes per pixel.
You can generate your image in a program and output it in PNG format using many of the libraries that there are out there.
For example, you can make your image in OpenCV and then output it with imWrite. One of the parameters can make it output to a PNG.
If you have the gray-scale 16-bit pixel values, then you can put them into a Mat.
Then convert that to an IplImage: Converting cv::Mat to IplImage*
Then you can output it to a file.
Just for completeness (eboix's answer is right on the spot)
11- What is the following data?
C6 25 AA 3E 00 00 00 C2
Each chunk ends with a CRC (4 bytes), and starts with 4 bytes that tell its length.
So, C6 25 AA 3E is the CRC of the previous chunk (IHDR) and 00 00 00 C2 (194) is the length of the following (IDAT) chunk.
In the same way, the last 4 bytes is the CRC of the IEND chunk.
I did not look too carefully but from looking at the structure...
Q11.
C6 25 AA 3E = CRC32
00 00 00 C2 = Size of next chunk
Q13.
check the png spec's you referred to earlier that looks like the IDAT chunk you allready know the compression applied to it!
Q15.
AE 42 60 82 = CRC32

What is the smallest valid jpeg file size (in bytes)

I'd like to screen some jpegs for validity before I send them across the network for more extensive inspection. It is easy enough to check for a valid header and footer, but what is the smallest size (in bytes) a valid jpeg could be?
A 1x1 grey pixel in 125 bytes using arithmetic coding, still in the JPEG standard even if most decoders can't decode it:
ff d8 : SOI
ff e0 ; APP0
00 10
4a 46 49 46 00 01 01 01 00 48 00 48 00 00
ff db ; DQT
00 43
00
03 02 02 02 02 02 03 02
02 02 03 03 03 03 04 06
04 04 04 04 04 08 06 06
05 06 09 08 0a 0a 09 08
09 09 0a 0c 0f 0c 0a 0b
0e 0b 09 09 0d 11 0d 0e
0f 10 10 11 10 0a 0c 12
13 12 10 13 0f 10 10 10
ff c9 ; SOF
00 0b
08 00 01 00 01 01 01 11 00
ff cc ; DAC
00 06 00 10 10 05
ff da ; SOS
00 08
01 01 00 00 3f 00 d2 cf 20
ff d9 ; EOI
I don't think the mentioned 134 byte example is standard, as it is missing an EOI. All decoders will handle this but the standard says it should end with one.
That file can be generated with:
#!/usr/bin/env bash
printf '\xff\xd8' # SOI
printf '\xff\xe0' # APP0
printf '\x00\x10'
printf '\x4a\x46\x49\x46\x00\x01\x01\x01\x00\x48\x00\x48\x00\x00'
printf '\xff\xdb' # DQT
printf '\x00\x43'
printf '\x00'
printf '\x03\x02\x02\x02\x02\x02\x03\x02'
printf '\x02\x02\x03\x03\x03\x03\x04\x06'
printf '\x04\x04\x04\x04\x04\x08\x06\x06'
printf '\x05\x06\x09\x08\x0a\x0a\x09\x08'
printf '\x09\x09\x0a\x0c\x0f\x0c\x0a\x0b'
printf '\x0e\x0b\x09\x09\x0d\x11\x0d\x0e'
printf '\x0f\x10\x10\x11\x10\x0a\x0c\x12'
printf '\x13\x12\x10\x13\x0f\x10\x10\x10'
printf '\xff\xc9' # SOF
printf '\x00\x0b'
printf '\x08\x00\x01\x00\x01\x01\x01\x11\x00'
printf '\xff\xcc' # DAC
printf '\x00\x06\x00\x10\x10\x05'
printf '\xff\xda' # SOS
printf '\x00\x08'
printf '\x01\x01\x00\x00\x3f\x00\xd2\xcf\x20'
printf '\xff\xd9' # EOI
and opened fine with GNOME Image Viewer 3.38.0 and GIMP 2.10.18 on Ubuntu 20.10.
Here's an upload on Imgur. Note that Imgur process the file making it larger however if you download it to check, and as seen below, the width=100 image shows white on Chromium 87:
It occurs to me you could make a progressive jpeg with only the DC coefficients, that a single grey pixel could be encoded in 119 bytes. This reads just fine in a few programs I've tried it in (Photoshop, GNOME Image Viewer 3.38.0, GIMP 2.10.18, and others).
ff d8 : SOI
ff db ; DQT
00 43
00
01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01
ff c2 ; SOF
00 0b
08 00 01 00 01 01 01 11 00
ff c4 ; DHT
00 14
00
01 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
03
ff da ; SOS
00 08
01 01 00 00 00 01 3F
ff d9 ; EOI
The main space savings is to only have one Huffman table. Although this is slightly smaller than the 125 byte arithmetic encoding given in another answer, the arithmetic encoding without the JFIF header would be smaller yet (107 bytes), so that should still be considered the smallest known.
The above file can be generated with:
#!/usr/bin/env bash
printf '\xff\xd8' # SOI
printf '\xff\xdb' # DQT
printf '\x00\x43'
printf '\x00'
printf '\x01\x01\x01\x01\x01\x01\x01\x01'
printf '\x01\x01\x01\x01\x01\x01\x01\x01'
printf '\x01\x01\x01\x01\x01\x01\x01\x01'
printf '\x01\x01\x01\x01\x01\x01\x01\x01'
printf '\x01\x01\x01\x01\x01\x01\x01\x01'
printf '\x01\x01\x01\x01\x01\x01\x01\x01'
printf '\x01\x01\x01\x01\x01\x01\x01\x01'
printf '\x01\x01\x01\x01\x01\x01\x01\x01'
printf '\xff\xc2' # SOF
printf '\x00\x0b'
printf '\x08\x00\x01\x00\x01\x01\x01\x11\x00'
printf '\xff\xc4' # DHT
printf '\x00\x14'
printf '\x00'
printf '\x01\x00\x00\x00\x00\x00\x00\x00'
printf '\x00\x00\x00\x00\x00\x00\x00\x00'
printf '\x03'
printf '\xff\xda' # SOS
printf '\x00\x08'
printf '\x01\x01\x00\x00\x00\x01\x3F'
printf '\xff\xd9' # EOI
Try the following (134 bytes):
FF D8 FF E0 00 10 4A 46 49 46 00 01 01 01 00 48 00 48 00 00
FF DB 00 43 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF C2 00 0B 08 00 01 00 01 01 01
11 00 FF C4 00 14 10 01 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 FF DA 00 08 01 01 00 01 3F 10
Source: Worlds Smallest, Valid JPEG? by Jesse_hz
Found "the tiniest GIF ever" with only 26 bytes.
47 49 46 38 39 61 01 00 01 00
00 ff 00 2c 00 00 00 00 01 00
01 00 00 02 00 3b
Python literal:
b'GIF89a\x01\x00\x01\x00\x00\xff\x00,\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x00;'
While I realize this is far from the smallest valid jpeg and has little or nothing to do with your actual question, I felt I should share this as I'd been looking for a very small JPEG that actually looked like something to do some testing with when i'd found your question. I'm sharing it here because its valid, its small, and it makes me ROFL.
Here is a 384 byte JPEG image that I made in photoshop. It is the letters ROFL hand drawn by me and then saved with max compression settings while still being sort of readable.
Hex sequences:
my #image_hex = qw{
FF D8 FF E0 00 10 4A 46 49 46 00 01 02 00 00 64
00 64 00 00 FF EC 00 11 44 75 63 6B 79 00 01 00
04 00 00 00 00 00 00 FF EE 00 0E 41 64 6F 62 65
00 64 C0 00 00 00 01 FF DB 00 84 00 1B 1A 1A 29
1D 29 41 26 26 41 42 2F 2F 2F 42 47 3F 3E 3E 3F
47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47
47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47
47 47 47 47 47 47 47 47 47 47 47 47 01 1D 29 29
34 26 34 3F 28 28 3F 47 3F 35 3F 47 47 47 47 47
47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47
47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47
47 47 47 47 47 47 47 47 47 47 47 47 47 FF C0 00
11 08 00 08 00 19 03 01 22 00 02 11 01 03 11 01
FF C4 00 61 00 01 01 01 01 00 00 00 00 00 00 00
00 00 00 00 00 00 04 02 05 01 01 01 01 00 00 00
00 00 00 00 00 00 00 00 00 00 00 02 04 10 00 02
02 02 02 03 01 00 00 00 00 00 00 00 00 00 01 02
11 03 00 41 21 12 F0 13 04 31 11 00 01 04 03 00
00 00 00 00 00 00 00 00 00 00 00 00 21 31 61 71
B1 12 22 FF DA 00 0C 03 01 00 02 11 03 11 00 3F
00 A1 7E 6B AD 4E B6 4B 30 EA E0 19 82 39 91 3A
6E 63 5F 99 8A 68 B6 E3 EA 70 08 A8 00 55 98 EE
48 22 37 1C 63 19 AF A5 68 B8 05 24 9A 7E 99 F5
B3 22 20 55 EA 27 CD 8C EB 4E 31 91 9D 41 FF D9
}; #this is a very tiny jpeg. it is a image representaion of the letters "ROFL" hand drawn by me in photoshop and then saved at the lowest possible quality settings where the letters could still be made out :)
my $image_data = pack('H2' x scalar(#image_hex), #image_hex);
my $url_escaped_image = uri_escape( $image_data );
URL escaped binary image data (can paste right into a URL)
%FF%D8%FF%E0%00%10JFIF%00%01%02%00%00d%00d%00%00%FF%EC%00%11Ducky%00%01%00%04%00%00%00%00%00%00%FF%EE%00%0EAdobe%00d%C0%00%00%00%01%FF%DB%00%84%00%1B%1A%1A)%1D)A%26%26AB%2F%2F%2FBG%3F%3E%3E%3FGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG%01%1D))4%264%3F((%3FG%3F5%3FGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG%FF%C0%00%11%08%00%08%00%19%03%01%22%00%02%11%01%03%11%01%FF%C4%00a%00%01%01%01%01%00%00%00%00%00%00%00%00%00%00%00%00%00%04%02%05%01%01%01%01%00%00%00%00%00%00%00%00%00%00%00%00%00%00%02%04%10%00%02%02%02%02%03%01%00%00%00%00%00%00%00%00%00%01%02%11%03%00A!%12%F0%13%041%11%00%01%04%03%00%00%00%00%00%00%00%00%00%00%00%00%00!1aq%B1%12%22%FF%DA%00%0C%03%01%00%02%11%03%11%00%3F%00%A1~k%ADN%B6K0%EA%E0%19%829%91%3Anc_%99%8Ah%B6%E3%EAp%08%A8%00U%98%EEH%227%1Cc%19%AF%A5h%B8%05%24%9A~%99%F5%B3%22%20U%EA'%CD%8C%EBN1%91%9DA%FF%D9
Here's the C++ routine I wrote to do this:
bool is_jpeg(const unsigned char* img_data, size_t size)
{
return img_data &&
(size >= 10) &&
(img_data[0] == 0xFF) &&
(img_data[1] == 0xD8) &&
((memcmp(img_data + 6, "JFIF", 4) == 0) ||
(memcmp(img_data + 6, "Exif", 4) == 0));
}
img_data points to a buffer containing the JPEG data.
I'm sure you need more bytes to have a JPEG that will decode to a useful image, but it's a fair bet that if the first 10 bytes pass this test, the buffer probably contains a JPEG.
EDIT: You can, of course, replace the 10 above with a higher value once you decide on one. 134, as suggested in another answer, for example.
It is not a requirement that JPEGs contain either a JFIF or Exif marker. But they must start with FF D8, and they must have a marker following that, so you can check for FF D8 FF.

Resources