Anyone using FWTools?


Now this is becoming a really good thread :)

Hope us hobbyists aren't scaring the crap out of the military people too much...:rotfl:
Move over NASA... I'm a FS pilot ;)

President Obama... What the hell happened to our Military Industrial complex?!!!!
Leon Panetta... Well its like this Mr President... there where these three Flight Simulator hobbyists... and they just took over the world ;)
Last edited:
Ah ha!
I knew it...

The dotNet 2 and 3.5 frameworks cant handle large Tiffs... any large images for that matter...
Also cant handle the 16 bit height maps so I cant do that cool thing and show the user the heights on an elevation map...

I was just about to send Gates and General Balmy to Guantanamo... :D
and then I found this...

Seems MS woke up... it can do it now... even though MS have gone and stuffed up the whole damn GDI API interface... its different because some MS guy suddenly realized that large maps need a memory mapped file... but its there.

I expect it should do at least 400 mb files on a 32 bit system now...
So... if you want to get serious about mapping on dotNet... start here.

It does mean that you'll have to push the user up to dotNet 4... but considering the download is smaller than FWTools... its an option I'm going to try...

I'm pretty sure dotNet will handle all aspects of tiffs now... MS seem to have caught up... anyway its the solution I was looking for... a driver (encoder) that can do it... all the power of C in dotNet... nice!

You have to upgrade the C# dev tools to 2010... just released...

It still supports XP (thank goodness) so I guess we'll have to let Gates live a little while longer ;)
Well I thought I'd just finish this thread off with how to use Microsofts "Big Tiff" driver to parse a GeoTiff...

There is just about nothing out there so someone will find this handy...

Besides MS having changed the whole damn interface... it works and I'm testing on a 12 meg file...

        UInt16 ImageWidth = 0; //pixels
        UInt16 ImageHeight = 0; //pixels
        Double LEFT_LONG = 0; //map coords
        Double TOP_LAT = 0; //map coords
        Double dXScale = 0; //degs/pixel
        Double dYScale = 0; //degs/pixel

        UInt16 GEOMODEL = 0;
        UInt16 GEORASTER = 0;
        UInt16 GeographicType = 0;
        UInt16 GeogAngularUnits = 0;

        public enum EXIFTags
            PixelScale = 0x830e,
            ModelTiePoint = 0x8482,
            GeoTiffDirectory = 0x87AF,
            ImageWidth = 0x0100,
            ImageHeight = 0x0101,
            BitsPerSample = 0x0102,
            Compression = 0x0103,
            Photometric = 0x0106,
            Thresholding = 0x0107,
            PlanarConfig = 0x011c

        public enum GEOVector
            Version = 0x0001,
            Model = 0x0400,
            Raster = 0x0401,
            Citation = 0x0402,
            GeographicType = 0x0800,
            GeogCitation = 0x0801,
            GeogGeodeticDatum = 0x0802,
            GeogPrimeMeridian = 0x0803,
            GeogLinearUnits = 0x0804,
            GeogLinearUnitSize = 0x0805,
            GeogAngularUnits = 0x0806,
            GeogAngularUnitSize = 0x0807,
            GeogEllipsoid = 0x0808,
            GeogSemiMajorAxis = 0x0809,
            GeogSemiMinorAxis = 0x080A,
            GeogInvFlattening = 0x080B,
            GeogAzimuthUnits = 0x080C,
            GeogPrimeMeridianLong = 0x080D,
            ProjectedCSType = 0x0c00,
            PCSCitation = 0x0c01,
            Projection = 0x0c02,
            ProjCoordTrans = 0x0c03,
            ProjLinearUnits = 0x0c04,
            ProjLinearUnitSize = 0x0c05,
            ProjStdParallel1 = 0x0c06,
            ProjStdParallel2 = 0x0c07,
            ProjNatOriginLong = 0x0c08,
            ProjNatOriginLat = 0x0c09,
            ProjFalseEasting = 0x0c0A,
            ProjFalseNorthing = 0x0c0B,
            ProjFalseOriginLong = 0x0c0C,
            ProjFalseOriginLat = 0x0c0D,
            ProjFalseOriginEasting = 0x0c0E,
            ProjFalseOriginNorthing = 0x0c0F,
            ProjCenterLong = 0x0c10,
            ProjCenterLat = 0x0c11,
            ProjCenterEasting = 0x0c12,
            ProjCenterNorthing = 0x0c13,
            ProjScaleAtNatOrigin = 0x0c14,
            ProjScaleAtCenter = 0x0c15,
            ProjAzimuthAngle = 0x0c16,
            ProjStraightVertPoleLong = 0x0c17,
            ProjRectifiedGridAngle = 0x0c18,
            VerticalCSType = 0x1000,
            VerticalCitation = 0x1001,
            VerticalDatum = 0x1002,
            VerticalUnits = 0x1003

        public bool CaseIFD(BitmapMetadata meta, int tag)
            object ifdData = meta.GetQuery("/ifd/{uint=" + tag + "}");
            switch (tag)
                case (int)EXIFTags.ImageWidth:

                        if (ifdData.GetType() != typeof(UInt16)) throw new Exception("Oops this code is not smart enuf");
                        ImageWidth = (UInt16)ifdData;

                        return true;
                case (int)EXIFTags.ImageHeight:

                        if (ifdData.GetType() != typeof(UInt16)) throw new Exception("Oops this code is not smart enuf");
                        ImageHeight = (UInt16)ifdData;

                        return true;

                case (int)EXIFTags.PixelScale:
                        if (ifdData.GetType() != typeof(double[])) throw new Exception("Oops this code is not smart enuf");
                        double[] data = (double[])ifdData;

                        dXScale = (Double)data[0];
                        dYScale = (Double)data[1];
                        Double dZScale = (Double)data[2];

                        return true;
                case (int)EXIFTags.ModelTiePoint:

                        if (ifdData.GetType() != typeof(double[])) throw new Exception("Oops this code is not smart enuf");
                        double[] data = (double[])ifdData;

                        Double d0 = (Double)data[0];
                        Double d1 = (Double)data[1];
                        Double d2 = (Double)data[2];
                        LEFT_LONG = (Double)data[3];
                        TOP_LAT = (Double)data[4];
                        Double d5 = (Double)data[5];

                        return true;
                case (int)EXIFTags.GeoTiffDirectory:

                        if (ifdData.GetType() != typeof(UInt16[])) throw new Exception("Oops this code is not smart enuf");
                        UInt16[] data = (UInt16[])ifdData;
                        int dataItem = 0;
                        while (dataItem < data.Length)

                            UInt16 vector = data[dataItem];
                            dataItem += 1;

                            switch (vector)
                                case (int)GEOVector.Version:
                                    UInt16 bV1 = data[dataItem];
                                    dataItem += 1;
                                    UInt16 bV2 = data[dataItem];
                                    dataItem += 1;
                                    UInt16 bV3 = data[dataItem];
                                    dataItem += 1;

                                    string GeoVersion = "" + bV1 + "." + bV2 + "." + bV3;


                                case (int)GEOVector.Model:
                                        UInt16 bSpacer1Unknown = data[dataItem];
                                        dataItem += 1;
                                        UInt16 bSpacer2Unknown = data[dataItem];
                                        dataItem += 1;
                                        GEOMODEL = data[dataItem]; // 1 = Projected,2 = Geographic,3 = Geocentric
                                        dataItem += 1;

                                case (int)GEOVector.Raster:
                                        UInt16 bSpacer1Unknown = data[dataItem];
                                        dataItem += 1;
                                        UInt16 bSpacer2Unknown = data[dataItem];
                                        dataItem += 1;
                                        GEORASTER = data[dataItem]; // 1 = Pixel Is Area, 2 = Pixel Is Point
                                        dataItem += 1;

                                case (int)GEOVector.GeographicType:
                                        UInt16 bSpacer1Unknown = data[dataItem];
                                        dataItem += 1;
                                        UInt16 bSpacer2Unknown = data[dataItem];
                                        dataItem += 1;
                                        GeographicType = data[dataItem]; // 4326 = WGS 84
                                        dataItem += 1;

                                case (int)GEOVector.GeogAngularUnits:
                                        UInt16 bSpacer1Unknown = data[dataItem];
                                        dataItem += 1;
                                        UInt16 bSpacer2Unknown = data[dataItem];
                                        dataItem += 1;
                                        GeogAngularUnits = data[dataItem]; // 9102	= Angular Degree
                                        dataItem += 1;

                                    Debug.WriteLine(" VECTOR Data that could be captured ");
                                    Debug.WriteLine(String.Format("{0:X}", vector));
                                    //Dummy Read
                                    dataItem += 3;
                            }// end vector switch

                        }// end while vector

                        return true;


            return false;


        public void initGeoTiff(String sPathToFile)
            Stream imageStreamSource = new FileStream(sPathToFile, FileMode.Open, FileAccess.Read, FileShare.Read);
            TiffBitmapDecoder decoder = new TiffBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
            BitmapSource bitmapSource = decoder.Frames[0];
            BitmapMetadata bitmapMetadata = (BitmapMetadata)decoder.Frames[0].Metadata;

            if((!CaseIFD(bitmapMetadata, (int)EXIFTags.ImageWidth)) ||
                (!CaseIFD(bitmapMetadata, (int)EXIFTags.ImageHeight)) ||
                (!CaseIFD(bitmapMetadata, (int)EXIFTags.PixelScale)) ||
                (!CaseIFD(bitmapMetadata, (int)EXIFTags.GeoTiffDirectory)) ||
                (!CaseIFD(bitmapMetadata, (int)EXIFTags.ModelTiePoint))
               ) throw new Exception("Critical Property not set... not a GeoTiff"); 

And MS... I dont like C# 2010... I hate the colors and the interface feels klunky... also this class is not intuitive... it doesnt load like other references... doesn't even have its own name... I nearly blew Bill away ;)


Staff member
Resource contributor

Thanks for the coding.

I've been using 2010 VS Express C#. Haven't used it a lot, but the price is right. :)

That TiffBitmapDecoder is for WPF programming, so that is new to the Express format in the 2010 edition. Are you sure .Net 3.0 doesn't work?


Windows 7, Windows Vista, Windows XP SP3, Windows Server 2008, Windows Server 2003

The .NET Framework and .NET Compact Framework do not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements.
Version Information
.NET Framework
Supported in: 4, [B]3.5, 3.0[/B]
.NET Framework Client Profile
Supported in: 4, [B]3.5[/B] SP1
Dick... you have read my mind... thats exactly what I've just been testing... because C# 2010 has gone too WPF for me... I hate the thing.

C# 2008 is a much better product I think... I've gone back to it...

This is the story...

You can get this to all work on C# 2008 Express (price is right) ;)

But you must get dotNet 3.5... quickly ;)

The Presentation Core... doesn't show in dotNet 2 and dotNet 4 doesn't show in C# 2008
So thats the Gotcha... if dotNet 3.5 is discontinued... you have to go to C# 2010

So thats my preferred dev enviroment for this... dotNet 3.5... C# 2008

Yeah sorry... I had actually stopped using MS dev tools for a long time, completely and its only because of my interest in Flight Sim that I revved up the MS stuff again... I actually love Java and Linux Open Source servers... thats my preference... but FS is MS and I really like that as well.

DotNet C# Window Forms 2008 is actually very nice... I like it... but there seems to be a common thread in the IT industry... if they go too XML crazy... its crap... namely I think WPF sucks ;)

But... thats where this graphic library actually sits...

So... whats really happening is that we digging into the WPF silver light graphics engine for big tiffs... which is what I think WPF and XAML yada blah is actually targeting... and staying as close as possible to the real windows engine... thats the idea...

Sort of Kind of... its never clear with MS...
If I had a big budget... I'd develop my own graphics lib... because when I look at all this MS stuff... there is no doubt in my mind that they going to swerve off the road and do a damn U turn again... when the next flavor of the month comes along...

That how I feel about it... but this idea will definitely get a nice mapping program going... that I can see already...

Probably a good idea if I tell you what the idea is hey... ha ha

The normal older MS GDI falls over on big graphics and it cant handle half the formats...
The TiffBitmapDecoder doesnt fall over... it lets you get at the properties (code above) and you can get at the bits...

Then what I'm doing is using the older GDI Bitmap technology to display just the "tiles" in a huge image... which it can handle... so... thats it ;)
Its never simple in MS... I think all the old graphics engines needed what more protocols and a memory mapped file...
So... I'm crossing over between Windows Generic and Silver Light engines... if you see what I mean...
Last edited:


Staff member
Resource contributor

SharpDevelop could also be an alternative to Visual Studio.

They are supposed to support .Net 3.5

Hell no... head hurts already... just got this figured out.
Hard to see how SharpDevelop competes with MS... all MS has to do is license a protocol and they dead.

Thats actually Java's problem... Suns video engines suck because I think MS has a big "dont touch or we'll sue you blind" sign on their protocols...

I've actually done it another way on my Pojo server... I don't swim up stream... I just make Full Java Apps jump out of the browser... its better than WPF, SilverLight, Flex, JavaFX etc...

Its dotNet compatible (final modules) so the Java apps can use dotNet modules... so Java can jump out of the browser and if need be, it just uses dotNet modules for video or whatever...

Who wants dumbed down X(A)ML with the IQ of Java Script... I make accounting apps and full games jump out of a browser in 5 seconds... ha ha

Thanks... the dotNet app has a home when the time comes ;)

I think things like SharpDevelop has to be part of Microsoft's marketing strategy... or they would be dead.

Ever wondered why linux after all these years still doesn't know what a file association is and has a mouse that hardly works... they either really damn stupid or Bills bank has a ton of money... its all a big smoke screen ;)

Ever noticed how the really good coders make it look so simple... its because they figured out whats bullshit and whats not... built in smog detectors... ha ha

I think if I get the time, this will make SBuilder into one hell of a product... I think I have something thats going to work here...

Final note for anyone taking the plunge in this area... it works :)

The WPF graphic lib has to be just about the most unintuitive thing I've ever played with... forget all your GDI knowledge... its completely different... but its extremely powerful...

The big difference to GDI is that you can do all the manipulation on the raw data before making it a BitMap... convert it, flip it, rotate it, make it gray scale, apply pallets, crop it... and thats all working against streams, raw data... and then the last thing you do is display it...

GDI loads straight up into memory... and thats why it struggles...

It eats GeoTiffs for breakfast ;) are the bestest.....

Thanks for saving me hours and hours of work........
I especially liked your initial response that it was brilliant....very perceptive......
Last edited: