Fixing Image Rotation Using JavaScript and PHP with GD Library

When users upload images from various devices, the orientation metadata (EXIF data) may cause the images to appear rotated incorrectly. This blog post will guide you through fixing image rotation using client-side JavaScript to capture user input and server-side PHP with the GD library for processing. We'll provide code snippets and explanations for each step.

Step1: Client-Side (HTML + JavaScript)

HTML Form

The HTML form allows users to upload an image and provides buttons to rotate the image by 90 degrees clockwise and counterclockwise.


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Image Upload with Rotation</title>
    <style>
        #preview {
            display: block;
            margin-top: 10px;
            max-width: 200px; /* Adjust thumbnail size */
        }
    </style>
</head>
<body>
    <form id="uploadForm" enctype="multipart/form-data">
        <input type="file" name="image" id="image" accept="image/png, image/jpeg" onchange="showThumbnail(this)">
        <button type="button" onclick="rotateImage(90)">Rotate 90° CW</button>
        <input type="hidden" name="rotation" id="rotation" value="0">
        <button type="submit">Upload</button>
    </form>

    <img id="preview" src="" alt="Image preview">
</body>
</html>
    

JavaScript

The JavaScript handles image rotation and captures the rotation angle to send it along with the image when the form is submitted.


let rotation = 0;

function showThumbnail(input) {
    const file = input.files[0];
    const reader = new FileReader();

    reader.onload = function(e) {
        const img = document.getElementById('preview');
        img.src = e.target.result;
        img.style.transform = 'rotate(0deg)';  // Reset rotation
    };

    reader.readAsDataURL(file);
}

function rotateImage(angle) {
    rotation = (rotation + angle) % 360;
    document.getElementById('rotation').value = rotation;
    const img = document.getElementById('preview');
    img.style.transform = rotate(${rotation}deg);
}

document.getElementById('uploadForm').addEventListener('submit', function(e) {
    e.preventDefault();
    const formData = new FormData(this);
    fetch('upload.php', {
        method: 'POST',
        body: formData
    })
    .then(response => response.text())
    .then(data => alert(data))
    .catch(error => console.error('Error:', error));
});
    

Explanation

  • HTML Form:
    • <input type="file" name="image" id="image" accept="image/png, image/jpeg" onchange="showThumbnail(this)">: Allows the user to select an image file and triggers the showThumbnail function to display a preview of the image.
    • <button type="button" onclick="rotateImage(90)">Rotate 90° CW</button>: Button to rotate the image 90 degrees clockwise. The rotateImage function updates the rotation angle and the image preview.
    • <input type="hidden" name="rotation" id="rotation" value="0">: Hidden input to store the rotation angle, which is sent to the server when the form is submitted.
  • JavaScript:
    • showThumbnail(input): This function reads the selected image file and displays a thumbnail preview. It also resets the rotation when a new image is selected.
    • rotateImage(angle): This function updates the rotation angle when the user clicks one of the rotation buttons. The angle is stored in the hidden input field named rotation and applied to the image preview.
    • Event Listener: The form submission is intercepted to handle the file upload using JavaScript's Fetch API. The rotation value and the image file are sent to the server.

Step2: Server-Side Code (PHP with GD)

In Step 1, we covered the client-side HTML and JavaScript code to capture user input for image rotation and display a thumbnail preview. In this step, we will cover the server-side PHP script using the GD library to process the uploaded image, apply the specified rotation, and compress the image before saving it to the server. Additionally, we'll provide information on how to handle different image formats like PNG, JPG, and JPEG.

The PHP script processes the uploaded image, applies the specified rotation, and compresses the image before saving it to the server.


<?php
function rotateImage($sourcePath, $destinationPath, $angle, $mime) {
    switch ($mime) {
        case 'image/jpeg':
        case 'image/jpg':
            $sourceImage = imagecreatefromjpeg($sourcePath);
            break;
        case 'image/png':
            $sourceImage = imagecreatefrompng($sourcePath);
            break;
        default:
            return false;
    }
    
    $rotatedImage = imagerotate($sourceImage, -$angle, 0); // Negative angle for correct rotation direction
    switch ($mime) {
        case 'image/jpeg':
        case 'image/jpg':
            imagejpeg($rotatedImage, $destinationPath, 75); // Adjust the quality as needed (e.g., 75)
            break;
        case 'image/png':
            imagepng($rotatedImage, $destinationPath);
            break;
    }
    imagedestroy($sourceImage);
    imagedestroy($rotatedImage);
    return true;
}

// Define directory paths
$uploadDirectory = 'upload/';
$thumbnailDirectory = 'thumbnail/';

// Ensure directories exist (create if necessary)
if (!file_exists($uploadDirectory)) {
    mkdir($uploadDirectory, 0755, true);
}
if (!file_exists($thumbnailDirectory)) {
    mkdir($thumbnailDirectory, 0755, true);
}

// Process uploaded file
if (isset($_FILES['image'])) {
    $sourcePath = $_FILES['image']['tmp_name'];
    $originalFilename = $_FILES['image']['name'];
    $rotation = intval($_POST['rotation']);
    $mime = mime_content_type($sourcePath);

    // Define paths for the processed images
    $uniqueFilename = uniqid(time(), true) . '.jpg'; // Use .jpg extension
    $lightCompressedPath = $uploadDirectory . $uniqueFilename;
    $hardCompressedPath = $thumbnailDirectory . $uniqueFilename;

    // Step 1: Rotate the image based on user input
    if (rotateImage($sourcePath, $lightCompressedPath, $rotation, $mime)) {
        // Step 2: Create a hard compressed version of the image
        if (!compressImage($lightCompressedPath, $hardCompressedPath, $mime, 50)) {
            echo "Failed to process hard compression.<br>";
        } else {
            echo "Image uploaded and processed successfully!<br>";
        }
    } else {
        echo "Failed to rotate image.<br>";
    }
} else {
    echo "No image uploaded.";
}

function compressImage($sourcePath, $destinationPath, $mime, $quality) {
    switch ($mime) {
        case 'image/jpeg':
        case 'image/jpg':
            $sourceImage = imagecreatefromjpeg($sourcePath);
            imagejpeg($sourceImage, $destinationPath, $quality);
            break;
        case 'image/png':
            $sourceImage = imagecreatefrompng($sourcePath);
            imagepng($sourceImage, $destinationPath);
            break;
        default:
            return false;
    }
    imagedestroy($sourceImage);
    return true;
}
?>
    

Explanation

  • rotateImage($sourcePath, $destinationPath, $angle, $mime): This function uses the GD library to rotate the image by the specified angle based on its MIME type (JPEG or PNG) and save it with a quality of 75 for JPEGs.
  • compressImage($sourcePath, $destinationPath, $mime, $quality): This function uses the GD library to compress the image to the specified quality level, handling both JPEG and PNG formats.
  • Directory Paths: Define paths for the upload and thumbnail directories and ensure they exist and are writable.
  • Process Uploaded File: Handle the uploaded file, apply the user-specified rotation, and compress the image before saving it.

Conclusion

By combining client-side JavaScript to capture user input and server-side PHP with the GD library to process images, you can ensure that uploaded images are correctly oriented and compressed. This approach provides a better user experience and ensures consistent image handling across different devices.

Feel free to adapt and expand on this code to suit your specific needs. Happy coding!

For those looking for a solution using the Imagick library, check out our blog post on how to fix image rotation using JavaScript and PHP with Imagick.

11 0

0 Comment

Leave a Reply

Your email address will not be published. Required fields are marked *


You may like to read


Follow Us

Sponsored Ads

GranNino Ads

Newsletter

Subscribe to our Newsletter to read our latest posts at first

We would not spam your inbox! Promise
Get In Touch

© Fullstack Coding Tips. All Rights Reserved.