# Convert x, y position in georeferenced image (with world file) to longitude, latitude?

What steps do I need to do in order to calculate longitude and latitude for a specific pixel in a georeferenced image? For example this image http://www.shadedreliefarchive.com/medit_Mideast_africa_copy.html contains information, .tfw file:

1627.32174969982000
0.00000000000000
0.00000000000000
-1627.32174969982000
-4957506.34276705000000
6096922.76188281000000


and .prj file:

PROJCS["Lambert Azimuthal Equal-Area",
GEOGCS["GCS_WGS_1984",
DATUM["D_WGS_1984", SPHEROID["WGS_1984", 6378137, 298.257223563]],
PRIMEM["Greenwich", 0],
UNIT["Degree", 0.017453292519943295]],
PROJECTION["Lambert_Azimuthal_Equal_Area"],
PARAMETER["false_easting", 0],
PARAMETER["false_northing", 0],
PARAMETER["latitude_of_origin", 0],
PARAMETER["central_meridian", 20],
PARAMETER["xy_plane_rotation", 0],
UNIT["Meter", 1]]


I've created this snippet of javascript to compute new x1 and y1 values for specific pixels in the image:

var A = 1627.32174969982000,
D = 0.00000000000000,
B = 0.00000000000000,
E = -1627.32174969982000,
C = -4957506.34276705000000,
F = 6096922.76188281000000;

function x1(x, y) { return A*x + B*y + C; }

function y1(x, y) { return D*x + E*y + F; }


What more do I have to do to get longitude and latitude? For example C, F represents the top-left corner of the image, right? Then how do I translate C, F to get longitude and latitude?

I want do do it using javascript only, have looked at http://proj4js.org/ but don't really understand what to do with the values I get...

• don't you need to reproject the raster image with a GIS package first? – Mapperz Apr 12 '11 at 14:10
• Hopefully not, I would like to have a function to convert pixel positions in the image to long/lat positions and also preferable the reverse translation. – antonj Apr 12 '11 at 14:25
• Just a comment: usually people use the coordinates of pixel centers for computing their (lat, lon). If that's your intention, then in your snippet you should therefore first add 1/2 to each of x and y (assuming they are row and column indices). – whuber Apr 12 '11 at 14:56
• @whuber, that sounds reasonable – antonj Apr 12 '11 at 15:11
• @whuber @antonj -- just a note that the .tfw already includes an offset to the pixel center; adding another 1/2 will put you at the bottom right of the pixel. (Line 5 & 6, the "origin" of the affine transform in the .tfw, are the coordinates of the center of the top-left pixel, not the coordinates of the top-left of the top-left pixel.) – Dan S. Apr 12 '11 at 15:55

The .tfw represents the affine transform for the image -- how image pixel coordinates map to coordinates in the space defined by the .prj.

Here's an explanation of the values: http://en.wikipedia.org/wiki/World_file

(What isn't in Wikipedia these days?)

Getting to geographic coordinates is thus a two-step process:

• Find the coordinates of the pixel in the projected coordinate system
• Unproject this coordinate back to the geographic coordinate system to arrive at lat & lon.

The formula for the first step:

X_proj = C + (A * X_img) + (B * Y_img)
Y_proj = F + (E * Y_img) + (D * X_img)


Note: I'm using the variables A..F from the article I linked, not from your code above! I don't believe they correspond; the Wikipedia article chose labels that don't correspond to line numbers.

Now you have X & Y coordinates in your desired coordinate system. Since you're using Javascript (using proj4js; forgive me if I haven't tested the code below):

var source = new Proj4js.Proj('PROJ4_ARGS_FOR_YOUR_PROJECTION');
var dest = new Proj4js.Proj('EPSG:4326') // geographic coordinates + WGS84 (which matches the ellipsoid used in your .prj)

var p = new Proj4js.Point(X_proj, Y_proj)
Proj4js.transform(source, dest, p)

// p.x & p.y are now lat & lon. (or lon & lat, can't recall coord order)


I (ab)used spatialrefrence.org to convert your .prj into arguments for Proj4; you can see it here by clicking on 'proj4': http://spatialreference.org/ref/sr-org/7119/ In general, .prj to proj4 args is a purely mechanical transformation.

Cheers!

• Thanks I don't understand what happens at spatialreference.org but I have some stuff to test now :) – antonj Apr 12 '11 at 16:03
• @antonj -- It's just the lazy (and web-linkable) way I used to convert your .prj parameters into proj4j arguments. The site gives you lots of ways to download a spatial reference, but the "proj4" link is the one you care about. They're all the same spatial reference info, just different formats. E.g. the "Lambert Azimuthal Equal-Area" in your .prj translates directly into the +proj=laea argument on the "proj4" version; the "central-meridian" of 20 translates to +lon_0=20, etc. – Dan S. Apr 12 '11 at 16:15

I'm not much of a js programmer, but this works for me:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<HTML>
<TITLE>Geographic Coordinate Transformations in Javascript</TITLE>

<script src="lib/OLprototype.js"></script>
<script src="lib/proj4js-combined.js"></script>

<SCRIPT type="text/javascript">
// Put your projection definition here.
Proj4js.defs["EPSG:3575"] = "+proj=laea +lat_0=90 +lon_0=10 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs";

var A = 1627.32174969982000,
D = 0.00000000000000,
B = 0.00000000000000,
E = -1627.32174969982000,
C = -4957506.34276705000000,
F = 6096922.76188281000000;

function frompixel(px, py) {
px += 0.5; // Add a half-pixel offset to get the coordinates of the centre of the pixel.
py += 0.5;
return {x : A*px + B*py + C, y: D*px + E*py + F};
}

function tolatlong(x, y) {
var src = new Proj4js.Proj('EPSG:3575'); // Same code as you defined above. Alternatively, let proj4js get the definition from spatialreference.org
var dest = new Proj4js.Proj('EPSG:4326');
var p = frompixel(x, y);

document.write('From coordinates: ');
document.writeln(p.x, ',', p.y);

// This is the bit that does the transformation from map coordinates to lat/long.
Proj4js.transform(src, dest, p);
document.write('To lat/long: ');
document.writeln(p.x, ',', p.y);
}
</SCRIPT>

<BODY>
<SCRIPT type="text/javascript">
tolatlong(100, 100);
</SCRIPT>
</BODY>
</HTML>


Naturally, you will have to play around with the code a bit to integrate it with your web page, but the principle should be right.

• Amusing... we gave, more or less, the exact same answer at the exact same time. ;) – Dan S. Apr 12 '11 at 15:23
• It's good to know we both stand a reasonable chance of being right :) – MerseyViking Apr 12 '11 at 15:29
• Upon a closer read, I'm not certain your +0.5 is correct. (See the comment I left in the discussion on the main question.) – Dan S. Apr 12 '11 at 15:58
• Thanks, although I don't understand where you got "EPSG:3575" from? – antonj Apr 12 '11 at 16:05
• @antonj -- that's the EPSG code for the projection MerseyViking is using, which incidentally is not the same one as in your question. (Frequently used projections have a code assigned to them by the EPSG. I bet yours has an EPSG code too, but it wasn't included in the .prj). – Dan S. Apr 12 '11 at 16:17