此处将为大家介绍关于delphi–比较JPEG图像的最快解决方案是什么?(忽略元数据,只是“像素”)的详细内容,此外,我们还将为您介绍关于c–在OpenGL中每帧绘制新的全屏图像的最快方法是什么?、c
此处将为大家介绍关于delphi – 比较JPEG图像的最快解决方案是什么? (忽略元数据,只是“像素”)的详细内容,此外,我们还将为您介绍关于c – 在OpenGL中每帧绘制新的全屏图像的最快方法是什么?、c – 暂停和恢复pthread的最佳解决方案是什么?、delphi – 使用TidHttp从URL下载Jpeg图像(只有那些存在的)?、delphi – 加载和重新调整图像大小的最快方法是什么?的有用信息。
本文目录一览:- delphi – 比较JPEG图像的最快解决方案是什么? (忽略元数据,只是“像素”)
- c – 在OpenGL中每帧绘制新的全屏图像的最快方法是什么?
- c – 暂停和恢复pthread的最佳解决方案是什么?
- delphi – 使用TidHttp从URL下载Jpeg图像(只有那些存在的)?
- delphi – 加载和重新调整图像大小的最快方法是什么?
delphi – 比较JPEG图像的最快解决方案是什么? (忽略元数据,只是“像素”)
我写了一个函数,它完全像我想要的那样…(如果图像相似,只有元数据改变与否,函数返回True;如果至少有一个像素改变,则返回False)但是,我想要改善表现……
瓶颈是bmp.Assign(jpg);
function CompareImages(fnFrom,fnTo: TFileName): Boolean; var j1,j2: TJpegImage; b1,b2: TBitmap; s1,s2: TMemoryStream; begin Result := False; sw1.Start; j1 := TJpegImage.Create; j2 := TJpegImage.Create; sw1.Stop; sw2.Start; s1 := TMemoryStream.Create; s2 := TMemoryStream.Create; sw2.Stop; //sw3.Start; b1 := TBitmap.Create; b2 := TBitmap.Create; //sw3.Stop; try sw1.Start; j1.LoadFromFile(fnFrom); j2.LoadFromFile(fnTo); sw1.Stop; // the very long part... sw3.Start; b1.Assign(j1); b2.Assign(j2); sw3.Stop; sw4.Start; b1.SavetoStream(s1); b2.SavetoStream(s2); sw4.Stop; sw2.Start; s1.Position := 0; s2.Position := 0; sw2.Stop; sw5.Start; Result := IsIdenticalStreams(s1,s2); sw5.Stop; finally // sw3.Start; b1.Free; b2.Free; // sw3.Stop; sw2.Start; s1.Free; s2.Free; sw2.Stop; sw1.Start; j1.Free; j2.Free; sw1.Stop; end; end;
sw1,…,sw5是TStopWatch,我用来识别花费的时间.
IsIdenticalStreams来自here.
如果我直接比较TJpegImage,流是不同的……
有没有更好的代码编写方式?
问候,
W.
更新:
测试从注释中提取的一些解决方案,我对此代码具有相同的性能:
type TMyJpeg = class(TJPEGImage) public function Equals(Graphic: TGraphic): Boolean; override; end; ... function CompareImages(fnFrom,j2: TMyJpeg; begin sw1.Start; Result := False; j1 := TMyJpeg.Create; j2 := TMyJpeg.Create; try j1.LoadFromFile(fnFrom); j2.LoadFromFile(fnTo); Result := j1.Bitmap.Equals(j2.Bitmap); finally j1.Free; j2.Free; end; sw1.Stop; end;
有没有直接访问文件中的像素数据字节(跳过元数据字节)而无需位图转换的方法?
解决方法
chunk type marker (big-endian FFxx) chunk length (big-endian word) data (length-2 bytes)
编辑:SOS块受另一个标记的限制,而不是长度.
元数据块以APPn标记(FFEn)开始,但具有JFIF标题的APP0(FFE0)标记除外.
所以我们只能读取和比较重要的块并忽略APPn块和COM块(如TLama注意到的).
示例:某些jpeg文件的十六进制视图:
它以SOI(图像开始)标记FFD8(独立,无长度)开始,
然后APP0块(FFE0)长度= 16字节,
然后APP1块(FFE1),其中包含元数据(EXIF数据,NIKON COOLPIX名称等),因此我们可以忽略9053字节(23 5D)并检查地址2373处的下一个块标记,依此类推……
编辑:简单解析示例:
var jp: TMemoryStream; Marker,Len: Word; Position: Integer; PBA: PByteArray; procedure ReadLenAndMovePosition; begin Inc(Position,2); Len := Swap(PWord(@PBA[Position])^); Inc(Position,Len); end; begin jp := TMemoryStream.Create; jp.LoadFromFile('D:\3.jpg'); Position := 0; PBA := jp.Memory; while (Position < jp.Size - 1) do begin Marker := Swap(PWord(@PBA[Position])^); case Marker of $FFD8: begin Memo1.Lines.Add('Start Of Image'); Inc(Position,2); end; $FFD9: begin Memo1.Lines.Add('End Of Image'); Inc(Position,2); end; $FFE0: begin ReadLenAndMovePosition; Memo1.Lines.Add(Format('JFIF Header Len: %d',[Len])); end; $FFE1..$FFEF,$FFFE: begin ReadLenAndMovePosition; Memo1.Lines.Add(Format('APPn or COM Len: %d Ignored',[Len])); end; $FFDA: begin //SOS marker,data stream,ended by another marker except for RSTn Memo1.Lines.Add(Format('SOS data stream started at %d',[Position])); Inc(Position,2); while Position < jp.Size - 1 do begin if PBA[Position] = $FF then if not (PBA[Position + 1] in [0,$D0..$D7]) then begin Inc(Position,2); Memo1.Lines.Add(Format('SOS data stream ended at %d',[Position])); Break; end; Inc(Position); end; end; else begin ReadLenAndMovePosition; Memo1.Lines.Add(Format('Marker %x Len: %d Significant',[Marker,Len])); end; end; end; jp.Free; end;
c – 在OpenGL中每帧绘制新的全屏图像的最快方法是什么?
目前,我正在将图像数据上传到纹理,然后渲染全屏四边形.但是,这在我尝试的不同机器上运行得不是很快.
解决方法
Currently,I’m uploading the image data to a texture and then rendering a fullscreen quad. However,this doesn’t run very quickly on a different machine that tried. Any ideas? Thanks.
glTexImage2D执行完整的纹理初始化(这意味着,分配,对象设置等).如果您只想用相同大小的图像替换纹理图像,请使用glTexSubImage2D,这要快得多.如果你想异步这样做,那么看看Pixel Buffer Objects
c – 暂停和恢复pthread的最佳解决方案是什么?
我想知道下面的代码是否有效,如果是这样,为什么同一个锁被用来调用pthread_cond_wait以及访问它,然后立即解锁:
void suspendMe(){ pthread_mutex_lock(&m_SuspendMutex); pthread_cond_wait(&m_ResumeCond,&m_SuspendMutex); pthread_mutex_unlock(&m_SuspendMutex);}
在这里使用2个独立的互斥体是不是更好,或者这是挂起pthread的正确方法?
提前致谢!
编辑:
真棒回复,谢谢大家.
只是一个有关的问题.既然我想在另一个函数中单独恢复一个线程,那么在恢复它时会更合适吗?
void suspendMe(){ pthread_mutex_lock(&m_SuspendMutex); pthread_cond_wait(&m_ResumeCond,&m_SuspendMutex);}void resumeMe(){ pthread_cond_signal(&m_ResumeCond); pthread_mutex_unlock(&m_SuspendMutex);}
再次感谢大家! :〜)
解决方法
看这个代码 – 什么是互斥体保护?什么保护暂停/恢复状态?
void suspendMe(){ pthread_mutex_lock(&m_SuspendMutex); pthread_cond_wait(&m_ResumeCond,&m_SuspendMutex);}void resumeMe(){ pthread_cond_signal(&m_ResumeCond); pthread_mutex_unlock(&m_SuspendMutex);}
这是对的:
void suspendMe(){ // tell the thread to suspend pthread_mutex_lock(&m_SuspendMutex); m_SuspendFlag = 1; pthread_mutex_unlock(&m_SuspendMutex);}void resumeMe(){ // tell the thread to resume pthread_mutex_lock(&m_SuspendMutex); m_SuspendFlag = 0; phtread_cond_broadcast(&m_ResumeCond); pthread_mutex_unlock(&m_SuspendMutex);}void checkSuspend(){ // if suspended,suspend until resumed pthread_mutex_lock(&m_SuspendMutex); while (m_SuspendFlag != 0) pthread_cond_wait(&m_ResumeCond,&m_SuspendMutex); pthread_mutex_unlock(&m_SuspendMutex);}
线程应该在可以暂停的安全点调用checkSuspend.其他线程可以调用suspendMe和resumeMe挂起/恢复线程.
请注意,现在mutex保护m_SuspendFlag变量,确保线程被告知要暂停,被告知恢复,并检查是否应该暂停或保持暂停,使代码线程安全.
Would it not be better to use 2 separate mutexes here,or is this the correct way to suspend a pthread??
使用两个互斥体将会消除条件变量的整个点.他们工作的整个机制是,您可以检查是否有某些您应该等待,然后在等待或不得不释放锁然后等待的情况下等待它,而不用持有锁.如果您在等待时握住锁,任何其他线程如何改变状态?如果你释放锁,然后等待,如果你错过了状态的变化会发生什么?
顺便说一下,暂停或恢复线程几乎没有意义.如果你觉得你需要从外面暂停一个线程,那就只是表示你编码的线程来做你实际上不想做的事情.关于暂停或恢复线程的问题通常表明线程编程的心理模型不正确.线程可能需要等待某事,但不应该从外部“暂停”,因为它应该已经知道自己的编码,当它不应该做一些特定的工作.
delphi – 使用TidHttp从URL下载Jpeg图像(只有那些存在的)?
问题是缺少许多图像(例如:7403,7412等)
我如何仅测试那些存在并将其保存到文件?
procedure TForm.Button1Click(Sender: TObject); var MS : TMemoryStream; JPEGImage: TJPEGImage; Url,numString: String; I,Code: Integer; begin for I := 7400 to 7500 do begin { Url :='http://www.mywebpage.com/images/DSC' + numString+ '.jpg'; try idhttp1.Head(URL); code := idhttp1.ResponseCode; except on E: EIdHTTPProtocolException do code := idhttp1.ResponseCode; end;//try except if code = 200 then begin MS := TMemoryStream.Create; JPEGImage := TJPEGImage.Create; try try idhttp1.Get(Url,MS); //Send the request and get the image code := idhttp1.ResponseCode; MS.Seek(0,soFromBeginning); JPEGImage.LoadFromStream(MS);//load the image in a Stream Image1.Picture.Assign(JPEGImage);//Load the image in a timage component Image1.Picture.SavetoFile('C:\Museum_Data\DSC' + numString + '.jpg'); Application.ProcessMessages; except on E: EIdHTTPProtocolException do code := idhttp1.ResponseCode; // or: code := E.ErrorCode; end; //try except finally MS.free; JPEGImage.Free; end; //try finally end; //if end; end;
解决方法
试试这个:
procedure TForm.Button1Click(Sender: TObject); var MS: TMemoryStream; JPEG: TJPEGImage; Url: String; I: Integer; begin MS := TMemoryStream.Create; try JPEG := TJPEGImage.Create; try for I := 7400 to 7500 do begin Url := 'http://www.mywebpage.com/images/DSC' + IntToStr(I) + '.jpg'; MS.Clear; try IdHTTP1.Get(Url,MS); except on E: EIdHTTPProtocolException do Continue; end; MS.Position := 0; JPEG.LoadFromStream(MS); Image1.Picture.Assign(JPEG); JPEG.SavetoFile('C:\Museum_Data\DSC' + IntToStr(I) + '.jpg'); Application.ProcessMessages; end; finally JPEG.Free; end; finally MS.Free; end; end;
实际上,您不需要timage来将数据保存到文件中.如果您可以省略timage.Picture.Assign()阶段,那么通过完全消除TJPEGImage(除非您尝试验证下载文件是有效的),代码更简单一点,例如:
procedure TForm.Button1Click(Sender: TObject); var MS: TMemoryStream; Url: String; I: Integer; begin MS := TMemoryStream.Create; try for I := 7400 to 7500 do begin Url := 'http://www.mywebpage.com/images/DSC' + IntToStr(I) + '.jpg'; MS.Clear; try IdHTTP1.Get(Url,MS); except on E: EIdHTTPProtocolException do Continue; end; MS.Position := 0; MS.SavetoFile('C:\Museum_Data\DSC' + IntToStr(I) + '.jpg'); Application.ProcessMessages; end; finally MS.Free; end; end;
要么:
procedure TForm.Button1Click(Sender: TObject); var FS: TFileStream; Url,FileName: String; I: Integer; begin for I := 7400 to 7500 do begin Url := 'http://www.mywebpage.com/images/DSC' + IntToStr(I) + '.jpg'; FileName := 'C:\Museum_Data\DSC' + IntToStr(I) + '.jpg'; FS := TFileStream.Create(FileName,fmCreate); try try try IdHTTP1.Get(Url,FS); except on E: EIdHTTPProtocolException do Continue; end; Application.ProcessMessages; finally Fs.Free; end; except DeleteFile(FileName); end; end; end;
delphi – 加载和重新调整图像大小的最快方法是什么?
它似乎工作正常,但是对于较大的图像,速度会慢下来.
是否有更快的方法从磁盘加载(图像)文件并调整它们的大小?
谢谢,彼得
解决方法
线程架构本身有几个选项.执行所有映像的单个线程,或者线程只知道如何处理单个映像的线程池. AsyncCalls库甚至是另一种方式,可以保持相当简单.
关于delphi – 比较JPEG图像的最快解决方案是什么? (忽略元数据,只是“像素”)的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于c – 在OpenGL中每帧绘制新的全屏图像的最快方法是什么?、c – 暂停和恢复pthread的最佳解决方案是什么?、delphi – 使用TidHttp从URL下载Jpeg图像(只有那些存在的)?、delphi – 加载和重新调整图像大小的最快方法是什么?的相关知识,请在本站寻找。
本文标签: