【问题标题】:The program for converting ppm to ASCII art does not work properly将 ppm 转换为 ASCII 艺术的程序无法正常工作
【发布时间】:2015-08-04 21:28:21
【问题描述】:

我正在编写一个程序,用于将文件从 PPM 格式转换为 ASCII 艺术。通过计算红色绿色和蓝色值((red + green +blue)/3) 的平均值,将输入图像的每个像素转换为灰度。

基础版的升级是我在n*n大小的窗口中计算RGB的平均值,并将其转换为可以减小图像大小的字符。因此,如果给定数字n3,则窗口的大小为3*3,这意味着您将所有九个红色、绿色和蓝色值相加,然后将其除以n*n 的3 倍(在此为3*3案子)。当程序计算第一个窗口的灰度时,它会移动到另一个窗口,依此类推,直到结束。当有宽度结束时,它向下跳n个像素并读取下一行,等等。

当灰度被计算后,它被转换为一个字符,这个字符被写入输出文件以形成一个 ASCII 艺术图像。

我的程序确实可以编译,但是当我测试它时,我得到了错误的图像。一个非常简单的图像转换为空白文件,另一个看起来像棋盘,但它打印了一个非常大的列图像。通过扫描 1*1 像素块,这两个图像都被转换为 ASCII 艺术。第三张图很大,应该按3*3块转换,但是我得到的输出文件太大打不开。在一个简单的文本编辑器中。

谁能告诉我哪里出错了?

代码如下:

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

// convert the calculated greyscale to a character based on brightness
char method_of_conversion(int greyscale){
    if(greyscale >= 230){
        return ' ';
    }else if(greyscale >= 200 && greyscale < 230){
        return '.';
    }else if(greyscale >= 180 && greyscale < 200){
        return '\'';
    }else if(greyscale >= 160 && greyscale < 180){
        return ':';
    }else if(greyscale >= 130 && greyscale < 160){
        return 'o';
    }else if(greyscale >= 100 && greyscale < 130){
        return '&';
    }else if(greyscale >= 70 && greyscale < 100){
        return '8';
    }else if(greyscale >= 50 && greyscale < 70){
        return '#';
    }else if(greyscale < 50){
        return '@';
    }
}

int main(){
    char ppmFile[100];
    char outputFile[100];

    int n;

    scanf("%s", &ppmFile); //read the name of input file
    scanf("%s", &outputFile); //read the name of output file 
    // the size of a window of pixels you have to convert to ascii art character
    scanf("%d", &n); 

    FILE *input = fopen(ppmFile, "rb");
    FILE *output = fopen(outputFile, "w"); 

    int width, height; // max pixel is always 255
    // read the header from the ppm file
    fscanf(input, "P6\n%d %d\n255\n", &width, &height);

    // allocate place for array[width][length][3]
    int a, b;
    int ***array;
    array = malloc(width*sizeof(int **));
    for(a = 0; a < width; a++){
        array[a] = malloc(height*sizeof(int *));
        for(b = 0; b < height; b++){
            array[a][b] = malloc(3*sizeof(int));
        }
    }

    int x, y;
    for (x = 0; x < width; x++){ 
        for(y=0; y < height; y++){
            array[x][y][0] = fgetc(input); //red
            array[x][y][1] = fgetc(input); //green
            array[x][y][2] = fgetc(input); //blue

            int greyscale;
            int i, j;
            // convert blocks of pixels to a character and write it into output file
            for(i = 0; i < width; i+=n){
                for(j=0; j < height; j+=n){
                    // greyscale = (red + green +blue)/3;
                    greyscale = (array[i][j][0] + array[i][j][1] +array[i][j][2])/(3*n*n);
                    char c = method_of_conversion(greyscale);
                    fprintf(output,"%c",c); // write the ASCII art directly in the output file
                }
            }   
        }fprintf(output,"\n"); // dont forget to go into a new line
    }

    free(array);
    fclose(input);
    fclose(output);

    return 0;
}

【问题讨论】:

  • 您可能希望先读取整个文件,然后扫描它并写入您的输出。现在,您正在为每个像素写入大量输出,并对数组中尚未读取的部分进行索引。
  • 考虑在array 中使用 RGB 结构而不是第三维。阅读起来更干净,并且您不需要在此处使用数组,因为您没有在其上循环。

标签: c rgb grayscale ascii-art


【解决方案1】:

这些行:

       for(i = 0; i < width; i+=n){
            for(j=0; j < height; j+=n){

可能不正确。如果n = 3,您将读取图像 X 和 Y 上的每 3 个像素,而不是本地块。这会给你一个分散的数据集而不是一个块。

或者...您在此代码中放置第二组 for 循环,从 0 计数到 n-1 并读取所有要平均的像素。这实际上可能是这里缺少的部分。

       for(i = 0; i < width; i+=n){
            for(j=0; j < height; j+=n){

               for(blockx = 0; blockx  < n; blockx++){
                    for(blocky=0; blocky < n; blocky++){
                        // Use current averaging code to gather all numbers, 
                        // being careful of overflow.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-10
    • 2011-11-14
    • 1970-01-01
    • 2010-09-28
    • 2021-11-28
    相关资源
    最近更新 更多