Skip to content

Commit

Permalink
Merge pull request #365 from kartoza/osundwajeff/issue348
Browse files Browse the repository at this point in the history
Convert raster to 8bit function and test
  • Loading branch information
osundwajeff authored Oct 3, 2024
2 parents 0a8ffae + 76cad6c commit e60ad6f
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 2 deletions.
57 changes: 57 additions & 0 deletions geest/core/convert_to_8bit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import os
import processing
from qgis.core import QgsMessageLog, Qgis, QgsRasterLayer, QgsProject


class RasterConverter:
"""
A class to handle the conversion of rasters to 8-bit TIFFs.
"""

def __init__(self, feedback=None):
"""
Initialize the RasterConverter with optional feedback for progress reporting.
:param feedback: Optional QgsFeedback object for reporting progress.
"""
self.feedback = feedback

def convert_to_8bit(self, input_raster: str, output_raster: str) -> bool:
"""
Convert the input raster to an 8-bit TIFF using gdal:translate.
:param input_raster: Path to the input raster file.
:param output_raster: Path to the output 8-bit TIFF file.
:return: True if conversion is successful, False otherwise.
"""
QgsMessageLog.logMessage(
f"Converting {input_raster} to 8-bit TIFF at {output_raster}.",
tag="RasterConverter",
level=Qgis.Info,
)

params = {
"INPUT": input_raster,
"TARGET_CRS": None, # Use input CRS
"NODATA": -9999,
"COPY_SUBDATASETS": False,
"OPTIONS": "",
"EXTRA": "",
"DATA_TYPE": 1, # 1 = Byte (8-bit unsigned)
"OUTPUT": output_raster,
}

try:
# Run the gdal:translate processing algorithm
processing.run("gdal:translate", params, feedback=self.feedback)
QgsMessageLog.logMessage(
f"Successfully converted {input_raster} to 8-bit TIFF.",
tag="RasterConverter",
level=Qgis.Info,
)
return True
except Exception as e:
QgsMessageLog.logMessage(
f"Failed to convert {input_raster} to 8-bit: {str(e)}",
tag="RasterConverter",
level=Qgis.Critical,
)
return False
17 changes: 15 additions & 2 deletions geest/core/workflows/factor_aggregation_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
)
from qgis.analysis import QgsRasterCalculator, QgsRasterCalculatorEntry
from .workflow_base import WorkflowBase
from geest.core.convert_to_8bit import RasterConverter


class FactorAggregationWorkflow(WorkflowBase):
Expand Down Expand Up @@ -113,6 +114,16 @@ def aggregate_vrt_files(self, vrt_files: list) -> None:
# Run the calculation
result = calc.processCalculation()

converter = RasterConverter()

aggregation_output_8bit = aggregation_output.replace(".tif", "_8bit.tif")

# Convert the aggregated raster to 8-bit
converter.convert_to_8bit(aggregation_output, aggregation_output_8bit)

if os.path.exists(aggregation_output_8bit):
os.remove(aggregation_output)

if result == 0:
QgsMessageLog.logMessage(
"Raster aggregation completed successfully.",
Expand All @@ -121,7 +132,7 @@ def aggregate_vrt_files(self, vrt_files: list) -> None:
)
# Add the aggregated raster to the map
aggregated_layer = QgsRasterLayer(
aggregation_output, f"{self.indicator_name}"
aggregation_output_8bit, f"{self.indicator_name}"
)
if aggregated_layer.isValid():
# Copy the style (.qml) file to the same directory as the VRT
Expand All @@ -134,7 +145,9 @@ def aggregate_vrt_files(self, vrt_files: list) -> None:
qml_dest_path = os.path.join(
self.workflow_directory,
"contextual",
os.path.basename(aggregation_output).replace(".tif", ".qml"),
os.path.basename(aggregation_output_8bit).replace(
".tif", ".qml"
),
)
shutil.copy(qml_src_path, qml_dest_path)
QgsMessageLog.logMessage(
Expand Down
61 changes: 61 additions & 0 deletions test/test_convert_to_8bit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import os
import unittest
from qgis.core import QgsApplication, QgsRasterLayer, Qgis
from geest.core.convert_to_8bit import RasterConverter


class TestRasterConverter(unittest.TestCase):

@classmethod
def setUpClass(self):

# Define paths to input and output files
self.input_raster = os.path.join(
os.path.dirname(__file__), "test_data/rasters/raster.tif"
)
self.output_raster = os.path.join(
os.path.dirname(__file__), "output/output_raster_8bit.tif"
)

def test_convert_to_8bit(self):
"""
Test the convert_to_8bit method of the RasterConverter class.
"""
# Create an instance of RasterConverter
converter = RasterConverter()

# Ensure input file exists before running the test
self.assertTrue(
os.path.exists(self.input_raster), "Input raster file does not exist"
)

# Check if the input image is 32-bit using QGIS API
input_layer = QgsRasterLayer(self.input_raster, "Test Raster")
self.assertTrue(input_layer.isValid(), "Raster layer is not valid")

# Get the raster band data type
input_provider = input_layer.dataProvider()
input_band_data_type = input_provider.dataType(1)

self.assertEqual(input_band_data_type, Qgis.Float32, "Input raster is 32-bit")

# Run the conversion
success = converter.convert_to_8bit(self.input_raster, self.output_raster)

# Check if the conversion was successful
self.assertTrue(success, "Raster conversion failed")

# Check if the output image is 8-bit using QGIS API
raster_layer = QgsRasterLayer(self.output_raster, "Test Raster")
self.assertTrue(raster_layer.isValid(), "Raster layer is not valid")

# Get the raster band data type
provider = raster_layer.dataProvider()
band_data_type = provider.dataType(1)

# Assert if the raster data type is 8-bit
self.assertEqual(band_data_type, Qgis.Byte, "Output raster is not 8-bit")


if __name__ == "__main__":
unittest.main()
Binary file added test/test_data/rasters/raster.tif
Binary file not shown.

0 comments on commit e60ad6f

Please sign in to comment.