2

I have a static image of a Bing maps tile (Mercator EPSG: 3857) with satellite overlay in PNG format. I read the PNG as a raster and georeferenced it in R by setting the corner coordinates using the raster package.

Here is the original PNG. enter image description here

r <- raster("mymap.png")
# add coordinate system
crs(r) <- "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs"
# plot raster
plot(r)
# try some different colors, not true color though
colortable(r) <- rainbow(256)
plot(r)

enter image description here However, when I try to plot the raster, I get some kooky colors. I can change the colortable, but it doesn't match the true color of the PNG. What is happening to the "color values" when I read a PNG with the raster package?

Here is the raster:

Formal class 'RasterLayer' [package "raster"] with 12 slots
  ..@ file    :Formal class '.RasterFile' [package "raster"] with 13 slots
  .. .. ..@ name        : chr "C:\\Users\\me\\Documents\\traffic\\bing\\images\\mymap.png"
  .. .. ..@ datanotation: chr "INT1U"
  .. .. ..@ byteorder   : chr "little"
  .. .. ..@ nodatavalue : num -Inf
  .. .. ..@ NAchanged   : logi FALSE
  .. .. ..@ nbands      : int 3
  .. .. ..@ bandorder   : chr "BIL"
  .. .. ..@ offset      : int 0
  .. .. ..@ toptobottom : logi TRUE
  .. .. ..@ blockrows   : int 1
  .. .. ..@ blockcols   : int 2560
  .. .. ..@ driver      : chr "gdal"
  .. .. ..@ open        : logi FALSE
  ..@ data    :Formal class '.SingleLayerData' [package "raster"] with 13 slots
  .. .. ..@ values    : logi(0) 
  .. .. ..@ offset    : num 0
  .. .. ..@ gain      : num 1
  .. .. ..@ inmemory  : logi FALSE
  .. .. ..@ fromdisk  : logi TRUE
  .. .. ..@ isfactor  : logi FALSE
  .. .. ..@ attributes: list()
  .. .. ..@ haveminmax: logi TRUE
  .. .. ..@ min       : num 0
  .. .. ..@ max       : num 255
  .. .. ..@ band      : int 1
  .. .. ..@ unit      : chr ""
  .. .. ..@ names     : chr "mymap"
  ..@ legend  :Formal class '.RasterLegend' [package "raster"] with 5 slots
  .. .. ..@ type      : chr(0) 
  .. .. ..@ values    : logi(0) 
  .. .. ..@ color     : logi(0) 
  .. .. ..@ names     : logi(0) 
  .. .. ..@ colortable: logi(0) 
  ..@ title   : chr(0) 
  ..@ extent  :Formal class 'Extent' [package "raster"] with 4 slots
  .. .. ..@ xmin: num 0
  .. .. ..@ xmax: num 2560
  .. .. ..@ ymin: num 0
  .. .. ..@ ymax: num 1280
  ..@ rotated : logi FALSE
  ..@ rotation:Formal class '.Rotation' [package "raster"] with 2 slots
  .. .. ..@ geotrans: num(0) 
  .. .. ..@ transfun:function ()  
  ..@ ncols   : int 2560
  ..@ nrows   : int 1280
  ..@ crs     :Formal class 'CRS' [package "sp"] with 1 slot
  .. .. ..@ projargs: chr "+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +no_defs"
  ..@ history : list()
  ..@ z       : list()

I'm not entirely sure why it says there are 3 bands when this is just a single band PNG image.

4
  • 1
    Would you be able to provide the code you have tried for plotting and saving the raster? Commented Mar 5, 2018 at 23:01
  • Could you provide the code that you are using? Also see [oscarperpinan.github.io/rastervis/](rastervis). Or gis.stackexchange.com/questions/102788/…
    – GISHuman
    Commented Mar 5, 2018 at 23:02
  • 1
    As the raster has three bands, have you tried using plotRGB()? Commented Mar 5, 2018 at 23:06
  • @GISKid @Mikey Thanks for responding. I've added the code and the original PNG. Not sure why it says 3 band - it's just a single band PNG. plotRGB says "unable to find an inherited method for function ‘plotRGB’ for signature ‘"RasterLayer"
    – la_leche
    Commented Mar 6, 2018 at 0:01

2 Answers 2

4

I'm a little late to the party, but figured I could contribute a more complete answer to the question than the bits left in comments here.

raster::raster() only reads a single band when handed a multi-band raster, though it does let you choose which one via the band argument. As you wound up figuring out, for loading a single file as a multi-band raster, you want to use the raster::brick() function (or, if your bands are stored as separate files, raster::stack()). You're then able to plot the multi-band image via raster::plotRGB().

As for your second question, of why there are three bands to begin with: the PNG format your image is in represents each pixel in the grid with 3 (or 4) numbers: the amount of red in the pixel, the amount of green, and the amount of blue (with the 4th band being opacity). Each of those values are stored in the image as their own separate band, which is why you need to pull out raster::brick() instead of simply raster::raster() -- your original example was visualizing only the red band of the image, without paying attention to the other two values that make up the color for each pixel.

3

I can get the correct colors if I use brick() rather than raster()

r <- brick("mymap.png")
plotRGB(r)

However, I am still confused as to why there are 3 bands to begin with if this is just a static map PNG and not, say, a Landsat image with data from different sensor bands. Would appreciate any information on this matter!

3
  • 2
    All images such as this are RGB. Just take a look at a photograph from a digital camera. Commented Mar 6, 2018 at 1:51
  • @JeffreyEvans the exception is palletted images, where a full colour image is a single-band raster where the raster value is a lookup into a palette table. PNGs can be palletted single band images.
    – Spacedman
    Commented Nov 9, 2020 at 23:03
  • @Spacedman, ah true, thanks for pointing out this format. Commented Nov 9, 2020 at 23:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.