[comp.lang.perl] PERL Novice needs help.

blu@millipore.com (Brian Utterback) (01/08/91)

Okay perl hackers, I need your help.  I have oft'times seen it written that
if you are iterating over a variable you are probably doing it wrong in perl.
So, I need an alternate approach since the one I thought of is abysmally 
slow.

I am processing some raw grey-scale image, 8 bits per value.  There are 
X scanlines of Y pixels each.  What I want is to tally the values into
a histogram and produce the hex dump of the values, but with the image scaled
down to a third it's original size. So in loose perl I have the following:

for (x=0;x<X;x++){
	sysread(FILE,$scanline,Y);
	$scanvalues = unpack("C$Y",$scanline);
	for (y=0;y<Y;y++) {
		@histogram[$scanvalue[$y]]++;
		if ((0 == $x%3) && (0 == $y%3)) {
			if ($scanvalue[$y] < 16) {print "0";}
			printf("%x",$scanvalue[$y]);
		}
	}
	if (0 == $x%3) {print "\n";}
}

I know, really ugly huh?  Only thing is, how do I speed it up?  Oh, by the way,
each value needs to be exactly 2 hex digits.

-- 
Brian Utterback, Millipore Corporation, 75G Wiggins Ave., Bedford Ma. 01730
Work:617-275-9200x8245, Home:603-891-2536
INTERNET:: blu@millipore.millipore.com
UUCP:: {samsung,cg-atla,merk,wang,bu-tyng}!millipore!blu

evans@decvax.DEC.COM (Marc Evans) (01/09/91)

In article <1991Jan7.205909.674@millipore.com>, blu@millipore.com (Brian Utterback) writes:
|> Okay perl hackers, I need your help.  I have oft'times seen it written that
|> if you are iterating over a variable you are probably doing it wrong in perl.
|> So, I need an alternate approach since the one I thought of is abysmally 
|> slow.
|> 
|> I am processing some raw grey-scale image, 8 bits per value.  There are 
|> X scanlines of Y pixels each.  What I want is to tally the values into
|> a histogram and produce the hex dump of the values, but with the image scaled
|> down to a third it's original size. So in loose perl I have the following:
|> 
|> for (x=0;x<X;x++){
|> 	sysread(FILE,$scanline,Y);
|> 	$scanvalues = unpack("C$Y",$scanline);
|> 	for (y=0;y<Y;y++) {
|> 		@histogram[$scanvalue[$y]]++;
|> 		if ((0 == $x%3) && (0 == $y%3)) {
|> 			if ($scanvalue[$y] < 16) {print "0";}
|> 			printf("%x",$scanvalue[$y]);
|> 		}
|> 	}
|> 	if (0 == $x%3) {print "\n";}
|> }

Unwinding loops can be helpful sometimes. I think I would do something like this:

	$name = '$histogram';
	$x = 0;
	while (! eof(FILE))
	{   read(FILE,$scanline,$Y) || die("Premature EOF found : $!\n");
	    $x++;
	    $scanline =~ s/(.)/var{'$1',$x}++;/g;
	    $scanline =~ s'var'$name'ge;
	}

This will create a two dimensional array ($histogram{count,x}) which contains
all of the information for the entire image. Given this, you could then print
any information you want. If the images are too large, you may want to make the
array a single dimension and process the information on-the-fly, simular to
what you did in your version.

- Marc
-- 
===========================================================================
Marc Evans - WB1GRH - evans@decvax.DEC.COM  | Synergytics     (603)635-8876
      Unix and X Software Contractor        | 21 Hinds Ln, Pelham, NH 03076
===========================================================================