Skip to content

Instantly share code, notes, and snippets.

@george-silva
Created January 12, 2016 12:48
Show Gist options
  • Save george-silva/8784d35857bfb778e80d to your computer and use it in GitHub Desktop.
Save george-silva/8784d35857bfb778e80d to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Output;
using ESRI.ArcGIS.esriSystem;
namespace OptimusGIS.MapGenerator.PrintEngine
{
/// <summary>
/// Classe responsável por exportar os resultados de um layout para
/// uma imagem em disco.
/// </summary>
public class FileRenderer
{
[DllImport("GDI32.dll")]
public static extern int GetDeviceCaps(int hdc, int nIndex);
[DllImport("User32.dll")]
public static extern int GetDC(int hWnd);
[DllImport("User32.dll")]
public static extern int ReleaseDC(int hWnd, int hDC);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool SystemParametersInfo(uint uiAction, uint uiParam, ref int pvParam, uint fWinIni);
private const uint SPI_GETFONTSMOOTHING = 74;
private const uint SPI_SETFONTSMOOTHING = 75;
private const uint SPIF_UPDATEINIFILE = 0x1;
public static void ExportActiveViewParameterized(IActiveView view,
long outputResolution,
long resampleRatio,
string exportType,
string fileName,
Boolean clipToExtent)
{
try
{
IActiveView docActiveView = view;
IExport docExport;
long previousOutputQuality;
IOutputRasterSettings docOutputRasterSettings;
IEnvelope PixelBoundsEnv;
tagRECT exportRECT;
tagRECT DisplayBounds;
IDisplayTransformation docDisplayTransformation;
IPageLayout docPageLayout;
IEnvelope docMapExtEnv;
long hdc;
long tmpDC;
long iScreenResolution;
IEnvelope docGraphicsExtentEnv;
IUnitConverter unitConverter;
switch (exportType)
{
case "PDF":
docExport = new ExportPDFClass();
break;
case "EPS":
docExport = new ExportPSClass();
break;
case "AI":
docExport = new ExportAIClass();
break;
case "BMP":
docExport = new ExportBMPClass();
break;
case "TIFF":
docExport = new ExportTIFFClass();
break;
case "SVG":
docExport = new ExportSVGClass();
break;
case "PNG":
docExport = new ExportPNGClass();
break;
case "GIF":
docExport = new ExportGIFClass();
break;
case "EMF":
docExport = new ExportEMFClass();
break;
case "JPG":
docExport = new ExportJPEGClass();
break;
default:
exportType = "EMF";
docExport = new ExportEMFClass();
break;
}
// save the previous output image quality, so that when the export is complete it will be set back.
docOutputRasterSettings = docActiveView.ScreenDisplay.DisplayTransformation as IOutputRasterSettings;
previousOutputQuality = docOutputRasterSettings.ResampleRatio;
if (docExport is IExportImage)
// always set the output quality of the DISPLAY to 1 for image export formats
SetOutputQuality(docActiveView, 1);
else
// for vector formats, assign the desired ResampleRatio to control drawing of raster layers at export time
SetOutputQuality(docActiveView, resampleRatio);
// set the export filename (which is the nameroot + the appropriate file extension)
docExport.ExportFileName = fileName;
/* Get the device context of the screen */
tmpDC = GetDC(0);
/* Get the screen resolution. */
iScreenResolution = GetDeviceCaps((int)tmpDC, 88);
//88 is the win32 const for Logical pixels/inch in X)
/* release the DC. */
ReleaseDC(0, (int)tmpDC);
docExport.Resolution = outputResolution;
if (docActiveView is IPageLayout)
{
//get the bounds of the "exportframe" of the active view.
DisplayBounds = docActiveView.ExportFrame;
//set up pGraphicsExtent, used if clipping to graphics extent.
docGraphicsExtentEnv = GetGraphicsExtent(docActiveView);
}
else
{
//Get the bounds of the deviceframe for the screen.
docDisplayTransformation = docActiveView.ScreenDisplay.DisplayTransformation;
DisplayBounds = docDisplayTransformation.get_DeviceFrame();
}
PixelBoundsEnv = new Envelope() as IEnvelope;
if (clipToExtent && (docActiveView is IPageLayout))
{
docGraphicsExtentEnv = GetGraphicsExtent(docActiveView);
docPageLayout = docActiveView as PageLayout;
unitConverter = new UnitConverter();
//assign the x and y values representing the clipped area to the PixelBounds envelope
PixelBoundsEnv.XMin = 0;
PixelBoundsEnv.YMin = 0;
PixelBoundsEnv.XMax =
unitConverter.ConvertUnits(docGraphicsExtentEnv.XMax, docPageLayout.Page.Units,
esriUnits.esriInches) * docExport.Resolution -
unitConverter.ConvertUnits(docGraphicsExtentEnv.XMin, docPageLayout.Page.Units,
esriUnits.esriInches) * docExport.Resolution;
PixelBoundsEnv.YMax =
unitConverter.ConvertUnits(docGraphicsExtentEnv.YMax, docPageLayout.Page.Units,
esriUnits.esriInches) * docExport.Resolution -
unitConverter.ConvertUnits(docGraphicsExtentEnv.YMin, docPageLayout.Page.Units,
esriUnits.esriInches) * docExport.Resolution;
//'assign the x and y values representing the clipped export extent to the exportRECT
exportRECT.bottom = (int)(PixelBoundsEnv.YMax) + 1;
exportRECT.left = (int)(PixelBoundsEnv.XMin);
exportRECT.top = (int)(PixelBoundsEnv.YMin);
exportRECT.right = (int)(PixelBoundsEnv.XMax) + 1;
//since we're clipping to graphics extent, set the visible bounds.
docMapExtEnv = docGraphicsExtentEnv;
}
else
{
double tempratio = outputResolution / iScreenResolution;
double tempbottom = DisplayBounds.bottom * tempratio;
double tempright = DisplayBounds.right * tempratio;
//'The values in the exportRECT tagRECT correspond to the width
//and height to export, measured in pixels with an origin in the top left corner.
exportRECT.bottom = (int)Math.Truncate(tempbottom);
exportRECT.left = 0;
exportRECT.top = 0;
exportRECT.right = (int)Math.Truncate(tempright);
//populate the PixelBounds envelope with the values from exportRECT.
// We need to do this because the exporter object requires an envelope object
// instead of a tagRECT structure.
PixelBoundsEnv.PutCoords(exportRECT.left, exportRECT.top, exportRECT.right, exportRECT.bottom);
//since it's a page layout or an unclipped page layout we don't need docMapExtEnv.
docMapExtEnv = null;
}
// Assign the envelope object to the exporter object's PixelBounds property. The exporter object
// will use these dimensions when allocating memory for the export file.
docExport.PixelBounds = PixelBoundsEnv;
// call the StartExporting method to tell docExport you're ready to start outputting.
hdc = docExport.StartExporting();
// Redraw the active view, rendering it to the exporter object device context instead of the app display.
// We pass the following values:
// * hDC is the device context of the exporter object.
// * exportRECT is the tagRECT structure that describes the dimensions of the view that will be rendered.
// The values in exportRECT should match those held in the exporter object's PixelBounds property.
// * docMapExtEnv is an envelope defining the section of the original image to draw into the export object.
docActiveView.Output((int)hdc, (int)docExport.Resolution, ref exportRECT, docMapExtEnv, null);
//finishexporting, then cleanup.
docExport.FinishExporting();
docExport.Cleanup();
//set the output quality back to the previous value
SetOutputQuality(docActiveView, previousOutputQuality);
docMapExtEnv = null;
PixelBoundsEnv = null;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
throw;
}
finally
{
EnableFontSmoothing();
}
}
/// <summary>
/// Sets OutputImageQuality for activeview. If this is pageLayout, set
/// output image quality for each data frame.
/// </summary>
/// <param name="docActiveView"></param>
/// <param name="iResampleRatio"></param>
private static void SetOutputQuality(IActiveView docActiveView, long iResampleRatio)
{
IGraphicsContainer oiqGraphicsContainer;
IElement oiqElement;
IOutputRasterSettings docOutputRasterSettings;
IMapFrame docMapFrame;
IActiveView tempActiveView;
if (docActiveView is IMap)
{
docOutputRasterSettings = docActiveView.ScreenDisplay.DisplayTransformation as IOutputRasterSettings;
docOutputRasterSettings.ResampleRatio = (int) iResampleRatio;
}
else if (docActiveView is IPageLayout)
{
//assign ResampleRatio for PageLayout
docOutputRasterSettings = docActiveView.ScreenDisplay.DisplayTransformation as IOutputRasterSettings;
docOutputRasterSettings.ResampleRatio = (int) iResampleRatio;
//and assign ResampleRatio to the Maps in the PageLayout
oiqGraphicsContainer = docActiveView as IGraphicsContainer;
oiqGraphicsContainer.Reset();
oiqElement = oiqGraphicsContainer.Next();
while (oiqElement != null)
{
if (oiqElement is IMapFrame)
{
docMapFrame = (IMapFrame) oiqElement;
tempActiveView = (IActiveView) docMapFrame.Map;
docOutputRasterSettings = tempActiveView.ScreenDisplay.DisplayTransformation as IOutputRasterSettings;
docOutputRasterSettings.ResampleRatio = (int) iResampleRatio;
}
oiqElement = oiqGraphicsContainer.Next();
}
docMapFrame = null;
oiqGraphicsContainer = null;
tempActiveView = null;
}
docOutputRasterSettings = null;
}
/// <summary>
/// This method gets the extent of all objects in the map
/// </summary>
/// <param name="docActiveView"></param>
/// <returns></returns>
private static IEnvelope GetGraphicsExtent(IActiveView docActiveView)
{
IEnvelope GraphicsBounds;
IEnvelope GraphicsEnvelope;
IGraphicsContainer oiqGraphicsContainer;
IPageLayout docPageLayout;
IDisplay GraphicsDisplay;
IElement oiqElement;
GraphicsBounds = new EnvelopeClass();
GraphicsEnvelope = new EnvelopeClass();
docPageLayout = docActiveView as IPageLayout;
GraphicsDisplay = docActiveView.ScreenDisplay;
oiqGraphicsContainer = docActiveView as IGraphicsContainer;
oiqGraphicsContainer.Reset();
oiqElement = oiqGraphicsContainer.Next();
while (oiqElement != null)
{
oiqElement.QueryBounds(GraphicsDisplay, GraphicsEnvelope);
GraphicsBounds.Union(GraphicsEnvelope);
oiqElement = oiqGraphicsContainer.Next();
}
return GraphicsBounds;
}
/// <summary>
/// Disable font smoothing
/// </summary>
private static void DisableFontSmoothing()
{
bool iResult;
int pv = 0;
/* call to systemparametersinfo to set the font smoothing value */
iResult = SystemParametersInfo(SPI_SETFONTSMOOTHING, 0, ref pv, SPIF_UPDATEINIFILE);
}
/// <summary>
/// Enable font smoothing
/// </summary>
private static void EnableFontSmoothing()
{
bool iResult;
int pv = 0;
iResult = SystemParametersInfo(SPI_SETFONTSMOOTHING, 1, ref pv, SPIF_UPDATEINIFILE);
}
/// <summary>
/// Gets if the font smoothing is enabled
/// </summary>
/// <returns></returns>
private static Boolean GetFontSmoothing()
{
bool iResult;
int pv = 0;
/* call to systemparametersinfo to get the font smoothing value */
iResult = SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, ref pv, 0);
return pv > 0;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment