Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include "stb_image_write.h"
- #define STB_IMAGE_WRITE_IMPLEMENTATION
- #define CHANNELS 3 // number of color channels
- #define BICUBIC_ORDER 4 // bicubic interpolation order
- #define BICUBIC_SIZE (BICUBIC_ORDER + 1) // bicubic interpolation kernel size
- // calculate bicubic kernel weights
- void bicubic_weights(float weights[BICUBIC_SIZE], float x)
- {
- float absx = fabsf(x);
- if (absx <= 1.0)
- {
- weights[0] = (1.5 * absx - 2.5) * absx * absx + 1.0;
- weights[1] = (2.0 - 1.5 * absx) * absx * absx;
- weights[2] = 0.5 * (absx - 1.0) * absx * absx;
- weights[3] = 0.0;
- }
- else if (absx <= 2.0)
- {
- weights[0] = -0.5 * absx * absx * absx + 2.5 * absx * absx - 4.0 * absx + 2.0;
- weights[1] = 0.5 * absx * absx * absx - 2.5 * absx * absx + 4.0 * absx;
- weights[2] = -0.5 * absx * absx * absx + 1.5 * absx * absx;
- weights[3] = 0.0;
- }
- else
- {
- weights[0] = 0.0;
- weights[1] = 0.0;
- weights[2] = 0.0;
- weights[3] = 0.0;
- }
- }
- // perform bicubic interpolation on an image
- void bicubic_interpolation(unsigned char *input, int in_w, int in_h, unsigned char *output, int out_w, int out_h)
- {
- int x, y, c, i, j;
- float u, v;
- float weights_x[BICUBIC_SIZE], weights_y[BICUBIC_SIZE];
- int x_min, y_min, x_max, y_max;
- int index, index_offset, offset;
- unsigned char pixel[CHANNELS];
- // calculate scaling factors for x and y axes
- float sx = (float)in_w / (float)out_w;
- float sy = (float)in_h / (float)out_h;
- for (y = 0; y < out_h; y++)
- {
- for (x = 0; x < out_w; x++)
- {
- // calculate input image coordinates for the current output pixel
- u = (float)x * sx;
- v = (float)y * sy;
- // determine the range of input pixel coordinates to use for interpolation
- x_min = (int)floorf(u) - BICUBIC_ORDER / 2;
- y_min = (int)floorf(v) - BICUBIC_ORDER / 2;
- x_max = x_min + BICUBIC_ORDER;
- y_max = y_min + BICUBIC_ORDER;
- // clamp the input pixel coordinate range to the image bounds
- if (x_min < 0)
- x_min = 0;
- if (y_min < 0)
- y_min = 0;
- if (x_max >= in_w)
- x_max = in_w;
- if (y_max >= in_h)
- y_max = in_h - 1;
- // initialize output pixel values to zero
- for (c = 0; c < CHANNELS; c++)
- {
- pixel[c] = 0;
- }
- // perform bicubic interpolation for each color channel
- for (c = 0; c < CHANNELS; c++)
- {
- for (j = y_min; j <= y_max; j++)
- {
- // calculate weights for the y-axis interpolation
- bicubic_weights(weights_y, v - (float)j);
- for (i = x_min; i <= x_max; i++)
- {
- // calculate weights for the x-axis interpolation
- bicubic_weights(weights_x, u - (float)i);
- // calculate the input pixel index and offset for the current channel
- index = (j * in_w + i) * CHANNELS + c;
- index_offset = index - (BICUBIC_ORDER / 2) * in_w * CHANNELS - (BICUBIC_ORDER / 2) * CHANNELS;
- // perform the bicubic interpolation for the current pixel
- for (offset = 0; offset < BICUBIC_SIZE; offset++)
- {
- pixel[c] += input[index_offset + offset * in_w * CHANNELS] * weights_x[offset] * weights_y[BICUBIC_SIZE - 1];
- }
- }
- }
- }
- // copy the output pixel values to the output image
- for (c = 0; c < CHANNELS; c++)
- {
- output[(y * out_w + x) * CHANNELS + c] = (unsigned char)pixel[c];
- }
- }
- }
- }
- // example usage
- int main()
- {
- int in_w = 640;
- int in_h = 480;
- int out_w = 320;
- int out_h = 240;
- // allocate memory for the input and output images
- unsigned char *input = (unsigned char *)malloc(in_w * in_h * CHANNELS);
- unsigned char *output = (unsigned char *)malloc(out_w * out_h * CHANNELS);
- // populate the input image with data
- for (int y = 0; y < in_h; y++)
- {
- for (int x = 0; x < in_w; x++)
- {
- for (int c = 0; c < CHANNELS; c++)
- {
- // calculate the pixel value for the current channel
- unsigned char value = (unsigned char)((x + y) / 2);
- // set the pixel value in the input image
- input[(y * in_w + x) * CHANNELS + c] = value;
- }
- }
- }
- // perform bicubic interpolation on the input image
- bicubic_interpolation(input, in_w, in_h, output, out_w, out_h);
- // write the output image to disk
- if (stbi_write_png("output.png", out_w, out_h, CHANNELS, output, out_w * CHANNELS) == 0)
- {
- fprintf(stderr, "Error writing output image to disk\n");
- }
- // free the allocated memory
- free(input);
- free(output);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement