You can use the python img.getbbox method to identify and remove transparent images.
import os
from PIL import Image
if img.getbbox() is None:
os.remove(path)
Just copy the following code into a file with '.py' extension and place this file into your QGIS folder with python scripts. It should be this path in Windows:
C:\Users\username\AppData\Roaming\QGIS\QGIS3\profiles\default\processing\scripts
or in Linux:
/home/username/.local/share/QGIS/QGIS3/profiles/default/processing/scripts
After restarting QGIS you'll find the script in the bottom of the processing toolbox in QGIS. Choose the path of the folder with tiles. It will look through all subfolders, identify transparent tiles, delete them and also delete all empty folders. It also works well in the model designer.
I didn't test it with other formats than png. You can try it by replacing png in the code with another format that also is transparent.
from qgis.core import QgsProcessing
from qgis.core import QgsProcessingAlgorithm
from qgis.core import QgsProcessingParameterFolderDestination
from qgis.core import QgsProcessingMultiStepFeedback
import processing
from PIL import Image
import os
class deleteemptytiles(QgsProcessingAlgorithm):
def initAlgorithm(self, config=None):
# Add a folder input parameter to the algorithm
self.addParameter(
QgsProcessingParameterFolderDestination(
'INPUT_FOLDER',
'Input Folder containing tiles'
)
)
def processAlgorithm(self, parameters, context, model_feedback):
feedback = QgsProcessingMultiStepFeedback(1, model_feedback)
results = {}
outputs = {}
# Retrieve the folder path from the parameter
tile_folder = self.parameterAsFile(parameters, 'INPUT_FOLDER', context)
# Delete transparent tiles
for root, dirs, files in os.walk(tile_folder, topdown=False):
for filename in files:
if filename.endswith('.png'):
path = os.path.join(root, filename)
try:
img = Image.open(path)
if img.getbbox() is None: # Check if the image is fully transparent
os.remove(path)
feedback.pushInfo(f"Deleted {filename}")
except Exception as e:
feedback.reportError(f"Error processing {filename}: {str(e)}")
# Remove empty folders
for root, dirs, files in os.walk(tile_folder, topdown=False):
for dir in dirs:
dirpath = os.path.join(root, dir)
if not os.listdir(dirpath): # Check if the directory is empty
os.rmdir(dirpath)
feedback.pushInfo(f"Removed empty directory {dirpath}")
return results
def name(self):
return 'DeleteEmptyTiles'
def displayName(self):
return 'Delete empty tiles and directories'
def group(self):
return ''
def groupId(self):
return ''
def createInstance(self):
return deleteemptytiles()