Quantcast
Channel: Question and Answer » gdal
Viewing all 397 articles
Browse latest View live

GDAL polygonize lines

$
0
0

I have a raster file containing roads (left image). I polygonize the raster file with GDAL (see the script below). In the end I like to have vector lines. However GDAL only gives me something like this back (right image). Obviously this is correct, since polygonize creates polygons. Is there a way to “linize” a raster?

enter image description here

Here is my code:

import gdal,ogr,os

# open raster file
raster = gdal.Open('test.tif')
band = raster.GetRasterBand(1)

#create new shp file
newSHPfn = 'test.shp'
shpDriver = ogr.GetDriverByName("ESRI Shapefile")
if os.path.exists(newSHPfn):
    shpDriver.DeleteDataSource(newSHPfn)
outDataSource = shpDriver.CreateDataSource(newSHPfn)
outLayer = outDataSource.CreateLayer(newSHPfn, geom_type=ogr.wkbLineString )

# polygonize
gdal.Polygonize(band, None, outLayer, 1) 

OGRFeature::DestroyFeature fails

$
0
0

I am using OGR to read features from a shape file; when the feature is destroyed I am getting an error 0xC0000005: Access violation reading location 0xffffffffffffffff.

This secton of the code looks pointless but is a simplification of a larger section showing where the error is occuring. I have removed lines of code that could interfere with the objects and I am still getting the same error message.

OGRDataSource *hDS;
OGRSFDriver   *Driver;
OGRFeature    *pFeat;

hDS = OGRSFDriverRegistrar::Open(BasePath,FALSE,&Driver);
OGRLayer *Layer = hDS->GetLayerByName(ThisLayerName);
Layer->ResetReading();

while ((pFeat = Layer->GetNextFeature()) != NULL)
{
    // I did intend to do something here
    OGRFeature::DestroyFeature(pFeat); // error occurs here
}
OGRDataSource::DestroyDataSource(hDS);

I am using OGR2OGR source as a reference on how to read an OGR datasource. I can see in the reference that each feature returned is destroyed before grabbing a new one until the last feature and the datasource is destroyed thereafter.

I am using GDAL version 1.10 64bit on Windows 7 64bit; I have tried previous versions 1.9.2 and 1.8 and they all return the same error. I am using Visual C++ if that makes any difference.

Trying to build GDAL's ECW plugin in 64 bit Linux

$
0
0

I’m trying to build the GDAL’s ECW plugin in Linux. I’m using the latest version of the SDK from Intergraph’s site (5.0). It fails because it tries to compile against the 32 bit version of the library and not the 64. Here’s the error message where the process dies:

/usr/bin/ld: skipping incompatible  
/usr/local/ecwjp2_sdk/lib/x86/release/libNCSEcw.so when searching for -lNCSEcw
/usr/bin/ld: skipping incompatible    
/usr/local/ecwjp2_sdk/lib/x86/release/libNCSEcw.a when searching for -lNCSEcw
/usr/bin/ld: cannot find -lNCSEcw

I have pointed ldconfig to look in /usr/local/ecwjp2_sdk/lib/x64/release, but that seems to be ignored. Is there any way to force it to look in the 64 bit version’s directory, or can I get away with changing the symlinks for the 32 bit version and have them point to the 64′s instead?

Can GDAL Retile run multi-threaded?

$
0
0

gdal_retile is currently using only one CPU of the available eight and it is taking a while (48 hours already) to retile 5TB of data.

why readOGR() is not reading projection information from .spj – r

$
0
0

0 down vote favorite

I successfully import a polygon shapefile with readOGR, however the information in the .prj file is not being imported.

test class : SpatialPolygonsDataFrame nfeatures : 19407 extent : 35551.4, 1585917, 6318047, 9408727 (xmin, xmax, ymin, ymax) coord. ref. : NA

summary(test) Object of class SpatialPolygonsDataFrame Coordinates: min max x 35551.4 1585917 y 6318047.3 9408727 Is projected: NA proj4string : [NA]

the projection should be utm21n complex zone

How to define a BoundingBox when using GDAL's WCS Driver (Java API)?

$
0
0

Is it possible to define a bounding box when requesting a coverage subset using the GDAL WCS Driver, accessed using GDAL’s Java API? I’ve read several mailing lists and related posts on gis.stackexchange, but have not located a clear solution.

The driver documentation (http://www.gdal.org/frmt_wcs.html) does not contain a bounding box definition, unlike the WMS driver. I attempted to define the bounding box in the xml configuration, but the requests generated by the driver when using gdal.open(wcs.xml) return the entire coverage instead of the requested area.

<WCS_GDAL>
<ServiceURL>http://myserver/geoserver/wcs?</ServiceURL>
<Version>1.1.0</Version>
<CoverageName>MyWorkspace:MyCoverage</CoverageName>
<GetCoverageExtra>&BoundingBox=65.0104,31.1977,65.3287,31.4623,urn:ogc:def:crs:OGC:1.3:CRS84</GetCoverageExtra>
</WCS_GDAL>

AND

<WCS_GDAL>
<ServiceURL>http://myserver/geoserver/wcs?BoundingBox=65.0104,31.1977,65.3287,31.4623,urn:ogc:def:crs:OGC:1.3:CRS84</ServiceURL>
<Version>1.1.0</Version>
</WCS_GDAL>

Ideally, I’d be able to retrieve the required data and process it using tools provided by the GDAL. I am able to define a url string (below) containing the desired bounding box, open an HttpUrlConnection, and get a MimeMessage containing the desired raster data as an InputStream.

String url = "http://myserver/geoserver/wcs?service=wcs&version=1.1.1&request=GetCoverage&format=image/geotiff&identifier=MyWorkspace:MyCoverage&BoundingBox=65.0104,31.1977,65.3287,31.4623,urn:ogc:def:crs:OGC:1.3:CRS84";

However, I haven’t figured out how to convert the InputStream to a GDAL DataSet object.

How do I iterate through every cell in a continuous raster?

$
0
0

See this link for more details.

The Problem:

I want to loop through a continuous raster (one that has no attribute table), cell by cell, and get the value of the cell. I want to take those values and run conditionals on them, emulating the map algebra steps detailed below without actually using the raster calculator.

Per request of comments below, I have added details providing background to the problem and justifying the need to implement a method as such in the section below called “The analysis needed:”.

The analysis proposed below, while being relevant to my problem by providing background,does not need to be implemented in an answer. The scope of the question only pertains to iterating through a continuous raster to get/set the cell values.

The analysis needed:

If ANY of the following conditions are fulfilled, give output cell a value of 1. Only give output cell a value of 0 if none of the conditions are fulfilled.

Condition 1: If cell value is greater than top and bottom cells, give value of 1:

Con("raster" > FocalStatistics("raster", NbrIrregular("C:filepathkernel_file.txt"), "MAXIMUM"), 1, 0)

Where kernel file looks like this:

3 3 
0 1 0
0 0 0
0 1 0

Condition 2: If cell value is greater than left and right cells, give value of 1:

Con("raster" > FocalStatistics("raster", NbrIrregular("C:filepathkernel_file.txt"), "MAXIMUM"), 1, 0)

Where kernel file looks like this:

3 3 
0 0 0
1 0 1
0 0 0  

Condition 3: If cell value is greater than topleft and bottomright cells, give value of 1:

Con("raster" > FocalStatistics("raster", NbrIrregular("C:filepathkernel_file.txt"), "MAXIMUM"), 1, 0)

Where kernel file looks like this:

3 3 
1 0 0
0 0 0
0 0 1 

Condition 4: If cell value is greater than bottomleft and topright cells, give value of 1:

Con("raster" > FocalStatistics("raster", NbrIrregular("C:filepathkernel_file.txt"), "MAXIMUM"), 1, 0)

Where kernel file looks like this:

3 3 
0 0 1
0 0 0
1 0 0 

Condition 5: If any one of the adjacent cells has a value EQUAL to the center cell, give the output raster a value of 1 (using focal variety with two nearest neighborhood calculations)

Why not use map algebra?

It has been noted below that my problem could be solved using map algebra but as seen above this is a grand total of six raster calculations, plus one to combine all of the rasters created together. It seems to me that it is much more efficient to go cell-by-cell and do all of the comparisons at once in each cell instead of looping through each individually seven times and utilizing quite a bit of memory to create seven rasters.

How should the problem be attacked?

The link above advises to use IPixelBlock interface, however it is unclear from ESRI documentation whether you are actually accessing a single cell value itself through IPixelBlock, or if you are accessing multiple cell values from the size of the IPixelBlock you set. A good answer should suggest a method for accessing the cell values of a continuous raster and provide an explanation of the methodology behind the code, if not apparently obvious.

In summary:

What is the best method to loop through every cell in a CONTINUOUS raster (which has no attribute table) to access its cell values?

A good answer need not implement the analysis steps described above, it needs only to provide a methodology to access cell values of a raster.

Uninstall ERDAS ECW/JP2 SDK Version 5.0 (Ubuntu)

$
0
0

I am using Ubuntu Linux as main OS when it comes to geoprocessing but I am not yet an expert using it. I recently needed QGIS to have ECW support, so I followed the instructions of Luke in the following question and got it working.

ECW for QGIS 1.8 in Ubuntu 12.04

Now I discovered that I keep getting following error message when doing python geoprocessing which involves any GDAL features

ERROR 1: /usr/lib/gdalplugins/1.10/gdal_ECW_JP2ECW1.so: undefined symbol: _ZTI14GDALPamDataset

It doesn’t affect the outcome of the script or crashes it, but it is annoying to get the terminal spammed with this error message during the usage of the script.

Is there a solution for that? If not, could anybody guide me through the uninstall process?
Note to myself: temporary stuff always in a VM ;)


gdalinfo image.tif>stats.txt – returns empty text file (Windows 7 64 bit)

$
0
0

I am trying to output the gdalinfo image statistics results into a text file with the following command:

gdalinfo image.tif>stats.txt 

The stats.txt file gets created, however it is empty.
It does not contain any statistical information that is printed out in the command window, with the gdalinfo image.tif.

Any help much appreciated!

Many thanks

How do I convert a VMAP to a shapefile using GDAL?

$
0
0

This is my first time trying to convert a VMAP to a shapefile and the examples online aren’t as straightforward to me. Any guidance is appreciated.

Reproject MODIS level 3 chlorophyll data using gdal

$
0
0

I am trying to reproject MODIS Level 3 chlorophyll data (for instance, this file) using gdal in R.

I used gdal_translate and gdalwarp functions. There was no crs information associated with A20121832012213.L3m_MO_CHL_chlor_a_4km.hdf file.

I used:

s_srs= "+proj=eqc +lat_ts=0 +lat_0=0 +lon_0=0 +x_0=0 +y_0=0 +units=m +no_defs +R=6371007.181"

gdalwarp(source,dest,
s_srs="+proj=eqc +lat_ts=0 +lat_0=0 +lon_0=0 +x_0=0 +y_0=0 +units=m +no_defs +R=6371007.181",
t_srs="+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0",srcnodata=-32767,dstnodata=NA)

Although gdal_translate can translate hdf file to other formats, like img, this file cannot be reprojected by gdalwarp because there is an error:

GeoTransform values not available which is returned by function
GetGeoTransform

PS:
Description of Level 3 data says:

This image is typically a scaled value (16bit), two-dimensional array of an Equidistant Cylindrical projection of the globe.

However MODIS Level 3 data is different from SeaWifs Level 3 data. There is no problem with reprojecting SeaWifs data, but not MODIS.

Read large raster into lat/lon value pair to csv file using python and/or gdal?

$
0
0

I have rasters for all of the states in US and they are in 10m resolution. So they can be very large, containing a large number of pixels if you think of TX or AK. I want to create a csv file with each line representing the lat/lon value of the pixel, with comma separating lat and lon. So far the methods that I have tried for MN state:

  1. gdal2xyz—-running time is reasonable, but there is extra column for z value in the csv file. I need to later delete this column through code.

  2. iterate each pixel in the raster, get it’s lat and lon, and write the value into csv—really takes a long time…

To sum up, I just want a csv file with the lat/lon value pair from raster. I feel like it is not hard to achieve. It is just the matter of the running time. I hope there could be some work around. Thank you.

Use GDAL command line to copy projections

$
0
0

I have two images, a georeferenced Tiff and a second Tiff without a reference. The second image is a copy of the first, but it lost its reference. Now, I want to copy the reference from the first Tiff to the second Tiff using GDAL using the command line.

I had a look at several gdal utilities like gdalwarp, gdal_translate etc. but it seems that they only work on one image at a time and cannot “copy” a projection.

Does anybody had a similar problem? Thx!

Some background: I am using ImageJ for image analysis (segmentation) on 600 Tiff-images, all formerly geotiffs. However, during import ImageJ sets the xmin,ymin to (0,0) and looses all spatial information. Now, I try to use GDAL within an ImageJ macro to reload the spatial information so that the segmentation output also has a proper spatial reference

Adding a Vertex To Exisiting Feature(linear) Using OGR Python

$
0
0

I am working on a project that involves finding the intersection of linears in a shapefile, if that vertex(the found intersection) doesn’t already exist for each(or one) of the features, then that vertex(the found intersection point) should be added to both features. I’m using the shapely and OGR modules for python. Can somebody just give me a general example of adding a vertex to an existing feature in shapefile using either or and saving it. Thanks.

gdal2Tiles output differs from MapTiler

$
0
0

I’m in need to process a large batch of Landsat images with MapTiler and since the version I’m using (1.0 Beta 2) does not support multiple input files, I created a simple python script that calls gdal2tiles for every file.

The problem is that using, apparently, the same settings, I get different coordinates.

This is the correct output from MapTiler:

 <?xml version="1.0" encoding="utf-8"?>
    <TileMap version="1.0.0" tilemapservice="http://tms.osgeo.org/1.0.0">
      <Title>mar_apr.tif</Title>
      <Abstract></Abstract>
      <SRS>EPSG:900913</SRS>
      <BoundingBox minx="-26.36147186954573" miny="-65.83667775218426" maxx="-21.96598523780907" maxy="-62.31334995428857"/>
      <Origin x="-26.36147186954573" y="-65.83667775218426"/>
      <TileFormat width="256" height="256" mime-type="image/png" extension="png"/>
      <TileSets profile="mercator">
        <TileSet href="6" units-per-pixel="2445.98490468750010" order="6"/>
        <TileSet href="7" units-per-pixel="1222.99245234375010" order="7"/>
        <TileSet href="8" units-per-pixel="611.49622617187504" order="8"/>
        <TileSet href="9" units-per-pixel="305.74811308593752" order="9"/>
        <TileSet href="10" units-per-pixel="152.87405654296876" order="10"/>
        <TileSet href="11" units-per-pixel="76.43702827148438" order="11"/>
        <TileSet href="12" units-per-pixel="38.21851413574219" order="12"/>
        <TileSet href="13" units-per-pixel="19.10925706787110" order="13"/>
      </TileSets>
    </TileMap>

And this is the incorrect output from gdal2Tiles:

<?xml version="1.0" encoding="utf-8"?>
    <TileMap version="1.0.0" tilemapservice="http://tms.osgeo.org/1.0.0">
      <Title>mar_apr_CLIP1.tif</Title>
      <Abstract></Abstract>
      <SRS>EPSG:900913</SRS>
      <BoundingBox minx="-25.32504747468283" miny="1.94797423573108" maxx="-21.33272919903126" maxy="5.10698976386579"/>
      <Origin x="-25.32504747468283" y="1.94797423573108"/>
      <TileFormat width="256" height="256" mime-type="image/png" extension="png"/>
      <TileSets profile="mercator">
        <TileSet href="6" units-per-pixel="2445.98490468750010" order="6"/>
        <TileSet href="7" units-per-pixel="1222.99245234375010" order="7"/>
        <TileSet href="8" units-per-pixel="611.49622617187504" order="8"/>
        <TileSet href="9" units-per-pixel="305.74811308593752" order="9"/>
        <TileSet href="10" units-per-pixel="152.87405654296876" order="10"/>
        <TileSet href="11" units-per-pixel="76.43702827148438" order="11"/>
        <TileSet href="12" units-per-pixel="38.21851413574219" order="12"/>
        <TileSet href="13" units-per-pixel="19.10925706787110" order="13"/>
      </TileSets>
    </TileMap>

Does MapTiler perform any other operations besides running gdal2Tiles?

Thanks in advance!


gdal_grid with CSV file and VRT "No point geometry found on layer"

$
0
0

Given the following .vrt file which I manually created:

<OGRVRTDataSource>
    <OGRVRTLayer name="DGM5_BE">
        <SrcDataSource>DGM5_BE.txt</SrcDataSource>
        <SrcLayer>DGM5_BE</SrcLayer>
        <LayerSRS>EPSG:25833</LayerSRS>
        <GeometryType>wkbPoint</GeometryType>
        <GeometryField encoding="PointFromColumns" x="x" y="y" z="d"/>
    </OGRVRTLayer>
</OGRVRTDataSource>

and the associated DGM5_BE.txt – here are the first lines:

x;y;d
397200;5837250;59,15
397205;5837250;59,04
397200;5837245;59,03
397205;5837245;58,94
397195;5837240;58,93
397200;5837240;58,9
397205;5837240;58,86
397210;5837240;58,9
397190;5837235;58,98

I run the following command to convert the DGM5:

$ gdal_grid -of GTiff -ot Float32 -l DGM5_BE DGM5_BE.vrt DGM5_BE.tif

This fails with the following error message:

ERROR 1: Failed to open datasource `DGM5_BE.txt’.
No point geometry found on layer DGM5_BE, skipping.

Creating records in output shapefile using Python

$
0
0

I have a list (output from a previous loop) containing attributes from an input shapefile. What I am stuck with is inputting those attributes to a new shapefile.

I have plotted the point data using w.point(x, y) and also created the relevant fields w.field() from the input shapefile fields.

Where I am stuck is with the copy of the records, which is giving me an Error related to Deletion Flag.

AttributeError: ‘tuple’ object has no attribute ‘startswith’

I am pasting a section of the code with my queries.

from datetime import datetime
import osgeo.ogr, osgeo.ogr
from osgeo import ogr
from osgeo import gdal
import shapefile
import os

sf = shapefile.Reader("-- Input File Location --") # Reading the Shapefile
fields = sf.fields # Reading the attribute fields
records = sf.records() # Reading the records of the features
shapRecs = sf.shapeRecords() # Read Geometry and Records simultaneously 

w = shapefile.Writer(shapefile.POINT)
w.autoBalance = 1
result1 = []
result2 = [] # ??? Is the error because we cannot query for list in a list ???

print '** Call function pt(p) where p is node index... **' # Prompting the user to 
                                                           # call the function with 
                                                           # the required number of nodes
def pt(p):
    for i in range(len(shapRecs)):
        u = shapRecs[i].shape.points[p-1]   # Gives the XY Coordinates of
                                            # the queried points

        v = shapRecs[i].record[0:]          # Generating the Attributes
        result1.append(u)
        result2.append(v)

        w.point(u[0], u[1]) # Create points from coordinates each time the loop runs
        w.autoBalance = 1

    # -- Adding the fields
    w.field(fields[0]) # Adding the first field, WITH Deletion Flag (???)
    for i in range(1, len(fields)): # Loop begins from the second field (???)
        w.field(fields[i])
        w.autoBalance = 1

    # CODE SHOWS THE ERROR STATED ABOVE FROM THE w.record() statement
    # -- Adding the records 
    for i in range(len(result2)):
        w.record(*result2[i])       
        w.autoBalance = 1

    w.save('-- Output File Location --')    

MySQL+GDal+MapServer+OpenLayers WebMercator problem

$
0
0

I have a problem/question what is the most efficiant way to go from WGS84 (epsg:4326) to webmercator.

Outline of the structure right now:

  1. MySQL Database: with point Latitude/Lontiude Data [~200 million points]
    these points i bin myself with a SQL query, right now I just bin them with (I insert into separate table for convenience):
    SELECT 
        (FLOOR((longitude/100000)/(360/(POWER(2,16))))*(360/(POWER(2,16)))) AS pixel_X,     
        (FLOOR((latitude/100000)/(180/(POWER(2,15))))*(180/(POWER(2,15)))) AS pixel_Y,
        count(*) AS Amount
        FROM PointData
        GROUP BY pixel_X, pixel_Y
        ORDER BY pixel_X ASC, pixel_Y ASC;
    

    I think this should give me a raster in EPSG:4326.
    This is where I think would be the best place to introduce a change to bin into EPSG:3857 (webmercator, epsg:900913).
    I bin the information here because it’s impossible to send 200-300 million points to GDAL so I have to give up some correctness.

  2. GDAL_grid that creates a raster img-file from the data in the Database (the DBConnection.vrt is just a database connection).
     gdal_grid -of HFA -a nearest:radius1=0.0054931640625:radius2=0.0054931640625 -outsize 65536 32768 -l layer DBConnection.vrt Rasters/output.img --config GDAL_NUM_THREADS ALL_CPUS

    right now this creates a img in EPSG:4326. The nearest algorithm is used to keep the binned raster from mySQL as unchanged as possible.

  3. MapServer reading the img raster
     MAP
            NAME "TestMap"
            PROJECTION
                "init=epsg:4326"
            END
            STATUS OFF
            EXTENT -180 -90 180 90
            UNITS DD
            SHAPEPATH "./layers"
            WEB
                IMAGEPATH "/ms4w/tmp/ms_tmp/"
                IMAGEURL "/ms_tmp/"
                METADATA
                    "wms_title" "Test Server"
                    "wms_onlineresource" "http://localhost/cgi-bin/mapserv?map=/ms4w/apps/TestMaps/TestMap.map&"
                    "wms_enable_request" "*"
                END
            END         
            [...]   
            LAYER
                NAME TestLayer
                STATUS OFF
                TYPE RASTER
                DATA "Rastersoutput.img"
                METADATA
                    "wms_title" "output"
                    "wms_transparent" "true"
                END
                PROJECTION
                    "init=epsg:4326"
                END
                CLASSITEM "pixel"
                PROCESSING "SCALE=0,1000"
                PROCESSING "SCALE_BUCKETS=100"
                CLASS
                    [...] (just some coloring to give a makeshift heatmap)
                END
            END
        END
        
  4. OpenLayers connects to Mapserver and shows the map in the browser.
     function init() {
        map = new OpenLayers.Map("Map", {
                [...]
            ]
        });
        [...]
        var TestLayer = new OpenLayers.Layer.WMS(
            "TestLayer", 
            "http://localhost/cgi-bin/mapserv.exe?map=/ms4w/apps/TestMaps/TestMap.map", 
            {layers: 
                'TestLayer',
                transparent: 'true'
            }, {
                isBaseLayer:false,
                visibility: true
            }
        );
        [...]
    

So at this point the maps show up fine in a EPSG:4326 projection, no problem at all, I have EPSG:4326 country polygons that I use as a base layer right now.

Result in epsg:4326

The problem is I would like to have a webmercator map, street map and so on, but I cant get the projection to change.

So far I’ve tried

  • changing the Projection “init:epsg:4326″ in MapServer to epsg:3857 but to no avail, the layers are not recognized by open layers any more and I just get picture not received error.
  • using gdal_warp on the output.img and change to epsg:3857, didn’t work either, same problem, also this is really time inefficient because warp takes forever and I might aswell put it into the right projection right away in the Database or in the GDAL_GRID.

I have probably been misunderstanding projections and GIS terms so if so let me know, this is the first time I do anything like this, only worked with the Google Maps API before with small amounts of Lat/Lng points where you just send the latlng to Google and it does the rest.

I tried to include as much information as I could, if anything is missing or unclear let me know.

How can you calculate the union/merge two polygons in ogr2ogr?

$
0
0

I want to calculate the union/merge two overlapping polygons using ogr2ogr (as I have 300+ to do). I want the output to be the same as you would get if you used the ‘Merge shapefiles to one’ command in QGIS (Vector > Data Management Tools > Merge shapefiles to one). Does anyone know whether or how this is possible?

My input files are two vector grids populated with statistics – I want to merge two files but keep the attributes of both. The files are exactly the same dimensions and the column names within the two files are different.

I’ve tried ogr2ogr -update -append etc… but this only allows me to keep one set of attributes.

Thanks in advance.

raster2pgsql does nothing

$
0
0

I try to load rasters through raster2pgsql. I try to call it through pgAdmin command line, but when I call any raster2pgsql command (even raster2pgsql -G), it does nothing, I just get another line to write more commands. No output, no time doing something. Non-gdal psql commands work as expected. raster2pgsql leads to “invalid command” error. I am new to the command line and psql, so I’m stuck here.

I have PostgreSQL 9.3.4, PostGIS 2.1.3 and pgAdmin III 1.18.1 on WIndows XP 32 bit. I made sure that raster2pgsql.exe is in its place in bin folder, but I don’t know of other ways to validate whether it is installed properly.

Viewing all 397 articles
Browse latest View live


Latest Images