-1

I want to add two images using c programming language. If the dimension of the images is 600*600, then from the 1st image, 1 to 300 pixels will be there in the new image and 300 to 600 pixel of the second image will be there in the new image.

Original images

enter image description here

enter image description here

Adding two images together looks like

enter image description here

My code of adding image

#include <stdio.h>
#include <stdlib.h>

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
int main() {

    int width, height, channels;
     //read image using stbi_load function
     unsigned char *apple = stbi_load("apple.jpg", &width, &height, &channels, 0);
     unsigned char *orange = stbi_load("orange.jpg", &width, &height, &channels, 0);

     size_t img_size = width * height * channels;
     size_t new_img_size = width * height * channels;
     unsigned char *new_img = malloc(new_img_size);
     for(unsigned char *p = apple, *q = orange, *pg = new_img; p != apple + img_size/2 && q!=(orange+300)+img_size ; p += channels , q += channels, pg+=channels) {

        *pg       = (*p + *q);
         *(pg + 1) =  (*(p+1) + *(q+1));
        *(pg + 2) =  (*(p+2)+*(q+2));
     }
    
     stbi_write_jpg("new_image.jpg", width, height, channels, new_img, 100);

}

The output of the code

enter image description here

In this for loop for(unsigned char *p = apple, *q = orange, *pg = new_img; p != apple + img_size/2 && q!=(orange+300)+img_size ; p += channels , q += channels, pg+=channels)

I tried to implement *p loop over 1st pixel of the image apple through 300th pixel and *q loop over 300th pixel of image orange through the last pixel.

I like to know what logic error is there in my code block. Thank you. Any help would be appreciated.

Encipher
  • 1,370
  • 1
  • 14
  • 31
  • Have you tried running your code line-by-line in a debugger while monitoring the values of all variables, in order to determine in which line your program stops behaving as intended? If you did not try this, then you may want to read this: [What is a debugger and how can it help me diagnose problems?](https://stackoverflow.com/q/25385173/12149471) You may also want to read this: [How to debug small programs?](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) – Andreas Wenzel Sep 27 '22 at 04:09
  • I did not have any compiler error. The code runs fine. There are some logic error so the lower portion of the image getting dark. – Encipher Sep 27 '22 at 04:19
  • 1
    You are adding color components of both images together (and they wrap around). Split your single loop into two: In first fill left part of destination with pixels from left side of `apple` image and check if it works. In second loop fill right side of destination with pixels from right side of `orange`. You won't add color components of different images unless you want a kind of alpha blending. – dimich Sep 27 '22 at 04:47
  • *p is the pointer which keep track on the pixel of apple image. So *p looping over the half size of the image. This had been done on the for loop. It is not clear to me how could the values of *p assign to the new image. There is no array concept. – Encipher Sep 27 '22 at 05:17
  • Any reference to read write image in C other than my method? – Encipher Sep 27 '22 at 05:19

1 Answers1

1

You just need to choose which image you're copying from, based on whether you're on the left or right half of the image. You don't need to go nuts with pointers, just use indices and let the compiler optimize it.

A compact option is to choose with conditional operator, although it's unclear whether the compiler will optimize this nicely:

size_t img_size = width * height * channels;
size_t img_stride = width * channels;
size_t img_split = img_stride / 2;

unsigned char *new_img = malloc(img_size);
if (new_img != NULL)
{
    for (size_t i = 0; i < img_size; i++)
    {
        new_img[i] = (i % img_stride < img_split) ? apple[i] : orange[i];
    }
}

Another option is to just use two loops to copy each half of each row. Here's the basic idea:

size_t img_size = width * height * channels;
size_t img_stride = width * channels;
size_t img_split = img_stride / 2;

unsigned char *new_img = malloc(img_size);
if (new_img != NULL)
{
    for (size_t row_idx = 0; row_idx < img_size; row_idx += img_stride)
    {
        size_t x = 0;
        for (; x < img_split; x++) new_img[row_idx + x] = apple[row_idx + x];
        for (; x < img_stride; x++) new_img[row_idx + x] = orange[row_idx + x];
    }
}

Of course, at that point you may as well use memcpy:

    for (size_t row = 0; row < img_size; row += img_stride)
    {
        memcpy(&new_img[row], &apple[row], img_split);
        memcpy(&new_img[row + img_split], &orange[row + img_split], img_stride - img_split);
    }
paddy
  • 60,864
  • 6
  • 61
  • 103
  • It works well. Thank you. However, can you please let me know what is the functionality of img_stride and img_split? – Encipher Sep 27 '22 at 14:17
  • Also, please let me know what should be the initialization of the for loop for the second method. I tried to initialize the for loop with x=0 which did not work. – Encipher Sep 27 '22 at 14:23
  • Also, for (; x < img_split; x++) new_img[row_idx + x] = apple[row_idx + x]; and for (; x < img_stride; x++) new_img[row_idx + x] = orange[row_idx + x]; touches the same cells, only orange for loop touches apple for loop cells, and also some extra cells on right hand side. My question is why I am not getting a half blending image where blending should occur on the left-hand side? – Encipher Sep 27 '22 at 15:18
  • 1
    `img_stride` represents the number of pixel channel values in a single row of data, and `img_split` is of course half of that. So, the "split" is the boundary between the two image halves. There is no initialization of `x` in those loops. I left that part empty for a reason. You don't just randomly change that without understanding what it does. `x` is defined outside those loops. The first loop runs `x` up to the halfway point, and the second loop continues until the end of the row. – paddy Sep 27 '22 at 20:43