Đối với một dự án được lập trình bằng C, chúng tôi đang cố gắng chuyển đổi hình ảnh thành dữ liệu nhị phân và ngược lại. Tất cả các giải pháp khác mà chúng tôi tìm thấy trực tuyến đều được viết bằng C++ hoặc Java. Đây là những gì chúng tôi đã thử:
Chuyển đổi hình ảnh thành tệp văn bản chứa dữ liệu nhị phân. Khi mở hình ảnh bằng trình soạn thảo văn bản, cứ 8 ký tự sẽ tương ứng với một byte ký tự.
Sau đó, chúng tôi cố gắng sử dụng chương trình C để chuyển đổi dữ liệu nhị phân trở lại các ký tự tương ứng.
Sau đó, chúng tôi mở kết quả bằng trình xem ảnh Picasa. Chúng tôi nhận được một hình ảnh không hợp lệ.
Làm thế nào để chúng ta lấy lại hình ảnh ban đầu? Đây là mã chúng tôi sử dụng để chuyển đổi hình ảnh thành tệp văn bản:
#include
#include
khoảng trống chính()
{
clrscr();
TẬP TIN *fptr;
TẬP TIN *txt;
int c;
fptr=fopen("D:\\aa.bmp","r");
txt=fopen("D:\\test1.txt","w");
nếu(fptr==NULL)
{
printf("KHÔNG CÓ GÌ TRONG TẬP TIN");
fclose(fptr);
}
khác
{
printf("thành công");
do
{
c=fgetc(fptr);
for(int i=0;i<=7;i++)
{
if(c&(1<<(7-i)))
{
fputc('1',txt);
}
khác
{
fputc('0',txt);
}
}
// fprintf(txt,"\t");
}while(c!=EOF);
}
fclose(fptr);
fclose(txt);
printf("ghi đè");
getch();
}
Dưới đây là đoạn mã để chuyển đổi tệp văn bản được tạo thành tệp hình ảnh chứa đầy các ký tự nhị phân, nghĩa là tệp văn bản chỉ có số 1 và số 0.
#include
#include
\\Hàm sau đây chuyển đổi số 1 và số 0 trong tệp văn bản thành ký tự.
\\Ví dụ: tệp văn bản có thể có 8 ký tự liên tiếp '1','0','0','0','1','0','0','0'.
\\Điều này chuyển đổi nó thành ký tự tương đương với giá trị nhị phân \\10001000
char bytefromtext(char* văn bản)
{
kết quả char=0;
for(int i=0;i<8;i++)
{
if(văn bản[i]=='1')
{
kết quả |= (1<< (7-i) );
}
}
return result;
}
khoảng trống chính()
{
clrscr();
TẬP TIN *pfile;
TẬP TIN *hình ảnh;
char buf[8];
ký tự c;
int j=0;
image=fopen("D:\\aa2.bmp","w"); //mở một tệp .bmp trống để
//ghi các ký tự từ file ảnh nguồn
pfile=fopen("D:\\test1.txt","r");
nếu(pfile==NULL)
printf("lỗi");
khác
{
c=fgetc(pfile);
while(c!=EOF)
{
buf[j++]=c;
nếu(j==8)
{
fputc(bytefromtext(buf),hình ảnh);
j=0;
}
c=fgetc(pfile);
}
fclose(pfile);
fclose(hình ảnh);
}
getch();
}
Khi các ký tự được ghi vào tệp .bmp, chúng tôi nhận được một hình ảnh không hợp lệ. Khi chúng tôi mở tệp mới này bằng trình soạn thảo văn bản và khi chúng tôi mở tệp hình ảnh bằng trình soạn thảo văn bản, chúng tôi sẽ nhận được các ký tự giống nhau.
Hình ảnh vào tập tin văn bản
fptr=fopen("D:\\aa.bmp","r");
tập tin BMP必须ở chế độ nhị phân ("rb"
) được bật để đảm bảo rằng các giá trị byte được đọc chính xác. "r"
mode mở tệp ở chế độ văn bản, điều này có thể khiến một số ký tự bị chuyển đổi, dẫn đến đầu ra bị hỏng.
Ví dụ: trên Windows (hoặc ít nhất là DOS), phần cuối dòng sẽ là từ "\r\n"
Đến từ sự chuyển đổi "\N"
và nhân vật "\x1a"
có thể được hiểu là và EOF
chỉ báo và cắt bớt đầu vào của bạn.
Mặt khác, không có sự khác biệt nào trên các hệ thống giống UNIX.
do
{
c=fgetc(fptr);
for(int i=0;i<=7;i++)
{
/* ... */
}
// fprintf(txt,"\t");
}while(c!=EOF);
Chu kỳ này là hoàn toàn sai. bạn cần kiểm tra EOF
ở đầu vòng lặp. khifgetc()
trở lại EOF
, mã của bạn sẽ sử dụng EOF
giá trị (thường -1
) và xuất ra 1 và 0 tương ứng trước khi thoát khỏi vòng lặp. Điều này cũng sẽ phá hủy đầu ra của bạn.
Thay vào đó, bạn nên làm điều này:
while ((c = fgetc (fptr)) != EOF) {
{
/* ... */
}
Nếu bạn không thoải mái với việc gán và so sánh trong cùng một biểu thức thì có một cách giải quyết:
trong khi (1)
{
c = fgetc(fptr);
nếu (c == EOF)
phá vỡ;
/* ... */
}
Cũng xin lưu ý fgetc()
cũng trở lại EOF
sai lầm. BạnnênKiểm tra điều này (nếu (ferror (fptr))
) và báo cáo sự cố cho người dùng.
fclose(fptr);
fclose(txt);
Bạnnên检查 fclose()
trả về giá trị và báo cáo bất kỳ lỗi nào cho người dùng, ít nhất là trên luồng đầu ra. Trên một số hệ thống tệp, đầu ra cuối cùng không được ghi vào đĩa cho đến khi luồng bị đóng và mọi lỗi được ghi vào đó sẽ được thay thế bằng fclose()
Báo cáo. .nhìn thấy "Lý do cần kiểm tra lỗi khi đóng() là gì?"Tìm hiểu những câu chuyện đầy cảm hứng về những gì xảy ra khi bạn không làm như vậy.
Chuyển đổi tập tin văn bản thành hình ảnh
image=fopen("D:\\aa2.bmp","w"); //mở một tệp .bmp trống để
Bạn必须Sử dụng chế độ nhị phân như trên ("wb"
).
char bytefromtext(char* văn bản)
{
kết quả char=0;
for(int i=0;i<8;i++)
{
if(văn bản[i]=='1')
{
kết quả |= (1<< (7-i) );
}
}
return result;
}
Bạnnênsử dụng ký tự không dấu
Khi xử lý dữ liệu nhị phân. đơn giản ký tự
Đúng đã ký
hoặc không dấu
Được người triển khai lựa chọn (ví dụ: nhà cung cấp trình biên dịch).
Nếu giá trị được lưu trữ trongkết quả
không thể ở đó ký tự đã ký
được thể hiện bằng (chẳng hạn như 1<<7
), hóa rathực hiện xác định. Về mặt lý thuyết, điều này có thể làm hỏng đầu ra của bạn. Mặc dù tôi nghĩ mã của bạn có thể sẽ hoạt động như mong đợi trong hầu hết các trường hợp, nhưng bạn vẫn nên sử dụng ký tự không dấu
như một vấn đề nguyên tắc.
(Tất nhiên, điều này giả định ký tự
Không lớn hơn 8 bit, thường là như vậy. )
ký tự c;
/* ... */
c=fgetc(pfile);
while(c!=EOF)
{
/* ... */
c=fgetc(pfile);
}
Chu kỳ này sai vì một lý do khác. Nếu bình thường ký tự
xảy ra là không được ký,c
Sẽmãi mãiso sánh bằngEOF
Nó luôn có giá trị âm. bạn nên sử dụng int
biến, cho EOF
Kiểm tra trước khi sử dụng giá trị làm giá trị ký tự.
fclose(pfile);
fclose(hình ảnh);
Bạn nên kiểm tra giá trị trả về như đã đề cập ở trên.
Các câu hỏi khác
Tôi có một số câu hỏi khác về mã của bạn.
Trong C,chủ yếu()
luôn luôn trở lại int
, bạn nên trả về một giá trị thích hợp để biểu thị thành công hay thất bại. (Điều này không áp dụng chomôi trường độc lập, chẳng hạn như chương trình C chạy mà không cần hệ điều hành. )
Phần bình luận trong chương trình thứ hai sử dụng dấu gạch chéo ngược thay vì dấu gạch chéo lên. Khi đăng mã, bạn phải luôn sao chép/dán mã để tránh gây ra lỗi mới.
Tôi là một lập trình viên xuất sắc, rất giỏi!