Updated Answer
Ok, I have done some work on this and can extract the map automatically using the script below which does more or less as I suggested below:
#!/bin/bash
################################################################################
# File: extractMap
# Usage:
# extractMap survey.gif
# Result is in extracted/survey.gif
################################################################################
image="$1"
mkdir extracted 2> /dev/null
# Step1: Trim off border around edge of image
convert "$image" -shave 50x50 step1.gif
# Step 2: Squeeze image till 1 pixel wide x original height
convert step1.gif -scale 1x! -threshold 65533 step2.gif
# Step 3: Find longest black line
result=$(convert step2.gif txt: | awk -F"[,: ]*" '/black/&&!inblack{inblack++;start=$2}/white/&&inblack{inblack=0;l=$2-start;if(l>longest){longest=l;x=start;y=$2}}END{print x,y}')
read a b <<< $result
# Step 4: Crop top and bottom off
h=$(identify -format "%h" step1.gif)
c=$((h-b))
convert step1.gif -chop 0x$a -gravity south -chop 0x$c out.gif
# Step 5: Squeeze image till 1 pixel tall
convert out.gif -scale x1! -threshold 65533 step3.gif
# Step 6: Find longest black line
result=$(convert step3.gif txt: | awk -F"[,: ]*" '/black/&&!inblack{inblack++;start=$1}/white/&&inblack{inblack=0;l=$1-start;if(l>longest){longest=l;x=start;y=$1}}END{print x,y}')
read a b <<< $result
# Step 7: Crop left and right off
w=$(identify -format "%w" out.gif)
c=$((w-b))
convert out.gif -chop ${a}x0 -gravity east -chop ${c}x0 "extracted/$image"
You would save the script above in a file called extractMap
, then run the following (just once) to make it executable
chmod +x extractMap
Now you can pass it the name of a survey like this and it will extract the map into a subdirectory called extracted
followed by the original filename:
./extractMap survey.gif
The main steps are:
- To remove the black border around the original image
- To then queeze the image til1 1 pixel wide and original height
- Find the longest black line in the squeezed image (that is the vertical edge of the map)
- Crop the top and bottom off according to that line
- Squeeze the image till 1 pixel tall
- Find longest black line which is the horizontal edge of the map area
- Crop left and right of map border and save in output directory
If you have a whole directory full of images, please back them up first then you can process the whole directory of thousands of files like this:
for f in *.gif; do ./extractMap "$f"; done
Orignal Answer
I am away without access to my computer for the weekend, so I can only suggest in general terms how to do it... will check back Sunday evening to see if anyone has developed the idea.
I would use ImageMagick which is available for Windows, Linux and OSX via commandline or with Perl, PHP, .NET and other bindings.
Then squeeze the image to a tall, 1 pixel wide image, using this command
convert inputimage.jpg -resize 1x\! output.jpg
Now look at the image, and you will see a short solid line corresponding to the image title block at top left, then another short line corresponding to the longitudes and then a LONG solid line corresponding to the sides of the map. This is readily identifiable and gives you the top and bottom of the map.
Now squidge the image to 1 pixel high with this
convert inputimage.jpg -resize x1\! output.jpg
and do it again to find the width of the map.
Then extract the map with
convert inputimage.jpg -crop XxY+M+N output.jpg
where X=map width, Y=map height, M=x offset to top left corner of map, N=y offset to top left corner of map.
You can change the output image name to txt:-
and it will list the pixel colours as text so you can parse them easily.
Thinking a little more, it would be better to crop the top and bottom of the image off after finding the longest vertical line and BEFORE squidging the image down to 1 pixel high - this would mean the header at the top and key at the bottom would not interfere with determining the width of the map.