Export ArcGIS tiles data to any image format

I added aerial imagery from GIS server and created fishnet over the area of interest: enter image description here

I use fishnet as index layer for my data driven pages, making sure the sorting order coincides with record order in fishnet table.

I applied script (see below) to travel through pages, export them to temp raster, clip it to PNG raster named after page name. Result shows clipped tiles with source image faded:

enter image description here

Script has 1 input parameter – output folder to save your tiles. Before running it I suggest you to play with resolution (dpi) and cell size (to get best resolution possible) of fishnet.

# EXPORT SCREENs TO RASTERs
import arcpy, traceback, os, sys, time
from arcpy import env
env.overwriteOutput = True
outFolder=arcpy.GetParameterAsText(0)
dpi=1200
tempRaster=outFolder+os.sep+"victim.png"

## ERROR HANDLING
def showPyMessage():
    arcpy.AddMessage(str(time.ctime()) + " - " + message)

try:
    mxd = arcpy.mapping.MapDocument("CURRENT")
    ddp = mxd.dataDrivenPages
    thePagesLayer = arcpy.mapping.ListLayers(mxd,ddp.indexLayer.name)[0]
#   GET RECTANGLES
    g=arcpy.Geometry()
    geometryList=arcpy.CopyFeatures_management(thePagesLayer,g)
#   EXPORT PAGES
    df = arcpy.mapping.ListDataFrames(mxd)[0]
    fld = ddp.pageNameField.name
    Page_Names=arcpy.da.TableToNumPyArray(thePagesLayer, fld)
    for pageID in range(1, ddp.pageCount+1):
        ddp.currentPageID = pageID
        arcpy.RefreshActiveView()
        time.sleep(3)
        arcpy.mapping.ExportToPNG(mxd,tempRaster,df,dpi,world_file=True)
        fName=outFolder+os.sep+Page_Names[pageID-1][0]+".png"
        anExtent=geometryList[pageID-1].extent
        envelope='%f %f %f %f' %(anExtent.XMin, anExtent.YMin, anExtent.XMax, anExtent.YMax,)
#   CLIP EXPORTED BY PAGE RECTANGLE
        arcpy.Clip_management (tempRaster, envelope,fName)
        arcpy.AddMessage('%s processed' %fName)
except:
    message = "\n*** PYTHON ERRORS *** "; showPyMessage()
    message = "Python Traceback Info: " + traceback.format_tb(sys.exc_info()[2])[0]; showPyMessage()
    message = "Python Error Info: " +  str(sys.exc_type)+ ": " + str(sys.exc_value) + "\n"; showPyMessage()

Sorting order of pages is most important. Before 'travel' starts script creates a list of rectangles/pages and uses i-th (page no -1) one to clip screenshot. If order of pages<>order of records in fishnet table, script will produce weird results if any.

Cancel script after few steps and check results. Restart if they make sense.

UPDATE May 3, 2016

It seems few people found script useful. I modified it, so that page order and field type to store page name don't matter anymore.

# EXPORTS SCREEN TO RASTER(s)
import arcpy, traceback, os, sys, time
from arcpy import env
env.overwriteOutput = True
outFolder=arcpy.GetParameterAsText(0)
env.workspace = outFolder
dpi=1200
tempRaster=outFolder+os.sep+"victim.png"
## ERROR HANDLING
def showPyMessage():
    arcpy.AddMessage(str(time.ctime()) + " - " + message)
try:
    mxd = arcpy.mapping.MapDocument("CURRENT")
    ddp = mxd.dataDrivenPages
#   GET PAGES INFO
    thePagesLayer = arcpy.mapping.ListLayers(mxd,ddp.indexLayer.name)[0]
    df = arcpy.mapping.ListDataFrames(mxd)[0]
    fld = ddp.pageNameField.name
    for pageID in range(1, ddp.pageCount+1):
        ddp.currentPageID = pageID
        arcpy.RefreshActiveView()
        time.sleep(3)
        arcpy.mapping.ExportToPNG(mxd,tempRaster,df,dpi,world_file=True)
        fName=outFolder+os.sep+str(ddp.pageRow.getValue(fld))+".png"
        rect=ddp.pageRow.getValue("Shape")
        anExtent=rect.extent
        envelope='%f %f %f %f' %(anExtent.XMin, anExtent.YMin, anExtent.XMax, anExtent.YMax,)
#   CLIP EXPORTED BY PAGE RECTANGLE
        arcpy.Clip_management (tempRaster, envelope,fName)
        arcpy.AddMessage('%s processed' %fName)
    arcpy.Delete_management(tempRaster)
except:
    message = "\n*** PYTHON ERRORS *** "; showPyMessage()
    message = "Python Traceback Info: " + traceback.format_tb(sys.exc_info()[2])[0]; showPyMessage()
    message = "Python Error Info: " +  str(sys.exc_type)+ ": " + str(sys.exc_value) + "\n"; showPyMessage()

I've written a python script for this. This is the initial version of the script, so it needs to add certain values manually into the script. I've mentioned that in script. Here it is

import math
from pyproj import Proj, transform

from PIL import Image
import glob, os
import sys
from os import walk
from os.path import join, getsize

#this function would convert utm coordinates to lat lng
#function taken from http://gis.stackexchange.com/questions/78838/how-to-convert-projected-coordinates-to-lat-lon-using-python
def utmToLatLng(x,y):
  inProj = Proj(init='epsg:3857')
  outProj = Proj(init='epsg:4326')

  x2,y2 = transform(inProj,outProj,x,y)
  return (x2,y2)



#this function would take lat lng and return the tile number
#function taken from http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
def deg2num(lat_deg, lon_deg, zoom):
  lat_rad = math.radians(lat_deg)
  n = 2.0 ** zoom
  xtile = int((lon_deg + 180.0) / 360.0 * n)
  ytile = int((1.0 - math.log(math.tan(lat_rad) + (1 / math.cos(lat_rad))) / math.pi) / 2.0 * n)
  return (xtile, ytile)

#this function would take a number and return it in hexa format
#taken from http://stackoverflow.com/questions/16414559/trying-to-use-hex-without-0x
def inttohexa(x):
  return format(x, 'x')


#this function would take a number and return a 9 letter word, the first letter
# would be static, should be R and C for folder and files respectivly
#this function can be improved further. Developed by muzaffar in hurry
#that's why you so see much if else in the function
def completeEightNumbers(number,letter):
  if len(number)<8:
    less_number = 8-len(number)
    if less_number==1:
      return letter+'0'+number
    elif less_number==2:
      return letter+'00'+number
    elif less_number==3:
      return letter+'000'+number
    elif less_number==4:
      return letter+'0000'+number
    elif less_number==5:
      return letter+'00000'+number
    elif less_number==6:
      return letter+'000000'+number
    elif less_number==7:
      return letter+'0000000'+number
    elif less_number==8:
      return letter+'00000000'+number
  else:
    return letter+number


#we need these four parameters
ymin = 4370513.4222595459
ymax = 4375009.1735663339
xmin = 8142366.0491449088
xmax = 8146042.4910550155

#resolution of the max zoom level
resolution = 0.59716428355981699
tile_diff = resolution * 256 #256 is the tile width



folders_name = [] #this list would contain the actual folders which have tiles inside
#storing ymax value in a variable for loop purpose only
ymax_loop = 4375009.1735663339
while (ymin < ymax_loop):#we would keep looping until the max value reach the ymin

  #xmin value would remain same while ymax_loop would change for each loop
  latlng =  utmToLatLng(xmin, ymax_loop) #sample output 36.538723, 73.144095
  tile_num =  deg2num(latlng[1], latlng[0], 18) #18 here is zoom level
  folder_name = inttohexa(tile_num[1])
  exact_folder_name = completeEightNumbers(folder_name,'R')

  #insert the folder name in list
  folders_name.append(exact_folder_name)

  #reduce the value of loop by tile_diff -- each time the loop execute
  ymax_loop = ymax_loop - tile_diff

print folders_name


file1 = "C:\Users\A\Desktop\mosaic\output.png"
file, ext = os.path.splitext(file1)
outfile = file + ".PNG"

result_width = 25*256
result_height = 30*256
result = Image.new('RGB', (result_width, result_height))

root = "C:\Users\A\Desktop\mosaic"
folders_index = 0
for single_folder in folders_name:

    print root+"\\"+single_folder
    files = glob.glob(root+"\\"+single_folder+"\\*")

    image_list = []
    files_index = 0

    for b in files:

      image_list.append(Image.open(b))

      result.paste(image_list[files_index], box=((files_index*256),(folders_index*256)))
      files_index += 1
      #print result

      #print folders_index*256  
    folders_index +=1

result.save(outfile, "PNG")
print "done"