ThinkGeo.com    |     Documentation    |     Premium Support

Tasks to be done inside GetImageCore








        










Hi everyone!



Here's my story.



I'm writing my own RasterLayer and RasterSource to add native .NET support to Map Suite 3.0 to work with BSB Charts (.KAP and Geo).



So far I’m able to decode correctly the image and extract all the georeference data.



In my very first approach I converted the BSB Image into a Gif and then I passed that gif to the GdiPlusRasterLayer, but

these files are really big so the GdiPlusRasterLayer failed on the drawing stage  because of a lack of memory (My laptop has 3 GB I think that's enough isn't it?)



So that's why I came up with the idea of implementing my on RasterLayer and RasterSource. So now everything is implemented but GetImageCore Method in the RasterSource derived class(Well as a matter of fact it is but I’m not so sure of what to do).



I've been doing some tests and I think I'm close, I can draw an almost well scaled and positioned image using the chart's extent,but I’m having problems to scale it while I zoom in.(Zooming out seems not a problem, because I'm already able to downscale the image).



So finally, my question is:



What are the tasks that have to be done inside GetImageCore method; do I have to clip the Image for panning and zooming? How do I compute the right source rectangle for any part of the image if I’m clipping the image? If just a little part of the image is visible do I have to build and return the whole Image for that extent?


So far this is what I have coded:


 Protected Overrides Function GetImageCore(ByVal worldExtent As ThinkGeo.MapSuite.Core.RectangleShape, ByVal canvasWidth As Integer, ByVal canvasHeight As Integer) As ThinkGeo.MapSuite.Core.GeoImage         Dim canvas As GdiPlusGeoCanvas         Dim imagenGeo As GeoImage         Dim imagenNativa As Bitmap         Dim imagenBSB As Bitmap         Dim gr As Graphics         Dim escalaY As Double         Dim regionOrigen As Rectangle         Dim regionDestino As Rectangle         Dim punto(3) As ScreenPointF #If DEBUG Then         Dim tiempo As System.Diagnostics.Stopwatch         tiempo = System.Diagnostics.Stopwatch.StartNew() #End If                   If worldExtent.Contains(_coverturaReal) Then                         punto(0) = New ScreenPointF(0, 0)             punto(1) = New ScreenPointF(_encabezado.Medidas.Width, _encabezado.Medidas.Height)              punto(2) = ExtentHelper.ToScreenCoordinate(worldExtent, _coverturaReal.UpperLeftPoint.X, _coverturaReal.UpperLeftPoint.Y, canvasWidth, canvasHeight)             punto(3) = ExtentHelper.ToScreenCoordinate(worldExtent, _coverturaReal.LowerRightPoint.X, _coverturaReal.LowerRightPoint.Y, canvasWidth, canvasHeight)         Else             punto(0) = ExtentHelper.ToScreenCoordinate(_coverturaReal, worldExtent.UpperLeftPoint.X, worldExtent.UpperLeftPoint.Y, _encabezado.Medidas.Width, _encabezado.Medidas.Height)             punto(1) = ExtentHelper.ToScreenCoordinate(_coverturaReal, worldExtent.LowerRightPoint.X, worldExtent.LowerRightPoint.Y, _encabezado.Medidas.Width, _encabezado.Medidas.Height)              punto(2) = New ScreenPointF(0, 0)             punto(3) = New ScreenPointF(canvasWidth, canvasHeight)         End If                   'Obtenemos el area que tenemos destinada para trabajar         regionOrigen = New Rectangle(CInt(punto(0).X), CInt(punto(0).Y), CInt(punto(1).X - punto(0).X), CInt(punto(1).Y - punto(0).Y))         regionDestino = New Rectangle(0, 0, CInt(punto(3).X - punto(2).X), CInt(punto(3).Y - punto(2).Y))          escalaY = CDbl(regionDestino.Height) / CDbl(regionOrigen.Height)         Debug.Print(escalaY)         If escalaY <= 1 Then             'achicamos la imagen             imagenNativa = CreaImagenEscalada(escalaY, regionOrigen, regionDestino.Width, regionDestino.Height)         Else             'tenemos que agrandar la imagen, creo que eso es mas facil             imagenBSB = CreaImagenEscalada(1, regionOrigen, regionOrigen.Width, regionOrigen.Height)             imagenNativa = New Bitmap(canvasWidth, canvasHeight)             gr = Graphics.FromImage(imagenNativa)             gr.DrawImage(imagenBSB, regionDestino, regionOrigen, GraphicsUnit.Pixel)         End If          canvas = New GdiPlusGeoCanvas()         imagenGeo = canvas.ToGeoImage(imagenNativa) #If DEBUG Then         tiempo.Stop()         Debug.Print(tiempo.ElapsedMilliseconds) #End If         Return imagenGeo     End Function 




Well I Know those are many questions, but they all fall inside the main question.What are the tasks that have to be done inside GetImageCore method?



I hope I didn’t got you bored with all this, and also I hope I got myself understood, and last and most importantly I hope someone can help me out with this.



Thank you.


 



Ingemar,


Thanks for your post and question, it sounds interesting. Hope my following can give you some hints.
 
Basicly the funciton GetImageCore is very critical for RasterLayer & RasterSource, it is the core place we implement our logic to get image back from the data source, then the rest of work is just put the image into proper place in the MapControl.
 
As you can see , following is the API for GetImageCore, I will explain it in detail.

protected override GeoImage GetImageCore(RectangleShape worldExtent, int canvasWidth, int canvasHeight)

 
worldExtent is the extent we want to view on the Map, that is the extent we panned or zoom in or zoom out, it also can be considered the canvas extent or map extent(in Desktop Edition), the canvasWidth and canvasHeight is the screen width & screen height for the worldExtent, it may be or may not be the final returned image widht and height.
 
1)If the worldExtent(viewExtent) is completely within the image extent. Then we do 2 steps:
      Step1: Fetch image accroding to the worldExtent and image extent, this image widht & height may not be identical with canvasWidth and canvasHeight.
      Step2: Scale up or Scale down the step1 image to match up the canvasWidth and canvasHeight.
 
2) If the worldExtent(viewExtent) is only patitional within the image extent. Then it will much more complex.
    Step1: Caculate the intersection extent between worldExtent and image extent, let us call intersectionExtent.
    Step2: Get the width and height for the intersectionExtent in the Canvas according to the worldExtent, canvasWidth and canvasHeight. Because when we do scaling up or scaling down, we will just math it to the intersectionCanvasWidth and canvasHeight.
   Step3: Fetch image from the accroding to the intersection extent and image extent.
   Step4: Scaling up and Scaling down the step3 image to match up the intersection extent canvas widht and intersection extent canvas height.
 
 
Following step is done in RasterLayer, if you also override the API in RasterLayer , you have to pay some attention to it:

protected override void DrawCore(GeoCanvas canvas, Collection<SimpleCandidate> labelsInAllLayers)

   Step5: Draw the scaled image in step4 into a proper place, so we we return the image, its widht and height is still canvasWidth and canvasHeight while only the intersection part have image on it.
 
If I am not clear, please feel free to let me know.
 
Thanks
 
Yale

Thanks a lot!! Yale. 
  
 It works!!! …well almost, I still have to deal with the coverage, as you can see on the image attached,  
 anyway the zoom it’s working. I hope I can finish this soon so I can use it and post it in the code community 
  
 Thanks a lot again!!!

Ingemar, 
  
 You are welcome, very glad to work with you. 
  
 Thanks for your post and sharing on this. Now, I am not very clear about your problem, also I did not see your image in attachment. 
  
 Any more information would be appricated. 
  
 Thanks. 
  
 Yale 


Yale, 
  
 Sorry about that, the Image I was writing about was the first Image I attached to the post. In the image you can see the BSB chart and above it a ShapeFileLayer. Seems that both aren’t matching. I’ve been reading a bit and seems that I gotta do some math to get an error factor and then apply that factor to the image extent so that both layers match on the very same place. 
  
 So my last task is gonna be that error factor… 
  
 I’ll let you know if something else comes out. 
  
 Thanks again

Ingemar, 
  
 Thanks for your sharing. You’re so welcome. 
  
 Just let us know if you have more questions.