dave@gitpyr.gatech.EDU (David Corbin) (01/13/87)
I am looking for information (programs, algorithms, references to texts) on how to scale a bit-mapped image from one resolution to another, in an intelligent manner. For example, say I have an image that was 'grabbed' from a screen with 640x400 pixels. Now, I want to print this image at the same size, but my printer has a higher resolution, so if I print it without modification, it will be smaller. Any suggestions at all would be appreciated. Please send me mail, as I don't read this newsgroup. Thank you very much. -- David Corbin Atlanta, GA ...!{akgua,allegra,amd,hplabs,ihnp4,masscomp,ut-ngp}!gatech!gitpyr!dave
ewhac@well.UUCP (Leo 'Bols Ewhac' Schwab) (01/15/87)
In article <2872@gitpyr.gatech.EDU> dave@gitpyr.gatech.EDU (David Corbin) writes: >I am looking for information (programs, algorithms, references to texts) >on how to scale a bit-mapped image from one resolution to another, in an >intelligent manner.... > >David Corbin >Atlanta, GA >...!{akgua,allegra,amd,hplabs,ihnp4,masscomp,ut-ngp}!gatech!gitpyr!dave I, too, would be interested in such information. Mail or net postings; makes no difference to me. Thanks in advance. _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ Leo L. Schwab ihnp4!ptsfa!well!ewhac The Guy in The Cape ..or.. well ---\ "Work FOR? I don't work FOR dual ----> !unicom!ewhac anybody. I'm just having fun." hplabs -/ ("AE-wack")
begeman@milano.UUCP (01/15/87)
> In article <2872@gitpyr.gatech.EDU> dave@gitpyr.gatech.EDU (David Corbin) writes: > >I am looking for information (programs, algorithms, references to texts) > >on how to scale a bit-mapped image from one resolution to another, in an > >intelligent manner.... Ok, here goes. There may be cheaper ways, but in my book there's one *right* way. What you have is an interpolation problem. Imagine your image (1st resolution) as a set of sampled data values. What you want is to derive other data values which are "in between" these. What you need to do is find a surface-fitting algorithm. You will feed it your data as (X, Y, Z==pixel_value) tuples. The algorithm will fit a surface to the data. Then you can use the surface to compute New_Z = f(New_X, New_Y) where f is the interpolation function as applied to the surface. This software falls into the domain of Numerical Analysis. I don't know of any public domain code which I can point you to, but I know that lots of PD NA software *does* exist. By the way, there will be a number of different surface-fitting algorithms to choose from - usually differing in the order of the polynomials used and your ability to "tension" the surface to remove any spikey anomalies which the mathematical representation of your original data may have introduced. Hit your local Numerical Analyst for guidance here. Good luck! ------- Of all the things I've lost, I miss my mind the most. Michael L. Begeman Microelectronics and Computer Technology Corp Software Technology Program Austin (where the sun always shines) Texas uucp: {ihnp4, seismo, harvard, gatech, pyramid}!ut-sally!im4u!milano!begeman arpa: begeman@mcc.com
sjrapaport@watcgl.UUCP (01/16/87)
In article <2406@well.UUCP> ewhac@well.UUCP (Leo 'Bols Ewhac' Schwab) writes: >In article <2872@gitpyr.gatech.EDU> dave@gitpyr.gatech.EDU (David Corbin) writes: >>I am looking for information (programs, algorithms, references to texts) >>on how to scale a bit-mapped image from one resolution to another, in an >>intelligent manner.... A simple but expensive way: map each new pixel onto the spot corresponding to its centre on the old image. Average the colors of all pixels that are covered, weighting the average by area covered. You now have a sloppy-looking reproduction of your original image. Most of the errors are high-frequency noise, though, so you can clean it up a lot by running it through a digital low-pass filter. There it is. I've never tried this myself, but it sounds feasible. -steve @ watcomputer
michael@orcisi.UUCP (01/16/87)
Reminder: the subject is resampling "bitmaps" (i.e. single bit pixels). A couple of the recent postings were addressing pixel arrays in general.
sierchio@milano.UUCP (01/17/87)
In article <776@orcisi.UUCP>, michael@orcisi.UUCP writes: > Reminder: the subject is resampling "bitmaps" (i.e. single bit pixels). > > A couple of the recent postings were addressing pixel arrays in general. Lissen, fella -- ya gotta say whatcha mean! You didn't say 1-bit pixels. Bitmap refers to the fact that there is a portion of memory mapped to the screen device. we don't say "byte-map" or "word-map". GET IT? -- Michael Sierchio @ MCC Software Technology Program UUCP: ut-sally!im4u!milano!sierchio ARPA: sierchio@mcc.ARPA "WE REVERSE THE RIGHT TO SERVE REFUSE TO ANYONE"
ktureski@omnitor.UUCP (01/19/87)
> > In article <2872@gitpyr.gatech.EDU> dave@gitpyr.gatech.EDU (David Corbin) writes: > > >I am looking for information (programs, algorithms, references to texts) > > >on how to scale a bit-mapped image from one resolution to another, in an > > >intelligent manner.... > > What you need to do is find a surface-fitting algorithm. You will > feed it your data as (X, Y, Z==pixel_value) tuples. The algorithm > will fit a surface to the data. Then you can use the surface to > compute New_Z = f(New_X, New_Y) where f is the interpolation function > as applied to the surface. True, but I think overly complex. Simply consider the problem as a pair of 2D passes ... to go from m*n to M*N, use a pass in X to interpolate the m values into M, then another pass in Y interpolate those results from n to N. You can use cubic interpolation if you like, but linear suffices visually. In fact, you can cheat on that too ... Consider the case where you wish to triple the width and height of the image, Our usual resolution is 512*484. But to save time in tests, we'll compute at "ninth res" and scale up to something close enough to 512*484. Using code in the Ikonas bitslice, we can do the scale in a couple of seconds. So here's what your pixels look like in the original scan line: abcde And this is what you want to end up with (I chose to interpolate only): aIJbIJcIJdIJe where I and J are interpolated values. Using linear interpolation, we get I = (2 * a + b) / 3 J = (a + 2 * b) / 3 To avoid the division, I cheated, and used I = (3 * a + b) / 4 [really I = (a + a + a + b) >> 2] J = (a + 3 * b) / 4 [really J = (a + b + b + b) >> 2] Visually, one could not tell which of the two methods was used (and our animators have good eyes for such things!). As a simple example, suppose a=1 and b=4. You'd expect the values for I and J to be 2 and 3 respectively. And that's what the first method gives. The other method produces I=1.75 and J=3.25 ... the sum of a+I+J+b is the same however, and that's one reason why the difference is negligible. Other factors include the way the pixels are displayed on the screen (they cover more area than they should, and mix together anyway). Kevin M Tureski Omnibus/Abel 2180 Yonge St. Toronto, Ontario, Canada M4S 2B9 UUCP: {allegra,decvax,ihnp4,utcsri}!watmath!omnitor!ktureski QUOTE: But some day you will be old enough to start reading fairy tales again. C. S. Lewis
adp@hp-sdd.HP.COM (Tony Parkhurst) (01/19/87)
I was unable to directly mail to you so here is a copy of the letter I tried to send. After seeing other responses to your request, I think you will prefer this method due to the simplicity and lower CPU required for the task. However, some may argue that this is not the proper method, but I think it will generate acceptable results. Have fun. -----------------------(undelivered letter)------------------------- Your in luck, I just devised a simple agorithm to resize any arbitrary size image to 640x400 for my Amiga. You should not have any problem modifying it to size the 640x400 images up to whatever resolution you are using. (simply change the 640x400 constants to your final resolution, and change 'xsize' and 'ysize' to 640x400.) Feel free to use as you wish as long as not for huge profits (unless I get a share :-) (also, if you are making a public domain printer driver, feel free to use it.) First, a couple of caveats: 1 -- This algorithm does pixel averaging, therefore, when resizing to a lower resolution (not your case), it behave like a low-pass filter, and you will tend to lose fine detail. 2 -- depending on the actual ratio of sizing up, there may or may not be artifacts. Try it and see how it looks. 3 -- The resizing is done first horizontally then vertically, therefore it is possible that some artifacts will be introduced at this level but it is not likely to make much difference. The program itself takes 4 input files (header, red, green and blue) of arbitrary size(the header file has the size in it) where each pixel is 24 bits (8 bits red, 8 bits green and 8 bits blue) and outputs one file which is 640x400 (but still has 24-bits per pixel aranged in the file as ...rgbrgbrgbrgbrgb...). The output is like this becuase then I run it into a different filter for dithering and diffusing etc. It should not be hard to modify for any reasonable format. The algorithm works like this (this is a conceptual model only, the implementation is a little simpler) if my input has a res of 1197x872, and my output is 640x400, I take the row of 1197 pixels and stretch it out 640 times, so there are 640 of the first pixel, 640 of the next and so forth. Then, for output, I gather up 1197 pixels (add them together and divide by 1197) then output one pixel (I do this 640 times). See how 640x1197 == 1197x640. I do the same thing for rows (872 ==> 400). Technically, the horizontal is resized before the verticle so there may be additional artifacts, but not too likely. The implementation doesn't bother stretching the pixels since we can assume that the pixels are replicas (that is part of the premise) so, all we have to do is keep kounts of what we need and what we have. hopefully, this will explain most of the inner workings of the program. Also, only integer math is used, so it is pretty efficient and accurate, and 32-bit integers should be uses (instead of 16-bit) because 1197 * 255 (max pixel value) > 32567. However, since you will be working with 4 bits per pixel (or whatever), you may be able to use 16-bit ints. Lotsa luck --- here is a shar file... ----------------------------------------------------------------------- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # picomp.c # This archive created: Wed Jan 14 10:21:33 1987 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'picomp.c'" '(3473 characters)' if test -f 'picomp.c' then echo shar: "will not over-write existing file 'picomp.c'" else sed 's/^ X//' << \SHAR_EOF > 'picomp.c' X/* Copyright (c) 1987 Tony Parkhurst */ X X/* This may be used for non-profit only and copyright notice X should remain intact. Usual courtesy and customs. X Feel free to include this in other non-profit software, X but usual credit where due please. X*/ X X/* picomp takes the image files of various sizes and compresses them X to a 640 by 400 rgb image. */ X X/* Usage: picomp image */ X/* inputs are image.red image.green image.blue image.header, X outputs image.rgb (640x400 rbyte, gbyte bbtye). */ X X/* basic algorithm is: if image is 1197 x 942, then X each of 1197 pixels is stretched out 640 times, then 1197 X are gathered at a time for 640 outputs... */ X X#include <stdio.h> X X#define HRES 1280 X#define VRES 1024 X#define HAMI 640 X#define VAMI 400 X X X#define MIN(x,y) (x<y?x:y) X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ X Xint x,y,i,j,c,ik,ir,ig,ib,ok,or,og,ob,kount,xsize,ysize; Xint i_r[HAMI],i_g[HAMI],i_b[HAMI]; Xint o_r[HAMI],o_g[HAMI],o_b[HAMI]; Xint r,g,b,o_k,i_k; XFILE *fr,*fg,*fb,*fh,*frgb,*fopen(); Xchar nr[25],ng[25],nb[25],nh[25],nrgb[25]; X Xif(argc < 2){ X fprintf(stderr,"Usage: %s image\n",argv[0]); X exit(-2); X } X X/* open the five files */ Xsprintf(nr,"%s.red",argv[1]); Xsprintf(ng,"%s.green",argv[1]); Xsprintf(nb,"%s.blue",argv[1]); Xsprintf(nh,"%s.header",argv[1]); Xsprintf(nrgb,"%s.rgb",argv[1]); /* this is for output */ X Xfr=fopen(nr,"r"); Xfg=fopen(ng,"r"); Xfb=fopen(nb,"r"); Xfh=fopen(nh,"r"); Xfrgb=fopen(nrgb,"w"); X Xif (fr == NULL || fg == NULL || fb == NULL || fh == NULL || frgb == NULL){ X perror("picomp: can't open file.\n"); X exit(-1); X } X X/* get the size of the image */ Xysize= getc(fh) + (int)getc(fh) * 256 ; Xxsize= getc(fh) + (int)getc(fh) * 256 ; X X Xi_k = 0; /* init input row count */ Xfor(y=0;y<VAMI;y++){ X for(x=0;x<HAMI;x++){ X o_r[x] = 0; X o_g[x] = 0; X o_b[x] = 0; X o_k = ysize; X } X X while(o_k){ /* while need more kounts */ X if(!i_k){ /* if none left, get another row */ X i_k = VAMI; /* 400 rows */ X X ik=0; /* init input pixel count */ X for(x=0;x<HAMI;x++) X { X or = 0; /* init pix holders */ X og = 0; X ob = 0; X ok = xsize; /* kount needed for outputting */ X while(ok){ X if(!ik){ /* no input, need another pixel */ X ik = HAMI; /* 640 kounts per pixel */ X ir = getc(fr); /* get new pixel value */ X ig = getc(fg); X ib = getc(fb); X } /* if (!ik) */ X kount = MIN(ok,ik); /* which is smaller */ X ok -= kount; /* knock off kount */ X ik -= kount; X or += kount * ir; /* add in kount pixel values */ X og += kount * ig; X ob += kount * ib; X } /* while (ok) */ X /* ok, now average out the pixels for output */ X i_r[x] = or / xsize; X i_g[x] = og / xsize; X i_b[x] = ob / xsize; X } /* for x */ X X } /* if (!i_k) */ X kount = MIN(o_k,i_k); /* which is smaller */ X o_k -= kount; /* knock off kount */ X i_k -= kount; X for(x=0;x<HAMI;x++){ X o_r[x] += kount * i_r[x]; /* add in kount row values */ X o_g[x] += kount * i_g[x]; X o_b[x] += kount * i_b[x]; X } /* for x */ X } /* while(o_k) */ X for(x=0;x<HAMI;x++){ X r = o_r[x] / ysize; /* now average out for output */ X g = o_g[x] / ysize; X b = o_b[x] / ysize; X X if(r > 255 || r < 0){ X fprintf(stderr,"Warning: Red component out of range: %d\n",r); X } X if(g > 255 || g < 0){ X fprintf(stderr,"Warning: Green component out of range: %d\n",g); X } X if(b > 255 || b < 0){ X fprintf(stderr,"Warning: Blue component out of range: %d\n",b); X } X X putc(r,frgb); X putc(g,frgb); X putc(b,frgb); X X } X X } /* for y */ X} SHAR_EOF if test 3473 -ne "`wc -c < 'picomp.c'`" then echo shar: "error transmitting 'picomp.c'" '(should have been 3473 characters)' fi fi exit 0 # End of shell archive -- **************** Insert 'Standard' Disclaimer here: OOP ACK! ***************** * Tony Parkhurst -- {hplabs|sdcsvax|ncr-sd|hpfcla|ihnp4}!hp-sdd!adp * * OR hp-sdd!adp@nosc.arpa * *******************************************************************************