Print Task on Custom ArcGISImageServiceLayer

3141
13
Jump to solution
12-09-2013 10:29 AM
RobertWinterbottom
Occasional Contributor
Hi Everyone,

  I am working on executing a print task on a map with a custom ArcGISImageServiceLayer and am hitting a bit of a snag.  It seems that when I execute the print task it will work but it returns back a incorrect image in grey and black and not one including the colors or parameters currently shown in the layer.  I noticed in the json being sent in it does not include any params or a rendering rule which I am assuming might have something to do with this.  Is there anyway to override a method in the layer so when using the print task I can include the rendering rule and any other necessary params into the request?
0 Kudos
1 Solution

Accepted Solutions
JianHuang
Occasional Contributor III
Robert,

Here is a simplest sample which works on my side.

custom layer, which inherits from ArcGISImageServiceLayer but do nothing.
define( [   "dojo/_base/declare",   "esri/layers/ArcGISImageServiceLayer" ], function(   declare, ArcGISImageServiceLayer ) {    var MyImageServiceLayer = declare([ArcGISImageServiceLayer], {     declaredClass: "esri.layers.ArcGISImageServiceLayer"       });   return MyImageServiceLayer;   }); 


Test page:
  var map, layer;   require(["esri/map", "esri/layers/MyImageServiceLayer", "esri/dijit/Print", "dojo/domReady!"],   function (Map, MyImageServiceLayer, Print) {     esri.config.defaults.io.proxyUrl = "/proxy.ashx";//use your own proxy instead of this.     map = new Map("map", {       basemap: "gray",       center: [-80.85, 35.22],       zoom: 14     });      var print = new Print({       map: map,       url: "http://sampleserver6.arcgisonline.com/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export%20Web%20Map%20Task"     }, "print");     print.startup();      layer = new MyImageServiceLayer("http://sampleserver6.arcgisonline.com/arcgis/rest/services/CharlotteLAS/ImageServer");      map.addLayer(layer);     layer.on("load", function () {       layer.renderingRule = {         "rasterFunction": "RFTShadedReliefElevationColorRamp"       };       layer.renderingRule.toJson = function () {         return {           "rasterFunction": "RFTShadedReliefElevationColorRamp"         };       };       layer.setRenderingRule(layer.renderingRule);     });   });

View solution in original post

0 Kudos
13 Replies
JianHuang
Occasional Contributor III
Can you give us a reproducible sample?
0 Kudos
RobertWinterbottom
Occasional Contributor
It's quite a bit of code and it's on a password protected staging url unfortunately, I could zip up the project and email it or would it be helpful if I uploaded my custom ImageServiceLayer class and provided the parameters I use with it such as my raster function and other settings I am using in the getImageUrl function I overrided.  I could probably extract the minimum resources necessary and put it in a fiddle if needs be.  Which would be the best for you?

Do you know if by default the print task is supposed to include the rendering rule from an ArcGISImageServiceLayer and that possibly in my implementation of the class I changed something that is causing it to not be picked up when the print task executes.

Here is some small snippets of how I am using the print task and from my custom class:
require(["esri/tasks/PrintTask","esri/tasks/PrintParameters","esri/tasks/PrintTemplate","mapui","mainmodel"],
        function(PrintTask,PrintParameters,PrintTemplate,MapUI,MainModel){
          var printConfig = Config.getConfig().print,
            printTask = new PrintTask(printConfig.url),
            params = new PrintParameters(),
            viewModel = MainModel.getVM();
          params.map = MapUI.getMap();
          params.template = new PrintTemplate();
          params.template.label = printConfig.template.label;
          params.template.format = printConfig.template.format;
          params.template.layout = printConfig.template.layout;
          params.template.layoutOptions = printConfig.template.layoutOptions;

          var languageIsEnglish = (query(".selectedLanguage")[0].id === "languageEnglish");

          if(languageIsEnglish)
            viewModel.printMap("Printing");
          else
            viewModel.printMap("Printing");

          printTask.execute(params,function(response){
            window.open(response.url);
            if(languageIsEnglish)
              viewModel.printMap("Print");
            else
              viewModel.printMap("Cetak");
          },function(error){
            if(languageIsEnglish)
              viewModel.printMap("Print");
            else
              viewModel.printMap("Cetak");
          });

        });


The printConfig looks like this :

print: {
               url:"http://gis-stage.wri.org/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export%20Web%20Map%20Task",
               template: {
                 label:"Map",
                 format:"PNG32",
                 layout:"A4 Landscape",
                 layoutOptions: {
                   titleText: "Suitability Map",
                   authorText: "WRI & esri",
                   copyrightText: "WRI",
                   scalebarUnit: "Miles"
                 }
               }
             }



and here is my getImageUrl method from my custom class
getImageUrl: function (extent, width, height, callback,options) {
        var _self = this;
        var bbox = [extent.xmin, extent.ymin, extent.xmax, extent.ymax],
          params,
          min,
          max,
          tempArray,
          membership_arguments;

        var rasterFunction = _self.getRenderingRule();
        if (options) {
            params = options;
            params['renderingRule'] = JSON.stringify(rasterFunction);
            params['bbox'] = bbox.join(",");
            callback(_self.url + "/exportImage?",params);
        }
        else {
            params = {
                noData: 0,
                noDataInterpretation: "esriNoDataMatchAny",
                interpolation: "RSP_BilinearInterpolation",
                renderingRule: JSON.stringify(rasterFunction),
                format: "png8",
                size: width + "," + height,
                imageSR: 3857,
                bboxSR: 3857,
                f: "image",
                pixelType: 'U8',
                bbox: bbox.join(",")

            };
            callback(_self.url + "/exportImage?" + dojo.objectToQuery(params));
        }
        
      },


Everything works fine except the print task is just not including the rendering rule.
0 Kudos
JianHuang
Occasional Contributor III
PrintTask includes renderingRule if that property exists in your layer. Please check yourCustomImageServiceLayer.renderingRule is there, and yourCustomImageServiceLayer.renderingRule.toJson() is a valid function.
0 Kudos
RobertWinterbottom
Occasional Contributor
PrintTask includes renderingRule if that property exists in your layer. Please check yourCustomImageServiceLayer.renderingRule is there, and yourCustomImageServiceLayer.renderingRule.toJson() is a valid function.


Ahh I think you may be on to something.  I logged the layer to the console and noticed the renderingRule was null, so I added a this.renderingRule = _self.getRenderingRule() inside the getImageUrl() function, which the getRenderingRule() is a function we have added in to build the custom rendering rule based off some slider and checkbox controls we have in the app.  After doing this I did a console.dir(layer.renderingRule.toJson()) and kept getting a blank object.  I overwrote the toJson method inside the constructor and was getting the same response, just a blank object, so I then moved it to the getImageUrl() function and was able to get it to retrieve the JSON string but still am unable to see it print.  I put in alert in the layer.renderingRule.toJson() and it does not fire when I call the print task.  I tried just logging layer.renderingRule.toJson() to the console and this was what it returned.

"{"rasterFunction":"PalmOilSuitabilityNew","rasterFunctionArguments":{"ElevRaster":"$1","SlopeRaster":"$2","WaterRaster":"$3","ConsRaster":"$4","STypeRaster":"$5","SDepthRaster":"$6","PeatRaster":"$7","SAcidRaster":"$8","SDrainRaster":"$9","RainfallRaster":"$10","LCRaster":"$11","ElevInpR":[0,100,100,1000000],"ElevOutV":[1,0],"SlopeInpR":[0,30,30,1000000],"SlopeOutV":[1,0],"WaterInpR":[0,10,10,1000000],"WaterOutV":[0,1],"ConsInpR":[0,10,10,1000000],"ConsOutV":[0,1],"RainfallInpR":[0,150,150,700,700,1000000],"RainfallOutV":[1,1,0],"SDepthInpR":[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7],"SDepthOutV":[1,0,0,0,1,1,1,1],"PeatInpR":[0,0,1,1,2,2,3,3,4,4,5,5,6,6],"PeatOutV":[1,0,0,0,0,0,0],"SAcidInpR":[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7],"SAcidOutV":[1,1,1,1,1,1,1,1],"SDrainInpR":[0,0,1,1,2,2,3,3,4,4],"SDrainOutV":[1,0,1,1,1],"LCInpR":[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8],"LCOutV":[1,1,1,1,0,0,0,0,0],"STypeInpR":[1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10],"STypeOutV":[1,1,1,0,1,1,1,1,1,0]}}"


does this look like a valid renderingRule and is setting the this.renderingRule to the newly created custom renderingRule in getImageUrl() the best way to keep it up to date and setting the toJson() function in the getImageUrl() as well the right way to override it ?
0 Kudos
RobertWinterbottom
Occasional Contributor
Would there happen to be a sample anywhere that shows print task working with ImageServiceLayer or a working URL so I could see what a successful request looks like, we tried manually changing the JSON at the rest endpoint and kept getting 404 errors because we are not sure what a successful request with a rendering rule would look like.
0 Kudos
JianHuang
Occasional Contributor III
I tested a simple case and print task works fine with renderingRule. This is how the JSON looks like:
{
    "mapOptions": {
        "showAttribution": true,
        "extent": {
            "xmin": -9002667.410873475,
            "ymin": 4193183.580948897,
            "xmax": -8996552.448610498,
            "ymax": 4195815.881110537,
            "spatialReference": {
                "wkid": 102100
            }
        },
        "spatialReference": {
            "wkid": 102100
        },
        "scale": 18055.954822005082
    },
    "operationalLayers": [
        {
            "id": "layer0",
            "title": "layer0",
            "opacity": 1,
            "minScale": 591657527.591555,
            "maxScale": 9027.977411,
            "url": "http://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer"
        },
        {
            "id": "layer2",
            "title": "layer2",
            "opacity": 1,
            "minScale": 0,
            "maxScale": 0,
            "url": "http://sampleserver6.arcgisonline.com/arcgis/rest/services/CharlotteLAS/ImageServer",
            "bandIds": null,
            "compressionQuality": null,
            "interpolation": null,
            "renderingRule": {
                "rasterFunction": "RFTShadedReliefElevationColorRamp"
            }
        },
        {
            "id": "layer1",
            "title": "layer1",
            "opacity": 1,
            "minScale": 591657527.591555,
            "maxScale": 9027.977411,
            "url": "http://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Reference/MapServer"
        },
        {
            "id": "map_graphics",
            "minScale": 0,
            "maxScale": 0,
            "featureCollection": {
                "layers": []
            }
        }
    ],
    "exportOptions": {
        "outputSize": [
            800,
            1100
        ],
        "dpi": 96
    }
}
0 Kudos
BrendanCollins
New Contributor II
Hey Jian,

Thanks for the example.  Is there an example using a renderingRule which has functionArguments?  Looks like all you have is the rasterFunction.

Thanks for you help with this.
0 Kudos
JianHuang
Occasional Contributor III
Can you post the web map json sent to print service?
0 Kudos
RobertWinterbottom
Occasional Contributor
Can you post the web map json sent to print service?


Ahhh that's it.  I was using GET not POST.   That got it working from the endpoint.  Im not sure why but on the JavaScript side when we call print task our renderingRule isn't being inserted automatically in to the web map JSON so I will do some digging to see if we messed something up with our custom ImageServiceLayer that's preventing this.

In the meantime, I was able to get it to work properly when I used something along the lines of this:

require(["esri/request"], function(request) {
  request.setRequestPreCallback(function(ioArgs) {
    // if request is to the PrintingTools url
        // Get my Image Service Layer from ioArgs.content.Web_Map_as_JSON
        // Add in my rendering rule and rasterFunctionArguments 
        // replace webmap JSON with updated JSON and request now uses POST instead of GET
    return ioArgs;
  });
});



Thanks for your help.
0 Kudos