- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试从磁盘加载 JPEG 图像并从中创建视频文件,但我无法执行此操作。我成功地使用 HBITMAP 处理程序创建了 BITMAP 图像的视频文件,但是位图图像的大小更大,所以我想用 Jpeg 图像制作视频。
这是我将 bmp 图像转换为 avi 文件的类:
#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <vfw.h>
#include "avi_utils.h"
// First, we'll define the WAV file format.
#include <pshpack1.h>
typedef struct
{ char id[4]; //="fmt "
unsigned long size; //=16
short wFormatTag; //=WAVE_FORMAT_PCM=1
unsigned short wChannels; //=1 or 2 for mono or stereo
unsigned long dwSamplesPerSec; //=11025 or 22050 or 44100
unsigned long dwAvgBytesPerSec; //=wBlockAlign * dwSamplesPerSec
unsigned short wBlockAlign; //=wChannels * (wBitsPerSample==8?1:2)
unsigned short wBitsPerSample; //=8 or 16, for bits per sample
} FmtChunk;
typedef struct
{ char id[4]; //="data"
unsigned long size; //=datsize, size of the following array
unsigned char data[1]; //=the raw data goes here
} DataChunk;
typedef struct
{ char id[4]; //="RIFF"
unsigned long size; //=datsize+8+16+4
char type[4]; //="WAVE"
FmtChunk fmt;
DataChunk dat;
} WavChunk;
#include <poppack.h>
// This is the internal structure represented by the HAVI handle:
typedef struct
{ IAVIFile *pfile; // created by CreateAvi
WAVEFORMATEX wfx; // as given to CreateAvi (.nChanels=0 if none was given). Used when audio stream is first created.
int period; // specified in CreateAvi, used when the video stream is first created
IAVIStream *as; // audio stream, initialised when audio stream is first created
IAVIStream *ps, *psCompressed; // video stream, when first created
unsigned long nframe, nsamp; // which frame will be added next, which sample will be added next
bool iserr; // if true, then no function will do anything
} TAviUtil;
HAVI CreateAvi(const char *fn, int frameperiod, const WAVEFORMATEX *wfx)
{ IAVIFile *pfile;
AVIFileInit();
HRESULT hr = AVIFileOpen(&pfile, fn, OF_WRITE|OF_CREATE, NULL);
if (hr!=AVIERR_OK) {AVIFileExit(); return NULL;}
TAviUtil *au = new TAviUtil;
au->pfile = pfile;
if (wfx==NULL) ZeroMemory(&au->wfx,sizeof(WAVEFORMATEX)); else CopyMemory(&au->wfx,wfx,sizeof(WAVEFORMATEX));
au->period = frameperiod;
au->as=0; au->ps=0; au->psCompressed=0;
au->nframe=0; au->nsamp=0;
au->iserr=false;
return (HAVI)au;
}
HRESULT CloseAvi(HAVI avi)
{ if (avi==NULL) return AVIERR_BADHANDLE;
TAviUtil *au = (TAviUtil*)avi;
if (au->as!=0) AVIStreamRelease(au->as); au->as=0;
if (au->psCompressed!=0) AVIStreamRelease(au->psCompressed); au->psCompressed=0;
if (au->ps!=0) AVIStreamRelease(au->ps); au->ps=0;
if (au->pfile!=0) AVIFileRelease(au->pfile); au->pfile=0;
AVIFileExit();
delete au;
return S_OK;
}
HRESULT SetAviVideoCompression(HAVI avi, HBITMAP hbm, AVICOMPRESSOPTIONS *opts, bool ShowDialog, HWND hparent)
{ if (avi==NULL) return AVIERR_BADHANDLE;
if (hbm==NULL) return AVIERR_BADPARAM;
DIBSECTION dibs; int sbm = GetObject(hbm,sizeof(dibs),&dibs);
if (sbm!=sizeof(DIBSECTION)) return AVIERR_BADPARAM;
TAviUtil *au = (TAviUtil*)avi;
if (au->iserr) return AVIERR_ERROR;
if (au->psCompressed!=0) return AVIERR_COMPRESSOR;
//
if (au->ps==0) // create the stream, if it wasn't there before
{ AVISTREAMINFO strhdr; ZeroMemory(&strhdr,sizeof(strhdr));
strhdr.fccType = streamtypeVIDEO;// stream type
strhdr.fccHandler = 0;
strhdr.dwScale = au->period;
strhdr.dwRate = 1000;
strhdr.dwSuggestedBufferSize = dibs.dsBmih.biSizeImage;
SetRect(&strhdr.rcFrame, 0, 0, dibs.dsBmih.biWidth, dibs.dsBmih.biHeight);
HRESULT hr=AVIFileCreateStream(au->pfile, &au->ps, &strhdr);
if (hr!=AVIERR_OK) {au->iserr=true; return hr;}
}
//
if (au->psCompressed==0) // set the compression, prompting dialog if necessary
{ AVICOMPRESSOPTIONS myopts; ZeroMemory(&myopts,sizeof(myopts));
AVICOMPRESSOPTIONS *aopts[1];
if (opts!=NULL) aopts[0]=opts; else aopts[0]=&myopts;
if (ShowDialog)
{ BOOL res = (BOOL)AVISaveOptions(hparent,0,1,&au->ps,aopts);
if (!res) {AVISaveOptionsFree(1,aopts); au->iserr=true; return AVIERR_USERABORT;}
}
HRESULT hr = AVIMakeCompressedStream(&au->psCompressed, au->ps, aopts[0], NULL);
AVISaveOptionsFree(1,aopts);
if (hr != AVIERR_OK) {au->iserr=true; return hr;}
DIBSECTION dibs; GetObject(hbm,sizeof(dibs),&dibs);
hr = AVIStreamSetFormat(au->psCompressed, 0, &dibs.dsBmih, dibs.dsBmih.biSize+dibs.dsBmih.biClrUsed*sizeof(RGBQUAD));
if (hr!=AVIERR_OK) {au->iserr=true; return hr;}
}
//
return AVIERR_OK;
}
HRESULT AddAviFrame(HAVI avi, HBITMAP hbm)
{ if (avi==NULL) return AVIERR_BADHANDLE;
if (hbm==NULL) return AVIERR_BADPARAM;
DIBSECTION dibs; int sbm = GetObject(hbm,sizeof(dibs),&dibs);
if (sbm!=sizeof(DIBSECTION)) return AVIERR_BADPARAM;
TAviUtil *au = (TAviUtil*)avi;
if (au->iserr) return AVIERR_ERROR;
//
if (au->ps==0) // create the stream, if it wasn't there before
{ AVISTREAMINFO strhdr; ZeroMemory(&strhdr,sizeof(strhdr));
strhdr.fccType = streamtypeVIDEO;// stream type
strhdr.fccHandler = 0;
strhdr.dwScale = au->period;
strhdr.dwRate = 1000;
strhdr.dwSuggestedBufferSize = dibs.dsBmih.biSizeImage;
SetRect(&strhdr.rcFrame, 0, 0, dibs.dsBmih.biWidth, dibs.dsBmih.biHeight);
HRESULT hr=AVIFileCreateStream(au->pfile, &au->ps, &strhdr);
if (hr!=AVIERR_OK) {au->iserr=true; return hr;}
}
//
// create an empty compression, if the user hasn't set any
if (au->psCompressed==0)
{ AVICOMPRESSOPTIONS opts; ZeroMemory(&opts,sizeof(opts));
opts.fccHandler=mmioFOURCC('D','I','B',' ');
HRESULT hr = AVIMakeCompressedStream(&au->psCompressed, au->ps, &opts, NULL);
if (hr != AVIERR_OK) {au->iserr=true; return hr;}
hr = AVIStreamSetFormat(au->psCompressed, 0, &dibs.dsBmih, dibs.dsBmih.biSize+dibs.dsBmih.biClrUsed*sizeof(RGBQUAD));
if (hr!=AVIERR_OK) {au->iserr=true; return hr;}
}
//
//Now we can add the frame
HRESULT hr = AVIStreamWrite(au->psCompressed, au->nframe, 1, dibs.dsBm.bmBits, dibs.dsBmih.biSizeImage, AVIIF_KEYFRAME, NULL, NULL);
if (hr!=AVIERR_OK) {au->iserr=true; return hr;}
au->nframe++; return S_OK;
}
HRESULT AddAviAudio(HAVI avi, void *dat, unsigned long numbytes)
{ if (avi==NULL) return AVIERR_BADHANDLE;
if (dat==NULL || numbytes==0) return AVIERR_BADPARAM;
TAviUtil *au = (TAviUtil*)avi;
if (au->iserr) return AVIERR_ERROR;
if (au->wfx.nChannels==0) return AVIERR_BADFORMAT;
unsigned long numsamps = numbytes*8 / au->wfx.wBitsPerSample;
if ((numsamps*au->wfx.wBitsPerSample/8)!=numbytes) return AVIERR_BADPARAM;
//
if (au->as==0) // create the stream if necessary
{ AVISTREAMINFO ahdr; ZeroMemory(&ahdr,sizeof(ahdr));
ahdr.fccType=streamtypeAUDIO;
ahdr.dwScale=au->wfx.nBlockAlign;
ahdr.dwRate=au->wfx.nSamplesPerSec*au->wfx.nBlockAlign;
ahdr.dwSampleSize=au->wfx.nBlockAlign;
ahdr.dwQuality=(DWORD)-1;
HRESULT hr = AVIFileCreateStream(au->pfile, &au->as, &ahdr);
if (hr!=AVIERR_OK) {au->iserr=true; return hr;}
hr = AVIStreamSetFormat(au->as,0,&au->wfx,sizeof(WAVEFORMATEX));
if (hr!=AVIERR_OK) {au->iserr=true; return hr;}
}
//
// now we can write the data
HRESULT hr = AVIStreamWrite(au->as,au->nsamp,numsamps,dat,numbytes,0,NULL,NULL);
if (hr!=AVIERR_OK) {au->iserr=true; return hr;}
au->nsamp+=numsamps; return S_OK;
}
HRESULT AddAviWav(HAVI avi, const char *src, DWORD flags)
{ if (avi==NULL) return AVIERR_BADHANDLE;
if (flags!=SND_MEMORY && flags!=SND_FILENAME) return AVIERR_BADFLAGS;
if (src==0) return AVIERR_BADPARAM;
TAviUtil *au = (TAviUtil*)avi;
if (au->iserr) return AVIERR_ERROR;
//
char *buf=0; WavChunk *wav = (WavChunk*)src;
if (flags==SND_FILENAME)
{ HANDLE hf=CreateFile(src,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
if (hf==INVALID_HANDLE_VALUE) {au->iserr=true; return AVIERR_FILEOPEN;}
DWORD size = GetFileSize(hf,NULL);
buf = new char[size];
DWORD red; ReadFile(hf,buf,size,&red,NULL);
CloseHandle(hf);
wav = (WavChunk*)buf;
}
//
// check that format doesn't clash
bool badformat=false;
if (au->wfx.nChannels==0)
{ au->wfx.wFormatTag=wav->fmt.wFormatTag;
au->wfx.cbSize=0;
au->wfx.nAvgBytesPerSec=wav->fmt.dwAvgBytesPerSec;
au->wfx.nBlockAlign=wav->fmt.wBlockAlign;
au->wfx.nChannels=wav->fmt.wChannels;
au->wfx.nSamplesPerSec=wav->fmt.dwSamplesPerSec;
au->wfx.wBitsPerSample=wav->fmt.wBitsPerSample;
}
else
{ if (au->wfx.wFormatTag!=wav->fmt.wFormatTag) badformat=true;
if (au->wfx.nAvgBytesPerSec!=wav->fmt.dwAvgBytesPerSec) badformat=true;
if (au->wfx.nBlockAlign!=wav->fmt.wBlockAlign) badformat=true;
if (au->wfx.nChannels!=wav->fmt.wChannels) badformat=true;
if (au->wfx.nSamplesPerSec!=wav->fmt.dwSamplesPerSec) badformat=true;
if (au->wfx.wBitsPerSample!=wav->fmt.wBitsPerSample) badformat=true;
}
if (badformat) {if (buf!=0) delete[] buf; return AVIERR_BADFORMAT;}
//
if (au->as==0) // create the stream if necessary
{ AVISTREAMINFO ahdr; ZeroMemory(&ahdr,sizeof(ahdr));
ahdr.fccType=streamtypeAUDIO;
ahdr.dwScale=au->wfx.nBlockAlign;
ahdr.dwRate=au->wfx.nSamplesPerSec*au->wfx.nBlockAlign;
ahdr.dwSampleSize=au->wfx.nBlockAlign;
ahdr.dwQuality=(DWORD)-1;
HRESULT hr = AVIFileCreateStream(au->pfile, &au->as, &ahdr);
if (hr!=AVIERR_OK) {if (buf!=0) delete[] buf; au->iserr=true; return hr;}
hr = AVIStreamSetFormat(au->as,0,&au->wfx,sizeof(WAVEFORMATEX));
if (hr!=AVIERR_OK) {if (buf!=0) delete[] buf; au->iserr=true; return hr;}
}
//
// now we can write the data
unsigned long numbytes = wav->dat.size;
unsigned long numsamps = numbytes*8 / au->wfx.wBitsPerSample;
HRESULT hr = AVIStreamWrite(au->as,au->nsamp,numsamps,wav->dat.data,numbytes,0,NULL,NULL);
if (buf!=0) delete[] buf;
if (hr!=AVIERR_OK) {au->iserr=true; return hr;}
au->nsamp+=numsamps; return S_OK;
}
unsigned int FormatAviMessage(HRESULT code, char *buf,unsigned int len)
{ const char *msg="unknown avi result code";
switch (code)
{ case S_OK: msg="Success"; break;
case AVIERR_BADFORMAT: msg="AVIERR_BADFORMAT: corrupt file or unrecognized format"; break;
case AVIERR_MEMORY: msg="AVIERR_MEMORY: insufficient memory"; break;
case AVIERR_FILEREAD: msg="AVIERR_FILEREAD: disk error while reading file"; break;
case AVIERR_FILEOPEN: msg="AVIERR_FILEOPEN: disk error while opening file"; break;
case REGDB_E_CLASSNOTREG: msg="REGDB_E_CLASSNOTREG: file type not recognised"; break;
case AVIERR_READONLY: msg="AVIERR_READONLY: file is read-only"; break;
case AVIERR_NOCOMPRESSOR: msg="AVIERR_NOCOMPRESSOR: a suitable compressor could not be found"; break;
case AVIERR_UNSUPPORTED: msg="AVIERR_UNSUPPORTED: compression is not supported for this type of data"; break;
case AVIERR_INTERNAL: msg="AVIERR_INTERNAL: internal error"; break;
case AVIERR_BADFLAGS: msg="AVIERR_BADFLAGS"; break;
case AVIERR_BADPARAM: msg="AVIERR_BADPARAM"; break;
case AVIERR_BADSIZE: msg="AVIERR_BADSIZE"; break;
case AVIERR_BADHANDLE: msg="AVIERR_BADHANDLE"; break;
case AVIERR_FILEWRITE: msg="AVIERR_FILEWRITE: disk error while writing file"; break;
case AVIERR_COMPRESSOR: msg="AVIERR_COMPRESSOR"; break;
case AVIERR_NODATA: msg="AVIERR_READONLY"; break;
case AVIERR_BUFFERTOOSMALL: msg="AVIERR_BUFFERTOOSMALL"; break;
case AVIERR_CANTCOMPRESS: msg="AVIERR_CANTCOMPRESS"; break;
case AVIERR_USERABORT: msg="AVIERR_USERABORT"; break;
case AVIERR_ERROR: msg="AVIERR_ERROR"; break;
}
unsigned int mlen=(unsigned int)strlen(msg);
if (buf==0 || len==0) return mlen;
unsigned int n=mlen; if (n+1>len) n=len-1;
strncpy(buf,msg,n); buf[n]=0;
return mlen;
}
这是我的主要内容:
int main ()
{
const char *fns[] = {"1.bmp","2.bmp","3.bmp","4.bmp","5.bmp"};
HAVI avi = CreateAvi("test.avi",1000/5,NULL);
for (int i=0; i<sizeof(fns)/sizeof(fns[0]); i++)
{
HBITMAP hbm=(HBITMAP)LoadImage(NULL,fns[i],IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
AddAviFrame(avi,hbm);
DeleteObject(hbm);
}
AddAviWav(avi,"wav.wav",SND_FILENAME);
CloseAvi(avi);
}
最佳答案
您需要提供更多详细信息。您使用位图文件制作了哪种类型的视频?以及如何?
要创建视频,帧(或图像)必须以未压缩的形式提供。
对于同一张图片,Bitmap和JPEG在解压缩时占用的空间是一样的。所以你需要做的是一个一个地解码 JPEG,并将它们传递给一些视频编解码器,如 Xvid 或 x264 来压缩流。尽管我不知道您如何将该流存储到 AVI 容器(使用 RIFF 格式,顺便说一句)。
解码 JPEG 文件不像位图那么容易,我建议使用库。例如,libjpeg。 http://www.ijg.org/
编辑:简而言之,读取 JPEG 而不是 Bitmap 是没有用的。我的建议是做你现在正在做的事,然后使用像 ffmpeg 这样的库压缩视频 http://www.ffmpeg.org或 libav http://libav.org/ .我相信您会通过搜索找到使用示例。祝你好运!
关于c++ - 如何在不使用 c++ 中的 opencv 的情况下从磁盘加载 Jpeg 图像并创建视频文件(.avi 等),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16387732/
在 Google 和许多 DICOM 章节中可以轻松找到有关 JPEG-LS 的信息。 但是,也有提到 JPEG-LL 的链接/页面/阅读资料。但是,我更深入地研究了 DICOM 标准,没有一章提到过
我有一个关于 DICOM 标准和 libjpeg 库的问题。在 DICOM 标准中,除其他外,还有传输语法: JPEG Lossless, Nonhierarchical, First- Order
APP0 到 APP15 标记每个只支持 65535 字节(我从 libjpeg.doc 中读到的)。如果要在 jpeg 文件中保存更大的数据 block 怎么办? 最佳答案 没有限制使用多个相同类型
我正在尝试构建一个上传器,它分两步上传渐进式文件: 上传最小字节数以创建缩略图 (0-10%) 上传缩略图的其余字节。 (11%-100%) 我想这样做是为了让缩略图更早可用,而不必上传单独的缩略图。
所以,假设我有一个大版本的图像,它只显示为缩略图。是否可以通过使用渐进式 jpeg 来避免为缩略图创建单独的文件,在达到一定数量的扫描时停止加载,并且仅在用户选择完全打开它时继续加载? 如果是这样,如
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 去年关闭。 Improve this
很难说出这里问的是什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或言辞激烈,无法以目前的形式合理回答。如需帮助澄清此问题以便可以重新打开,visit the help center . 9年前关闭
我想从 jpeg 中提取缩略图,无需任何外部库。我的意思是这并不太困难,因为我需要知道缩略图在文件中的开始位置和结束位置,然后简单地剪切它。我研究了许多文档(即: http://www.media.m
当 decoding entropy encoded DC values in JPEG (或 entropy encoded prediction differences in lossless J
问题是:如何区分两个文件?一个用 JPEG 编码,另一个用 JPEG2000 编码。 我需要特定于格式的文件读/写函数,我无法在不读取的情况下找到文件编码。JPEG 现在工作正常,但 JPEG fun
是否有结束 exif/end-of-xmp/end-of-iptc/start-of-data 标记,我可以用它来获取 jpg/jpeg(和其他图像格式)的数据部分的校验和? 最佳答案 我认为这个问题
不久前我收到一封电子邮件,其中包含图像附件。从那时起,hotmail 似乎已停止为我托管图像,因为当我打开邮件时,图像不再可用。 但是,消息源仍然完好无损,如果我没记错的话,消息源 - 以文本形式 -
我有一个提供高质量 MJPEG 的网络摄像头。 我需要通过网络发送小的、低质量的 JPEG。我的硬件是树莓派(700MHz ARM)。我希望代码使用尽可能少的 CPU 能力,并尽可能少地增加延迟。我可
有一个question with the same title但不幸的是它对我没有帮助。 我正在尝试解析 SOS 标记的数据。我能找到的所有文档都说在标记( 0xFFDA )之后是一个两字节的数字,它
每个人! 我处理来自 IP 摄像机的视频,并编写了基于解压缩视频分析的运动检测算法。但我真的更快。我找到了几篇关于压缩域分析的论文,但没有找到任何实现。 谁能推荐我一些代码? 找到的 Material
我在一个网站上工作,该网站涉及显示来自各种在线零售商的大量产品图片。由于大部分页面权重都在图像中,因此我认为值得研究一下减少文件大小的技术。 图像已经是 JPEG。我知道 PNG 有很多多余的东西,可
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 这个问题似乎不是关于 a specific programming problem, a software
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 6 年前。 Improve this ques
我有一个网络画廊,我在其中显示用户上传的文件大小和分辨率各不相同的图像。目前所有图像都是基线。所以我想知道如果我将它们转换为逐行图像是否真的会产生重大影响。使用渐进式图像的优点和缺点是什么。 最佳答案
我在许多链接和网站上保持头脑,但未能得到答案。我不想问这个,我知道 JPEG 压缩,它只制作压缩图像。甚至 Motion JPEG 也会制作压缩图像 I 帧。我的问题是有什么区别。我正在为需要发送视频
我是一名优秀的程序员,十分优秀!