Reljefizacija

Emboss filtar daje slici efekat 3D senke. Postiže se tako što se uzima piksel sa jedne strane centra i oduzima onaj koji se nalazi nasuprot njega u odnosu na centar. Pikseli mogu dobiti pozitivnu ili negativnu vrednost. Da bi koristili negativne piksele kao senke, a pozitivne kao svetlo, za isticanje reljefa može se dodati slici pomak (bias) od 128. Sada će veći deo slike biti siv a bokovi ili tamno sivi/crni ili svetlo sivi/beli.

 

Primer:

Implementirajte sledeću masku:

MASK[0][0] = -1.0;

MASK[0][1] = -1.0;

MASK[0][2] = -1.0; MASK[0][3] = -1.0;

MASK[0][4]
= 0.0;      

MASK[1][0] = -1.0;

MASK[1][1] = -1.0;

MASK[1][2] = -1.0; MASK[1][3] = 0.0;

MASK[1][4]
= 1.0;      

MASK[2][0] = -1.0;

MASK[2][1] = -1.0;

MASK[2][2] =

0.0; MASK[2][3] =

1.0; MASK[2][4]
= 1.0;          

MASK[3][0] = -1.0;

MASK[3][1] = 0.0;

MASK[3][2] =

1.0; MASK[3][3] =

1.0; MASK[3][4]
= 1.0;          

MASK[4][0] = 0.0;

MASK[4][1] = 1.0 ;

MASK[4][2] =

1.0; MASK[4][3] =

1.0; MASK[4][4]
= 1.0;          
 

Izvorni kôd za rad sa slikom u boji (cvet.bmp) dat je u fajlu EmbossKolor.c. Možete preuzeti arhivu emboss.rar.

Napomena: Čitaocima se ostavlja da analiziraju i optimizuju kôd.

/*

FILE: EmbossKolor.c

AUTH: Markoni

DESC: 5x5 mask for EMBOSS color image

DATE: april 2007

REFS:
*/

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

#include <malloc.h>

/*-------STRUCTURES---------*/

typedef struct {int rows; int cols; unsigned char* data;} sImage;

/*-------PROTOTYPES---------*/

long getImageInfo(FILE*, long, int);

void copyImageInfo(FILE* inputFile, FILE* outputFile);

void copyColorTable(FILE* inputFile, FILE* outputFile, int nColors);

int main(int argc, char* argv[])

 

{

FILE *bmpInput, *bmpOutput;

sImage originalImage, BoriginalImage, GoriginalImage,

RoriginalImage;

sImage

BedgeImage, GedgeImage,

RedgeImage;
unsigned int X, Y;  
int   I, J;  
long  

BSUM, GSUM, RSUM;

 
long   nColors;  
unsigned long vectorSize;  
int   nBits;  
unsigned long fileSize;  
double   MASK[5][5];  
unsigned char

*pChar, someChar;

 
unsigned int row, col;  

someChar = '0'; pChar = &someChar;

/* 5x5 mask for BLUR */

/* negative pixels shadow */

/* positive pixels light */

/* Bias = 128 */

//

MASK[0][0] = -1.0; MASK[0][1] = -1.0; MASK[0][2] = -1.0;

MASK[0][3] = -1.0; MASK[0][4] = 0.0;

MASK[1][0] = -1.0; MASK[1][1] = -1.0; MASK[1][2] = -1.0; MASK[1][3] = 0.0; MASK[1][4] = 1.0;

MASK[2][0] = -1.0; MASK[2][1] = -1.0; MASK[2][2] = 0.0; MASK[2][3] = 1.0; MASK[2][4] = 1.0;

MASK[3][0] = -1.0; MASK[3][1] = 0.0; MASK[3][2] = 1.0; MASK[3][3] = 1.0; MASK[3][4] = 1.0;

MASK[4][0] = 0.0; MASK[4][1] = 1.0 ; MASK[4][2] = 1.0; MASK[4][3] = 1.0; MASK[4][4] = 1.0;

if(argc < 2) {

printf("Usage: %s bmpInput.bmp\n", argv[0]);

exit(0);
};

printf("Reading filename %s\n", argv[1]);

/* open files for reading and writing to */

bmpInput = fopen(argv[1], "rb");

bmpOutput = fopen("EmbossKolor.bmp", "wb");

/* start pointer at beginning of file */

fseek(bmpInput, 0L, SEEK_END);

/* retrieve and print filesize and number of cols and rows */

fileSize = getImageInfo(bmpInput, 2, 4); originalImage.cols = (int)getImageInfo(bmpInput, 18, 4); originalImage.rows = (int)getImageInfo(bmpInput, 22, 4);

//

BedgeImage.rows = originalImage.rows; BedgeImage.cols = originalImage.cols;

//

GedgeImage.rows = originalImage.rows; GedgeImage.cols = originalImage.cols;

 

//

RedgeImage.rows = originalImage.rows; RedgeImage.cols = originalImage.cols;

printf("Width: %d\n", originalImage.cols); printf("Height: %d\n", originalImage.rows); printf("File size: %lu\n", fileSize);

/* Read BMP bits/pixel at byte #28 */

nBits = (int) getImageInfo(bmpInput, 28, 2);

printf("The image is \t%d-bit\n", nBits);

/* retrieve and print Number of colors */

nColors = pow(2L,nBits);

printf("nColors: %ld\n", nColors);

//vectorSize
//

vectorSize = (long)((long)originalImage.cols*(long)originalImage.rows);

//

printf("vectorSize: %lu\n", vectorSize);

//
// B plane
//

BedgeImage.data = malloc(vectorSize*sizeof(unsigned char));

if(BedgeImage.data == NULL) {

printf("Failed to malloc BedgeImage.data\n");

exit(0);
}

printf("%lu bytes malloc'ed for BedgeImage.data\n", vectorSize);

//
// G plane
//

GedgeImage.data = malloc(vectorSize*sizeof(unsigned char));

if(GedgeImage.data == NULL) {

printf("Failed to malloc GedgeImage.data\n");

exit(0);
}

printf("%lu bytes malloc'ed for GedgeImage.data\n", vectorSize);

//
// R plane
//

RedgeImage.data = malloc(vectorSize*sizeof(unsigned char));

if(RedgeImage.data == NULL) {

printf("Failed to malloc RedgeImage.data\n");

exit(0);
}

printf("%lu bytes malloc'ed for RedgeImage.data\n", vectorSize);

//
//
//

BoriginalImage.data = malloc(vectorSize*sizeof(unsigned char));

if(BoriginalImage.data == NULL) {

printf("Failed to malloc BoriginalImage.data\n");

exit(0);
}

 

printf("%lu bytes malloc'ed for BoriginalImage.data\n", vectorSize);

//

GoriginalImage.data = malloc(vectorSize*sizeof(unsigned char));

if(GoriginalImage.data == NULL) {

printf("Failed to malloc GoriginalImage.data\n");

exit(0);
}

printf("%lu bytes malloc'ed for GoriginalImage.data\n", vectorSize);

//

RoriginalImage.data = malloc(vectorSize*sizeof(unsigned char));

if(RoriginalImage.data == NULL) {

printf("Failed to malloc RoriginalImage.data\n");

exit(0);
}

printf("%lu bytes malloc'ed for RoriginalImage.data\n", vectorSize);

//
//

copyImageInfo(bmpInput, bmpOutput);

//

fseek(bmpInput, (14+40), SEEK_SET);

fseek(bmpOutput, (14+40), SEEK_SET);

/* Read input.bmp and store it's raster data into originalImage.data

*/

for(row=0; row<=originalImage.rows-1; row++) {

for(col=0; col<=originalImage.cols-1; col++) {

fread(pChar, sizeof(char), 1, bmpInput);

*(BoriginalImage.data + row*originalImage.cols + col) =

 

*pChar;
*pChar;
*pChar;

}


//

fread(pChar, sizeof(char), 1, bmpInput);

*(GoriginalImage.data + row*originalImage.cols + col) =

//

fread(pChar, sizeof(char), 1, bmpInput);

*(RoriginalImage.data + row*originalImage.cols + col) =

 

}
//

// BLUR - processing plane-by-plane

//

for(Y=0; Y<=(originalImage.rows-1); Y++) {

//
//

for(X=0; X<=(originalImage.cols-1); X++) { BSUM = 128; GSUM = 128; RSUM = 128;

/* image boundaries */

if(Y==0 || Y==1 || Y==originalImage.rows-2 || Y==originalImage.rows-1) {

//
// Bias = 128
//

BSUM = 128; GSUM = 128; RSUM = 128; }

 

else if(X==0 || X==1 || X==originalImage.cols-2 || X==originalImage.cols-1) {

BSUM = 128; GSUM = 128; RSUM = 128; }

/* Convolution starts here */

else {

for(I=-2; I<=2; I++) {

for(J=-2; J<=2; J++) {

BSUM = BSUM + (int)( (*(BoriginalImage.data + X + I +

(Y + J)*originalImage.cols)) * MASK[I+2][J+2]);

GSUM = GSUM + (int)( (*(GoriginalImage.data + X + I + (Y + J)*originalImage.cols)) * MASK[I+2][J+2]);

RSUM = RSUM + (int)( (*(RoriginalImage.data + X + I + (Y + J)*originalImage.cols)) * MASK[I+2][J+2]);

}
}
}

if(BSUM>255) BSUM=255; if(GSUM>255) GSUM=255; if(RSUM>255) RSUM=255;

//

if(BSUM<0) BSUM=0; if(GSUM<0) GSUM=0; if(RSUM<0) RSUM=0;

//
// new Blue
//

*(BedgeImage.data + X + Y*originalImage.cols) = (unsigned

 

char)(BSUM);

fwrite( (BedgeImage.data + X + Y*originalImage.cols),

 

sizeof(char), 1, bmpOutput);

//
// new Green
//

*(GedgeImage.data + X + Y*originalImage.cols) = (unsigned

char)(GSUM);

fwrite( (GedgeImage.data + X + Y*originalImage.cols), sizeof(char), 1, bmpOutput);

//
// new Red
//

*(RedgeImage.data + X + Y*originalImage.cols) = (unsigned

char)(RSUM);

fwrite( (RedgeImage.data + X + Y*originalImage.cols),

sizeof(char), 1, bmpOutput);

}

}

printf("See EmbossKolor.bmp for results\n");

fclose(bmpInput);

fclose(bmpOutput);

free(BedgeImage.data); /* Finished with edgeImage.data */

free(GedgeImage.data);

free(RedgeImage.data);

//

 

free(BoriginalImage.data);

free(GoriginalImage.data);

free(RoriginalImage.data); /* Finished with originalImage.data */

return 0;
}

/*----------GET IMAGE INFO SUBPROGRAM--------------*/

long getImageInfo(FILE* inputFile, long offset, int numberOfChars)

{
unsigned char   *ptrC;
long     value = 0L;
unsigned char   dummy;
int   i;  
dummy = '0';
ptrC = &dummy;

fseek(inputFile, offset, SEEK_SET);

for(i=1; i<=numberOfChars; i++)

{

fread(ptrC, sizeof(char), 1, inputFile);

/* calculate value based on adding bytes */

value = (long)(value + (*ptrC)*(pow(256, (i-1))));

}
return(value);

} /* end of getImageInfo */

/*-------------COPIES HEADER AND INFO HEADER----------------*/

void copyImageInfo(FILE* inputFile, FILE* outputFile)

{

unsigned char *ptrC; unsigned char dummy; int i;

dummy = '0';
ptrC = &dummy;

fseek(inputFile, 0L, SEEK_SET);

fseek(outputFile, 0L, SEEK_SET);

for(i=0; i<=50; i++)

{

fread(ptrC, sizeof(char), 1, inputFile);

fwrite(ptrC, sizeof(char), 1, outputFile);

}
}

/*----------------COPIES COLOR TABLE-----------------------------*/

void copyColorTable(FILE* inputFile, FILE* outputFile, int nColors)

{

unsigned char *ptrC; unsigned char dummy; int i;

 

dummy = '0';
ptrC = &dummy;

fseek(inputFile, 54L, SEEK_SET);

fseek(outputFile, 54L, SEEK_SET);

for(i=0; i<=(4*nColors); i++) /* there are (4*nColors) bytes in color table */

{

fread(ptrC, sizeof(char), 1, inputFile);

fwrite(ptrC, sizeof(char), 1, outputFile);

}
}
 

Pripremio Dragan Marković