c++,pthread合并ppm图片

程序作用:
1. 创建4个线程,读取4张PPM图片(都是350*350),合并生成一张PPM图片(700*700)。
2. 改写成 创建进程(fork),读取4张PPM图片(都是350*350),合并生成一张PPM图片(700*700)。
我写的代码如下,不知为何只能显示一张图片:


#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <sys/wait.h>
#include <pthread.h>

using namespace std;

pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;

struct pixel
{
    char r;
    char g;
    char b;
};
pixel pp[350*350][4];

ifstream fin;
ofstream fout;

void *CreateImage(void *num)
{
    long i = (long)num;
    cout << i << endl;
    int position=18;
    char filename[20];
    char line1[100];
    char line2[100];
    char line3[100];
    char line4[100];
    int count = 0;

    cout << "file name: ";
    cin >> filename;

    fin.open(filename, ios::out | ios::binary);
    if (!fin.good())
    {
        cout << "bad file!\n";
    }

    fin >> line1 >> line2 >> line3 >> line4;
    fin.ignore();
    fin.ignore();

    for (int m = 0; m < 350 * 350; m++)
    {
        fin.read((char*)&pp[m][i], sizeof(pixel));
    }
    fin.close();

    for (int j = 0; j < 350; j++)
    {
    /*
    for(row =0; row < x; row++) // image 1 and image 2
    {
        fout.seekp(18*sizeof(char),ios_base::beg); //ignore header
        fout.seekp((row*(y*2*3))*sizeof(char),ios_base::cur);//to go current row
        for(col=0; col < y*3; col++)
        {
            fin1.read((char *)&tmp,sizeof(char));
            fout.write((const char *)&tmp,sizeof(char));
        }
        for(col=0; col < y*3; col++)
        {
            fin2.read((char *)&tmp,sizeof(char));
            fout.write((const char *)&tmp,sizeof(char));
        }
    }
    */
        if (i == 0)
            fout.seekp(position + (sizeof(pixel) * 350 * j * 2), ios::beg);

        if (i == 1)
            fout.seekp(position + 350 * sizeof(pixel) + (sizeof(pixel) * 350 * j * 2), ios::beg);
            //fout.seekp(position + , ios::beg);

        if (i==2)
            fout.seekp(position+(sizeof(pixel)*350*j*2)+700*350*sizeof(pixel),ios::beg);
        if (i==3)
            fout.seekp(position+350*sizeof(pixel)+(sizeof(pixel)*350*j*2)+700*350*sizeof(pixel),ios::beg);

        for (int n = 0; n < 350; n++)
            fout.write((char*) &pp[(n + count)][i], sizeof(pixel));

        count+=350;
    }

    fout.close();
}

int main()
{
    pthread_t pt[4];
    fout.open("newImage.ppm");
    if (!fout.good())
    {
        cout << "bad output file!\n";
        exit(0);
    }

    fout << "P6" << endl;
    fout << "#." << endl;
    fout << "700 700" << endl;
    fout << "255" << endl;   // these 4 lines are the head information of a ppm figure.

    for (int i = 0; i < 4; i++)
    {
        pthread_mutex_lock(&counter_mutex);
        pthread_create(&pt[i], NULL, CreateImage, (void*)i);
        pthread_mutex_unlock(&counter_mutex);
        //pthread_join(pt[i], NULL);

    }

    pthread_exit( NULL );  
    /*
    for(int j = 0; j < 4; j++)
    {
        pthread_join(pt[j], NULL);
    }
    */
    return 0;
}

该回答引用ChatGPT-3.5,仅供参考,不保证完全正确

您的代码中存在一些问题,导致只能显示一张图片。以下是我对代码进行了一些修正的版本:

#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <sys/wait.h>
#include <pthread.h>

using namespace std;

pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;

struct pixel
{
    char r;
    char g;
    char b;
};
pixel pp[350 * 350][4];

ifstream fin;
ofstream fout;

void *CreateImage(void *num)
{
    long i = (long)num;
    cout << i << endl;
    int position = 18;
    char filename[20];

    cout << "file name: ";
    cin >> filename;

    fin.open(filename, ios::binary);
    if (!fin.good())
    {
        cout << "bad file!\n";
    }

    char line[100];
    fin.getline(line, sizeof(line)); // read and ignore the first line
    fin.getline(line, sizeof(line)); // read and ignore the second line
    fin.getline(line, sizeof(line)); // read and ignore the third line

    for (int m = 0; m < 350 * 350; m++)
    {
        fin.read((char *)&pp[m][i], sizeof(pixel));
    }
    fin.close();

    for (int j = 0; j < 350; j++)
    {
        if (i == 0)
            fout.seekp(position + (sizeof(pixel) * 350 * j * 2), ios::beg);

        if (i == 1)
            fout.seekp(position + 350 * sizeof(pixel) + (sizeof(pixel) * 350 * j * 2), ios::beg);

        if (i == 2)
            fout.seekp(position + (sizeof(pixel) * 350 * j * 2) + 700 * 350 * sizeof(pixel), ios::beg);

        if (i == 3)
            fout.seekp(position + 350 * sizeof(pixel) + (sizeof(pixel) * 350 * j * 2) + 700 * 350 * sizeof(pixel), ios::beg);

        for (int n = 0; n < 350; n++)
            fout.write((char *)&pp[(n + j * 350)][i], sizeof(pixel));
    }
}

int main()
{
    pthread_t pt[4];
    fout.open("newImage.ppm", ios::binary);
    if (!fout.good())
    {
        cout << "bad output file!\n";
        exit(0);
    }

    fout << "P6" << endl;
    fout << "#." << endl;
    fout << "700 700" << endl;
    fout << "255" << endl; // these 4 lines are the head information of a ppm figure.

    for (int i = 0; i < 4; i++)
    {
        pthread_mutex_lock(&counter_mutex);
        pthread_create(&pt[i], NULL, CreateImage, (void *)i);
        pthread_mutex_unlock(&counter_mutex);
    }

    for (int j = 0; j < 4; j++)
    {
        pthread_join(pt[j], NULL);
    }

    fout.close();

    return 0;
}

请注意以下几点:

  1. 修复了文件读取的错误。在ifstream打开文件时,使用了错误的文件打开模式ios::out,应改为ios::binary
  2. 修改了对文件头信息的读取方式。在CreateImage函数中,

读取文件头信息的代码有问题,现在使用getline函数来读取并忽略前三行。
3. 修正了像素写入的错误。在循环写入像素数据时,应该根据当前行的索引j来计算在pp数组中的偏移量。
4. 将文件的打开模式改为ios::binary,以二进制模式打开文件进行读写。

这样修改后,程序应该能够正确地合并四张PPM图片并生成新的PPM图片。