ส่วนที่ 4: การค้นหาจุดเริ่มต้นของ JPEG ใน BLOB
รูปแบบประเภทวัตถุ OLE - ใช้เวลาสาม!
ตอนนี้สิ่งที่เราต้องทำคือจัดเก็บอิมเมจลงดิสก์ (เป็นไฟล์ไบนารี่ธรรมดา) และทำความเข้าใจว่ามีอะไรอยู่ข้างใน
ไฟล์รูปภาพทั้งหมด (รูปแบบ) มีส่วนหัวของไฟล์ที่ระบุรูปภาพได้โดยไม่ซ้ำกัน ไฟล์ภาพ JPG เริ่มต้นด้วยสิ่งที่เรียกว่าแท็ก SOI ซึ่งมีค่าเลขฐานสิบหกคือ $FFD8
บรรทัดโค้ดต่อไปนี้จะเก็บค่าฟิลด์รูปภาพลงในไฟล์ที่เกี่ยวข้อง (BlobImage.dat) ในไดเร็กทอรีการทำงาน วางโค้ดนี้ในเหตุการณ์ OnCreate ของแบบฟอร์ม และลบออกหลังจากเริ่มโปรเจ็กต์
ADOTable1Picture.SaveToFile('BlobImage.dat');
เมื่อเราได้ไฟล์นี้แล้ว เราสามารถใช้โปรแกรมแก้ไข Hex เพื่อดูเนื้อหาได้
คุณเชื่อหรือไม่? การเข้าถึง MS จะจัดเก็บเส้นทางไปยังวัตถุ OLE ที่เชื่อมต่ออยู่ในเขตข้อมูลวัตถุ OLE ซึ่งเป็นส่วนหนึ่งของข้อกำหนดของวัตถุ เนื่องจากข้อกำหนดการจัดเก็บข้อมูลของวัตถุ OLE ไม่ได้รับการจัดทำเป็นเอกสาร (!? สิ่งนี้มาจาก MS โดยตรง) จึงไม่มีทางรู้ได้ว่าข้อมูลรูปภาพจริงจะได้รับอะไรก่อนที่จะเขียน
พิจารณาคำถามนี้ในสองส่วน ขั้นแรก: เราจำเป็นต้องค้นหา 'FFD8' และเริ่มอ่านภาพจากที่นั่น ประการที่สอง: 'FFD8' ไม่สามารถอยู่ในตำแหน่งเดียวกันในไฟล์ได้เสมอไป สรุป: เราต้องการฟังก์ชันที่ส่งคืนตำแหน่งของแท็ก SOI ของไฟล์ JPG ที่จัดเก็บเป็นวัตถุ OLE ในฐานข้อมูล Access
วิธีที่ถูกต้อง - เอาไปสี่!
เมื่อระบุฟิลด์ประเภท Blob ฟังก์ชันของเราควรส่งคืนตำแหน่งของสตริง 'FFD8' ใน ADOBlobStream ReadBuffer อ่านข้อมูลจากสตรีมไบต์ทีละไบต์ การเรียก ReadBuffer แต่ละครั้งจะย้ายตำแหน่งของสตรีมไบต์ทีละไบต์ ฟังก์ชันส่งคืนตำแหน่งของสตรีมเมื่อสองไบต์รวมกันนำไปสู่เครื่องหมาย SOI นี่คือฟังก์ชัน:
ฟังก์ชัน JpegStartsInBlob(PicField:TBlobField):จำนวนเต็ม;
var
BS : TADOBlobStream;
บัฟเฟอร์: Word;
hx: สตริง;
เริ่ม
ผลลัพธ์ := -1;
BS := TADOBlobStream.Create(PicField, bmRead);
พยายาม
ในขณะที่ (ผลลัพธ์ = -1) และ (bS.Position + 1 < bS.Size) ทำ
เริ่ม
BS.ReadBuffer(บัฟเฟอร์, 1);
hx:=IntToHex(บัฟเฟอร์, 2);
ถ้า hx = 'FF' ให้เริ่มเลย
BS.ReadBuffer(บัฟเฟอร์, 1);
hx:=IntToHex(บัฟเฟอร์, 2);
ถ้า hx = 'D8' ดังนั้นผลลัพธ์ := bS.Position - 2
อย่างอื่นถ้า hx = 'FF' แล้ว
bS.ตำแหน่ง := bS.ตำแหน่ง-1;
จบ; //ถ้า
จบ; //ในขณะที่
ในที่สุด
BS.ฟรี
จบ; //ลอง
จบ;
เมื่อเราได้ตำแหน่งของเครื่องหมาย SOI แล้ว เราก็สามารถใช้มันเพื่อค้นหาตำแหน่งของภาพในสตรีม ADOBlob ได้
ใช้ jpeg;
-
PROcedure TForm1.btnShowImageClick (ผู้ส่ง: TObject);
var
BS : TADOBlobStream;
ภาพ: TJpegImage;
เริ่ม
BS := TADOBlobStream.Create(AdoTable1Picture, bmRead);
พยายาม
BS.Seek(JpegStartsInBlob(AdoTable1Picture),soFromBeginning);
Pic:=TJpegImage.Create;
พยายาม
Pic.LoadFromStream(bS);
ADOImage.Picture.Graphic:=Pic;
ในที่สุด
Pic.ฟรี;
จบ;
ในที่สุด
BS.ฟรี
จบ;
จบ;
ดำเนินโครงการ ตกลง!
ตอนนี้ใครสามารถพูดได้ว่าการเขียนโปรแกรมไม่สนุก?
หมายเหตุ: ในโปรแกรมโค้ดจริง เราจะเพิ่มโค้ดเพื่ออ่านและแสดงรูปภาพจากแถวปัจจุบันในเหตุการณ์ AfterScroll ของ TDataSet (อยู่ในขั้นตอนเหตุการณ์ ADOTable1AfterScroll) เหตุการณ์ AfterScroll เกิดขึ้นเมื่อแอปพลิเคชันเลื่อนจากระเบียนหนึ่งไปยังอีกระเบียนหนึ่ง
ไอเดียที่ห้า!
นั่นคือสิ่งที่บทนี้เกี่ยวกับ ตอนนี้คุณสามารถจัดเก็บและแสดงภาพ JPG ทั้งหมดที่คุณสนใจได้แล้ว ในหน้าสุดท้ายของบทความนี้ ฉันจะระบุโค้ดที่สมบูรณ์ (หน่วย form1) การจัดเรียงข้อมูลทั้งหมดจะอยู่ในเหตุการณ์ OnCreate ของแบบฟอร์ม เพื่อให้แน่ใจว่าองค์ประกอบทั้งสามเชื่อมต่ออย่างถูกต้อง - คุณไม่จำเป็นต้องใช้ Object Inspector เมื่อออกแบบ
ฉันยอมรับว่าบทนี้ไม่เหมาะสำหรับผู้เริ่มต้น แต่โลกเป็นสถานที่ที่โหดร้าย! อีกประการหนึ่ง: คุณสังเกตเห็นว่าท้ายที่สุดแล้วคุณไม่รู้วิธีเปลี่ยน (หรือเพิ่มรูปภาพใหม่) ลงในตารางด้วยซ้ำ! ใช่แล้ว นั่นเป็นอีกเรื่องหนึ่ง!