我見過這個問題的最優雅的解決方案是肖恩巴雷特的writefv
,用在他的小圖像寫作庫stb_image_write
可用here。他只實現了幾個原語(並且沒有錯誤處理),但是相同的方法可以擴展到基本上是二進制的printf
(並且對於閱讀,可以執行相同的操作來獲得二進制scanf
)。非常優雅和整潔!事實上,整個事情就是這麼簡單,我也可能包括在這裏:
static void writefv(FILE *f, const char *fmt, va_list v)
{
while (*fmt) {
switch (*fmt++) {
case ' ': break;
case '1': { unsigned char x = (unsigned char) va_arg(v, int); fputc(x,f); break; }
case '2': { int x = va_arg(v,int); unsigned char b[2];
b[0] = (unsigned char) x; b[1] = (unsigned char) (x>>8);
fwrite(b,2,1,f); break; }
case '4': { stbiw_uint32 x = va_arg(v,int); unsigned char b[4];
b[0]=(unsigned char)x; b[1]=(unsigned char)(x>>8);
b[2]=(unsigned char)(x>>16); b[3]=(unsigned char)(x>>24);
fwrite(b,4,1,f); break; }
default:
assert(0);
return;
}
}
}
,這裏是使用它他是怎麼寫的真彩色.BMP文件:
static int outfile(char const *filename, int rgb_dir, int vdir, int x, int y, int comp, void *data, int alpha, int pad, const char *fmt, ...)
{
FILE *f;
if (y < 0 || x < 0) return 0;
f = fopen(filename, "wb");
if (f) {
va_list v;
va_start(v, fmt);
writefv(f, fmt, v);
va_end(v);
write_pixels(f,rgb_dir,vdir,x,y,comp,data,alpha,pad);
fclose(f);
}
return f != NULL;
}
int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
{
int pad = (-x*3) & 3;
return outfile(filename,-1,-1,x,y,comp,(void *) data,0,pad,
"11 4 22 4" "4 44 22 444444",
'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header
40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header
}
(的write_pixels
定義消隱因爲它在這裏非常相切)
'mmap()的' !與'union'一起處理未對齊的數據訪問。 – 2010-11-14 01:56:35
我希望我能做到,但性能命中值得嗎?這是避免它的最初意圖。我的意思是,說實話,無論如何,我可能會在不知情的情況下在我的'FILE'緩衝區中引起未對齊的內存訪問。 – duane 2010-11-14 02:11:42
您是否真的評估過性能? x86上的未對齊訪問相對便宜。 – Chris 2010-11-14 03:08:39