Luciani.org ..... Perl Hints

The jpg2pdf script combines multiple graphics files into a single PDF file. If no input files are specified the script will look for gif, jpg and tiff files in the current directory. Only the first type of graphic file that is found will be used in creating the output file. The tool requires Perl, the convert program from imagemagick and ghostscript.

Synopsis

jpg2pdf [--windows] output_file_name [input_file_names]

The --windows options calls the program gswin32 rather than the Linux version gs. Perl and the convert program need to be on your path.

Occasionally it is useful to convert a file containing column data (one item per line) to a file containing data records (multiple related items per line). For example --- when retrieving component specifications from a table with each row containing specifications for a single component it is convenient to use the Acrobat Reader to column copy the specification columns into an EMACS buffer (assuming that there are more specification columns than there are component rows). To group these specifications into data records use col2rec.

Example Data

The example below contains data for the Hirose FH12 connector. This was copied using the column copy in Acrobat Reader.
# part number
FH12-10S-0.5SH
FH12-11S-0.5SH

# number of contacts
10
11

# pad_row_length
04.5
05.0

# mounting_pad_extents
10.1
10.6

# mounting_pad_separation
06.5
07.0
The col2rec output is shown below.
FH12-10S-0.5SH | 10 | 04.5 | 10.1 | 06.5
FH12-11S-0.5SH | 11 | 05.0 | 10.6 | 07.0

jpg2pdf

#!/usr/bin/perl

# Perl script to combine graphic files into a single PDF file.

# Synopsis

# jpg2pdf [--windows] OUTPUT_FILE_NAME INPUT_FILE_NAMES

# Requirements ---

#   Perl ;-)
#   convert (imagemagick)
#   eps2pdf and gs (ghostscript)

# Copyright (C) 2007 John C. Luciani Jr. 

# This program may be distributed or modified under the terms of
# version 0.2 of the No-Fee Software License published by
# John C. Luciani Jr.

# A copy of the license is at the end of this file.

use strict;
use warnings;
use Carp;
use Getopt::Long;

my %Opt = (windows => 0);

GetOptions('windows' => \$Opt{windows});

# $Out    is the name of the output file witout an extension
# @In     names of the image files to process. If no names are 
#         on the command-line then gifs, jpegs, or tiffs in the
#         current directory will be used.
# $Ext    the extension of the graphics files

my $Out;   
my @In;
my $Ext;

($Out, @In) = @ARGV;
croak "(jpg2pdf) output filename was not defined" unless defined $Out;

$Out .= '.pdf' unless $Out =~ /\.pdf$/; 

if ($#In == -1) {
    foreach (qw(gif jpg JPG tif tiff)) {
	@In = sort { &file_sort } (<*.$_>); 
	$Ext = $_, last unless $#In == -1;
    }
    croak "(jpg2pdf) no graphics files found" unless defined $Ext;
} else {
    $Ext = $In[0];
    $Ext =~ s/.*\.//;
    croak "(jpg2pdf) no graphics files found" unless defined $Ext;
    my @missing_files;
    foreach (@In) {
	push @missing_files, $_ unless -f;
    }
    croak sprintf("(jpg2pdf) Missing files %s\n", join(', ', @missing_files)) 
	unless $#missing_files == -1;
}

printf("(jpg2pdf) found graphic files with a %s extension\n", $Ext);

foreach (@In) {
    printf("(jpg2pdf) converting file %s\n", $_);
    next unless s/\.($Ext)//;

    # Acroread and my laserjet appear to "do the right thing" with the
    # borders.  Some sort of border control may be needed if this
    # breaks.  A -border and -bordercolor option for convert or
    # something for gs.

    `convert  $_.$Ext $_.eps`;
    croak "(jpg2pdf) could not convert $_.$Ext to $_.eps" unless -f "$_.eps";
    `epstopdf $_.eps`;
    `rm $_.eps`;
}

my $In = join(' ', map { "$_.pdf" } @In);
my $Cmd = $Opt{windows} ? 'gswin32' : 'gs';
`$Cmd -sDEVICE=pdfwrite -dNOPAUSE -dQUIET -dBATCH -sOutputFile=$Out $In`;


sub file_sort  { 
    my ($a0,$b0) = ($a, $b);
    my ($a1,$a2, $b1, $b2);
    # remove path
    $a0 =~ s/.*\///;
    $b0 =~ s/.*\///;
    # check for filenames that have format of SECTION_NUMBER-PAGE_NUMBER
    ($a1,$a2) = ($1,$2) if $a0 =~ /^(\d+)-(\d+)/;
    ($b1,$b2) = ($1,$2) if $b0 =~ /^(\d+)-(\d+)/;
    # if the section number wasn't defined then 
    # check for filenames that have the format of PAGE_NUMBER
    $a1 = $1 unless defined $a2 && $a0 =~ /^(\d+)/;
    $b1 = $1 unless defined $b2 && $b0 =~ /^(\d+)/;
    # If section numbers were found then compare them
    if (defined $a1 && defined $b1) {
	return -1  if $a1 < $b1;
	return  1 if $b1 < $a1;
    } 
    # If page numbers where found then compare them
    if (defined $a2 && defined $b2) {
	return -1  if $a2 < $b2;
	return 1;
    }
   return $a0 cmp $b0;
}



# Style (adapted from the Perl Cookbook, First Edition, Recipe 12.4)

# 1. Names of functions and local variables are all lowercase.
# 2. The program's persistent variables (either file lexicals
#    or package globals) are capitalized.
# 3. Identifiers with multiple words have each of these
#    separated by an underscore for readability.
# 4. Constants are all uppercase.
# 5. If the arrow operator (->) is followed by either a
#    method name or a variable containing a method name then
#    there is a space before and after the operator.


##### No-Fee Software License Version 0.2

#### Intent

### The intent of this license is to allow for distribution of this
### software without fee. Usage of this software other than
### distribution, is unrestricted.

#### License

### Permission is granted to make and distribute verbatim copies of
### this software provided that (1) no fee is charged and (2) the
### original copyright notice and this license document are preserved
### on all copies.

### Permission is granted to make and distribute modified versions of
### this software under the conditions for verbatim copying provided
### that the entire resulting derived work is distributed under terms
### of a license identical to this one.


### This software is provided by the author "AS IS" and any express or
### implied warranties, including, but not limited to, the implied
### warranties of merchantability and fitness for a particular purpose
### are disclaimed. In no event shall the author be liable for any
### direct, indirect, incidental, special, exemplary, or consequential
### damages (including, but not limited to, procurement of substitute
### goods or services; loss of use, data, or profits; or business
### interruption) however caused and on any theory of liability,
### whether in contract, strict liability, or tort (including
### negligence or otherwise) arising in any way out of the use of this
### software, even if advised of the possibility of such damage.



    

col2rec listing

#!/usr/bin/perl

# Copyright (C) 2005 John C. Luciani Jr.

# This program may be distributed or modified under the terms of
# version 0.1 of the No-Fee Software License published by
# John C. Luciani Jr.

use strict;
use warnings;
use Carp;

# Formats column data into data records.

# The column data is arranged using one value per row in a file.  Each
# column is separated by an empty line. After the file is read a
# data records are output using the column data.

# Missing column data is output as empty strings.

my @Col;
my $New_col = 1; # =1 start a new column 
while (<>) {
    s/\#.*//; # Remove comments
    s/^\s*//; # Remove leading spaces
    s/\s*$//; # Revove trailing spaces

    # If this line is empty then set the new column flag and read the
    # next line.  Using the flag allows multiple empty lines (or lines
    # containing only comments) to be treated as one.

    $New_col = 1, next unless length; 

    # if the new column flag was set then push an anonymous array onto
    # column array (@Col) and reset the flag.

    push(@Col, []), $New_col = 0 if $New_col;
    push @ { $Col[$#Col] }, $_; # push a value onto the most recent column
}

while (1) {
    my $not_done = 0;
    foreach my $col_num (0..$#Col) {
	my $col_ref = $Col[$col_num];  # reference to the current column

	# column values are separated by vertical bars and undefined
	# values are output as empty strings. If any column array
	# contains a value then we are not done processing the column
	# data ($not_done = 1).

	my $col_val = shift @$col_ref;
	printf("%s%s", 
	       $col_num == 0 ? '' : ' | ',
	       defined $col_val ? $col_val : '');
	$not_done = 1 unless $#$col_ref == -1
    }
    print "\n";
    last unless $not_done;
}


# Style (adapted from the Perl Cookbook, First Edition, Recipe 12.4)

# 1. Names of functions and local variables are all lowercase.
# 2. The program's persistent variables (either file lexicals
#    or package globals) are capitalized.
# 3. Identifiers with multiple words have each of these
#    separated by an underscore to make it easier to read.
# 4. Constants are all uppercase.
# 5. If the arrow operator (->) is followed by either a
#    method name or a variable containing a method name then
#    there is a space before and after the operator.