0

I came across this, the C version of Bilinear interpolation. I can't figure out how to run it. I have an image called image_1.jpeg that I want to use...

It looks you just need to call scale(), but how exactly do you write the main() method to do that?

The Code ->

#include <stdint.h>
typedef struct {
    uint32_t *pixels;
    unsigned int w;
    unsigned int h;
} image_t;
#define getByte(value, n) (value >> (n*8) & 0xFF)

uint32_t getpixel(image_t *image, unsigned int x, unsigned int y){
    return image->pixels[(y*image->w)+x];
}
float lerp(float s, float e, float t){return s+(e-s)*t;}
float blerp(float c00, float c10, float c01, float c11, float tx, float ty){
    return lerp(lerp(c00, c10, tx), lerp(c01, c11, tx), ty);
}
void putpixel(image_t *image, unsigned int x, unsigned int y, uint32_t color){
    image->pixels[(y*image->w) + x] = color;
}
void scale(image_t *src, image_t *dst, float scalex, float scaley){
    int newWidth = (int)src->w*scalex;
    int newHeight= (int)src->h*scaley;
    int x, y;
    for(x= 0, y=0; y < newHeight; x++){
        if(x > newWidth){
            x = 0; y++;
        }
        float gx = x / (float)(newWidth) * (src->w-1);
        float gy = y / (float)(newHeight) * (src->h-1);
        int gxi = (int)gx;
        int gyi = (int)gy;
        uint32_t result=0;
        uint32_t c00 = getpixel(src, gxi, gyi);
        uint32_t c10 = getpixel(src, gxi+1, gyi);
        uint32_t c01 = getpixel(src, gxi, gyi+1);
        uint32_t c11 = getpixel(src, gxi+1, gyi+1);
        uint8_t i;
        for(i = 0; i < 3; i++){
            //((uint8_t*)&result)[i] = blerp( ((uint8_t*)&c00)[i], ((uint8_t*)&c10)[i], ((uint8_t*)&c01)[i], ((uint8_t*)&c11)[i], gxi - gx, gyi - gy); // this is shady
            result |= (uint8_t)blerp(getByte(c00, i), getByte(c10, i), getByte(c01, i), getByte(c11, i), gx - gxi, gy -gyi) << (8*i);
        }
        putpixel(dst,x, y, result);
    }
}

source: https://rosettacode.org/wiki/Bilinear_interpolation#C

  • 1
    It is more complex than just adding `main`. You also need to read the image. What is its format? Finally you need to write the scaled image back again. I suggest you get some help. It may too much to ask and explain here. – Paul Ogilvie Jul 16 '19 at 16:12
  • `image_1.jpeg` is the image I am using for this. The output can be whatever, `image_1_larger.jpeg` for example. It is bilinear interpolation, so it scales an image up 60%. My post got edited, so the link was lost: https://rosettacode.org/wiki/Bilinear_interpolation#C –  Jul 16 '19 at 16:50
  • Then you also need to decode the jpeg image. It's getting more complex... You could convert the jpeg to a bmp and then read the bmp, which is simpler but absolutely not rivial either. – Paul Ogilvie Jul 16 '19 at 17:32
  • If I just use a bmp, is there a simple way to do this? –  Jul 16 '19 at 17:54
  • My answer at https://stackoverflow.com/questions/47768094/pointer-file-randomly-changes-value-in-middle-of-reading-raw-bitmap-data shows how to read a bitmap image, however, you mus still convert scanlines to the pixel data of your structure. A scanline is rounded up and the last few bytes are unused, You must _not_ copy those to your image data. Still: it is probably too complex for you, I guess, but maybe this helps. – Paul Ogilvie Jul 16 '19 at 18:05
  • First one has to decode jpeg compression to get an uncompressed image, eg, https://keyj.emphy.de/nanojpeg/. At first glance, it appears their code is using 32-bit RGBA pixel format, but your jpeg file is probably 24-bits, so that may cause an issue. You could edit it with eg gimp to a format compatible with this code. – Neil Jul 16 '19 at 20:02

1 Answers1

0

Your problem here is probably less so figuring out how to call scale, and more so figuring out how to load your images. I recommend the SOIL library, it handles most common formats and gets you the raw pixel data.

You'll also most likely need some function to create the actual image_t instances from the raw image. SOIL and other image libraries should be able to provide you the width and height, as well as some kind of byte or int array for the image itself. image_t appears to be row-major in your example, so something like this could work:

image_t to_image_t(int width, int height, unsigned char* data) {
    image_t img = { malloc(sizeof(int) * width * height), width, height };
    for (int i = 0; i < width * height; i ++) {
        // You may need to fiddle with this based on your image's format
        // and how you load it.
        img->pixels[i] = (data[0] << 24)
                       | (data[1] << 16)
                       | (data[2] << 8)
                       | (data[3]);
    }
    return img;
}

Just remember to free your image's pixel data after you're done using it.

elucent
  • 36
  • 4