Ooops
February 27, 2021, 04:28:06 AM

Author Topic: [bmx] JPEG reference parser by BlitzSupport [ 1+ years ago ]  (Read 577 times)

Offline BlitzBot

  • Jr. Member
  • **
  • Posts: 1
Title : JPEG reference parser
Author : BlitzSupport
Posted : 1+ years ago

Description : This is mainly intended as a reference for parsing a JPEG file correctly/safely. Includes workarounds for common invalid/unexpected/truncated data, checks all byte reads (I think!) and deliberately parses the entire JPEG file.

Why? I wrote a simple JPEG parser as part of this Code Archives entry...

<a href="codearcs5629.html?code=2477" >Retrieve image information without loading entire image[/url]

... but it just aborts after reading the relevant information, which is fine for what it does.

However, on trying to expand on this to read EXIF data recently, although I had some success and now know how to do this, my EXIF reader crashed on files with unexpected data, as EXIF requires you to seek ahead/back, loop around all over the place, etc. (That's also why this code, unlike the above, will only read local files, since you can't seek back in online streams; in fact, this limitation turns out to be a deliberate part of the TIFF specification -- and EXIF uses the TIFF format, within a JPEG file, to store its data! Oh, what fun!)

So, this code tries to read each and every marker/section in a JPEG file properly and should serve as a reasonable basis for anyone trying to read JPEGs (in any language)... and for me to try and write a crash-free EXIF reader.

This is not optimised for speed (skipping scan data is done byte-by-byte and would be better done by reading chunks of the file for proper usage, but this brings in some complications so not done here).

TIP: You can add an "Exit" at the end of each Case statement under "Frame markers (image data)" to just show the width and height information for the main image in each file and ignore the rest of the file.

Tested on 15000+ images! If you find any JPEG files that cause it to spew, let me know...

Prepare for disappointment unless you're writing your own JPEG/EXIF reader! It was interesting to see just how many JPEG files are badly written, and how much wasteage there is in many files too. JPEGs can contain thumbnail images (that's why Windows, digital cameras, etc, can display previews so quickly), but my very own camera has produced JPEG photos 3072 x 2048 @ 24-bit that also contained a 'hidden' secondary image of 1536 x 1024 @ 24-bit. That's not a thumbnail! Don't know what that is! Kind of explains the 2 MB size... no need to worry about storage space on modern SD cards, I guess...

To self: "Right... deep breath... EXIF."


Code :
Code: BlitzMax
  1. ' -----------------------------------------------------------------------------
  2. ' JPEG reference parser...
  3. ' -----------------------------------------------------------------------------
  4.  
  5. SuperStrict
  6.  
  7. ' -----------------------------------------------------------------------------
  8. ' READ THIS! Change to your own image folder for demo...
  9. ' -----------------------------------------------------------------------------
  10.  
  11. ' Demo code at bottom includes single-file test...
  12.  
  13. Local folder$
  14. folder = "H:DocsMy Pictures"
  15.  
  16. ' -----------------------------------------------------------------------------
  17. ' Utility functions...
  18. ' -----------------------------------------------------------------------------
  19.  
  20. Function StreamRemainder:Int (jpeg:TStream)
  21.         Return StreamSize (jpeg) - StreamPos (jpeg)
  22. End Function
  23.  
  24. Function SkipData (jpeg:TStream, datalength:Int)
  25.         ReadString jpeg, Min (datalength, StreamRemainder (jpeg))
  26. End Function
  27.  
  28. Function PrintImageData (jpeg:TStream, datalength:Short)
  29.  
  30.         ' Check we have enough bytes left in file, abort if not...
  31.        
  32.         If StreamRemainder (jpeg) < datalength
  33.                 SkipData jpeg, datalength
  34.                 Return
  35.         EndIf
  36.        
  37.         Local bpp:Int = ReadByte (jpeg)         ' Bits per pixel
  38.         Local height:Int = ReadShort (jpeg)     ' Height
  39.         Local width:Int = ReadShort (jpeg)              ' Width
  40.         Local components:Int = ReadByte (jpeg)  ' Components per pixel (1 for grayscale, 3 for RGB)
  41.        
  42.         Local depth:Int = bpp * components
  43.         Local colors:Int = 2 ^ depth
  44.  
  45.         SkipData jpeg, datalength - 6 ' ' Skip rest of frame header after reading above six bytes...
  46.        
  47.         Print "Image details: " + width + " x " + height + " @ " + depth + "-bit (" + Int (2 ^ depth) + " colours)"
  48.  
  49. End Function
  50.  
  51. ' -----------------------------------------------------------------------------
  52. ' JPEG parser...
  53. ' -----------------------------------------------------------------------------
  54.  
  55. Function ParseJPEG (f:String)
  56.  
  57.         Print "Info for " + f + " (file size: " + FileSize (f) + " bytes)"
  58.         Print ""
  59.  
  60.         Local jpeg:TStream = BigEndianStream (ReadStream (f))
  61.                                
  62.         If jpeg And StreamSize (jpeg) > 1 ' Next two bytes are safe!
  63.  
  64.                 Try
  65.  
  66.                         ' Start of Image (SOI) marker ($FFD8) -- MUST BE PRESENT!
  67.                        
  68.                         If ReadByte (jpeg) = $FF And ReadByte (jpeg) = $D8
  69.  
  70.                                 Print ""
  71.                                 Print "--------------------------------------------------------------------------------"
  72.                                 Print "Start of Image marker $D8 found at byte offset 0"
  73.                                 Print "--------------------------------------------------------------------------------"
  74.                                 Print "Assuming JPEG file"
  75.                                
  76.                                 Local loop:Int                  ' For byte seek loops
  77.                                 Local datalength:Int    ' Block length store
  78.  
  79.                                 Local checkff:Byte              ' Byte to be tested for $FF (start of block)...
  80.                                 Local marker:Byte               ' Block marker code
  81.  
  82.                                 Local startofblock:Int  ' Record marker location
  83.                                 Local startofdata:Int   ' Record data location after marker
  84.  
  85.                                 Local markerinfo:String
  86.                                
  87.                                 ' OK, start reading the file...
  88.                                
  89.                                 While Not Eof (jpeg)
  90.                
  91.                                         ' Searching for blocks beginning with $FF, then single byte marker, then data...
  92.                                        
  93.                                         ' |FFxx|length_of_block|data_data_data...
  94.  
  95.                                         ' |FFxx|length_of_block| is four bytes total, two each...
  96.                                        
  97.                                         ' ---------------------------------------------------------
  98.                                         ' You are here --> |FFxx|length_of_block|data_data_data...
  99.                                         ' ---------------------------------------------------------
  100.                                        
  101.                                         startofblock = StreamPos (jpeg) ' Tracker for bytes read...
  102.                                        
  103.                                         ' Looking for FF first...
  104.                                        
  105.                                         Repeat
  106.                                                 checkff = ReadByte (jpeg) ' Some Photoshop 7 files have a huge string of zeroes directly after block's stated data length
  107.                                         Until (checkff = $FF) Or (Eof (jpeg))
  108.  
  109.                                         ' Used later...
  110.                                        
  111.                                         startofdata = 0
  112.                                         datalength = 0
  113.                                         markerinfo = ""
  114.                                        
  115.                                         If Not Eof (jpeg) And checkff = $FF
  116.        
  117.                                                 ' ... then xx, the byte AFTER the FF block marker, skipping if FF (padding)...
  118.                                                
  119.                                                 Repeat
  120.                                                         marker = ReadByte (jpeg)
  121.                                                 Until (marker <> $FF) Or (Eof (jpeg))
  122.  
  123.                                                 ' -----------------------------------------------------
  124.                                                 ' We are now here --> |length_of_block|data_data_data...
  125.                                                 ' -----------------------------------------------------
  126.                                                
  127.                                                 ' Grab next two bytes (length of block) before proceeding, unless marker is standalone...
  128.  
  129.                                                 Select marker
  130.                                                
  131.                                                         Case $D0, $D1, $D2, $D3, $D4, $D5, $D6, $D7, $D8, $D9, $0, $FF
  132.                                                        
  133.                                                                 ' Standalone markers with no following data.
  134.                                                        
  135.                                                         Default
  136.  
  137.                                                                 datalength = 0
  138.                                                                
  139.                                                                 If StreamRemainder (jpeg) > 1
  140.                                                                         datalength = ReadShort (jpeg) - 2 ' The 2 subtracted bytes store the length itself...
  141.                                                                 EndIf
  142.                                                
  143.                                                 End Select
  144.                                                
  145.                                                 ' -----------------------------------------------------
  146.                                                 ' Now here --> |data_data_data...
  147.                                                 ' -----------------------------------------------------
  148.                                                
  149.                                                 ' Record start of data so we can deduce how many bytes are read in each Case afterwards...
  150.  
  151.                                                 startofdata = StreamPos (jpeg)
  152.                                                
  153.                                                 Select marker
  154.  
  155.                                                         ' ------------------------------------------------
  156.                                                         ' Padding
  157.                                                         ' ------------------------------------------------
  158.                                                        
  159.                                                         Case $0, $FF
  160.                                                        
  161.                                                                 ' Ignore these...
  162.  
  163.                                                         ' ------------------------------------------------
  164.                                                         ' Frame decoding table markers
  165.                                                         ' ------------------------------------------------
  166.  
  167.                                                         Case $C4
  168.                                                        
  169.                                                                 markerinfo = "Define Huffman Table"
  170.  
  171.                                                                 Print ""
  172.                                                                 Print "--------------------------------------------------------------------------------"
  173.                                                                 Print markerinfo + " marker $" + Right (Hex (marker), 2) + " found at byte offset " + startofblock
  174.                                                                 Print "--------------------------------------------------------------------------------"
  175.                                                                 Print ""
  176.                                                                
  177.                                                                 If datalength
  178.                                                                         Print "Data starts at byte offset " + startofdata + " and is " + datalength + " bytes long"
  179.                                                                         SkipData jpeg, datalength                                                      
  180.                                                                 Else
  181.                                                                         Print "No data for this type of marker"
  182.                                                                 EndIf
  183.                                                                
  184.                                                         Case $CC
  185.                                                        
  186.                                                                 markerinfo = "Define Arithmetic Table"
  187.  
  188.                                                                 Print ""
  189.                                                                 Print "--------------------------------------------------------------------------------"
  190.                                                                 Print markerinfo + " marker $" + Right (Hex (marker), 2) + " found at byte offset " + startofblock
  191.                                                                 Print "--------------------------------------------------------------------------------"
  192.                                                                 Print ""
  193.                                                                
  194.                                                                 If datalength
  195.                                                                         Print "Data starts at byte offset " + startofdata + " and is " + datalength + " bytes long"
  196.                                                                         SkipData jpeg, datalength                                                      
  197.                                                                 Else
  198.                                                                         Print "No data for this type of marker"
  199.                                                                 EndIf
  200.                                                                
  201.                                                         ' ------------------------------------------------
  202.                                                         ' Frame markers (image data)
  203.                                                         ' ------------------------------------------------
  204.  
  205.                                                         ' NB. Printing data for ALL image frames found, but the first one listed is always the main image...
  206.                                                        
  207.                                                         ' You can add an "Exit" at the end of each of these cases to only read the main image
  208.                                                         ' information...
  209.                                                        
  210.                                                         Case $C0, $C1, $C2, $C3
  211.                                                        
  212.                                                                 markerinfo = "Start of Frame (non-differential Huffman coding)"
  213.  
  214.                                                                 Print ""
  215.                                                                 Print "--------------------------------------------------------------------------------"
  216.                                                                 Print markerinfo + " marker $" + Right (Hex (marker), 2) + " found at byte offset " + startofblock
  217.                                                                 Print "--------------------------------------------------------------------------------"
  218.                                                                 Print ""
  219.                                                                
  220.                                                                 If datalength
  221.                                                                         Print "Data starts at byte offset " + startofdata + " and is " + datalength + " bytes long"
  222.                                                                         PrintImageData jpeg, datalength
  223.                                                                 Else
  224.                                                                         Print "No data for this type of marker"
  225.                                                                 EndIf
  226.  
  227.                                                         Case $C5, $C6, $C7
  228.                                                        
  229.                                                                 markerinfo = "Start of Frame (differential Huffman coding)"
  230.  
  231.                                                                 Print ""
  232.                                                                 Print "--------------------------------------------------------------------------------"
  233.                                                                 Print markerinfo + " marker $" + Right (Hex (marker), 2) + " found at byte offset " + startofblock
  234.                                                                 Print "--------------------------------------------------------------------------------"
  235.                                                                 Print ""
  236.                                                                
  237.                                                                 If datalength
  238.                                                                         Print "Data starts at byte offset " + startofdata + " and is " + datalength + " bytes long"
  239.                                                                         PrintImageData jpeg, datalength
  240.                                                                 Else
  241.                                                                         Print "No data for this type of marker"
  242.                                                                 EndIf
  243.                                                
  244.                                                         Case $C8, $C9, $CA, $CB
  245.                                                        
  246.                                                                 markerinfo = "Start of Frame (non-differential arithmetic coding)"
  247.  
  248.                                                                 Print ""
  249.                                                                 Print "--------------------------------------------------------------------------------"
  250.                                                                 Print markerinfo + " marker $" + Right (Hex (marker), 2) + " found at byte offset " + startofblock
  251.                                                                 Print "--------------------------------------------------------------------------------"
  252.                                                                 Print ""
  253.                                                                
  254.                                                                 If datalength
  255.                                                                         Print "Data starts at byte offset " + startofdata + " and is " + datalength + " bytes long"
  256.                                                                         PrintImageData jpeg, datalength
  257.                                                                 Else
  258.                                                                         Print "No data for this type of marker"
  259.                                                                 EndIf
  260.                                                
  261.                                                         Case $CD, $CE, $CF
  262.                                                        
  263.                                                                 markerinfo = "Start of Frame (differential arithmetic coding)"
  264.  
  265.                                                                 Print ""
  266.                                                                 Print "--------------------------------------------------------------------------------"
  267.                                                                 Print markerinfo + " marker $" + Right (Hex (marker), 2) + " found at byte offset " + startofblock
  268.                                                                 Print "--------------------------------------------------------------------------------"
  269.                                                                 Print ""
  270.                                                                
  271.                                                                 If datalength
  272.                                                                         Print "Data starts at byte offset " + startofdata + " and is " + datalength + " bytes long"
  273.                                                                         PrintImageData jpeg, datalength
  274.                                                                 Else
  275.                                                                         Print "No data for this type of marker"
  276.                                                                 EndIf
  277.  
  278.                                                         ' ------------------------------------------------
  279.                                                         ' Restart markers (only used when decoding images)
  280.                                                         ' ------------------------------------------------
  281.  
  282.                                                         Case $D0, $D1, $D2, $D3, $D4, $D5, $D6, $D7
  283.                                                        
  284.                                                                 markerinfo = "Restart"
  285.  
  286.                                                                 Print ""
  287.                                                                 Print "--------------------------------------------------------------------------------"
  288.                                                                 Print markerinfo + " marker $" + Right (Hex (marker), 2) + " found at byte offset " + startofblock
  289.                                                                 Print "--------------------------------------------------------------------------------"
  290.                                                                 Print ""
  291.                                                                
  292.                                                                 Print "No data for this type of marker"
  293.                                                                
  294.                                                                 ' Standalone marker, no following data...
  295.                                                                
  296.                                                         ' ------------------------------------------------
  297.                                                         ' Start of JPEG data
  298.                                                         ' ------------------------------------------------
  299.  
  300.                                                         Case $D8
  301.                                                        
  302.                                                                 markerinfo = "Start of Image"
  303.  
  304.                                                                 Print ""
  305.                                                                 Print "--------------------------------------------------------------------------------"
  306.                                                                 Print markerinfo + " marker $" + Right (Hex (marker), 2) + " found at byte offset " + startofblock
  307.                                                                 Print "--------------------------------------------------------------------------------"
  308.                                                                 Print ""
  309.                                                                
  310.                                                                 If datalength
  311.                                                                         Print "Data starts at byte offset " + startofdata + " and is " + datalength + " bytes long"
  312.                                                                         SkipData jpeg, datalength                                                      
  313.                                                                 Else
  314.                                                                         Print "No data for this type of marker"
  315.                                                                 EndIf
  316.                                                                
  317.                                                                 ' Now going through scan (picture) data and ignoring it because it's bloody complicated...
  318.                                                        
  319.                                                                 Local newff:Byte
  320.                                                                 Local foundmarker:Int
  321.                                                                
  322.                                                                 Local startdatascan:Int = StreamPos (jpeg)
  323.                                                                 Local bytesread:Int
  324.                                                                
  325.                                                                 While Not Eof (jpeg) And (Not foundmarker)
  326.                                                                                
  327.                                                                         If ReadByte (jpeg) = $FF
  328.  
  329.                                                                                 If Not Eof (jpeg)
  330.  
  331.                                                                                         ' See if it's a new block marker...
  332.                                                                                        
  333.                                                                                         newff = ReadByte (jpeg)
  334.                                                                                        
  335.                                                                                         If (newff <> 0)
  336.                                                                                                 foundmarker = newff
  337.                                                                                                 Exit
  338.                                                                                         EndIf
  339.  
  340.                                                                                 EndIf
  341.  
  342.                                                                         EndIf
  343.                                                                        
  344.                                                                 Wend
  345.                                                                
  346.                                                                 If Eof (jpeg)
  347.                                                                        
  348.                                                                         If foundmarker
  349.                                                                                 Print "~nMarker $" + Right (Hex (foundmarker), 2) + " found at end of file"
  350.                                                                         Else
  351.                                                                                 Print "~nFile ends with extraneous data"
  352.                                                                         EndIf
  353.                                                                        
  354.                                                                 Else
  355.                                                                        
  356.                                                                         ' Go back two bytes if we ran into a marker so that it can be processed in main loop...
  357.                                                                        
  358.                                                                         If foundmarker Then SeekStream jpeg, StreamPos (jpeg) - 2
  359.                                                                        
  360.                                                                 EndIf
  361.                                                                        
  362.                                                         ' ------------------------------------------------
  363.                                                         ' End of JPEG data
  364.                                                         ' ------------------------------------------------
  365.  
  366.                                                         Case $D9
  367.  
  368.                                                                 markerinfo = "End of Image"
  369.  
  370.                                                                 Print ""
  371.                                                                 Print "--------------------------------------------------------------------------------"
  372.                                                                 Print markerinfo + " marker $" + Right (Hex (marker), 2) + " found at byte offset " + startofblock
  373.                                                                 Print "--------------------------------------------------------------------------------"
  374.                                                                 Print ""
  375.                                                                
  376.                                                                 If datalength
  377.                                                                         Print "Data starts at byte offset " + startofdata + " and is " + datalength + " bytes long"
  378.                                                                         SkipData jpeg, datalength                                                      
  379.                                                                 Else
  380.                                                                         Print "No data for this type of marker"
  381.                                                                 EndIf
  382.  
  383.                                                                 ' Now seeking through scan (picture) data...
  384.                                                        
  385.                                                                 Local newff:Byte
  386.                                                                 Local foundmarker:Int
  387.                                                                
  388.                                                                 Local startdatascan:Int = StreamPos (jpeg)
  389.                                                                 Local bytesread:Int
  390.                                                                
  391.                                                                 While Not Eof (jpeg) And (Not foundmarker)
  392.                                                                                
  393.                                                                         If ReadByte (jpeg) = $FF
  394.  
  395.                                                                                 If Not Eof (jpeg)
  396.                                                                                
  397.                                                                                         ' See if it's a new block marker...
  398.                                                                                        
  399.                                                                                         newff = ReadByte (jpeg)
  400.                                                                                        
  401.                                                                                         If (newff <> 0) And (newff <> $FF)
  402.                                                                                                 foundmarker = newff
  403.                                                                                                 Exit
  404.                                                                                         EndIf
  405.                                                                                        
  406.                                                                                 EndIf
  407.  
  408.                                                                         EndIf
  409.                                                                        
  410.                                                                 Wend
  411.                                                                
  412.                                                                 If Eof (jpeg)
  413.                                                                        
  414.                                                                         If foundmarker
  415.                                                                                 Print "~nMarker $" + Right (Hex (foundmarker), 2) + " found at end of file"
  416.                                                                         Else
  417.                                                                                 Print "~nFile ends with extraneous data"
  418.                                                                         EndIf
  419.                                                                        
  420.                                                                 Else
  421.                                                                        
  422.                                                                         ' Go back two bytes if we ran into a marker so that it can be processed in main loop...
  423.                                                                        
  424.                                                                         If foundmarker Then SeekStream jpeg, StreamPos (jpeg) - 2
  425.                                                                        
  426.                                                                 EndIf
  427.  
  428.                                                         ' ------------------------------------------------
  429.                                                         ' Image data
  430.                                                         ' ------------------------------------------------
  431.  
  432.                                                         Case $DA
  433.                                                        
  434.                                                                 markerinfo = "Start of Scan"
  435.                                                                
  436.                                                                 Print ""
  437.                                                                 Print "--------------------------------------------------------------------------------"
  438.                                                                 Print markerinfo + " marker $" + Right (Hex (marker), 2) + " found at byte offset " + startofblock
  439.                                                                 Print "--------------------------------------------------------------------------------"
  440.                                                                 Print ""
  441.                                                                
  442.                                                                 If datalength
  443.                                                                         Print "Data starts at byte offset " + startofdata + " and is " + datalength + " bytes long"
  444.                                                                         SkipData jpeg, datalength                                                      
  445.                                                                 Else
  446.                                                                         Print "No data for this type of marker"
  447.                                                                 EndIf
  448.                                                                
  449.                                                                 ' Now seeking through scan (picture) data...
  450.                                                        
  451.                                                                 Local newff:Byte
  452.                                                                 Local foundmarker:Int
  453.                                                                
  454.                                                                 Local startdatascan:Int = StreamPos (jpeg)
  455.                                                                 Local bytesread:Int
  456.                                                                
  457.                                                                 While Not Eof (jpeg) And (Not foundmarker)
  458.                                                                                
  459.                                                                         If ReadByte (jpeg) = $FF
  460.                                                                        
  461.                                                                                 If Not Eof (jpeg)
  462.          
  463.                                                                                         ' See if it's a new block marker...
  464.                                                                                        
  465.                                                                                         newff = ReadByte (jpeg)
  466.                                                                                        
  467.                                                                                         Select newff
  468.                                                                                
  469.                                                                                                 ' Ignore 0 (means valid FF value in scan data), FF (possible padding data), D0-D7 (restart markers)...
  470.                                                                                                
  471.                                                                                                 Case $0, $FF, $D0, $D1, $D2, $D3, $D4, $D5, $D6, $D7
  472.                                                                                                
  473.                                                                                                         ' Ignore these and move on...
  474.        
  475.                                                                                                 Default
  476.                                                                                                        
  477.                                                                                                         ' Valid marker; break out of bank stream reader and then the file stream reader...
  478.                                                                        
  479.                                                                                                         foundmarker = newff
  480.                                                                                                         Exit
  481.                                                                                                        
  482.                                                                                         End Select
  483.                                                                                
  484.                                                                                 EndIf
  485.                                                                        
  486.                                                                         EndIf
  487.                                                                        
  488.                                                                 Wend
  489.                                                                
  490.                                                                 If Eof (jpeg)
  491.                                                                        
  492.                                                                         If foundmarker
  493.                                                                                 Print "~nMarker $" + Right (Hex (foundmarker), 2) + " found at end of file"
  494.                                                                         Else
  495.                                                                                 Print "~nFile ends with extraneous data"
  496.                                                                         EndIf
  497.                                                                        
  498.                                                                 Else
  499.                                                                        
  500.                                                                         ' Go back two bytes if we ran into a marker so that it can be processed in main loop...
  501.                                                                        
  502.                                                                         If foundmarker Then SeekStream jpeg, StreamPos (jpeg) - 2
  503.                                                                        
  504.                                                                 EndIf
  505.                                                                
  506.                                                         ' ------------------------------------------------
  507.                                                         ' Quantization table, ignored
  508.                                                         ' ------------------------------------------------
  509.  
  510.                                                         Case $DB
  511.                                                        
  512.                                                                 markerinfo = "Define Quantization Table"
  513.  
  514.                                                                 Print ""
  515.                                                                 Print "--------------------------------------------------------------------------------"
  516.                                                                 Print markerinfo + " marker $" + Right (Hex (marker), 2) + " found at byte offset " + startofblock
  517.                                                                 Print "--------------------------------------------------------------------------------"
  518.                                                                 Print ""
  519.                                                                
  520.                                                                 If datalength
  521.                                                                         Print "Data starts at byte offset " + startofdata + " and is " + datalength + " bytes long"
  522.                                                                         SkipData jpeg, datalength                                                      
  523.                                                                 Else
  524.                                                                         Print "No data for this type of marker"
  525.                                                                 EndIf
  526.  
  527.                                                         ' ------------------------------------------------
  528.                                                         ' Number of lines in scan, ignored
  529.                                                         ' ------------------------------------------------
  530.                                                                
  531.                                                         Case $DC
  532.                                                        
  533.                                                                 markerinfo = "Define Number of Lines"
  534.  
  535.                                                                 Print ""
  536.                                                                 Print "--------------------------------------------------------------------------------"
  537.                                                                 Print markerinfo + " marker $" + Right (Hex (marker), 2) + " found at byte offset " + startofblock
  538.                                                                 Print "--------------------------------------------------------------------------------"
  539.                                                                 Print ""
  540.                                                                
  541.                                                                 If datalength
  542.                                                                         Print "Data starts at byte offset " + startofdata + " and is " + datalength + " bytes long"
  543.                                                                         SkipData jpeg, datalength                                                      
  544.                                                                 Else
  545.                                                                         Print "No data for this type of marker"
  546.                                                                 EndIf
  547.                                                                
  548.                                                         ' ------------------------------------------------
  549.                                                         ' Restart interval, ignored
  550.                                                         ' ------------------------------------------------
  551.                                                                
  552.                                                         Case $DD
  553.                                                        
  554.                                                                 markerinfo = "Define Restart Interval"
  555.                                                                
  556.                                                                 Print ""
  557.                                                                 Print "--------------------------------------------------------------------------------"
  558.                                                                 Print markerinfo + " marker $" + Right (Hex (marker), 2) + " found at byte offset " + startofblock
  559.                                                                 Print "--------------------------------------------------------------------------------"
  560.                                                                 Print ""
  561.                                                                
  562.                                                                 If datalength
  563.                                                                         Print "Data starts at byte offset " + startofdata + " and is " + datalength + " bytes long"
  564.                                                                         SkipData jpeg, datalength                                                      
  565.                                                                 Else
  566.                                                                         Print "No data for this type of marker"
  567.                                                                 EndIf
  568.                                                                
  569.                                                         ' ------------------------------------------------
  570.                                                         ' Hierarchical progression, ignored
  571.                                                         ' ------------------------------------------------
  572.                                                                
  573.                                                         Case $DE
  574.                                                        
  575.                                                                 markerinfo = "Define Hierarchical Progression"
  576.                                                                
  577.                                                                 Print ""
  578.                                                                 Print "--------------------------------------------------------------------------------"
  579.                                                                 Print markerinfo + " marker $" + Right (Hex (marker), 2) + " found at byte offset " + startofblock
  580.                                                                 Print "--------------------------------------------------------------------------------"
  581.                                                                 Print ""
  582.                                                                
  583.                                                                 If datalength
  584.                                                                         Print "Data starts at byte offset " + startofdata + " and is " + datalength + " bytes long"
  585.                                                                         SkipData jpeg, datalength                                                      
  586.                                                                 Else
  587.                                                                         Print "No data for this type of marker"
  588.                                                                 EndIf
  589.                                                                
  590.                                                         ' ------------------------------------------------
  591.                                                         ' Expand reference components, ignored
  592.                                                         ' ------------------------------------------------
  593.                                                                
  594.                                                         Case $DF
  595.                                                        
  596.                                                                 markerinfo = "Expand reference components"
  597.  
  598.                                                                 Print ""
  599.                                                                 Print "--------------------------------------------------------------------------------"
  600.                                                                 Print markerinfo + " marker $" + Right (Hex (marker), 2) + " found at byte offset " + startofblock
  601.                                                                 Print "--------------------------------------------------------------------------------"
  602.                                                                 Print ""
  603.                                                                
  604.                                                                 If datalength
  605.                                                                         Print "Data starts at byte offset " + startofdata + " and is " + datalength + " bytes long"
  606.                                                                         SkipData jpeg, datalength                                                      
  607.                                                                 Else
  608.                                                                         Print "No data for this type of marker"
  609.                                                                 EndIf
  610.                                                                
  611.                                                         ' ------------------------------------------------
  612.                                                         ' APP0 marker (mainly to state JFIF-compatibility)
  613.                                                         ' ------------------------------------------------
  614.                                                                
  615.                                                         Case $E0 ' JFIF marker
  616.                                                
  617.                                                                 markerinfo = "JFIF/APP0"
  618.  
  619.                                                                 Print ""
  620.                                                                 Print "--------------------------------------------------------------------------------"
  621.                                                                 Print markerinfo + " marker $" + Right (Hex (marker), 2) + " found at byte offset " + startofblock
  622.                                                                 Print "--------------------------------------------------------------------------------"
  623.                                                                 Print ""
  624.                                                                
  625.                                                                 If datalength
  626.                                                                         Print "Data starts at byte offset " + startofdata + " and is " + datalength + " bytes long"
  627.                                                                         SkipData jpeg, datalength                                                      
  628.                                                                 Else
  629.                                                                         Print "No data for this type of marker"
  630.                                                                 EndIf
  631.  
  632.                                                         ' ------------------------------------------------
  633.                                                         ' APP1 marker (mainly used for EXIF data)
  634.                                                         ' ------------------------------------------------
  635.  
  636.                                                         Case $E1 ' EXIF information
  637.                                                        
  638.                                                                 markerinfo = "EXIF/APP1"
  639.  
  640.                                                                 Print ""
  641.                                                                 Print "--------------------------------------------------------------------------------"
  642.                                                                 Print markerinfo + " marker $" + Right (Hex (marker), 2) + " found at byte offset " + startofblock
  643.                                                                 Print "--------------------------------------------------------------------------------"
  644.                                                                 Print ""
  645.                                                                
  646.                                                                 If datalength
  647.                                                                         Print "Data starts at byte offset " + startofdata + " and is " + datalength + " bytes long"
  648.                                                                         SkipData jpeg, datalength                                                      
  649.                                                                 Else
  650.                                                                         Print "No data for this type of marker"
  651.                                                                 EndIf
  652.  
  653.                                                         ' ------------------------------------------------
  654.                                                         ' Application-specific markers
  655.                                                         ' ------------------------------------------------
  656.  
  657.                                                         Case $E2, $E3, $E4, $E5, $E6, $E7, $E8, $E9, $EA, $EB, $EC, $EE, $EF
  658.                                                                
  659.                                                                 markerinfo = "Application-specific"
  660.  
  661.                                                                 Print ""
  662.                                                                 Print "--------------------------------------------------------------------------------"
  663.                                                                 Print markerinfo + " marker $" + Right (Hex (marker), 2) + " found at byte offset " + startofblock
  664.                                                                 Print "--------------------------------------------------------------------------------"
  665.                                                                 Print ""
  666.                                                                
  667.                                                                 If datalength
  668.                                                                         Print "Data starts at byte offset " + startofdata + " and is " + datalength + " bytes long"
  669.                                                                         SkipData jpeg, datalength                                                      
  670.                                                                 Else
  671.                                                                         Print "No data for this type of marker"
  672.                                                                 EndIf
  673.                                                                
  674.                                                         ' ------------------------------------------------
  675.                                                         ' Application-specific, but usually Photoshop
  676.                                                         ' ------------------------------------------------
  677.  
  678.                                                         Case $ED
  679.                                                        
  680.                                                                 markerinfo = "Photoshop/APP14"
  681.  
  682.                                                                 Print ""
  683.                                                                 Print "--------------------------------------------------------------------------------"
  684.                                                                 Print markerinfo + " marker $" + Right (Hex (marker), 2) + " found at byte offset " + startofblock
  685.                                                                 Print "--------------------------------------------------------------------------------"
  686.                                                                 Print ""
  687.                                                                
  688.                                                                 If datalength
  689.                                                                         Print "Data starts at byte offset " + startofdata + " and is " + datalength + " bytes long"
  690.                                                                         SkipData jpeg, datalength                                                      
  691.                                                                 Else
  692.                                                                         Print "No data for this type of marker"
  693.                                                                 EndIf
  694.                                                                
  695.                                                         ' ------------------------------------------------
  696.                                                         ' Comment marker
  697.                                                         ' ------------------------------------------------
  698.  
  699.                                                         Case $FE
  700.                                                        
  701.                                                                 markerinfo = "Comment"
  702.                                                                
  703.                                                                 Print ""
  704.                                                                 Print "--------------------------------------------------------------------------------"
  705.                                                                 Print markerinfo + " marker $" + Right (Hex (marker), 2) + " found at byte offset " + startofblock
  706.                                                                 Print "--------------------------------------------------------------------------------"
  707.                                                                 Print ""
  708.  
  709.                                                                 If datalength
  710.                                                                         SkipData jpeg, datalength                                                      
  711.                                                                         Print "Data starts at byte offset " + startofdata + " and is " + datalength + " bytes long"
  712.                                                                 Else
  713.                                                                         Print "No data for this type of marker"
  714.                                                                 EndIf
  715.  
  716.                                                         ' ------------------------------------------------
  717.                                                         ' Unknown marker. This shouldn't appear!
  718.                                                         ' ------------------------------------------------
  719.  
  720.                                                         Default
  721.                                                                
  722.                                                                 markerinfo = "UNIMPLEMENTED"
  723.  
  724.                                                                 Print ""
  725.                                                                 Print "--------------------------------------------------------------------------------"
  726.                                                                 Print markerinfo + " marker $" + Right (Hex (marker), 2) + " found at byte offset " + startofblock
  727.                                                                 Print "--------------------------------------------------------------------------------"
  728.                                                                 Print ""
  729.                                                                
  730.                                                                 If datalength
  731.                                                                         Print "Data starts at byte offset " + startofdata + " and is " + datalength + " bytes long"
  732.                                                                         SkipData jpeg, datalength                                                      
  733.                                                                 Else
  734.                                                                         Print "No data for this type of marker"
  735.                                                                 EndIf
  736.                                                                
  737.                                                 End Select
  738.  
  739.                                         Else
  740.                                        
  741.                                                 ' We reached end of file or read an invalid byte (should be an $FF marker)
  742.                                                 ' so ignore the rest of the file...
  743.  
  744.                                                 Exit
  745.  
  746.                                         EndIf
  747.                                        
  748.                                 Wend
  749.                
  750.                         Else
  751.                                 Print "Not a JPEG file!"
  752.                         EndIf
  753.  
  754.                         Catch ReadFail:Object
  755.                         Notify "Read error in " + f + "; " + StreamPos (jpeg)
  756.  
  757.                 End Try
  758.                
  759.                 CloseStream jpeg
  760.  
  761.         Else
  762.                 Print "File not found, or shorter than two required bytes!"
  763.         EndIf
  764.  
  765. End Function
  766.  
  767. ' -----------------------------------------------------------------------------
  768. ' D E M O . . .
  769. ' -----------------------------------------------------------------------------
  770.  
  771. ' Uncomment these 4 lines to test a single picture...
  772.  
  773. 'Local img$
  774. 'img = "CHANGE ME"
  775. 'ParseJPEG img
  776. 'End
  777.  
  778. ' -----------------------------------------------------------------------------
  779. ' Or name a local folder (sub-folders will be read too)...
  780. ' -----------------------------------------------------------------------------
  781.  
  782. ParseFolder folder
  783.  
  784. ' -----------------------------------------------------------------------------
  785. ' Test function to iterate through all sub-folders...
  786. ' -----------------------------------------------------------------------------
  787.  
  788. Global ImageCount:Long
  789.  
  790. Function ParseFolder (dir:String)
  791.  
  792.         If Right (dir:String, 1) <> "" And Right (dir:String, 1) <> "/"
  793.                 dir:String = dir:String + "/"
  794.         EndIf
  795.        
  796.         Local folder:Int = ReadDir (dir:String)
  797.  
  798.         If folder
  799.        
  800.                 Repeat
  801.  
  802.                         Local entry:String = NextFile (folder)
  803.  
  804.                         If entry = "" Then Exit
  805.                        
  806.                         If entry <> "." And entry <> ".."
  807.  
  808.                                 Local file:String
  809.                                 Local full:String
  810.                                
  811.                                 If FileType (dir + entry) = FILETYPE_FILE
  812.        
  813.                                         file = entry
  814.                
  815.                                         full = dir
  816.                
  817.                                         If Right (full, 1) <> "" And Right (full, 1) <> "/"
  818.                                                 full = full + ""
  819.                                         EndIf
  820.                
  821.                                         full = full + file
  822.                
  823.                                         ImageCount = ImageCount + 1
  824.                                        
  825.                                         Print ""
  826.                                         Print "--------------------------------------------------------------------------------"
  827.                                         Print "Reading image number " + ImageCount + "..."
  828.                                         Print "--------------------------------------------------------------------------------"
  829.                                        
  830.                                         ParseJPEG full
  831.                
  832.                                 Else
  833.                
  834.                                         If FileType (dir + entry) = FILETYPE_DIR
  835.        
  836.                                                 file = entry
  837.                
  838.                                                 If file <> "." And file <> ".."
  839.                
  840.                                                         Local ffolder:String = dir
  841.                
  842.                                                         If Right (ffolder, 1) <> "" And Right (ffolder, 1) <> "/"
  843.                                                                 ffolder = ffolder + ""
  844.                                                         EndIf
  845.        
  846.                                                         ffolder = ffolder + file
  847.                                                                
  848.                                                         ParseFolder (ffolder)
  849.                
  850.                                                 EndIf
  851.                
  852.                                         EndIf
  853.                
  854.                                 EndIf
  855.        
  856.                         EndIf
  857.  
  858.                 Forever
  859.        
  860.         EndIf
  861.  
  862. End Function


Comments : none...

 

SimplePortal 2.3.6 © 2008-2014, SimplePortal