0

I'm using a windows build of gphoto2 to generate a byte stream. Take the byte stream and look for the jpeg headers (ff d8) and footer (ff d9) and display a single image from the stream. Whenever I pass the parsed byte string into imdecode it returns None. I pass all of the data including the ff d8/ ff d9 into imdecode.

pipe = sp.Popen('gphoto2 --stdout-size --capture-movie', stdout = sp.PIPE)
founda=False
foundb=False
bytesl=b''
while True:
    bytesl=bytesl+pipe.stdout.readline()
    if ~founda:
        a = bytesl.find(b'\xff\xd8') # JPEG start
        bytesl = bytesl[a:]
        if a!=-1:
            founda=True
    if founda and ~foundb:
        b = bytesl.find(b'\xff\xd9') # JPEG end
        if a!=-1 and b!=-1:
            foundb=True
    if founda and foundb:
        jpgi = bytesl[:b+2]
        imfbuffh = cv2.imdecode(np.frombuffer(jpgi, dtype=np.uint8),cv2.IMREAD_COLOR)

I keep getting nothing from imdecode and I'm not sure why. The byte string appears to correctly parse the data. Any help would be greatly appreciated.

Edit: Something else I've noticed is if I just read a JPG from a file and I do a np.shape on the object from np.buffer I report something like (140000,1) versus when i do the np.shape when I'm reading it from the byte string I get (140000,). I've tried expanding the dimensions but that didn't work.

Edit2: Well I realized that the header for the mjpeg is not just a standard jpeg header. I'm not sure how to convert it to the standard format. If anyone has any tips that would be great.

Edit3: I simplified the output and write to file code to just read the pipe data.

I have two test cases one where I use --capture-movie 2 and one where I use --capture-image-and-download so that in the first case I capture 2 frames of MJPEG data and another where I capture 1 frame of jpeg data. I tried to display the data for both cases with my previous code and they failed to display the image even if I just wait for the stdout to finish rather than reading the data in real time.

Here is the code I used to just to write the bytes to a byte file. In my previous comment I was just recording the byte string from a print statement (stupid I know I'm not very good at this). Should be noted I think these byte strings need to be decoded.

pipe = sp.Popen('gphoto2 --stdout-size --capture-movie 2', stdout = sp.PIPE)
pipedata=pipe.stdout.read()
f = open('C:\\Users\\Work\\frame2out.txt', 'wb')
f.write(pipedata)

Attached are links to the two cases. 2 Frames from --capture-movie https://www.dropbox.com/s/3wvyg8s1tflzwaa/frame2out.txt?dl=0

Bytes from --capture-image-and-download https://www.dropbox.com/s/3arozhvfz6a77lr/imageout.txt?dl=0

Ricky Wahl
  • 11
  • 2
  • I don't think you can use `readline()` to read a binary file like a JPEG, because it isn't text and doesn't come in *"lines"*. Try `read(4096)` or similar. – Mark Setchell May 05 '20 at 06:49
  • Thanks for the tip I just tried that but I'm still getting the same errors. I think it's related to the header of each frame is not in JPEG format and I don't really know what I need to do to satisfy that or how to parse just the image data and create my own header. Also I'm not reading a JPEG, I have a stream of data coming in in MPEG format I'm trying to slice them into individual jpegs as they come in. – Ricky Wahl May 05 '20 at 07:08
  • You say the header is not standard, maybe you could be more explicit? Do you find the JPEG `0xff` `0xd8` or not? Do you find the JPEG `0xff` `0xd9` or not? Maybe you could accumulate say 1MB of MJPEG data and share it via Dropbox or Google Drive or somesuch. – Mark Setchell May 05 '20 at 08:20
  • Sure good Idea I was able to copy the whole byte string in a 1mb file. It is located here. Let me know if you're able to view it. https://www.dropbox.com/s/m7g54rpxq0h5ilb/bytes_MJPEG_slice.txt?dl=0 It does have ff d8 and ff d9 headers but other headers like the jfif_id is missing. – Ricky Wahl May 05 '20 at 14:27
  • I downloaded and looked at your data and it is not a valid JPEG. Can you update your question with you latest code showing how you read the MPEG stream - hopefully not with `readline()` - and how you saved the 1MB file so I can get a closer look please? – Mark Setchell May 05 '20 at 15:48
  • There's a Windows tool called `jpegsnoop` (I have never used it and have no idea if it is legitimate) but it may also give you some insights into the file. You appear to have an invalid DHT, which I tried unsuccessfully to replace with a decent DHT table - but I think the error is actually in the reading or writing. – Mark Setchell May 05 '20 at 15:49
  • Oh sir your best assumption is that I did something wrong haha I'm no programmer just a hobbyist most of my knowledge is from google. I updated the post to add more information please let me know if you can think of anything else. Thanks for the help! I'll try taking a look at jpegsnoop later tonight. – Ricky Wahl May 05 '20 at 17:08
  • It's not really my assumption that you did something wrong - it's just 30 years of programming tell me to check everything! :-) And anyway, we all make mistakes - it doesn't matter as long as we keep learning! – Mark Setchell May 05 '20 at 18:17

0 Answers0