At some point of time in an embedded engineer's life a need may arise to 'resize' an image. Resizing an image means changing its resolution.
The most common and well known resolutions which everybody encounters into their day-to-day life are:
VGA - 640x480 (Vector Graphics Array)
QVGA - 320 x 240 (Quarter Vector Graphics Array)
XGA - 1024 x 768 (Extended Graphics Array)
QXGA - 2048 x 1536 ('QUAD' (and not quarter) Extended Graphics Array)
and many more. Of these VGA and XGA are mostly used. For Example your desktop background is XGA resolution.
Imagine you are using a phone or any other handheld device which has a frame buffer smaller than VGA or XGA resolutions. In layman's language suppose your LCD can show image only in the QVGA resolution and you have an image in VGA resolution which you want to display it on your LCD. For this you can use the following C code and cross compile it for your architecture.
CODE:
FILE *fIN, *fOUT;
unsigned char ucBufInImage[ 640*480*3 ]; //buffer to store raw input image.
unsigned char ucBufOutImage[ 320*240*3 ]; //buffer to store raw and resized output
int iNewWidth,iNewWidth;
int iRowIndex, iColumnIndex;
int ind1, ind2, ind3;
iNewWidth = 320; //width after resize
iNewWidth = 240; //height after resize
iRowIndex = 0; //variable for maneuvering through rows
iColIndex = 0; //variable for maneuvering throughcolumns
fIN = fopen("<Input VGA filename>", "rb"); //opening input file
if(fIN == NULL)
{
fprintf( stderr, "Could not open the input file\n");
exit( EXIT_FAILURE );
}
fread( ucBufInImage, 640*480*3, 1, fIN ); //putting contents of input file to a buffer
fOUT = fopen("<Desired name of output QVGA file>", "wb"); //opening output file
if(fOUT == NULL)
{
fprintf( stderr, "Could not open file for output.\n");
exit( EXIT_FAILURE );
}
ind1 = 0; //various index variables
ind2 = 1920;
ind3 = 0;
for( iRowIndex = 0; iRowIndex < iNewHeight; iRowIndex++ ) //outer for loop for the rows
{
for( iColIndex = 0; iColIndex < ( iNewWidth ); iColIndex++, ind1 += 6, ind2 += 6, ind3 += 3 ) //inner for loop for columns
{
ucBufOutImage[ ind3 ] = ( ucBufInImage[ind1] + ucBufInImage[ind1 + 3] + ucBufInImage[ind2] + ucBufInImage[ind2 + 3] ); //averaging of RED components of adjacent four pixels
ucBufOutImage[ ind3 + 1 ] = ( ucBufInImage[ind1 + 1] + ucBufInImage[ind1 + 4] + ucBufInImage[ind2 + 1] + ucBufInImage[ind2 + 4] ); //averaging of GREEN components of adjacent four pixels
ucBufOutImage[ ind3 + 2 ] = ( ucBufInImage[ind1 + 2] + ucBufInImage[ind1 + 5] + ucBufInImage[ind2 + 2] + ucBufInImage[ind2 + 5] ); //averaging of BLUE components of adjacent four pixels
}
ind1 = ind1 + 1920; //incrementing the index for the next row
ind2 = ind2 + 1920; //incrementing the index for the next row
}
fwrite( ucBufOutImage, 320*240*3, 1, fOUT ); //dumping the output to the file
fclose( fIN ); //closing the input file
fclose( fOUT ); //closing the output file
EXPLANATION:
There are two ways in which you could resize any image; first in which you just drop the extra pixel information and keep the amount of info you want in the resized image. This is known as 'lossy' resizing. In the second approach, one which i have used in the above code, is 'lossless' resizing in which we do not drop the extra information but instead we take an average of respective components of certain number of pixels to create fewer numbers.
In the above code as we have to resize from VGA to QVGA, which is 1/4th of the original, so we take an average of four adjacent pixels to create one. This way we reduce the total size of the VGA image to 1/4th to create QVGA image. The four pixels are taken in the following way:
The most common and well known resolutions which everybody encounters into their day-to-day life are:
VGA - 640x480 (Vector Graphics Array)
QVGA - 320 x 240 (Quarter Vector Graphics Array)
XGA - 1024 x 768 (Extended Graphics Array)
QXGA - 2048 x 1536 ('QUAD' (and not quarter) Extended Graphics Array)
and many more. Of these VGA and XGA are mostly used. For Example your desktop background is XGA resolution.
Imagine you are using a phone or any other handheld device which has a frame buffer smaller than VGA or XGA resolutions. In layman's language suppose your LCD can show image only in the QVGA resolution and you have an image in VGA resolution which you want to display it on your LCD. For this you can use the following C code and cross compile it for your architecture.
CODE:
FILE *fIN, *fOUT;
unsigned char ucBufInImage[ 640*480*3 ]; //buffer to store raw input image.
unsigned char ucBufOutImage[ 320*240*3 ]; //buffer to store raw and resized output
int iNewWidth,iNewWidth;
int iRowIndex, iColumnIndex;
int ind1, ind2, ind3;
iNewWidth = 320; //width after resize
iNewWidth = 240; //height after resize
iRowIndex = 0; //variable for maneuvering through rows
iColIndex = 0; //variable for maneuvering throughcolumns
fIN = fopen("<Input VGA filename>", "rb"); //opening input file
if(fIN == NULL)
{
fprintf( stderr, "Could not open the input file\n");
exit( EXIT_FAILURE );
}
fread( ucBufInImage, 640*480*3, 1, fIN ); //putting contents of input file to a buffer
fOUT = fopen("<Desired name of output QVGA file>", "wb"); //opening output file
if(fOUT == NULL)
{
fprintf( stderr, "Could not open file for output.\n");
exit( EXIT_FAILURE );
}
ind1 = 0; //various index variables
ind2 = 1920;
ind3 = 0;
for( iRowIndex = 0; iRowIndex < iNewHeight; iRowIndex++ ) //outer for loop for the rows
{
for( iColIndex = 0; iColIndex < ( iNewWidth ); iColIndex++, ind1 += 6, ind2 += 6, ind3 += 3 ) //inner for loop for columns
{
ucBufOutImage[ ind3 ] = ( ucBufInImage[ind1] + ucBufInImage[ind1 + 3] + ucBufInImage[ind2] + ucBufInImage[ind2 + 3] ); //averaging of RED components of adjacent four pixels
ucBufOutImage[ ind3 + 1 ] = ( ucBufInImage[ind1 + 1] + ucBufInImage[ind1 + 4] + ucBufInImage[ind2 + 1] + ucBufInImage[ind2 + 4] ); //averaging of GREEN components of adjacent four pixels
ucBufOutImage[ ind3 + 2 ] = ( ucBufInImage[ind1 + 2] + ucBufInImage[ind1 + 5] + ucBufInImage[ind2 + 2] + ucBufInImage[ind2 + 5] ); //averaging of BLUE components of adjacent four pixels
}
ind1 = ind1 + 1920; //incrementing the index for the next row
ind2 = ind2 + 1920; //incrementing the index for the next row
}
fwrite( ucBufOutImage, 320*240*3, 1, fOUT ); //dumping the output to the file
fclose( fIN ); //closing the input file
fclose( fOUT ); //closing the output file
EXPLANATION:
There are two ways in which you could resize any image; first in which you just drop the extra pixel information and keep the amount of info you want in the resized image. This is known as 'lossy' resizing. In the second approach, one which i have used in the above code, is 'lossless' resizing in which we do not drop the extra information but instead we take an average of respective components of certain number of pixels to create fewer numbers.
In the above code as we have to resize from VGA to QVGA, which is 1/4th of the original, so we take an average of four adjacent pixels to create one. This way we reduce the total size of the VGA image to 1/4th to create QVGA image. The four pixels are taken in the following way:
Resizing from 640 x 480 to 320 x 240 |
Great work...Thanks for sharing this info...It helps me a lot...
ReplyDelete