App-BlurFill-Web

 view release on metacpan or  search on metacpan

lib/App/BlurFill/Web.pm  view on Meta::CPAN

=head1 NAME

App::BlurFill::Web - The web interface to App::BlurFill

=head1 SYNOPSIS

  # In a PSGI environment
  use App::BlurFill::Web;

  App::BlurFill::Web->to_app;

=head1 DESCRIPTION

App::BlurFill::Web is a web interface for the App::BlurFill module. It allows users
to upload an image file, specify the desired width and height, and receive a blurred
image file in response.

=head1 ROUTES

=head2 GET /

This route displays a web form where users can upload an image and specify
the desired width and height for the output. The form submits to the POST /blur
route.

=head2 POST /blur

This route accepts an image file upload and optional width and height parameters.
It processes the image and returns an HTML page displaying the blurred image with
a download link and an option to create another image.

=head2 GET /download/:filename

This route serves the processed image file for download. The filename parameter
should match a previously processed image stored in the temporary directory.

=head1 PARAMETERS

=head2 image

The image file to be processed. This parameter is required.
It should be a valid image file format (e.g., JPEG, PNG, GIF).

=head2 width

The desired width of the output image. Default is 650 pixels.

=head2 height

The desired height of the output image. Default is 350 pixels.

=head1 EXAMPLE

  POST /blur
  Content-Type: multipart/form-data

  image: <binary image data>
  width: 800
  height: 600

=head2 Using C<curl>

  # This will return HTML with the results page
  curl -X POST -F "image=@path/to/image.jpg" -F "width=800" -F "height=600" http://localhost:3000/blur
  
  # To download the image directly
  curl -OJ http://localhost:3000/download/image_blur.png

=head1 RESPONSE

The POST /blur response will be an HTML page displaying the blurred image with
download options. The GET /download/:filename response will be the actual image file.

=cut

use v5.40;

package App::BlurFill::Web;
use Dancer2;

our $VERSION = '0.1.0';

use File::Temp qw(tempfile tempdir);
use File::Spec;
use File::Copy;
use App::BlurFill;

# Create a persistent temp directory for storing processed images

lib/App/BlurFill/Web.pm  view on Meta::CPAN

get '/' => sub {
  my $css = _get_css();
  return <<"HTML";
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>BlurFill - Perfect crops, zero letterboxing: smart blur-fill from your source image.</title>
  <style>
$css
  </style>
</head>
<body>
  <div class="container">
    <h1>BlurFill</h1>
    <p class="subtitle">Perfect crops, zero letterboxing: smart blur-fill from your source image.</p>
    
    <form action="/blur" method="POST" enctype="multipart/form-data">
      <div class="form-group">
        <label for="image">Select Image</label>
        <input type="file" id="image" name="image" accept="image/jpeg,image/jpg,image/png,image/gif" required>
      </div>
      
      <div class="form-group">
        <label>Output Dimensions</label>
        <div class="dimensions">
          <div>
            <label for="width">Width (px)</label>
            <input type="number" id="width" name="width" value="650" min="1" max="4000">
          </div>
          <div>
            <label for="height">Height (px)</label>
            <input type="number" id="height" name="height" value="350" min="1" max="4000">
          </div>
        </div>
      </div>
      
      <button type="submit">Generate resized image</button>
    </form>
    
    <div class="info">
      <p><strong>How it works:</strong></p>
      <p>1. Upload your image (JPEG, PNG, or GIF)</p>
      <p>2. Set your desired output dimensions</p>
      <p>3. Click "Generate" to create a resized image with your source image centered and filled</p>
      <p>4. Your processed image will be displayed with a download link</p>
    </div>
    <div class="credits">
      Version $VERSION /
      Made by <a href="https://links.davecross.co.uk/">Dave Cross</a> /
      Code <a href="https://github.com/davorg-cpan/app-blurfill-web">on GitHub</a>
    </div>
  </div>
</body>
</html>
HTML
};

post '/blur' => sub {
  my $upload = upload('image')
    or return status 400, { error => 'Missing image file' };

  my $orig_name = $upload->filename;
  my ($name, $path, $ext) =
    File::Basename::fileparse($orig_name, qr/\.[^.]*$/);

  return status 400, { error => 'Uploaded file must have a file extension' }
    unless $ext;

  my $format = lc $ext;
  $format =~ s/^\.//;

  my %mime = (
    jpg  => 'image/jpeg',
    jpeg => 'image/jpeg',
    png  => 'image/png',
    gif  => 'image/gif',
  );

  return status 400, { error => "Unsupported file format: .$format" }
    unless exists $mime{$format};

  my $width  = query_parameters->get('width')  || 650;
  my $height = query_parameters->get('height') || 350;

  my $in_dir = File::Temp::tempdir;
  my $in_path = "$in_dir/$name$ext";
  $upload->copy_to($in_path);

  my $outfile;
  eval {
    my $blur = App::BlurFill->new(
      file   => $in_path,
      width  => $width,
      height => $height,
    );
    $outfile = $blur->process;
  } or return status 500, { error => "Processing failed: $@" };

  my ($out_name) = File::Basename::fileparse($outfile);
  
  # Copy the processed file to our persistent temp directory
  my $persistent_path = File::Spec->catfile($TEMP_DIR, $out_name);
  File::Copy::copy($outfile, $persistent_path) or die "Copy failed: $!";

  # Display results page with image preview and download link
  my $css = _get_css();
  return <<"HTML";
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>BlurFill - Result</title>
  <style>
$css
  </style>
</head>
<body>
  <div class="container">
    <h1>BlurFill</h1>
    <p class="subtitle">Your resized image is ready!</p>
    
    <div class="success-message">
      <strong>✓ Success!</strong> Your image has been processed successfully.
    </div>
    
    <div class="result-image">
      <img src="/download/$out_name" alt="Resized image preview">
    </div>
    
    <div class="action-buttons">
      <a href="/download/$out_name" class="button" download>Download image</a>
      <a href="/" class="button button-secondary">Create another</a>
    </div>
    
    <div class="info">
      <p><strong>What's next?</strong></p>
      <p>• Click "Download image" to save your resized background</p>
      <p>• Click "Create another" to process a new image</p>
    </div>
  </div>
</body>
</html>
HTML
};

get '/download/:filename' => sub {



( run in 0.981 second using v1.01-cache-2.11-cpan-b16cb0d3907 )