目前,我在MATLAB中将图像存储为MxNx3 uint8
数组。但是,我需要将其嵌入到HTML文档中,并且我不能单独包含该图像。
相反,我决定尝试将图像编码为base64
字符串。但是,我似乎找不到一种方法来将图像编码为字符串,而不必首先将图像保存到磁盘。我试着调查writebmp
之类的东西,但我似乎无法让它发挥作用。
我真的不想将图像写入文件,只是使用fread
将其读回来。我正在使用的计算机具有非常低的磁盘I / O,因此方式的时间太短。
任何帮助将不胜感激!
我看了here,但由于“找不到方法”,R2018b中的错误。当我线性化图像时,返回的字符串不正确
答案 0 :(得分:1)
function [header] = writeBMP(IM)
header = uint8([66;77;118;5;0;0;0;0;0;0;54;0;0;0;40;0;0;0;21;0;0;0;21;0;0;0;1;0;24;0;0;0;0;0;64;5;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0]);
IMr = IM(:,:,1);
IMg = IM(:,:,2);
IMb = IM(:,:,3);clear IM;
IM(:,:,1)=IMb';
IM(:,:,2)=IMg';
IM(:,:,3)=IMr';
IM(:,:,:)=IM(:,end:-1:1,:);
[i,j,~]=size(IM);
header(19:22) = typecast(int32(i),'uint8'); %width
header(23:26) = typecast(int32(j),'uint8'); %height
IM = permute(IM,[3,1,2]);
IM = reshape(IM,[i*3,j]);
W = double(i)*3;
W = ceil(W/4)*4;
IM(3*i+1:W,:)=0; %padd zeros
IM = IM(:); %linear
header(35:38) = typecast(uint32(length(IM)),'uint8'); %datasize
header = [header;IM];
header(3:6) = typecast(uint32(length(header)),'uint8'); %filesize
end
您还可以查看...\toolbox\matlab\imagesci\private\writebmp.m
以获取更详细的示例。
最好在mex文件中完成。
将此代码保存为encodeB64.c
并运行mex encodeB64.c
/*==========================================================
* encodeB64.c - converts a byte vector to base64
*
* The calling syntax is:
*
* [B] = encodeB64(B)
*
* input: - B : vector of uint8
*
* output: - B : vector of base64 char
*
* This is a MEX-file for MATLAB.
*
*========================================================*/
#include "mex.h"
/* The computational routine */
void Convert(unsigned char *in, unsigned char *out,unsigned long Nin, unsigned long Nout)
{
int temp;
static unsigned char alphabet[64] = {65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,48,49,50,51,52,53,54,55,56,57,43,47};
for (int i=0;i<(Nin-2);i+=3){
temp = in[i+2] | (int)in[i+1]<<8 | (int)in[i]<<16;
for (int j=0;j<4;j++){
out[3+(i/3)*4-j] = alphabet[(temp >> (j*6)) & 0x3f];
}
}
if (Nin%3==1){
temp = (int)in[Nin-1]<<16;
out[Nout-1] = 61;
out[Nout-2] = 61;
out[Nout-3] = alphabet[(temp >> 12) & 0x3f];
out[Nout-4] = alphabet[(temp >> 18) & 0x3f];
}
if (Nin%3==2){
temp = in[Nin-1]<<8 | (int)in[Nin-2]<<16;
out[Nout-1] = 61;
out[Nout-2] = alphabet[(temp >> 6) & 0x3f];
out[Nout-3] = alphabet[(temp >> 12) & 0x3f];
out[Nout-4] = alphabet[(temp >> 18) & 0x3f];
}
}
/* The gateway function */
void mexFunction( int nlhs, mxArray *plhs[],int nrhs, const mxArray *prhs[])
{
unsigned char *InputV; /* input vector 1*/
unsigned char *OutputV; /* output vector 1*/
unsigned long Nin;
unsigned long Nout;
/* check for proper number of arguments */
if(nrhs!=1) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nrhs","One inputs required.");
}
if(nlhs!=1) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nlhs","One output required.");
}
/* make sure the first input argument is scalar integer*/
if( !mxIsClass(prhs[0],"uint8") || mxGetNumberOfElements(prhs[0]) == 1 || mxGetN(prhs[0]) != 1) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:notRowInteger","Input one must be uint8 column vector.");
}
/* get the value of the scalar input */
InputV = mxGetPr(prhs[0]);
Nin = mxGetM(prhs[0]); /*number of input bytes */
Nout = 4*((Nin+2)/3);
/* create the output matrix */
plhs[0] = mxCreateNumericMatrix((mwSize)Nout,1,mxUINT8_CLASS,mxREAL);
/* get a pointer to the real data in the output matrix */
OutputV = (unsigned char *) mxGetData(plhs[0]);
/* call the computational routine */
Convert(InputV,OutputV,Nin,Nout);
}
要测试它,你可以运行
T = randi(255,[2^28,1],'uint8'); %250MB random data
tic;Res=encodeB64(T);t=toc %convert
(length(T)/2^20) / t %read in MB/s
(length(Res)/2^20) / t %write in MB/s
我的结果:
读:467 MB / s写:623 MB / s
file = 'test.html';
fid = fopen(file,'wt');
fwrite(fid,sprintf('<html>\n<header> </header>\n<body>\n'));
fwrite(fid,sprintf('<p>%s</p>\n','Show the Matlab demo image street1.jpg'));
IM = imread('street1.jpg');figure(1);clf;image(IM);
B = writeBMP(IM);
str = encodeB64(B);
fwrite(fid,sprintf('<img src="data:image/bmp;base64,%s"/>\n',str));
fwrite(fid,sprintf('</body>\n</html>'));
fclose(fid);
这应生成一个带有图像编码的1,229,008字节HTML文件。