|
@ -2135,11 +2135,12 @@ void ImageBlurGaussian(Image *image, int blurSize) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// The kernel matrix is assumed to be square. Only supply the width of the kernel. |
|
|
// The kernel matrix is assumed to be square. Only supply the width of the kernel. |
|
|
void f">ImageKernelConvolution(Image *image, float* kernel, int kernelSize){ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ImageKernelConvolution(Image *image, float* kernel, int kernelSize) |
|
|
|
|
|
{ |
|
|
if ((image->data == NULL) || (image->width == 0) || (image->height == 0) || kernel == NULL) return; |
|
|
if ((image->data == NULL) || (image->width == 0) || (image->height == 0) || kernel == NULL) return; |
|
|
|
|
|
|
|
|
int kernelWidth = (int)sqrtf((float)kernelSize); |
|
|
int kernelWidth = (int)sqrtf((float)kernelSize); |
|
|
|
|
|
|
|
|
if (kernelWidth*kernelWidth != kernelSize) |
|
|
if (kernelWidth*kernelWidth != kernelSize) |
|
|
{ |
|
|
{ |
|
|
TRACELOG(LOG_WARNING, "IMAGE: Convolution kernel must be square to be applied"); |
|
|
TRACELOG(LOG_WARNING, "IMAGE: Convolution kernel must be square to be applied"); |
|
@ -2152,7 +2153,8 @@ void ImageKernelConvolution(Image *image, float* kernel, int kernelSize){ |
|
|
Vector4 *temp = RL_MALLOC(kernelSize*sizeof(Vector4)); |
|
|
Vector4 *temp = RL_MALLOC(kernelSize*sizeof(Vector4)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(int i = 0; i < kernelSize; i++){ |
|
|
|
|
|
|
|
|
for (int i = 0; i < kernelSize; i++) |
|
|
|
|
|
{ |
|
|
temp[i].x = 0.0f; |
|
|
temp[i].x = 0.0f; |
|
|
temp[i].y = 0.0f; |
|
|
temp[i].y = 0.0f; |
|
|
temp[i].z = 0.0f; |
|
|
temp[i].z = 0.0f; |
|
@ -2164,44 +2166,49 @@ void ImageKernelConvolution(Image *image, float* kernel, int kernelSize){ |
|
|
float bRes = 0.0f; |
|
|
float bRes = 0.0f; |
|
|
float aRes = 0.0f; |
|
|
float aRes = 0.0f; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int startRange, endRange; |
|
|
|
|
|
if(kernelWidth % 2 == 0) |
|
|
|
|
|
|
|
|
int startRange = 0, endRange = 0; |
|
|
|
|
|
|
|
|
|
|
|
if (kernelWidth%2 == 0) |
|
|
{ |
|
|
{ |
|
|
startRange = -kernelWidth/2; |
|
|
startRange = -kernelWidth/2; |
|
|
endRange = kernelWidth/2; |
|
|
endRange = kernelWidth/2; |
|
|
} else |
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
{ |
|
|
{ |
|
|
startRange = -kernelWidth/2; |
|
|
startRange = -kernelWidth/2; |
|
|
endRange = kernelWidth/2+1; |
|
|
|
|
|
|
|
|
endRange = kernelWidth/2 + 1; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
for(int x = 0; x < image->height; x++) |
|
|
for(int x = 0; x < image->height; x++) |
|
|
{ |
|
|
{ |
|
|
for(int y = 0; y < image->width; y++) |
|
|
|
|
|
|
|
|
for (int y = 0; y < image->width; y++) |
|
|
{ |
|
|
{ |
|
|
|
|
|
|
|
|
for(int xk = startRange; xk < endRange; xk++) |
|
|
|
|
|
|
|
|
for (int xk = startRange; xk < endRange; xk++) |
|
|
{ |
|
|
{ |
|
|
for(int yk = startRange; yk < endRange; yk++) |
|
|
|
|
|
|
|
|
for (int yk = startRange; yk < endRange; yk++) |
|
|
{ |
|
|
{ |
|
|
int xkabs = xk + kernelWidth/2; |
|
|
int xkabs = xk + kernelWidth/2; |
|
|
int ykabs = yk + kernelWidth/2; |
|
|
int ykabs = yk + kernelWidth/2; |
|
|
size_t imgindex = image->width * (x+xk) + (y+yk); |
|
|
|
|
|
if(imgindex < 0 || imgindex >= image->width * image->height){ |
|
|
|
|
|
|
|
|
unsigned int imgindex = image->width*(x + xk) + (y + yk); |
|
|
|
|
|
|
|
|
|
|
|
if (imgindex >= image->width*image->height) |
|
|
|
|
|
{ |
|
|
temp[kernelWidth * xkabs + ykabs].x = 0.0f; |
|
|
temp[kernelWidth * xkabs + ykabs].x = 0.0f; |
|
|
temp[kernelWidth * xkabs + ykabs].y = 0.0f; |
|
|
temp[kernelWidth * xkabs + ykabs].y = 0.0f; |
|
|
temp[kernelWidth * xkabs + ykabs].z = 0.0f; |
|
|
temp[kernelWidth * xkabs + ykabs].z = 0.0f; |
|
|
temp[kernelWidth * xkabs + ykabs].w = 0.0f; |
|
|
temp[kernelWidth * xkabs + ykabs].w = 0.0f; |
|
|
} else { |
|
|
|
|
|
temp[kernelWidth * xkabs + ykabs].x = ((float)pixels[imgindex].r)/255.0f * kernel[kernelWidth * xkabs + ykabs]; |
|
|
|
|
|
temp[kernelWidth * xkabs + ykabs].y = ((float)pixels[imgindex].g)/255.0f * kernel[kernelWidth * xkabs + ykabs]; |
|
|
|
|
|
temp[kernelWidth * xkabs + ykabs].z = ((float)pixels[imgindex].b)/255.0f * kernel[kernelWidth * xkabs + ykabs]; |
|
|
|
|
|
temp[kernelWidth * xkabs + ykabs].w = ((float)pixels[imgindex].a)/255.0f * kernel[kernelWidth * xkabs + ykabs]; |
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
temp[kernelWidth * xkabs + ykabs].x = ((float)pixels[imgindex].r)/255.0f*kernel[kernelWidth*xkabs + ykabs]; |
|
|
|
|
|
temp[kernelWidth * xkabs + ykabs].y = ((float)pixels[imgindex].g)/255.0f*kernel[kernelWidth*xkabs + ykabs]; |
|
|
|
|
|
temp[kernelWidth * xkabs + ykabs].z = ((float)pixels[imgindex].b)/255.0f*kernel[kernelWidth*xkabs + ykabs]; |
|
|
|
|
|
temp[kernelWidth * xkabs + ykabs].w = ((float)pixels[imgindex].a)/255.0f*kernel[kernelWidth*xkabs + ykabs]; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
for(int i = 0; i < kernelSize; i++) |
|
|
|
|
|
|
|
|
for (int i = 0; i < kernelSize; i++) |
|
|
{ |
|
|
{ |
|
|
rRes += temp[i].x; |
|
|
rRes += temp[i].x; |
|
|
gRes += temp[i].y; |
|
|
gRes += temp[i].y; |
|
@ -2209,43 +2216,25 @@ void ImageKernelConvolution(Image *image, float* kernel, int kernelSize){ |
|
|
aRes += temp[i].w; |
|
|
aRes += temp[i].w; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if(rRes < 0.0f) |
|
|
|
|
|
{ |
|
|
|
|
|
rRes = 0.0f; |
|
|
|
|
|
} |
|
|
|
|
|
if(gRes < 0.0f) |
|
|
|
|
|
{ |
|
|
|
|
|
gRes = 0.0f; |
|
|
|
|
|
} |
|
|
|
|
|
if(bRes < 0.0f) |
|
|
|
|
|
{ |
|
|
|
|
|
bRes = 0.0f; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (rRes < 0.0f) rRes = 0.0f; |
|
|
|
|
|
if (gRes < 0.0f) gRes = 0.0f; |
|
|
|
|
|
if (bRes < 0.0f) bRes = 0.0f; |
|
|
|
|
|
|
|
|
if(rRes > 1.0f) |
|
|
|
|
|
{ |
|
|
|
|
|
rRes = 1.0f; |
|
|
|
|
|
} |
|
|
|
|
|
if(gRes > 1.0f) |
|
|
|
|
|
{ |
|
|
|
|
|
gRes = 1.0f; |
|
|
|
|
|
} |
|
|
|
|
|
if(bRes > 1.0f) |
|
|
|
|
|
{ |
|
|
|
|
|
bRes = 1.0f; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (rRes > 1.0f) rRes = 1.0f; |
|
|
|
|
|
if (gRes > 1.0f) gRes = 1.0f; |
|
|
|
|
|
if (bRes > 1.0f) bRes = 1.0f; |
|
|
|
|
|
|
|
|
imageCopy2[image->width * (x) + (y)].x = rRes; |
|
|
|
|
|
imageCopy2[image->width * (x) + (y)].y = gRes; |
|
|
|
|
|
imageCopy2[image->width * (x) + (y)].z = bRes; |
|
|
|
|
|
imageCopy2[image->width * (x) + (y)].w = aRes; |
|
|
|
|
|
|
|
|
imageCopy2[image->width*x + y].x = rRes; |
|
|
|
|
|
imageCopy2[image->width*x + y].y = gRes; |
|
|
|
|
|
imageCopy2[image->width*x + y].z = bRes; |
|
|
|
|
|
imageCopy2[image->width*x + y].w = aRes; |
|
|
|
|
|
|
|
|
rRes = 0.0f; |
|
|
rRes = 0.0f; |
|
|
gRes = 0.0f; |
|
|
gRes = 0.0f; |
|
|
bRes = 0.0f; |
|
|
bRes = 0.0f; |
|
|
aRes = 0.0f; |
|
|
aRes = 0.0f; |
|
|
|
|
|
|
|
|
for(int i = 0; i < kernelSize; i++) |
|
|
|
|
|
|
|
|
for (int i = 0; i < kernelSize; i++) |
|
|
{ |
|
|
{ |
|
|
temp[i].x = 0.0f; |
|
|
temp[i].x = 0.0f; |
|
|
temp[i].y = 0.0f; |
|
|
temp[i].y = 0.0f; |
|
@ -2255,17 +2244,16 @@ void ImageKernelConvolution(Image *image, float* kernel, int kernelSize){ |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
for (int i = 0; i < (image->widthp">) * (image->height); i++) |
|
|
|
|
|
|
|
|
for (int i = 0; i < (image->width*image->height); i++) |
|
|
{ |
|
|
{ |
|
|
float alpha = (float)imageCopy2[i].w; |
|
|
float alpha = (float)imageCopy2[i].w; |
|
|
|
|
|
|
|
|
pixels[i].r = (unsigned char)((imageCopy2[i].x)*255.0f); |
|
|
pixels[i].r = (unsigned char)((imageCopy2[i].x)*255.0f); |
|
|
pixels[i].g = (unsigned char)((imageCopy2[i].y)*255.0f); |
|
|
pixels[i].g = (unsigned char)((imageCopy2[i].y)*255.0f); |
|
|
pixels[i].b = (unsigned char)((imageCopy2[i].z)*255.0f); |
|
|
pixels[i].b = (unsigned char)((imageCopy2[i].z)*255.0f); |
|
|
pixels[i].a = (unsigned char)((alpha)*255.0f); |
|
|
pixels[i].a = (unsigned char)((alpha)*255.0f); |
|
|
// printf("pixels[%d] = %d", i, pixels[i].r); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int format = image->format; |
|
|
int format = image->format; |
|
|
RL_FREE(image->data); |
|
|
RL_FREE(image->data); |
|
|
RL_FREE(imageCopy2); |
|
|
RL_FREE(imageCopy2); |
|
|