cf1244E. Minimizing Difference [二分+单调队列]

博客探讨了一道题目,要求通过在数组元素上进行+1或-1操作,使得最大值与最小值之差尽可能小。解决方案采用二分查找,并结合单调队列来维护可能的最小值和最大值,从而在操作次数限制内找到最优解。

传送门

题意:给一个数组,可以对任意元素进行+1或者-1的操作,操作可以进行k(k<=1e14)次,求整个数组内最大值-最小值最小为多少

题解:二分。先排序,对于某个待检验的答案,只需要假设当前元素为最小值时是否成立以及当前元素为最大值时是否成立即可,其中可以用单调队列维护出当前元素为最小值或最小值时之前的满足条件的元素同时使用一个变量num记录不满足条件元素的个数遍历数组时计算贡献即可

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
#define debug(x) cout<<#x<<" is "<<x<<endl;

const ll inf=1e18;
const int maxn=1e5+5l;

ll n,k,a[maxn],sum[maxn];
int pos[maxn];

bool check(ll x){
   
   
    int head=1;
    int tail=0;
    ll num=0;
    ll xx=0;
    for(int i=1;i<=n;i++
Tasks Image gray-scaling is one of the most common image processing tasks. A simplest way to gray-scale an image is to set each pixel to the mean of the RGB channels. Gray = (R +G + B)/3 Figure 1: Grayscaling example. 1 Serial Version (45 points) PBM, PGM, and PPM files are all image file formats that hold data in regards to pixels of an image. Compared to formats like PNG, JPG, etc, these formats are very simplistic, offering no compression. These are simple formats that store the colours of pixels as bytes which can be read into your program. Thebelowimage.ppmisgivenasanexample, more detail ppm specifications can be found at https://netpbm. sourceforge.net/doc/ppm.html 50 (0 + 50 + 100) / 3 = 50 100 0 image.ppm 50 50 50 P3 3 2 255 255 0 0 0255 0 0 0255 255 255 0 255 255 255 0 0 0 P3- Magic Number (Tells the program this is a PPM file) 3- Width 2- Height 255- Colour Range (0 = Black, This Number = White) Write a C program to read the given im.ppm image (you can find it on LMO along with this document), convert RGBto grayscale, then output the grayscale image to im-gray.ppm. 3 Your program should be compiled and executed by: make ./grayscale You code will be evaluated based on the following criteria: • Correctness (15 points): you should use the exact same algorithm provided in section 1. • Performance (15 points): you should optimise your code for maximum performance and minimum memory usage. • Codingquality(10points): youshouldfollowgoodcodingpracticethat the codeshouldbeeasytounderstand and easy to maintain. • Robustness (5 points): the program should be able to handle any cases
最新发布
10-15
<think>We are going to write a C program to read a PPM image (P3 format), convert it to grayscale by taking the mean of the RGB values for each pixel, and then write the grayscale image to a new PPM file (also in P3 format). Steps: 1. Read the input PPM file (im.ppm) and parse its content. 2. The PPM file format (P3) is a text-based format. The header contains: - Magic number "P3" - Width and height (as integers) - Maximum color value (usually 255) 3. After the header, there are width*height*3 integer values representing the R, G, B components for each pixel. 4. For each pixel, compute the grayscale value as: gray = (R + G + B) / 3 Then set R, G, B to this gray value. Since it's grayscale, all three components are the same. 5. Write the result to a new PPM file (im-gray.ppm) in the same P3 format. However, note that the example output in the problem statement shows the output as a PGM file? But the problem says to output a PPM. But the example output image shows: P3 3 2 255 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 So we are outputting a PPM with the same dimensions and max value, but each pixel has three equal values. But note: the problem says "output the grayscale image to im-gray.ppm", so we are writing a PPM file. Important: We must optimize for performance and memory usage. Approach: - We'll read the file line by line, but note that the pixel data might be in a long list of numbers (could be one number per line or multiple per line). - According to the specification, the header is in plain text, and the pixel data can be separated by whitespace (and there can be comments, but we assume none for simplicity?). - However, the problem says "robustness", so we should handle comments? But the input image is given (im.ppm) and we know it has no comments? But to be robust, we should skip comments (lines starting with '#'). Steps for reading: - Open the file. - Read the magic number (first two bytes, then skip the rest of the line?). - Skip any comments (lines starting with '#'). - Read width and height. - Read max color value. Then, read the pixel data. Each pixel has three values (R, G, B). We'll read until we have width*height*3 integers. We can read the file token by token using fscanf, but note that the numbers can be separated by any whitespace. We'll allocate memory for the image as a 1D array of size width*height*3 (each pixel has 3 unsigned chars, but we read as integers and then we know max is 255). However, the problem says to minimize memory usage. So we can process the image row by row? We don't need to store the entire image if we can process as we read. But note: we have to write the entire image to the output file. We can write the header immediately, then for each pixel we read, we compute the grayscale and write the three same values. So we don't need to store the entire image in memory. We can read in chunks? Actually, we can read one pixel at a time (3 integers) and then write one pixel (three integers) to the output. This will use minimal memory: only 3 integers per pixel (but we are reading one pixel at a time). Steps: 1. Open input file "im.ppm" for reading. 2. Open output file "im-gray.ppm" for writing. 3. Read the header: char magic[3]; fgets(magic, 3, input); // but then we have two characters and then we must read the newline? Actually, we can read the first token with fscanf: fscanf(input, "%s", magic) to read the magic number (which is two characters but stored as string of length 3?). Then check if it's "P3". 4. Then skip comments: any line starting with '#' we skip. Also skip any whitespace. 5. Then read width, height and max_value. 6. Write the header to the output: fprintf(output, "P3\n%d %d\n%d\n", width, height, max_value); 7. Then, for each pixel (width*height times): Read R, G, B as integers. Compute gray = (R + G + B) / 3 (using integer division). Write to the output: "%d %d %d ", gray, gray, gray. But note: we have to format the output so that each line does not exceed 70 characters? The specification says that it's recommended to limit lines to 70 characters. However, the problem does not specify and the example does not break lines. But to be safe, we can output one pixel per line? But that might be too long. Alternatively, we can output the pixels in rows without any specific line breaking. The specification says that the pixels are in order, and any whitespace is allowed. However, for readability (and to match the example) we can output each row of pixels on a separate line? But the example input has multiple pixels per line. Since the problem does not specify, we can output each pixel as a triplet and then put a newline after each row? That would be: for (i=0; i<height; i++) for (j=0; j<width; j++) read R, G, B compute gray write gray, gray, gray and then if j==width-1, put a newline? Otherwise, put a space. But note: the example output had the entire row as one line? The example: "50 50 50 50 50 50 50 50 50\n50 50 50 ..." Actually, the example output in the problem: "50 50 50 50 50 50 50 50 50\n50 50 50 ..." But that is 9 numbers per line? The example width is 3, so 3 pixels per line? And each pixel is 3 numbers -> 9 numbers per line. We can output a newline after each row? That would be: for (i=0; i<height; i++) { for (j=0; j<width; j++) { read R, G, B gray = (R+G+B)/3; fprintf(output, "%d %d %d", gray, gray, gray); if (j < width-1) fprintf(output, " "); // space between pixels } fprintf(output, "\n"); // newline at the end of row } 8. Close the files. However, we must handle comments in the header? The specification says that comments can appear anywhere in the header. So we must skip any line that starts with '#' until we have read the header. Steps for reading the header: char buffer[256]; // Read magic number if (fscanf(fp_in, "%s", buffer) != 1) { error ... } if (strcmp(buffer, "P3") != 0) { error ... } // Skip comments and whitespace until we get width int c; while ((c = fgetc(fp_in)) == '#' || isspace(c)) { if (c == '#') { // skip until newline while ( (c = fgetc(fp_in)) != '\n' && c != EOF) {} } } ungetc(c, fp_in); // put back the non-space and non-comment character Then read width, height, max_value. But note: after the magic number, the next tokens are width (int), height (int), max_value (int). But there might be comments in between. Alternatively, we can read tokens and skip any token that is a comment? Actually, we can read tokens and if the token starts with '#' then skip the entire line. We can do: int width, height, max_value; int count = 0; char line[256]; while (fgets(line, sizeof(line), fp_in)) { // Skip empty lines and comments if (line[0] == '#') continue; if (count == 0) { // we are expecting the width and height if (sscanf(line, "%d %d", &width, &height) == 2) { count = 1; } } else if (count == 1) { if (sscanf(line, "%d", &max_value) == 1) { break; } } } However, this might break if the width and height are on separate lines? The specification says the header tokens can be separated by any whitespace, including newline. We can use a token-based approach: int tokens = 0; char token[256]; while (tokens < 3) { if (fscanf(fp_in, "%s", token) != 1) { // error } if (token[0] == '#') { // skip the rest of the line while ( (c = fgetc(fp_in)) != '\n' && c != EOF) {} } else { if (tokens == 0) { width = atoi(token); tokens++; } else if (tokens == 1) { height = atoi(token); tokens++; } else if (tokens == 2) { max_value = atoi(token); tokens++; } } } This is more robust. Considering performance: we are reading token by token. But the header is very small, so it's acceptable. After reading the header, we have the width, height and max_value. Then we read the pixel data. We cannot rely on fscanf for tokens because there might be comments? But the specification says comments are allowed anywhere? However, the problem says "robustness", so we should skip comments even in the pixel data? But note: the specification says that comments can occur anywhere, but typically they are only in the header. And for performance, we can skip comments in the pixel data as well. We can read the entire pixel data token by token (each token being a string of non-whitespace) and skip any token that is a comment (starts with '#')? But note: the pixel data are numbers. So if we see a token that starts with '#' then we skip the rest of that line? However, the problem does not specify whether the input has comments in the pixel data. Since the example does not, and the assignment image (im.ppm) does not, we can assume none? But for robustness, we'll handle it. Alternatively, note that the specification says: "Each PPM image consists of the following: 1. A "magic number" for identifying the file type. ... 2. Whitespace (blanks, TABs, CRs, LFs). 3. The width, formatted as ASCII characters in decimal. 4. Whitespace. 5. The height, in ASCII decimal. 6. Whitespace. 7. The maximum color value, in ASCII decimal. 8. Whitespace. 9. Width * height * 3 bytes of data, ... " But then it says: "The "magic number" is "P3" for a portable pixmap in the plain (text) version." And it also says: "A comment starts with a '#' and extends to the next carriage return or line feed (or until the end of the file) ... ... but note that it is the application's responsibility to avoid including a carriage return or line feed in the middle of a number in the header lines." So the header might have comments, and the pixel data might also have comments? We'll design the pixel reading: We are going to read tokens (strings separated by whitespace) and skip any token that is a comment (i.e., starts with '#') and skip the rest of the line for that comment. But note: the pixel data are numbers. So we can read token by token and parse them as integers until we have read width*height*3 numbers. Steps: int count = 0; int total_pixels = width * height; int total_numbers = total_pixels * 3; int *pixels = (int*)malloc(total_numbers * sizeof(int)); // but we don't want to store all? we want to process on the fly. Actually, we can avoid storing the entire pixel array. We can process each pixel as we read it. We'll read token by token: int numbers_read = 0; char token[256]; while (numbers_read < total_numbers) { if (fscanf(fp_in, "%s", token) != 1) { // error: premature end of file break; } if (token[0] == '#') { // skip the rest of the line while ( (c = fgetc(fp_in)) != '\n' && c != EOF) {} } else { int value = atoi(token); // Now, we have one number. We are reading in order: R, G, B for each pixel. // We are at position: numbers_read % 3 -> 0: R, 1: G, 2: B // But we want to compute the gray only when we have a full pixel? So we have to store the three components until we have them? Actually, we can do: We have three variables: r, g, b. But we don't know which one we are reading? We are reading sequentially: the first number is R of the first pixel, then G of the first pixel, then B. So: int index_in_pixel = numbers_read % 3; if (index_in_pixel == 0) { r = value; } else if (index_in_pixel == 1) { g = value; } else if (index_in_pixel == 2) { b = value; // now we have a full pixel: compute gray int gray = (r + g + b) / 3; // write the pixel to the output: three times gray fprintf(output, "%d %d %d", gray, gray, gray); // Now, if we are at the end of a row? But we are writing per pixel? We can format after writing the pixel? } numbers_read++; } } But how do we format the output? We want to break lines per row. We can keep a counter for the current pixel index (from 0 to total_pixels-1). Then: int pixel_index = numbers_read / 3; // because each pixel uses 3 numbers Then, if we are at the last number of the pixel (index_in_pixel==2) then we have written a pixel. How to break lines? We can break after each row. The row index is: row = pixel_index / width. The next row? We break at the end of the row: if (pixel_index % width == width-1) then we output a newline, else we output a space. Actually, in the inner loop we are writing each pixel as three numbers. We can write the three numbers without spaces in between? But we must separate them by space. We are writing: "%d %d %d" -> that already writes three numbers with a space between them. Then, after that, if we are at the last pixel in a row, we write a newline? But note: the next pixel will be in the next row? Actually, we can do: if ( (pixel_index % width) == (width-1) ) { fprintf(output, "\n"); } else { fprintf(output, " "); // space between pixels (after the triplet) } But note: the example shows the pixels in one row without a newline until the end of the row. However, we are writing the entire triplet for the pixel without breaking. Then we put a space between the triplets? Actually, we are writing: first pixel: "50 50 50" then if we are not at the end of the row: we write a space -> "50 50 50 " then next pixel: "50 50 50" -> becomes "50 50 50 50 50 50" Then at the end of the row, we break. But note: the last pixel in a row should not be followed by a space? But the problem does not require a specific format. The specification allows any whitespace. Alternatively, we can write: for the first pixel in a row: write the triplet without a leading space. for the next: write a space and then the triplet. But it's easier to write the triplet and then after the triplet, if we are not at the end of the row, write a space? Actually, we are writing after the triplet: if (index_in_pixel == 2) { // just wrote a pixel if ( (pixel_index % width) == (width-1) ) { fprintf(output, "\n"); } else { fprintf(output, " "); } } But note: the next pixel will be written with a triplet without any leading space? And we are putting a space between the triplets? That would be: triplet1 + " " + triplet2 + ... and at the end of the row, tripletN + "\n" That produces: triplet1 triplet2 ... tripletN\n That is acceptable. However, there is a performance concern: we are doing a lot of fscanf for tokens and then atoi. And then we are writing with fprintf for each pixel? That might be slow. We can read the entire file in one go? But the file might be large. We want minimal memory. Alternatively, we can read the rest of the file as tokens with fscanf until we have the required numbers. But note: we are reading the file token by token and writing as we go. This uses very little memory. Let's code accordingly. Steps summary: FILE *input = fopen("im.ppm", "r"); FILE *output = fopen("im-gray.ppm", "w"); // Read magic number char magic[3]; if (fscanf(input, "%2s", magic) != 1) { ... } if (strcmp(magic, "P3") != 0) { ... } // Read header tokens (width, height, max_value) skipping comments int width, height, max_value; int tokens = 0; char token[256]; while (tokens < 3) { if (fscanf(input, "%255s", token) != 1) { // error } if (token[0] == '#') { // skip the rest of the line int c; while ( (c = fgetc(input)) != '\n' && c != EOF) {} } else { if (tokens == 0) { width = atoi(token); tokens++; } else if (tokens == 1) { height = atoi(token); tokens++; } else if (tokens == 2) { max_value = atoi(token); tokens++; } } } // Write header to output fprintf(output, "P3\n%d %d\n%d\n", width, height, max_value); int total_pixels = width * height; int total_numbers = total_pixels * 3; int numbers_read = 0; int r, g, b; int pixel_index = 0; while (numbers_read < total_numbers) { if (fscanf(input, "%255s", token) != 1) { // error: break break; } if (token[0] == '#') { // skip the rest of the line int c; while ( (c = fgetc(input)) != '\n' && c != EOF) {} } else { int value = atoi(token); switch (numbers_read % 3) { case 0: r = value; break; case 1: g = value; break; case 2: b = value; int gray = (r + g + b) / 3; // Write the pixel triplet fprintf(output, "%d %d %d", gray, gray, gray); // Now, check if we are at the end of a row? pixel_index = numbers_read / 3; // because numbers_read will be the index of the next number? // At this point, we have written one pixel? Actually, numbers_read at this point is the index of the blue value? // Then numbers_read is the index in [0, total_numbers-1]. The pixel index is numbers_read/3 (integer division) and then modulo width? // But note: we haven't incremented numbers_read for blue yet? // Actually, we are about to increment numbers_read after the switch. // But we are writing the pixel only when we have blue. Then we can compute the current pixel index as: // current_pixel_index = numbers_read / 3; // because we have read numbers_read+1 numbers? Actually, we are at the blue value, which is the third of the pixel. // Actually, at this point, numbers_read is the count of numbers we have read so far (excluding this one). // So after we process this blue, we will increment numbers_read -> then the pixel index becomes (numbers_read+1)/3? // Instead, let's compute the current pixel index as: // pixel_index = (numbers_read) / 3; -> because we have read numbers_read numbers (which doesn't include the blue we are processing). // Then after we process blue, we will have read numbers_read+1 numbers, and the pixel index for the blue pixel is (numbers_read+1-1)/3? // Actually, we haven't processed this token yet as increasing the count? // Let's restructure: we are about to set the blue value. Then we compute the gray and write the pixel. Then we increment numbers_read. // So the current pixel index is: numbers_read / 3 (integer division) because we have read numbers_read numbers, which is exactly (numbers_read)/3 full pixels? // But numbers_read mod 3 tells us the component. When numbers_read mod 3 is 0,1,2 we are in the R, G, B of the next pixel. // Actually, we have: // numbers_read = k, then we are reading the (k mod 3) component of the pixel at index k/3 (integer division). // So when k mod 3 is 2, we are reading the blue of the pixel at index (k)/3. // Therefore, the pixel index = k / 3. // Then the row index = (k/3) / width, and the column index = (k/3) % width. // Now, we are at k = numbers_read (before incrementing for blue) and we are processing blue -> so pixel index = numbers_read / 3. int current_pixel_index = numbers_read / 3; int col = current_pixel_index % width; // After writing the triplet, if we are at the last column, write a newline, else a space between the triplets (for the next pixel triplet) if (col == width - 1) { fprintf(output, "\n"); } else { fprintf(output, " "); } break; } numbers_read++; } } But note: in the case of blue, we break the switch and then we increment numbers_read. So the blue is accounted for. However, what about the R and G components? They don't write anything? Correct. Only the blue triggers the write. Also, note that the first two components (R and G) we just store. Then when we get the blue, we write the entire triplet. But what about the last pixel? We must ensure that we write the triplet only when we have blue. We assume that the file has exactly total_numbers numbers? If there are more, we break at total_numbers. Also, we must close the files. Let's test with the example: Example input: P3 3 2 255 255 0 0 0 255 0 0 0 255 255 255 0 255 255 255 0 0 0 We read header: width=3, height=2, max=255. Then we read 9 numbers? Actually, 3*2*3 = 18 numbers? But the example has 9 numbers per row? Actually, the example has 6 pixels? 3 width and 2 height -> 6 pixels, each with 3 components -> 18 numbers. How does the example input represent the data? First row of pixels: pixel1: 255 0 0 -> R=255, G=0, B=0 -> gray = (255+0+0)/3 = 85 pixel2: 0 255 0 -> 85 pixel3: 0 0 255 -> 85 Second row: pixel4: 255 255 0 -> (255+255+0)/3 = 170 pixel5: 255 255 255 -> 255 pixel6: 0 0 0 -> 0 But the example output in the problem statement says: 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 Why? Because the example input in the problem had: P3 3 2 255 255 0 0 0 255 0 0 0 255 255 255 0 255 255 255 0 0 0 But wait, that input has: First row: 255 0 0 -> (255+0+0)/3 = 85 0 255 0 -> (0+255+0)/3 = 85 0 0 255 -> (0+0+255)/3 = 85 Then second row: 255 255 0 -> (255+255+0)/3 = 170 255 255 255 -> 255 0 0 0 -> 0 So the gray values would be: 85, 85, 85, 170, 255, 0. But the example output was 50? That doesn't match. Actually, the example in the problem had: Input pixel: R: 0, G:50, B:100 -> (0+50+100)/3 = 50. And the input image had: P3 3 2 255 255 0 0 0 255 0 0 0 255 255 255 0 255 255 255 0 0 0 This doesn't match the 0,50,100 example. The example input file (im.ppm) is given on LMO, so we assume it's the one with the 0,50,100? But the example input header says 3 2 and then the numbers. However, the problem says: "thebelowimage.ppmisgivenasanexample", and then shows: P3 3 2 255 255 0 0 0 255 0 0 0 255 255 255 0 255 255 255 0 0 0 So we use that example. And the example output for the first pixel (255 0 0) would be (255+0+0)/3 = 85. Then the first pixel triplet: 85 85 85. The example output in the problem statement shows 50? That must be from a different example? The figure says: Input: 0,50,100 -> gray= (0+50+100)/3=50. So the example output file should have 50 for each component? But the input file we are given (im.ppm) might have the example values? We are told: "convert the given im.ppm image ... then output ...". So we must use the file "im.ppm" which is provided. We don't know its content? But we know it's a PPM file. Therefore, we assume our algorithm is correct. But note: the example output in the problem statement for the entire image is: 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 That matches if the input image had every triplet as (0,50,100). So we'll code accordingly. Finally, we must make sure to close the files. Performance: We are reading token by token with fscanf and then processing. This might be slow for very large images? But we are doing minimal memory usage. We can try to read whole lines and parse numbers? But the problem doesn't require a specific performance, just to optimize. Alternatively, we can use fgets and then parse numbers from the line? But we have to handle comments and arbitrary whitespace. We'll stick with the token approach for simplicity and robustness. Coding quality: We'll write in a modular way? But it's a small program. Let's write the code accordingly. We'll include error checking. </think>To solve this problem, we need to read a PPM image file in P3 format, convert each pixel to grayscale by computing the mean of its RGB values, and then write the resulting grayscale image to a new PPM file. The solution must be efficient in terms of both memory usage and performance while maintaining robustness to handle various edge cases such as comments in the input file. ### Approach 1. **Reading the PPM File**: The PPM file starts with a header containing the magic number "P3", followed by the image width, height, and the maximum color value. These values are read first, skipping any comments (lines starting with '#'). 2. **Processing Pixel Data**: After the header, the pixel data consists of RGB triplets (each with three integers). For each triplet, the grayscale value is computed as the average of the RGB values. This grayscale value is then used for all three components (R, G, B) in the output pixel. 3. **Writing the Output File**: The output file is written in the same P3 format. The header information (magic number, width, height, max color value) is written first, followed by the grayscale pixel data formatted to ensure each row of pixels is on a new line for readability. 4. **Efficiency**: The solution processes the image pixel by pixel, minimizing memory usage by not storing the entire image in memory. Each pixel is read, converted to grayscale, and written immediately to the output file. ### Solution Code ```c #include <stdio.h> #include <stdlib.h> #include <string.h> int main() { FILE *input = fopen("im.ppm", "r"); if (input == NULL) { perror("Error opening input file"); return 1; } FILE *output = fopen("im-gray.ppm", "w"); if (output == NULL) { perror("Error opening output file"); fclose(input); return 1; } char magic[3]; if (fscanf(input, "%2s", magic) != 1) { fprintf(stderr, "Error reading magic number\n"); fclose(input); fclose(output); return 1; } if (strcmp(magic, "P3") != 0) { fprintf(stderr, "Invalid PPM file: must be P3 format\n"); fclose(input); fclose(output); return 1; } int width, height, max_value; int tokens = 0; char token[256]; while (tokens < 3 && fscanf(input, "%255s", token) == 1) { if (token[0] == '#') { while (fgetc(input) != '\n' && !feof(input)); } else { if (tokens == 0) { width = atoi(token); tokens++; } else if (tokens == 1) { height = atoi(token); tokens++; } else if (tokens == 2) { max_value = atoi(token); tokens++; } } } if (tokens != 3) { fprintf(stderr, "Error reading header\n"); fclose(input); fclose(output); return 1; } fprintf(output, "P3\n%d %d\n%d\n", width, height, max_value); int total_numbers = width * height * 3; int numbers_read = 0; int r, g, b; while (numbers_read < total_numbers) { if (fscanf(input, "%255s", token) != 1) { break; } if (token[0] == '#') { while (fgetc(input) != '\n' && !feof(input)); } else { int value = atoi(token); switch (numbers_read % 3) { case 0: r = value; break; case 1: g = value; break; case 2: b = value; int gray = (r + g + b) / 3; fprintf(output, "%d %d %d", gray, gray, gray); int current_pixel_index = numbers_read / 3; if ((current_pixel_index % width) == (width - 1)) { fprintf(output, "\n"); } else { fprintf(output, " "); } break; } numbers_read++; } } fclose(input); fclose(output); return 0; } ``` ### Explanation 1. **File Handling**: The input file "im.ppm" is opened for reading, and the output file "im-gray.ppm" is opened for writing. Error checks ensure files are accessible. 2. **Header Parsing**: The magic number "P3" is read first. Subsequent tokens (width, height, max color value) are read while skipping any comments (lines starting with '#'). 3. **Pixel Processing**: Each pixel's RGB values are read sequentially. The grayscale value is computed as the average of these values. The result is written to the output file as three identical values (R=G=B=gray). 4. **Output Formatting**: After processing each pixel, a newline is written at the end of each row to maintain readable formatting. Spaces separate pixel triplets within the same row. 5. **Resource Management**: File handles are closed properly to prevent resource leaks, and error handling ensures graceful termination in case of issues. This approach efficiently processes the image with minimal memory overhead, ensuring correctness and robustness while adhering to PPM format specifications. ###
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值