Featured image of post Handling TIFF Images with Python, Flask and AJAX

Handling TIFF Images with Python, Flask and AJAX

Python Version of the Blazor Article

See C# version here for explanation
Handling TIFF Images in Blazor with SignalR

This project provides a simple Python Flask backend to upload and convert TIFF images to PNG, ensuring compatibility with web browsers. The frontend uses HTML, JavaScript, and AJAX to upload and display the converted image.


Install Your Tools

1
pip install flask pillow

How the Python Server Works

The Flask server handles both file uploads and the TIFF-to-PNG conversion.

  1. File Upload (/upload route):

    • The user selects a TIFF file in the browser and uploads it to the server.
    • Flask saves the uploaded file in the uploads/ folder.
    • The server responds with a success message and the file path.
  2. TIFF-to-PNG Conversion (/convert route):

    • The client sends the TIFF file path to this route.
    • The Pillow (PIL) library loads the TIFF file.
    • The image is converted and saved as a PNG file.
    • The PNG file is then sent back to the client.

server.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from flask import Flask, request, jsonify, send_file
from PIL import Image
import os

app = Flask(__name__)
UPLOAD_FOLDER = "uploads"
os.makedirs(UPLOAD_FOLDER, exist_ok=True)

@app.route("/upload", methods=["POST"])
def upload_file():
    if 'file' not in request.files:
        return jsonify({"error": "No file part"}), 400
    file = request.files['file']
    if file.filename == '':
        return jsonify({"error": "No selected file"}), 400
    
    file_path = os.path.join(UPLOAD_FOLDER, file.filename)
    file.save(file_path)
    return jsonify({"message": "File uploaded successfully", "file_path": file_path})

@app.route("/convert", methods=["POST"])
def convert_tiff_to_png():
    data = request.json
    file_path = data.get("file_path")
    if not file_path or not os.path.exists(file_path):
        return jsonify({"error": "File not found"}), 400
    
    img = Image.open(file_path)
    png_path = file_path.rsplit(".", 1)[0] + ".png"
    img.save(png_path, "PNG")
    
    return send_file(png_path, mimetype='image/png')

if __name__ == "__main__":
    app.run(debug=True)

Step 3: How the HTML and JavaScript Work

The frontend consists of an HTML page and JavaScript using AJAX to communicate with the server.

  1. User Selects a File:

    • The <input> element allows users to pick a TIFF file.
  2. Upload the File to Flask:

    • JavaScript grabs the selected file and sends it via an AJAX POST request.
  3. Request PNG Conversion:

    • After upload, the client sends another AJAX request to convert the TIFF to PNG.
    • The server responds with the converted PNG file.
    • JavaScript updates the <img> element with the PNG file URL.

index.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>TIFF to PNG Converter</title>
</head>
<body>
    <h3>TIFF to PNG Image Display</h3>
    <input type="file" id="fileInput">
    <button onclick="uploadFile()">Upload & Convert</button>
    <br>
    <p id="statusMessage"></p>
    <img id="imageDisplay" style="border: 1px solid #000; max-width: 500px;" />

    <script>
        async function uploadFile() {
            let fileInput = document.getElementById("fileInput");
            let file = fileInput.files[0];
            if (!file) {
                alert("Please select a TIFF file");
                return;
            }
            
            let formData = new FormData();
            formData.append("file", file);
            let response = await fetch("/upload", { method: "POST", body: formData });
            let result = await response.json();
            if (result.error) {
                alert(result.error);
                return;
            }
            
            let pngResponse = await fetch("/convert", { method: "POST", body: JSON.stringify({ file_path: result.file_path }), headers: { "Content-Type": "application/json" }});
            if (pngResponse.ok) {
                let blob = await pngResponse.blob();
                document.getElementById("imageDisplay").src = URL.createObjectURL(blob);
                document.getElementById("statusMessage").textContent = "Image converted successfully";
            } else {
                alert("Error converting image");
            }
        }
    </script>
</body>
</html>