2012-12-16 17 views
5

पर बिटमैप्स लिखना/पढ़ना मैंने खोजा और खोजा है और ऐसा कुछ भी नहीं ढूंढ रहा है जो वर्णन करता है कि मैं डेल्फी कोड में क्या करना चाहता हूं। सोल्यूटीन कभी-कभी नज़दीक होते हैं लेकिन मुझे पता लगाने के लिए पर्याप्त नहीं होते हैं। तो यहां मैं पूछ रहा हूं ..एक tfilestream

मेरे पास कई बिटमैप हैं जो मैं स्क्रीनशॉट से पुनः सहेज रहा हूं। मैं जो कर रहा हूं वह bitmaps_001.bmp पर सहेज रहा है, लेकिन इसमें बहुत अधिक संग्रहण स्थान लगता है, इसलिए मैंने नियमित रूप से bitmaps_001.png के रूप में सहेजने के लिए अपग्रेड किया, और यह और भी अधिक जगह बचाता है, लेकिन अब मैं एक फ़ाइल को सहेजना चाहता हूं, एक tfilestream, और एक tprogressbar का उपयोग कर इसे से पढ़ा है कि मैं स्क्रीन पर छवियों के रूप में बाएं/दाएं खींच सकते हैं।

मूल रूप से, मैं निम्नलिखित पूरा करने के लिए कोशिश कर रहा हूँ:

procedure SaveBMPtoStream(st: tfilestream; bmp: tbitmap); 
procedure ReadBMPfrStream(st: tfilestream; bmp: tbitmap; bnum: integer); 
अब तक कोड (नीचे)

काम करता है के रूप में है, (यह लिखते हैं और एक tbutton की प्रेस में एक बिटमैप छवि में पढ़ता है), लेकिन मैं केवल एक बिटमैप छवि लिख सकते हैं। मुझे रीयलटाइम में tfilestream के लिए आवश्यक प्रति सत्र जितनी छवियां लिखनी होंगी, संभवतः एक टीटीमर नियंत्रण का उपयोग करके और जब तक मैं स्टॉप tbutton दबाता हूं तब तक इसे कई छवियों को लिखने दें। इसे हल करने के लिए नीचे दिए गए कोड को संशोधित करने के लिए मैं क्या कर सकता हूं? धन्यवाद।

मैं विंडोज एक्सपी चला रहा हूं, एनटीएफएस फाइल सिस्टम के साथ बाहरी यूएसबी 3.0 1 टीबी ड्राइव से जुड़ा हुआ है।

type 
    TMS = TFileStream; 
var 
    MS: TMS; 
    pos: int64; // bnum for 0-99,999 images. 
    sz: integer; // size of the image/stream ? 

//write bitmaps to stream 
procedure SaveBMPtoStream(ms: TMS; Bmp: TBitmap; bnum: integer); 
begin 
    // create (or append to) stream 
    if fileexists('d:\streams\s.stm') then MS := TFileStream.Create('d:\streams\s.stm', fmOpenReadWrite) 
    else MS := TFileStream.Create('d:\streams\s.stm', fmCreate); 
    //sz:=MS.Size; pos:=ms.Position; 
    bmp.SaveToStream(MS); 
    // free stream 
    ms.free; 
end; 

//read bitmaps from stream 
procedure ReadBMPfrStream(ms: TMS; Bmp: TBitmap; bnum: integer); 
begin 
    // open stream. 
    MS := TFileStream.Create ('d:\streams\s.stm', fmOpenReadWrite); 
    // read in bitmap from stream 
    //sz:=MS.Size; pos:=ms.Position; 
    bmp.LoadFromStream(MS); 
    // free stream 
    ms.free; 
end; 
+0

आपके पास कुछ प्रतिलिपि/पेस्ट त्रुटियां हैं (?), जैसे प्रकार टीएमएस: TFileStream; '। ;) यदि जानकारी सत्रों में लगातार नहीं रहती है, तो आप शायद बिटमैप नंबर - स्ट्रीम स्थिति/आकार का एक अलग इंडेक्स रख सकते हैं और उस भाग को पढ़ने के लिए अस्थायी स्ट्रीम में कॉपी कर सकते हैं। अन्यथा, आप स्ट्रीम से बिटमैप जानकारी शीर्षलेखों को स्ट्रीम से अग्रेषित करने के लिए स्ट्रीम से अग्रेषित कर सकते हैं और फिर फिर से कॉपी कर सकते हैं, या एप्लिकेशन की शुरुआत में एक ही तरह से इंडेक्स बना सकते हैं। लेकिन उत्तरार्द्ध अधिक काम होगा। –

+0

ओह, वह एक टाइपो था। अभी ठीक किया गया धन्यवाद। – johnm2

+0

जहां आप देखते हैं (//sz:=MS.Size; pos: = ms.Position;) मैं उन्हें कोशिश करते समय विभिन्न स्थानों पर कोड स्निपेट के कुछ हिस्सों का शोध कर रहा था। यह सब मेरे लिए भ्रमित है और मैं इसे समझने के लिए प्रतीत नहीं कर सकता। यह मेरे सिर पर है, लेकिन मुझे इसे सब कुछ समझने की ज़रूरत है, इसलिए मैं अभी भी महीनों में हूं। यही कारण है कि मैं जवाब पाने के लिए यहां आया था। लेकिन अभी भी कोई नहीं। तो, मैं खोज रखता हूँ। कोशिश करने के लिए शुक्रिया। – johnm2

उत्तर

5
Function LoadBMPFromStream(const fn: String; Bmp: TBitmap; Nr: Integer):Boolean; 
var // Nr is 0 based first Bitmap=0 
    fs: TFileStream; 
    ms: TMemoryStream; 
    intNr: Integer; 
    pos: Cardinal; 
    size: DWord; 
begin 
    intNr := 0; 
    if fileexists(fn) then 
    begin 
    Result := true; 
    fs := TFileStream.Create(fn, fmOpenRead or fmShareDenyNone); 
    try 
     fs.Read(size, SizeOf(DWord)); // Read Size of first Bitmap 
     while (Nr > intNr) and (fs.Position < fs.size) do 
     begin 
     fs.Seek(size, soFromCurrent); 
     fs.Read(size, SizeOf(DWord)); // Read Size of Bitmap with intNr 
     inc(intNr); 
     end; 
     if fs.Position < fs.size then 
     begin 
     ms := TMemoryStream.Create; 
     try 
      ms.CopyFrom(fs, size); 
      ms.Position := 0; 
      Bmp.LoadFromStream(ms); 
     finally 
      ms.Free; 
     end; 
     end 
     else Result := false; 
    finally 
     fs.Free; 
    end; 

    end; 
end; 


procedure SaveBMPtoStream(const fn: String; Bmp: TBitmap); 
var 
    fs: TFileStream; 
    ms: TMemoryStream; 
    pos: Cardinal; 
    size: DWord; 
begin 
    if fileexists(fn) then 
    begin 
    fs := TFileStream.Create(fn, fmOpenReadWrite or fmShareDenyNone); 
    fs.Seek(0, soEnd); 
    end 
    else 
    begin 
    fs := TFileStream.Create(fn, fmCreate or fmShareDenyNone); 
    end; 
    try 
    ms := TMemoryStream.Create; 
    try 
     Bmp.SaveToStream(ms); 
     size := ms.size; 
     ms.Position := 0; 
     fs.Write(size, SizeOf(DWord)); // Write Size of next Bitmap first 
     fs.CopyFrom(ms, size); 
    finally 
     ms.Free; 
    end; 
    finally 
    fs.Free; 
    end; 

end; 

procedure TForm6.Button2Click(Sender: TObject); 
begin 
    // load first Picture 
    LoadBMPFromStream('C:\temp\test.str', Image3.picture.bitmap, 0); 
    // load third picture 
    // LoadBMPFromStream('C:\temp\test.str', Image3.picture.bitmap, 2); 
end; 

procedure TForm6.Button1Click(Sender: TObject); 
begin 
    SaveBMPtoStream('C:\temp\test.str', Image1.picture.bitmap); 
    SaveBMPtoStream('C:\temp\test.str', Image2.picture.bitmap); 
    SaveBMPtoStream('C:\temp\test.str', Image1.picture.bitmap); 
end; 
+2

आपका कोड कुछ 'अंततः प्रयास करें' ब्लॉक के साथ कर सकता है। –

+0

@ मारजन वेनेमा आप सही हैं ... – bummi

+0

@ बम्मी, धन्यवाद, आपके पढ़ने/लिखने के दिनचर्या के रूप में काम किया है। मैंने प्रगति पट्टी जोड़ा और बाएं/दाएं स्कैन कर सकते हैं। हालांकि, एक मामूली समस्या, क्योंकि मुझे अंतिम छवि संख्या नहीं पता है, जब मैं एक निश्चित संख्या से पहले नियमित क्रैश करता हूं। क्या अंतिम छवि संख्या को स्टोर करने का कोई तरीका है? मैं gl_cntr का उपयोग कर छवियों की संख्या के रूप में उपयोग कर रहा हूँ। मैं एक और tbutton जोड़ सकता हूं जो फ़ाइल को अंतिम संख्या के साथ बंद कर देगा। धन्यवाद। – johnm2

0

आप सभी छवियों को एक ही फ़ाइल में सहेजना चाहते हैं? आपका सबसे आसान विकल्प तब 0 संपीड़न (केवल स्टोर) के साथ 7zip फ़ाइल का उपयोग करेगा, यह आपके लिए संग्रह से फ़ाइलों की अनुक्रमण/बचत/पुनर्प्राप्ति का प्रबंधन करेगा। http://www.rg-software.de/rg/index.php?option=com_content&view=article&id=29&Itemid=51

तुम भी अब फिर से केवल बिटमैप्स का उपयोग कर, 7zip में एक तेजी से संपीड़न सेटिंग का उपयोग करते समय की कोशिश कर सकते, यह शायद पीएनजी की तुलना में बेहतर गति को प्राप्त होगा:

यहाँ एक अच्छा मुक्त घटक है कि यह कर सकते हैं है।

+0

यह मेरे लिए काम नहीं करेगा क्योंकि मैं जितनी जल्दी हो सके और रीयलटाइम में छवियों को पढ़/लिख रहा हूं। – johnm2

+0

क्या आपको छवियों को स्थायी रूप से स्टोर करने की आवश्यकता है, या केवल प्रोग्राम चल रहा है, अस्थायी रूप से? – hikari

+0

मुझे यकीन नहीं है। लेकिन जिस तरह से मैं इस बिंदु पर कर रहा हूं वह पीएनजी छवि को डिस्क पर सहेज रहा था, एक-एक करके यह चलता है। मुझे यह बताने के लिए एक काउंटर है कि कितने पीएनजी छवियां बनाई गई थीं और यह संख्या फ़ाइल नाम के लिए गद्दीदार सूचकांक है, bmp001.png bmp002.png, ... bmp998.png, आदि तो मैं देखने के लिए एक और ऐप के अंदर खोलता हूं। लेकिन मैं अपने सभी ऐप के अंदर से इन सभी (और अधिक) करना चाहता हूं। एक फ़ाइल (स्ट्रीम) को लिखना मुझे अंतरिक्ष बचाएगा और प्रक्रिया को और अधिक कुशल बनाने में मदद करेगा। – johnm2