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 или 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 или tamno sivi/crni или 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: 5×5 mask for EMBOSS color image

DATE: april 2007

REFS:
*/

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

#include <malloc.h>

/*——-STRUЦТURES———*/

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;

/* 5×5 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.bmpn“, argv[0]);

exit(0);
};

printf(„Reading filename %sn“, 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: %dn“, originalImage.cols); printf(„Height: %dn“, originalImage.rows); printf(„File size: %lun“, fileSize);

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

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

printf(„The image is t%d-bitn“, nBits);

/* retrieve and print Number of colors */

nColors = pow(2L,nBits);

printf(„nColors: %ldn“, nColors);

//vectorSize
//

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

//

printf(„vectorSize: %lun“, vectorSize);

//
// B plane
//

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

if(BedgeImage.data == NULL) {

printf(„Failed to malloc BedgeImage.datan“);

exit(0);
}

printf(„%lu bytes malloc’ed for BedgeImage.datan“, vectorSize);

//
// G plane
//

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

if(GedgeImage.data == NULL) {

printf(„Failed to malloc GedgeImage.datan“);

exit(0);
}

printf(„%lu bytes malloc’ed for GedgeImage.datan“, vectorSize);

//
// R plane
//

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

if(RedgeImage.data == NULL) {

printf(„Failed to malloc RedgeImage.datan“);

exit(0);
}

printf(„%lu bytes malloc’ed for RedgeImage.datan“, vectorSize);

//
//
//

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

if(BoriginalImage.data == NULL) {

printf(„Failed to malloc BoriginalImage.datan“);

exit(0);
}

printf(„%lu bytes malloc’ed for BoriginalImage.datan“, vectorSize);

//

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

if(GoriginalImage.data == NULL) {

printf(„Failed to malloc GoriginalImage.datan“);

exit(0);
}

printf(„%lu bytes malloc’ed for GoriginalImage.datan“, vectorSize);

//

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

if(RoriginalImage.data == NULL) {

printf(„Failed to malloc RoriginalImage.datan“);

exit(0);
}

printf(„%lu bytes malloc’ed for RoriginalImage.datan“, 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 resultsn“);

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ć

2068-reljefizacija