Code:
#include <stdio.h>
#include <stdbool.h>
#define MAXSIZE 512 /* the size limit for icons */
#define CHARNUM 8 /* number of bits in a byte */
#define MASKPACK 1 /* mask for packing of data */
#define MASKUN 128 /* mask for unpacking of data */
/* header structure definition */
/* the header size should be 3 bytes to match the file format */
#pragma pack(push, 1)
typedef struct
{
char format; /* 'U' - unpacked format, 'P' - packed format */
unsigned char width; /* icon width and icon height */
unsigned char height;
}header;
#pragma pop
/* - function prototypes - */
int displayMenu(int version);
void clearStdin(void);
header openIcon( unsigned char pixelData[] );
void displayIcon( unsigned char pixelData[], header iconParam );
bool saveIconPacked( unsigned char pixelData[], header iconParam );
void packIconData( unsigned char pixelData[], header iconParam );
void unpackIcon( unsigned char pixelData[], header iconParam );
int main(void)
{
int menuOption; /* suppose to be 1 or 2, if entered by a user correctly*/
int menuVersion=1; /* 1 - the first menu, 2 - the second menu, 1 or 2 is context dependent */
header icParam;
unsigned char pixelData[MAXSIZE]; /* icon pixel data from a file*/
do
{
menuOption = displayMenu(menuVersion); /* display menu an get the option entered */
if((menuOption != 1) && (menuOption != 2) && (menuOption != 3)
{ /* only menu options 1 and 2 and 3 are valid */
fprintf(stderr, "\nIncorrect option!\n");
}
else if(menuOption==1)
{
if(menuVersion==1) /* if menu version is 1 - open an icon */
{
icParam = openIcon( pixelData );
if( icParam.format == -1 )
{
fprintf(stderr, "\nThe icon cannot be opened!\n");
return -1;
}
if(icParam.format=='U')
{
menuVersion = 2;
}
}
else if(menuVersion==2); /* if menu version is 2 - save the icon */
{
if( saveIconPacked( pixelData, icParam ) == false )
{
fprintf(stderr, "The icon cannot be saved!\n");
return -1;
}
fprintf(stderr, "The icon has been packed and saved\n");
menuVersion = 1; /* change the menu to menu 1*/
}
}
}while( menuOption != 3 ); /* repeat while option 2 is not selected */
{
printf("Bye-bye!\n");
}
return 0;
}
/*- function definitions -*/
/* printf("displayMenu is called and printed") */
int displayMenu(int Version)
{
int option=0;
printf("\n----Menu----\n");
if(Version == 1)
printf("1 Open an Icon\n");
printf("2 New Icon\n");
printf("3 Exit the Program\n");
printf("Please select an option (1 -3): ");
else
printf("1 Save an Icon in the Packed Format\n");
printf("2 Zoom In x2\n");
printf("3 Exit the program\n");
printf("Please select an option (1 - 3): ");
if(scanf("%d", &option) !=1) /* input failure? */
clearStdin(); /* remove wrong characters from stdin */
return option;
}
/*printf("clearStdin is called and performed") */
void clearStdin(void) /* remove wrong characters from stdin */
{
scanf("%*[^\n]"); /* skip to the end-of-line */
scanf("%*1[\n]"); /* skip one new-line */
return;
}
/*printf("openIcon is passed through the header file and performed")*/
header openIcon( unsigned char data[] )
{
char iconFormat; /* 'U' - unpacked format, 'P' - packed format */
char fileName[20];
FILE *iconF;
header fileHeader; /* width, height and number of values of an icon */
int values;
printf("\nEnter the file name:");
scanf("%s", fileName);
iconF = fopen(fileName, "rb" ); /* open a file stream for reading, the binary mode */
if( iconF == NULL )
{
fileHeader.format = -1; /* return -1, if the icon cannot be opened */
return fileHeader;
}
/* read the header */
if( fread( &fileHeader, sizeof(header), 1, iconF ) != 1 )
{
fileHeader.format = -1; /* return -1, file read error */
return fileHeader;
}
values = fileHeader.width * fileHeader.height;
/* check if the icon size is not above the limit */
if( values>512 )
{
fileHeader.format = -1; /* return -1, the icon is to big to be opened */
return fileHeader;
}
if(iconFormat == 'P') /* packed data require 8 times less values */
values /= 8;
if( fread( data, sizeof(unsigned char), values, iconF ) != values ) /* read the pixel values */
{
fileHeader.format = -1; /* return -1, error */
return fileHeader;
}
fclose( iconF );
displayIcon( data, fileHeader );
return fileHeader;
}
void displayIcon( unsigned char data[], header iconPar )
{
int column, row;
/* display the header info */
if(iconPar.format == 'U')
printf("File format: Unpacked\n" );
else
{
printf("File format: Packed\n");
unpackIcon( data, iconPar ); /* unpack pixels before displaying */
}
printf("Icon width: %d pixels\n", iconPar.width);
printf("Icon height: %d pixels\n", iconPar.height);
/* display the icon */
for(row=0; row<iconPar.height; row++)
{
printf("\n");
for(column=0; column<iconPar.width; column++)
{
if(data[iconPar.width*row + column] == 1) printf("*");
else printf(" ");
}
}
printf("\n");
return;
}
/* the function takes the icon data from pixelData array
unpack them and places back into the pixelData array */
void unpackIcon( unsigned char pixelData[], header iconParam )
{
int a, b, c=0;
unsigned char unp[MAXSIZE];
for(a=0; a<=(iconParam.height*iconParam.width/CHARNUM); a++)
{ /* allocates the pixel values with one bit per pixel value */
for(b=1; b<=CHARNUM; b++)
{
if((pixelData[a] & MASKUN)>0)
{
unp[c] = 1;
}
else unp[c] = 0;
pixelData[a]<<=1;
c++;
}
}
for(a=0; a<=MAXSIZE; a++)
{
pixelData[a] = unp[a];
}
return;
}
/* the function takes the icon data from pixelData array
pack them and places back into the pixelData array */
void packIconData( unsigned char pixelData[], header iconParam )
{
int a, b, c=0;
unsigned char packb;
for(a=0; a<(iconParam.height*iconParam.width/CHARNUM); a++)
{
packb = 0; /* resets packbyte(packb) to 0 */
for(b=0; b<CHARNUM; b++)
{
if(pixelData[b] == MASKPACK)
{
packb = packb | MASKPACK;
} /* shifts packbyte(packb) left 1 place after equalling 1 */
if(b<(CHARNUM-1))
{
packb<<=1;
}
c++;
}
pixelData[a]=packb;
}
return;
}
/* the function takes two parameters:
-an array filled with unpacked pixel data
-the iconParam - format, width , height
calls packIconData() function
saves packed icon in a binary file
returns true if OK, otherwise false */
bool saveIconPacked( unsigned char pixelData[], header iconParam )
{
FILE *Save;
char filename;
unsigned char bytes = (iconParam.height*iconParam.width/CHARNUM);
printf("Enter the file name:");
scanf("%s", &filename);
iconParam.format = 'P'; /* the data has become packed */
packIconData(pixelData, iconParam);
Save = fopen(filename, "wb");
if(Save == NULL)
{
fprintf(stderr, "Could not find file!\n"); /* error recovery for saving of file */
return false;
}
else if(fwrite(&iconParam, sizeof(header), 1, Save)!=1) /* saves header to the new file */
{
return false;
}
else if(fwrite(pixelData, sizeof(unsigned char), bytes, Save)!=bytes) /* saves pixel data to the new file */
{
return false;
}
else
fclose(Save); /* closes file and returns to the start */
return true;
}