in reply to Imager: Gateway Timeout

Finally managed to get things to work. It was via a "keep alive" command that sends data back to the browser every now and then to say "I'm still here ..." I don't profess to know HOW it works ... but it does

I also used an option called "qtype" which allows 'normal' - the default for high quality, or 'preview' for lower quality (but =I= can't see the difference. Apparentely, the former is done via a 'filter' whilst the latter is via a pixel 'near neighbour' (???)

Now just got to master how to place a full size watermark over the medium images. Something for Christmas morn !

$| = 1; # set autoflush sub processPics(){ $newDat=''; # read image dir to set @pics array for (my $p=0; $p<@pics; $p++){ print "$pics[$p]<br>"; $img->read(file=>$baseURL.$type.'/'.$pics[$p],type=>'jpeg') or di +e $img->errstr(); $img->copy()->scale(xpixels=>750, qtype=>'preview')->write(file=>$ +baseURL.$type.'/medium/'.$pics[$p]) or die $image->errstr; # Write ou +t an image as medium $img->scale(ypixels=>150, qtype=>'preview')->write(file=>$baseURL. +$type.'/thumbs/'.$pics[$p]) or die $image->errstr; # Resizes the medi +um before write out as thumbs my $rot90 = $img->rotate(degrees=>-90); $rot90->write(file=>$baseURL.$type.'/upright/'.$pics[$p]) or die $ +image->errstr; # Write out an image as medium my @pic=split(/\./,$pics[$p]); $newDat.=$pic[0].'|'; The dat data is stored as one continuous +string separated with pipe (ie "amazing|beaver|biggus") } unless ($_ % 10){ print "<br>" } }

The magic is via 'autoflush' and the 'unless' entry. (As I say, no idea what "$_ % 10" does ... but it prints data to browser screen every few seconds or so)

Replies are listed 'Best First'.
Re^2: Imager: Gateway Timeout (OMP)
by vr (Curate) on Dec 25, 2019 at 01:26 UTC

    I thought using "degrees" with Imager::rotate was demonstrated to be too slow. I should have said, perhaps, that timings for my previous answer were taken at very old machine, but principle remains the same. Addressing (partially) some of your remarks, (1) I suspect prejudice against GD w.r.t. colour is because "$truecolor" boolean argument was not supplied to its newFromXXX methods; (2) it requires either special test images (example), or, with usual day-to-day photos, quite some training to see re-sampling artefacts, but, for the love of god, please don't use nearest-neighbour interpolation for anything but thumbnail size previews; (3) GD is listed as available for ActiveState PPM and is pre-installed with Strawberry Perl; (4) source image must be physically rotated before being sent to printer? is that so?

    It's good you're moving forward with solving the problem, and you can skip what follows -- sorry to hijack this thread for a little demo, moreover not sure if it's exactly 100% Perl. Assuming the task "open jpg/scale1/scale2/rotate original file/save all" exists, downsampling with reasonable quality appears to be quite fast, and slowest part is rotation. I looked here and there, and it seems, for rotation, GD is faster than Imager, and PDL::IO::Image is faster yet. I'd say the latter is wrapper for (some of) FreeImage functions, with abilities to export image data to piddles, and "PDL" in its name doesn't mean that anything PDL-related is required to be used at all.

    Looking into FreeImage, it reminded me of lossless JPG transformations, right-angle rotation among them, which is (a) good because it preserves quality, (b) fast because it doesn't require total (de/en)coding. Not implemented in PDL::IO::Image, can't find anything similar on CPAN. Closest would be shelling out and using CL tools.

    However, I felt it's good opportunity to also test/demo a kind of parallelization not very frequent with Perl, i.e. OMP. Test subject is 4009*3521 image, let's pretend 8 such files are to be rotated, using reasonably recent i5 with 4 cores, hence "4" threads below. Changing it to "1" results in ~3.5 seconds for FreeImage, still quite faster than GD because of (b). I copied filenames in Perl array to C array so that no Perl functions/macros are used in fragment to be run in parallel, because they are not re-entrant(?). I used pre-compiled FreeImage dll with Strawberry Perl, should be possible to install OS package under Linux.

    use strict; use warnings; use Time::HiRes 'time'; use GD; use File::Copy 'copy'; use constant ORIG => 'potw1949a'; my @list; # list of filenames w/o extension for ( 1 .. 8 ) { # 8 copies my $s = ORIG . $_; push @list, $s; copy ORIG . '.jpg', "$s.jpg" or die; } ############### GD my $t = time; for ( @list ) { GD::Image-> newFromJpeg( "$_.jpg", 1 ) -> copyRotateInterpolated( 90, 0 ) -> _file( "$_+.jpg" ); } printf "GD, sequential, %.2f s\n", time - $t; ############### FreeImage $t = time; parallel( \@list ); printf "FreeImage, parallel, %.2f s\n", time - $t; unlink glob ORIG . '?.jpg'; unlink glob ORIG . '?+.jpg'; use Inline C => config => ccflagsex => '-fopenmp', LIBS => '-lgomp -lFreeImage'; use Inline C => <<'END_OF_C'; #include <FreeImage.h> #include <omp.h> void parallel(SV *array) { int i, nfiles, len; char *fname, *tmp; char **fnames; nfiles = av_len((AV *)SvRV(array)); fnames = malloc((nfiles + 1) * sizeof(char*)); for (i = 0; i <= nfiles; i++) { tmp = SvPV(*av_fetch((AV *)SvRV(array), i, 0), len); fname = malloc(len + 1); memcpy(fname, tmp, len + 1); fnames[i] = fname; } #pragma omp parallel num_threads (4) { #pragma omp for for (i = 0; i <= nfiles; i++) { char *src, *dst; asprintf(&src, "%s%s", fnames[i], ".jpg" ); asprintf(&dst, "%s%s", fnames[i], "+.jpg" ); FreeImage_JPEGTransform(src, dst, FIJPEG_OP_ROTATE_90, 0); } } for (i = 0; i <= nfiles; i++) free(fnames[i]); free(fnames); } END_OF_C __END__ GD, sequential, 7.00 s FreeImage, parallel, 1.14 s

    Edit: Fixed off-by-one error with array length in C code, + couple most obvious "bugs" with my English. Ubuntu (Debian) FreeImage package has "FreeImage_JPEGTransform" family of functions disabled, had to compile from source. Interesting, under Linux GD performs twice as fast and so is slightly ahead of single-threaded FreeImage.