القسم 4: العثور على بداية JPEG في BLOB
تنسيق نوع كائن OLE - خذ ثلاثة!
الآن كل ما يتعين علينا فعله هو تخزين الصورة على القرص (كملف ثنائي عادي) وفهم ما بداخلها.
تحتوي جميع ملفات الصور (التنسيقات) على رؤوس ملفات تحدد الصورة بشكل فريد. تبدأ ملفات صور JPG بما يسمى بعلامة SOI، وقيمتها السداسية العشرية هي $FFD8.
يقوم السطر التالي من التعليمات البرمجية بتخزين قيمة حقل الصورة في الملف ذي الصلة (BlobImage.dat) في دليل العمل. ضع هذا الكود في حدث OnCreate الخاص بالنموذج وقم بإزالته بعد بدء المشروع.
ADOTable1Picture.SaveToFile('BlobImage.dat');
بمجرد أن يكون لدينا هذا الملف. يمكننا استخدام محرر Hex لعرض محتواه.
هل تصدق ذلك؟ يقوم MS Access بتخزين المسار إلى كائن OLE المتصل في حقل كائن OLE كجزء من تعريف الكائن. نظرًا لأن تعريف تخزين كائنات OLE غير موثق (!؟ يأتي هذا مباشرة من MS)، فلا توجد طريقة لمعرفة ما ستحصل عليه بيانات الصورة الفعلية قبل كتابتها.
النظر في هذا السؤال في جزأين. أولاً: نحتاج إلى العثور على "FFD8" والبدء في قراءة الصورة من هناك. ثانيًا: لا يمكن أن يكون "FFD8" دائمًا في نفس الموضع في الملف. الخلاصة: نحتاج إلى وظيفة تقوم بإرجاع موقع علامة SOI لملف JPG المخزن ككائن OLE في قاعدة بيانات Access.
الطريقة الصحيحة - خذ أربعة!
مع توفير حقل نوع Blob، يجب أن تقوم وظيفتنا بإرجاع موضع السلسلة "FFD8" في ADOblobStream. يقرأ ReadBuffer البيانات من الدفق بايتًا بايت. يقوم كل استدعاء لـ ReadBuffer بنقل موضع الدفق بايتًا بايت. ترجع الدالة موضع الدفق عندما تؤدي وحدتا البايت معًا إلى علامة SOI. هذه هي الوظيفة:
الدالة JpegStartsInBlob(PicField:TBlobField):integer;
فار
بس: TADOblobStream؛
المخزن المؤقت: كلمة؛
hx: سلسلة؛
يبدأ
النتيجة := -1؛
bS := TADOlobStream.Create(PicField, bmRead);
يحاول
بينما (النتيجة = -1) و (bS.Position + 1 < bS.Size) تفعلان
يبدأ
bS.ReadBuffer(buffer, 1);
hx:=IntToHex(buffer, 2);
إذا كان hx = 'FF'، فابدأ
bS.ReadBuffer(buffer, 1);
hx:=IntToHex(buffer, 2);
إذا كان hx = 'D8'، فإن النتيجة:= bS.Position - 2
وإلا إذا كان hx = 'FF' إذن
bS.Position := bS.Position-1;
نهاية؛ //إذا
النهاية؛ //بينما
أخيراً
مجاني
النهاية؛ // حاول
نهاية؛
بمجرد أن نحصل على موقع علامة SOI، يمكننا استخدامها للعثور على موقع الصورة في دفق ADOblob.
يستخدم الحياة السياسية في فرنسا.
...
PROcedure TForm1.btnShowImageClick(Sender: TObject);
فار
بس: TADOblobStream؛
الموافقة المسبقة عن علم: TJpegImage؛
يبدأ
bS := TADOblobStream.Create(AdoTable1Picture, bmRead);
يحاول
bS.Seek(JpegStartsInBlob(AdoTable1Picture),soFromBeginning);
الموافقة المسبقة عن علم:=TJpegImage.Create;
يحاول
Pic.LoadFromStream(bS);
ADOImage.Picture.Graphic:=Pic;
أخيراً
Pic.Free;
نهاية؛
أخيراً
مجاني
نهاية؛
نهاية؛
قم بتشغيل المشروع، حسنًا!
الآن من يستطيع أن يقول أن البرمجة ليست ممتعة؟
ملاحظة: في برنامج الكود الحقيقي، سنضيف كودًا لقراءة وعرض الصورة من الصف الحالي في حدث AfterScroll الخاص بـ TDataSet (وهو موجود في إجراء الحدث ADOTable1AfterScroll). يحدث حدث AfterScroll عندما يقوم التطبيق بالتمرير من سجل إلى آخر.
الفكرة الخامسة!
هذا ما يدور حوله هذا الفصل. يمكنك الآن تخزين وعرض جميع صور JPG التي تهمك. في الصفحة الأخيرة من هذه المقالة، سأقدم الكود الكامل (وحدة النموذج 1)؛ ويتم وضع جميع ترتيبات البيانات في حدث OnCreate الخاص بالنموذج. يضمن ذلك توصيل المكونات الثلاثة بشكل صحيح - لا تحتاج إلى استخدام Object Inspector عند التصميم.
أعترف أن هذا الفصل ليس للمبتدئين، لكن العالم مكان قاسٍ! شيء آخر: لاحظت أنك في النهاية لا تعرف حتى كيفية تغيير (أو إضافة بعض الصور الجديدة) إلى الجدول! نعم، هذه قصة أخرى تمامًا!