Python and the JPEG Image File, Part 1, The Header

Thread Solved

Join Date: Oct 2004
Posts: 3,941
Reputation: vegaseat is just really nice vegaseat is just really nice vegaseat is just really nice vegaseat is just really nice vegaseat is just really nice 
Solved Threads: 911
Moderator
vegaseat's Avatar
vegaseat vegaseat is offline Offline
DaniWeb's Hypocrite

Python and the JPEG Image File, Part 1, The Header

 
0
  #1
Sep 22nd, 2005
Python and the JPEG Image File, Part 1, The Header

Intro

The JPEG image file format (.jpg) is very popular on the internet because you can pack a lot of picture information into a relatively small file. There are competing file formats like GIF and PNG. GIF is rather limited to the number of colors (8 bit = 256) compared to JPEG (24 bit = 16,777,216). JPEG can typically achieve 10:1 to 20:1 compression without visible loss. It allows you to specify a quality setting (1 - 100) with higher quality giving less compression.

JPEG header

Sharp edges in images like borders and embedded text give JPEG a hard time, that's why you can insert a text comment directly into the JPEG file header. As the name implies, the header is the first part of the JPEG file, followed by the compressed picture. In this part of the tutorial we take a look at the header of the a typical JPEG file and extract some information it contains. To make things simple, I have attached a sample JPEG image file that contains a 80x80 blue square at a resolution of 200dpi. This file also contains a text comment that can be extracted. Blue is the favorite color of vegaseat.

  1. # print out the hex bytes of a jpeg file, find end of header, image size, and extract any text comment
  2. # (JPEG = Joint Photographic Experts Group)
  3. # tested with Python24 vegaseat 21sep2005
  4.  
  5. try:
  6. # the sample jpeg file is an "all blue 80x80 200dpi image, saved at a quality of 90"
  7. # with the quoted comment added
  8. imageFile = 'Blue80x80x200C.JPG'
  9. data = open(imageFile, "rb").read()
  10. except IOError:
  11. print "Image file %s not found" % imageFile
  12. raise SystemExit
  13.  
  14. # initialize empty list
  15. hexList = []
  16. for ch in data:
  17. # make a hex byte
  18. byt = "%02X" % ord(ch)
  19. hexList.append(byt)
  20.  
  21. #print hexList # test
  22.  
  23. print
  24.  
  25. print "hex dump of a 80x80 200dpi all blue jpeg file:"
  26. print "(the first two bytes FF and D8 mark a jpeg file)"
  27. print "(index 6,7,8,9 spells out the subtype JFIF)"
  28. k = 0
  29. for byt in hexList:
  30. # add spacer every 8 bytes
  31. if k % 8 == 0:
  32. print " ",
  33. # new line every 16 bytes
  34. if k % 16 == 0:
  35. print
  36. print byt,
  37. k += 1
  38.  
  39. print
  40. print "-"*50
  41.  
  42. # the header goes from FF D8 to the first FF C4 marker
  43. for k in range(len(hexList)-1):
  44. if hexList[k] == 'FF' and hexList[k+1] == 'C4':
  45. print "end of header at index %d (%s)" % (k, hex(k))
  46. break
  47.  
  48. # find pixel width and height of image
  49. # located at offset 5,6 (highbyte,lowbyte) and 7,8 after FF C0 or FF C2 marker
  50. for k in range(len(hexList)-1):
  51. if hexList[k] == 'FF' and (hexList[k+1] == 'C0' or hexList[k+1] == 'C2'):
  52. #print k, hex(k) # test
  53. height = int(hexList[k+5],16)*256 + int(hexList[k+6],16)
  54. width = int(hexList[k+7],16)*256 + int(hexList[k+8],16)
  55. print "width = %d height = %d pixels" % (width, height)
  56.  
  57. # find any comment inserted into the jpeg file
  58. # marker is FF FE followed by the highbyte/lowbyte of comment length, then comment text
  59. comment = ""
  60. for k in range(len(hexList)-1):
  61. if hexList[k] == 'FF' and hexList[k+1] == 'FE':
  62. #print k, hex(k) # test
  63. length = int(hexList[k+2],16)*256 + int(hexList[k+3],16)
  64. #print length # test
  65. for m in range(length-3):
  66. comment = comment + chr(int(hexList[k + m + 4],16))
  67. #print chr(int(hexList[k + m + 4],16)), # test
  68. #print hexList[k + m + 4], # test
  69.  
  70. if len(comment) > 0:
  71. print comment
  72. else:
  73. print "No comment"
Last edited by vegaseat; Aug 12th, 2009 at 5:17 pm. Reason: Formatting
Attached Files
File Type: zip Blue80x80x200C.zip (384 Bytes, 108 views)
May 'the Google' be with you!
Reply With Quote Quick reply to this message  
Reply

This thread has been marked solved.
Perhaps start a new thread instead?
Message:


Thread Tools Search this Thread



About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC