public void decompress(TaskMonitor monitor) throws CancelledException, IOException {

		SparseHeader sparseHeader = new SparseHeader(reader);
		if (sparseHeader.getMajor_version() != SparseConstants.MAJOR_VERSION_NUMBER) {
			throw new IOException("Unsupported major version number.");
		}

		this.blockSize = sparseHeader.getBlk_sz();

		int totalBlocks = 0;
		monitor.setMaximum(sparseHeader.getTotal_chunks());
		monitor.setProgress(0);

		for (int i = 0; i < sparseHeader.getTotal_chunks(); i++) {
			monitor.checkCancelled();
			monitor.setMessage(
				"Processing chunk " + i + " of " + sparseHeader.getTotal_chunks() + "...");

			ChunkHeader chunkHeader = new ChunkHeader(reader);
			short chunkType = chunkHeader.getChunk_type();
			int chunkSize = chunkHeader.getChunk_sz();
			if (chunkType == SparseConstants.CHUNK_TYPE_RAW) {
				processRawChunk(chunkSize, monitor);
				totalBlocks += chunkSize;
			}
			else if (chunkType == SparseConstants.CHUNK_TYPE_FILL) {
				processFillChunk(chunkSize, monitor);
				totalBlocks += chunkSize;
			}
			else if (chunkType == SparseConstants.CHUNK_TYPE_DONT_CARE) {
				processSkipChunk(chunkSize, monitor);
				totalBlocks += chunkSize;
			}
			else if (chunkType == SparseConstants.CHUNK_TYPE_CRC32) {
				processCrcChunk();
				totalBlocks += chunkSize;
			}
			else {
				throw new IOException("Unkown chunk type: " + chunkType);
			}
			monitor.incrementProgress(1);
		}

		long totalSize = (long) totalBlocks * sparseHeader.getBlk_sz();
		monitor.setMessage("Total bytes: " + totalSize);
	}
Performs the decompression of the file, writing all bytes available to the
output stream.

@param monitor {@link TaskMonitor} to watch for cancel and to update with progress info.
@throws CancelledException if user cancels
@throws IOException if error when reading or writing.
Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/sparseimage/SparseImageDecompressor.java