图像恢复程序有问题
image recovery program has an issue
基本上我为我的计算机课程(shoutout CS50)编写了这个程序,它从 .raw 文件中恢复图像。我已经设法让程序恢复了该文件中 50 个文件中的 48 个。
我现在遇到的问题是程序无法同时恢复位于 .raw 上的第一个和第二个文件。它要么读取和写入第一个文件(白雪皑皑的背景中的这个女孩),要么读取和写入 .raw 上的第二个文件(书后的人)。
出于某种原因,如果我将 fopen 从写入更改为追加,我可以在女孩和男孩的照片之间切换,但我似乎无法同时打开两者。
https://github.com/CoreData/cs50/blob/master/pset4/jpg/card.raw
这是 link 到 card.raw,不幸的是,它与我使用的不同,但即使使用这个,你也会得到 image1.jpg 的两个不同图像,具体取决于你是否使用 "a" 或 "w".
有什么想法吗???
如果你们需要任何其他信息,请告诉我
#include <stdio.h>
#include <stdlib.h>
#include "bmp2.h"
int main(void)
{
/*OPEN CARD FILE*/
char* infile = "card.raw";;
FILE* card = fopen(infile, "r");
if (card == NULL)
{
printf("Could not open %s.\n", "card.raw");
return 2;
}
int f = 0, c = 0, l = 0, x = 128, imageno = 1;
// c signals that a jpg is being written
// l size control, 0 means 0 jpgs
FILE* images;
char* title = (char*)malloc(15);
/*repeat until end of card*/
do
{
//read one block into buffer
INTROJPG *buffer = (INTROJPG*)malloc(sizeof(INTROJPG)*x);
for (int i = 0; i < 128; i++)
{
fread(&buffer[i], sizeof(INTROJPG), 1, card);
}
if (buffer[0].first == 0xff && buffer[0].second == 0xd8 && buffer[0].third == 0xff)
{
sprintf(title, "image%d.jpg", imageno); //change jpg title
if (f == 1) //close previous jpg
{
fclose(images);
imageno++;
}
images = fopen(title, "w");
f = 1; //very first jpg has been opened
c = 1; //jpg open
l++; //jpg count + 1
}
//jpg already open?
if (c == 1)
{
for (int i = 0; i < 128; i++)
{
fwrite(&buffer[i], sizeof(INTROJPG), 1, images);
}
}
free(buffer);
}
while (l < 50);
free(title);
return 5;
//close any remaining files
}
and this is my bmp2.h file
#include <stdint.h>
/**
* Common Data Types
*
* The data types in this section are essentially aliases for C/C++
* primitive data types.
*
* Adapted from http://msdn.microsoft.com/en-us/library/cc230309.aspx.
* See http://en.wikipedia.org/wiki/Stdint.h for more on stdint.h.
*/
typedef uint8_t BYTE;
typedef uint32_t DWORD;
typedef int32_t LONG;
typedef uint16_t WORD;
/**
* BITMAPFILEHEADER
*
* The BITMAPFILEHEADER structure contains information about the type, size,
* and layout of a file that contains a DIB [device-independent bitmap].
*
* Adapted from http://msdn.microsoft.com/en-us/library/dd183374(VS.85).aspx.
*/
typedef struct
{
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} __attribute__((__packed__))
BITMAPFILEHEADER;
/**
* BITMAPINFOHEADER
*
* The BITMAPINFOHEADER structure contains information about the
* dimensions and color format of a DIB [device-independent bitmap].
*
* Adapted from http://msdn.microsoft.com/en-us/library/dd183376(VS.85).aspx.
*/
typedef struct
{
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} __attribute__((__packed__))
BITMAPINFOHEADER;
/**
* RGBTRIPLE
*
* This structure describes a color consisting of relative intensities of
* red, green, and blue.
*
* Adapted from http://msdn.microsoft.com/en-us/library/aa922590.aspx.
*/
typedef struct
{
BYTE rgbtBlue;
BYTE rgbtGreen;
BYTE rgbtRed;
} __attribute__((__packed__))
RGBTRIPLE;
typedef struct
{
BYTE first;
BYTE second;
BYTE third;
BYTE fourth;
} __attribute__((__packed__))
INTROJPG;
typedef struct
{
BYTE image;
}
BYTEIMAGE;
首先,我会尝试改进您的代码中的一些内容。我也做了这个pset,能帮助到别人真是太好了。
INTROJPG *buffer = (INTROJPG*)malloc(sizeof(INTROJPG)*x);
在这部分,您知道了INTROJPG 和x 的大小都是常量,因此不需要在每次迭代时不断地分配和释放内存,这比简单地创建一个普通数组要花费更多的时间。另外,为什么缓冲区是指向 INTROJPG 的指针?如果只是在每次迭代时测试 header,我认为这不值得,您可以简单地访问普通 BYTE 数组的前 4 个字节。
我会创建一个 512 BYTE 的静态数组(库中的结构),因为这是您不断分配和释放的大小,而且您使用的是 BYTE,而不是 INTROJPG。
其次,在这个部分和另一个类似的部分:
for (int i = 0; i < 128; i++)
{
fread(&buffer[i], sizeof(INTROJPG), 1, card);
}
绝对不需要这个循环,甚至不需要使用 INTROJPG。你总是读写 512 字节,你可以使用:
fread(buffer, 4, 128, card);
// or even better
fread(buffer, 512, 1, card);
关于你的问题,我已经多次测试你的代码(没有任何修改),没有发现 image1.jpg 和 image2.jpg 有任何问题。是的,我将 "w" 模式更改为 "a" 和 vice-versa。
然而,关于最后一张图片,你的代码是错误的,你的最后一张图片是image49.jpg,而它应该是image50.jpg,而你的image49.jpg甚至打不开,那是因为循环在 image49.jpg 的其余部分被存储之前就完成了,也就是说,你只存储了 image49.jpg.
的前 512 个字节
为了解决这个问题,我更改了 do-while 循环的条件以继续执行直到卡片文件结束,IIRC 问题保证最后一个块是最后一个图像或类似内容的一部分如果没有,则由您来解决这个小问题!
#include <stdio.h>
#include <stdlib.h>
#include "bmp2.h"
int main(void)
{
/*OPEN CARD FILE*/
char* infile = "card.raw";;
FILE* card = fopen(infile, "r");
if (card == NULL)
{
printf("Could not open %s.\n", "card.raw");
return 2;
}
int f = 0, c = 0, imageno = 1;
// c signals that a jpg is being written
// l size control, 0 means 0 jpgs
FILE* images;
char title[25];
BYTE buffer[512];
/*repeat until end of card*/
do
{
fread(buffer, 512, 1, card);
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff)
{
sprintf(title, "image%d.jpg", imageno); //change jpg title
if (f == 1) //close previous jpg
{
fclose(images);
imageno++;
}
images = fopen(title, "w");
f = 1; //very first jpg has been opened
c = 1; //jpg open
}
//jpg already open?
if (c == 1) fwrite(buffer, 512, 1, images);
}
while (!feof(card));
return 5;
//close any remaining files
}
最后一件事,你为什么在程序结束时返回 5?只是好奇。
基本上我为我的计算机课程(shoutout CS50)编写了这个程序,它从 .raw 文件中恢复图像。我已经设法让程序恢复了该文件中 50 个文件中的 48 个。
我现在遇到的问题是程序无法同时恢复位于 .raw 上的第一个和第二个文件。它要么读取和写入第一个文件(白雪皑皑的背景中的这个女孩),要么读取和写入 .raw 上的第二个文件(书后的人)。
出于某种原因,如果我将 fopen 从写入更改为追加,我可以在女孩和男孩的照片之间切换,但我似乎无法同时打开两者。
https://github.com/CoreData/cs50/blob/master/pset4/jpg/card.raw 这是 link 到 card.raw,不幸的是,它与我使用的不同,但即使使用这个,你也会得到 image1.jpg 的两个不同图像,具体取决于你是否使用 "a" 或 "w".
有什么想法吗???
如果你们需要任何其他信息,请告诉我
#include <stdio.h>
#include <stdlib.h>
#include "bmp2.h"
int main(void)
{
/*OPEN CARD FILE*/
char* infile = "card.raw";;
FILE* card = fopen(infile, "r");
if (card == NULL)
{
printf("Could not open %s.\n", "card.raw");
return 2;
}
int f = 0, c = 0, l = 0, x = 128, imageno = 1;
// c signals that a jpg is being written
// l size control, 0 means 0 jpgs
FILE* images;
char* title = (char*)malloc(15);
/*repeat until end of card*/
do
{
//read one block into buffer
INTROJPG *buffer = (INTROJPG*)malloc(sizeof(INTROJPG)*x);
for (int i = 0; i < 128; i++)
{
fread(&buffer[i], sizeof(INTROJPG), 1, card);
}
if (buffer[0].first == 0xff && buffer[0].second == 0xd8 && buffer[0].third == 0xff)
{
sprintf(title, "image%d.jpg", imageno); //change jpg title
if (f == 1) //close previous jpg
{
fclose(images);
imageno++;
}
images = fopen(title, "w");
f = 1; //very first jpg has been opened
c = 1; //jpg open
l++; //jpg count + 1
}
//jpg already open?
if (c == 1)
{
for (int i = 0; i < 128; i++)
{
fwrite(&buffer[i], sizeof(INTROJPG), 1, images);
}
}
free(buffer);
}
while (l < 50);
free(title);
return 5;
//close any remaining files
}
and this is my bmp2.h file
#include <stdint.h>
/**
* Common Data Types
*
* The data types in this section are essentially aliases for C/C++
* primitive data types.
*
* Adapted from http://msdn.microsoft.com/en-us/library/cc230309.aspx.
* See http://en.wikipedia.org/wiki/Stdint.h for more on stdint.h.
*/
typedef uint8_t BYTE;
typedef uint32_t DWORD;
typedef int32_t LONG;
typedef uint16_t WORD;
/**
* BITMAPFILEHEADER
*
* The BITMAPFILEHEADER structure contains information about the type, size,
* and layout of a file that contains a DIB [device-independent bitmap].
*
* Adapted from http://msdn.microsoft.com/en-us/library/dd183374(VS.85).aspx.
*/
typedef struct
{
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} __attribute__((__packed__))
BITMAPFILEHEADER;
/**
* BITMAPINFOHEADER
*
* The BITMAPINFOHEADER structure contains information about the
* dimensions and color format of a DIB [device-independent bitmap].
*
* Adapted from http://msdn.microsoft.com/en-us/library/dd183376(VS.85).aspx.
*/
typedef struct
{
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} __attribute__((__packed__))
BITMAPINFOHEADER;
/**
* RGBTRIPLE
*
* This structure describes a color consisting of relative intensities of
* red, green, and blue.
*
* Adapted from http://msdn.microsoft.com/en-us/library/aa922590.aspx.
*/
typedef struct
{
BYTE rgbtBlue;
BYTE rgbtGreen;
BYTE rgbtRed;
} __attribute__((__packed__))
RGBTRIPLE;
typedef struct
{
BYTE first;
BYTE second;
BYTE third;
BYTE fourth;
} __attribute__((__packed__))
INTROJPG;
typedef struct
{
BYTE image;
}
BYTEIMAGE;
首先,我会尝试改进您的代码中的一些内容。我也做了这个pset,能帮助到别人真是太好了。
INTROJPG *buffer = (INTROJPG*)malloc(sizeof(INTROJPG)*x);
在这部分,您知道了INTROJPG 和x 的大小都是常量,因此不需要在每次迭代时不断地分配和释放内存,这比简单地创建一个普通数组要花费更多的时间。另外,为什么缓冲区是指向 INTROJPG 的指针?如果只是在每次迭代时测试 header,我认为这不值得,您可以简单地访问普通 BYTE 数组的前 4 个字节。
我会创建一个 512 BYTE 的静态数组(库中的结构),因为这是您不断分配和释放的大小,而且您使用的是 BYTE,而不是 INTROJPG。
其次,在这个部分和另一个类似的部分:
for (int i = 0; i < 128; i++)
{
fread(&buffer[i], sizeof(INTROJPG), 1, card);
}
绝对不需要这个循环,甚至不需要使用 INTROJPG。你总是读写 512 字节,你可以使用:
fread(buffer, 4, 128, card);
// or even better
fread(buffer, 512, 1, card);
关于你的问题,我已经多次测试你的代码(没有任何修改),没有发现 image1.jpg 和 image2.jpg 有任何问题。是的,我将 "w" 模式更改为 "a" 和 vice-versa。
然而,关于最后一张图片,你的代码是错误的,你的最后一张图片是image49.jpg,而它应该是image50.jpg,而你的image49.jpg甚至打不开,那是因为循环在 image49.jpg 的其余部分被存储之前就完成了,也就是说,你只存储了 image49.jpg.
的前 512 个字节为了解决这个问题,我更改了 do-while 循环的条件以继续执行直到卡片文件结束,IIRC 问题保证最后一个块是最后一个图像或类似内容的一部分如果没有,则由您来解决这个小问题!
#include <stdio.h>
#include <stdlib.h>
#include "bmp2.h"
int main(void)
{
/*OPEN CARD FILE*/
char* infile = "card.raw";;
FILE* card = fopen(infile, "r");
if (card == NULL)
{
printf("Could not open %s.\n", "card.raw");
return 2;
}
int f = 0, c = 0, imageno = 1;
// c signals that a jpg is being written
// l size control, 0 means 0 jpgs
FILE* images;
char title[25];
BYTE buffer[512];
/*repeat until end of card*/
do
{
fread(buffer, 512, 1, card);
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff)
{
sprintf(title, "image%d.jpg", imageno); //change jpg title
if (f == 1) //close previous jpg
{
fclose(images);
imageno++;
}
images = fopen(title, "w");
f = 1; //very first jpg has been opened
c = 1; //jpg open
}
//jpg already open?
if (c == 1) fwrite(buffer, 512, 1, images);
}
while (!feof(card));
return 5;
//close any remaining files
}
最后一件事,你为什么在程序结束时返回 5?只是好奇。