/*
For Scale_Down:
ScaleFactor = Height/NewHeight - 1;
ScaleFactor = Width/NewWidth - 1;
Use whichever scalefactor is larger.
So scaling from 640x480 to 320x240 would have a scale of 1.0
So scaling from 640x480 to 320x200 would have a scale of 1.4
For Scale_Up:
ScaleFactor = NewHeight/Height - 1;
ScaleFactor = NewWidth/Width - 1;
Use whichever scalefactor is larger.
So scaling from 320x240 to 640x480 would have a scale of 1.0
So scaling from 320x200 to 640x480 would have a scale of 1.4
*/
/*----------------------------------------------------------------------*/
/*----------------------------------------------------------------------*/
void Scale_Down(float ScaleFactor)
{
int i,j,m,n;
float XCount,YCount;
/*
Use the ImageBuffer for source and destination.
ImageBuffer[i+m][j+n] is the source pixel.
ImageBuffer[i][j] is the destination pixel.
XCount and YCount are used to determine when to skip pixels
or lines, respectively. This 'shrinks' the image.
X = original, O = new, W = Width, H = Height:
Original ImageBuffer Scale_Down ImageBuffer
W W
XXXX OOOX
XXXX OOOX
XXXX OOOX H
XXXX H XXXX
The ImageBuffer does not change size, the pixels are simply moved and
a new Height and Width are declared.
*/
for (i=m=YCount=0; i+m < Height; i++, YCount+=ScaleFactor)
{
while (YCount >= 1 && i+m < Height-1)
{
YCount -= 1;
m++; // skip this line
}
for (j=n=XCount=0; j+n < Width; j++, XCount+=ScaleFactor)
{
while (XCount >= 1 && j+n < Width-1)
{
XCount -= 1;
n++; // skip this pixel
}
ImageBuffer[i][j] = ImageBuffer[i+m][j+n];
}
}
Width = j-1; // set new Width for the image
Height = i-1; // set new Height for the image
}
/*----------------------------------------------------------------------*/
void Scale_Up(float ScaleFactor)
{
int i,j,m,n,NewHeight,NewWidth,Size;
float XCount,YCount;
unsigned char **Line;
/*
Copy ImageBuffer into Line.
Expand ImageBuffer.
Use Line for source and ImageBuffer for destination.
Line[i][j] is the source pixel.
ImageBuffer[i+m][j+n] is the destination pixel.
XCount and YCount are used to determine when to duplicate pixels
or lines, respectively. This 'expands' the image.
The ImageBuffer does change size, the pixels are moved and
a new Height and Width are declared.
*/
NewHeight = Height + Height * ScaleFactor;
NewWidth = Width + Width * ScaleFactor;
// make a source Buffer
if ((Line = (unsigned char **)
malloc(Height * sizeof(unsigned char **))) == NULL)
report_fatal_error("Scaling:","Failed to allocate memory required.");
Size = Width * sizeof(unsigned char); /* Size in bytes one row.*/
// make a copy of the image into this source Buffer
for (i = 0; i < Height; i++)
{
if ((Line[i] = (unsigned char *) calloc(1,Size)) == NULL)
report_fatal_error("Scaling:","Failed to allocate memory required.");
memcpy(Line[i],ImageBuffer[i],Size);
}
// now expand the destination buffer
if ((ImageBuffer = (unsigned char **)
realloc(ImageBuffer,NewHeight * sizeof(unsigned char **))) == NULL)
report_fatal_error("Scaling:","Failed to allocate memory required.");
Size = NewWidth * sizeof(unsigned char); /* Size in bytes new row.*/
for (i = 0; i < Height; i++)
{
if ((ImageBuffer[i] = (unsigned char *) realloc(ImageBuffer[i],Size)) == NULL)
report_fatal_error("Scaling:","Failed to allocate memory required.");
}
for (; i < NewHeight; i++)
{
if ((ImageBuffer[i] = (unsigned char *) calloc(1,Size)) == NULL)
report_fatal_error("Scaling:","Failed to allocate memory required.");
}
// now scaling routine from source(Line) to destination(ImageBuffer).
for (i=m=YCount=0; i < Height; i++, YCount+=ScaleFactor)
{
for (j=n=XCount=0; j < Width; j++, XCount+=ScaleFactor)
{
ImageBuffer[i+m][j+n] = Line[i][j];
while (XCount >= 1)
{
XCount -= 1;
n++; // duplicate this pixel
ImageBuffer[i+m][j+n] = Line[i][j];
}
if (YCount >= 1 && j+1 == Width)
{
YCount -= 1;
m++;
j=n=XCount=0; // duplicate this line
}
}
free(Line[i]);
}
free(Line);
Width = NewWidth;
Height = NewHeight;
}
/*----------------------------------------------------------------------*/