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 #include 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