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;
}
//
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
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; |
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;
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ć