1

I tried sending and receiving images between the parent and child processes using normal pipes, using the OpenCV Mat object.

The algorithm being used is:
1. Child reads an image
2. Stores it in a pipe
3. Signals the Parent that image has been written into pipe
4. Parent receives the signal and (in signal_handler) reads the image from the pipe and displays the image.

This is to be compiled as:
$ g++ simple_pipe.cpp -o sp pkg-config --cflags --libs opencv

The code goes by...

#include <bits/stdc++.h>
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/wait.h>

// OpenCV 3.4 libraries
#include <opencv2/opencv.hpp>   // FOR OpenCV
#include <opencv2/core.hpp>     // Basic OpenCV structures (cv::Mat)
#include <opencv2/videoio.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>



// #defines...
#define IMG_HT 180      // == ROWS 
#define IMG_WD 180      // == COLS
#define BUFF_SIZE (3*IMG_HT*IMG_WD)
#define BFSZ 1024
#define SLEEP_FOR_SOME_TIME 10

using namespace std;

int fd1[2], fd2[2];
// fd1 => for parent ; 0 - read, 1 - write
// fd2 => for child ; 0 - read, 1 - write

pid_t child_pid;

void signal_handler(int signal_number) {

    if (child_pid == 0) {
        // the child part
    }
    else {
        // the parent part
        printf("Signalled, with signum = %d, and PID = %d\n", signal_number, getpid());
        // close unwanted ends
        close(fd1[1]);
        close(fd2[1]);
        close(fd1[0]);

        unsigned char buffer[BUFF_SIZE];
        read(fd2[0], buffer, BUFF_SIZE);
        close(fd2[0]);

        for (int i=0; i<100; i++) {
            printf("%u ", buffer[i]);
        }
        cout << "\n";

        cv::Mat img(IMG_HT, IMG_WD, CV_8UC3, cv::Scalar(0, 0, 0));
        img.data = (buffer);

        pid_t theProcess = getpid();
        string windowName = to_string(theProcess);

        cv::imshow(windowName, img);
        cv::waitKey(0); 
    }

}



int main() {

    int res1 = pipe(fd1);
    int res2 = pipe(fd2);

    if (res1 == -1 or res2 == -1) {
        printf("Pipe failed!\n");
        exit(EXIT_FAILURE);
    }

    signal(SIGABRT, signal_handler);

    child_pid = fork();

    if (child_pid < 0) {
        printf("Fork failed!\n");
        exit(EXIT_FAILURE);
    }

    if (child_pid == 0) {
        // child part
        printf("This is the child, with PID = %d, and parent PID = %d\n", getpid(), getppid());
        char *imgName = "Dbo2.jpg";
        // open image
        cv::Mat img = cv::imread(imgName);
        // cv::resize(img, img, cv::Size(IMG_WD, IMG_HT));

        // close unwanted ends
        close(fd1[1]);
        close(fd1[0]);
        close(fd2[0]);

        write(fd2[1], img.data, sizeof(img.data));
        close(fd2[1]);

        kill(getppid(), SIGABRT);

        while (1) {
            sleep(SLEEP_FOR_SOME_TIME);
        }
    }
    else {
        // parent part
        printf("The parent PID is: %d, with child PID = %d\n", getpid(), child_pid);
        while (1) {
            sleep(SLEEP_FOR_SOME_TIME);
        }
    }


    return 0;
}

The problem I am facing is that the image obtained is corrupted - meaning, it's completely black

This is the original image being read
wormhole.jpg And, this is the black resulting image read by the parent:
result

I wanted to know where I am missing out on the reading/writing(or compressing) part so that I can read the same image on the parent side?

Bms bharadwaj
  • 483
  • 5
  • 18
  • Original image not displayed, can you fix it? – Yunus Temurlenk Jan 30 '20 at 05:26
  • It is not about the image you read, even if you dont add any image the result is same. I searched but couldnt find a solution. – Yunus Temurlenk Jan 30 '20 at 14:03
  • 1
    You write `sizeof(img.data)` bytes. That is the size of a pointer, which is 8 bytes. You need to write `width*height*channels*bits_per_channel` bytes. – Cris Luengo Jan 30 '20 at 14:13
  • @CrisLuengo I made that change in the `write()` function, but my code was stuck in the write function. I checked the image size using this (https://stackoverflow.com/a/26441073/9247555) post, and it gave the total size (in bytes) to be 97200. Is it because of this size that the `write()` function is slowing heavily? – Bms bharadwaj Jan 30 '20 at 15:11
  • Well, you need to read the same number of bytes as you write. AFAIK, if you read less, the `write` call will just sit there waiting for its data to be taken. – Cris Luengo Jan 30 '20 at 15:39
  • I made changes so that `read()` reads the same number of bits that would be written. But in my code, `read()` will be called only after `write()` is done and the child calls a `kill()` on the parent. Does this mean that I will never be able to read the image ? – Bms bharadwaj Jan 30 '20 at 15:49

0 Answers0