| 
<?php
 include('class.jpeg_decoder.php');
 
 $inputFile = "./input.jpg"; // Replace with your input file path
 $jpeg_decoder_output_png = './output.png';
 
 echo "<html><head><title>PHP JPEG Decoder Test</title></head><body>";
 echo "<p>This is an experimental JPEG encoder and decoder ported to PHP from the JavaScript JPEG codec.</p>
 <h1>Decoding: " . htmlspecialchars($inputFile) . "</h1>";
 echo "<hr>";
 echo "<h2>Decoder Output:</h2>";
 echo "<pre style='background-color:#f0f0f0; border:1px solid #ccc; padding: 10px; max-height: 300px; overflow-y: scroll;'>";
 
 try {
 // --- Run the Decoder ---
 list($frame, $jfif, $adobe, $components, $comments) = read_image_file($inputFile);
 
 echo "</pre>"; // End decoder output pre block
 echo "<hr>";
 echo "<h2>Image Details:</h2>";
 echo "<ul>";
 echo "<li>Dimensions: {$frame['samplesPerLine']} x {$frame['scanLines']}</li>";
 echo "<li>Precision: {$frame['precision']} bits</li>";
 echo "<li>Mode: " . ($frame['baseline'] ? 'Baseline' : ($frame['progressive'] ? 'Progressive' : ($frame['extended'] ? 'Extended Sequential' : 'Unknown'))) . " (SOF Marker: 0x" . dechex($frame['type']) . ")</li>";
 echo "<li>Components: " . count($frame['components']) . "</li>";
 if ($jfif) echo "<li>JFIF Version: {$jfif['version']['major']}.{$jfif['version']['minor']}</li>";
 if ($adobe) echo "<li>Adobe Marker Found: Yes (Transform: {$adobe['transformCode']})</li>";
 if ($comments) echo "<li>Comments: " . count($comments) . "</li>";
 echo "</ul>";
 
 
 // --- Prepare for Image Output ---
 $width = $frame['samplesPerLine'];
 $height = $frame['scanLines'];
 
 echo "<hr><h2>Processing Component Data for Output:</h2><pre>";
 // Combine components into RGBA pixel data using getData
 $pixelDataRGBA = getData($components, $width, $height, $adobe);
 echo "</pre>";
 
 
 // Prepare imageData structure (though copyToImageData doesn't strictly need it now)
 $imageData = [
 'width' => $width,
 'height' => $height,
 'data' => [] // Will be filled by copyToImageData (or directly assign $pixelDataRGBA)
 ];
 // Copy (or just assign) the RGBA data
 $imageData['data'] = $pixelDataRGBA;
 
 
 // --- Create image with GD library ---
 echo "<hr><h2>Creating PNG with GD:</h2>";
 $image = imagecreatetruecolor($width, $height);
 if (!$image) {
 throw new Exception("GD: imagecreatetruecolor failed.");
 }
 // Enable alpha blending for transparency handling if needed (usually not for JPEG)
 imagealphablending($image, true); // Blend alpha channel
 imagesavealpha($image, true); // Save full alpha channel
 
 $pixelIndex = 0;
 for ($y = 0; $y < $height; $y++) {
 for ($x = 0; $x < $width; $x++) {
 if (!isset($imageData['data'][$pixelIndex+3])) {
 // Data array might be shorter than expected if getData had issues
 echo "<p>Warning: Ran out of pixel data at ($x, $y)</p>";
 // Set pixel to black or break? Let's set to magenta for visibility
 $color = imagecolorallocatealpha($image, 255, 0, 255, 0); // Opaque magenta
 imagesetpixel($image, $x, $y, $color);
 // Ensure pixelIndex advances correctly even on error if we continue
 $pixelIndex += 4; // Move past the expected RGBA group
 continue; // Skip to next pixel
 }
 $r = $imageData['data'][$pixelIndex++];
 $g = $imageData['data'][$pixelIndex++];
 $b = $imageData['data'][$pixelIndex++];
 $a_byte = $imageData['data'][$pixelIndex++]; // Alpha 0-255
 
 // GD alpha is 0 (opaque) to 127 (transparent)
 $a_gd = floor((127 * (255 - $a_byte)) / 255); // Convert 0-255 alpha to 0-127 GD alpha
 $a_gd = max(0, min(127, $a_gd)); // Clamp just in case
 
 $color = imagecolorallocatealpha($image, $r, $g, $b, $a_gd);
 if ($color === false) {
 echo "<p>Warning: GD: imagecolorallocatealpha failed for pixel ($x, $y) with RGBA($r, $g, $b, $a_byte). Setting black.</p>";
 $color = imagecolorallocatealpha($image, 0, 0, 0, 0); // Fallback: opaque black
 }
 imagesetpixel($image, $x, $y, $color);
 }
 }
 echo "<p>GD Image object created.</p>";
 
 
 // --- Save and Display ---
 echo "<p>Saving PNG to: $jpeg_decoder_output_png</p>";
 $saveResult = imagepng($image, $jpeg_decoder_output_png);
 if (!$saveResult) {
 echo "<p><b>Error: Failed to save PNG image! Check permissions and GD installation.</b></p>";
 } else {
 echo "<p>PNG saved successfully.</p>";
 }
 imagedestroy($image);
 
 echo "<hr><h2>Comparison:</h2>";
 echo "<h3>Original Input Image:</h3>";
 echo "<img src='" . htmlspecialchars($inputFile) . "' alt='Original JPEG' title='Original JPEG' style='max-width: 400px; border: 1px solid blue;'>";
 echo "<h3>Decoded Output Image (PNG):</h3>";
 if ($saveResult) {
 echo "<img src='" . htmlspecialchars($jpeg_decoder_output_png) . "?t=" . time() . "' alt='Decoded PNG' title='Decoded PNG' style='max-width: 400px; border: 1px solid green;'>"; // Add timestamp to avoid caching
 } else {
 echo "<p>(Failed to save decoded image)</p>";
 }
 
 
 } catch (Exception $e) {
 echo '</pre><hr><h2 style="color: red;">Caught exception:</h2><pre>';
 echo 'Message: ',  htmlspecialchars($e->getMessage()), "\n";
 echo 'File: ', $e->getFile(), "\n";
 echo 'Line: ', $e->getLine(), "\n";
 echo "\nStack trace:\n", htmlspecialchars($e->getTraceAsString());
 echo "</pre>";
 }
 
 echo "</body></html>";
 
 |