PDA

View Full Version : نوشتن متن بر روی تصویر



A.Nemati
شنبه 31 شهریور 1386, 11:52 صبح
سلام.
دنبال کدی می‌گردم که بتونم روی محل خاصی از یک تصویر، متن بنویسم.
نمی‌خوام از کامپوننت استفاده کنم و ممنون می‌شم که دوستان راهنماییم کنند.

مصطفی ساتکی
شنبه 31 شهریور 1386, 12:53 عصر
سلام
کامپوننت TImage دارای یه خصوصیت Canvas که شما از طریق متد TextOut(x,y,String) می تونید رشته مورد نظر خودتون در هر موقعیت دلخواه بنویسید البته برای تظیم فونت نوشته خاصیت Font را تغییر دهید و برای transparent شدن خاصیت Style مربوط به Canvas رو با مقدار BSClear تنظیم نماید


procedure DrawText;
var Image1 : Timage;
begin
Image1 := Tiamge1.create(Self);
with Image1 do
begin
picture.loadfromfile(filename);
Canvas.font.name := 'b titr';
Canvas.font.size := 14;
Canvas.font.color := clred;
Canvas.brush.style := bsclear;
Canvas.textout(10,10,String);
end;

A.Nemati
شنبه 31 شهریور 1386, 17:50 عصر
خیلی ممنون. اما من از کامپوننت TImage استفاده نمی‌کنم، یک تصویر رو از دیتابیس می‌خونم، در یک Stream نگه می‌دارم (که اگه لازم باشه می‌تونم بریزمش توی یک متغیر TBitmap) و اونو در یک فایل ذخیره می‌کنم.
می‌خوام قبل از ذخیره کردن در فایل، متن رو روش بنویسم. اگه در این مورد راهنماییم کنید ممنون می‌شم.

vcldeveloper
شنبه 31 شهریور 1386, 18:02 عصر
می‌تونم بریزمش توی یک متغیر TBitmap
TBitmap خودش خصوصیت Canvas داره، می تونی از همون کد بالا استفاده کنی، فقط بجای Image از Bitmap استفاده کن، و بجای Picture.LoadFromFile از Bitmap.LoadFromStream استفاده کن.

hossein taghi zadeh
شنبه 31 شهریور 1386, 18:04 عصر
با سلام


Var
bkMode: Integer;
Bitmap: TBitmap;
Begin
Bitmap := TBitmap.Create;

Bitmap.LoadFromStream(MyStream);

bkMode := SetBkMode(Bitmap.Canvas.Handle, 1);
Bitmap.Canvas.TextOut(2, 2, 'MyString');
If bkMode <> 0 Then
SetBkMode(Bitmap.Canvas.Handle, bkMode);

Bitmap.SaveToStream(MyStream);
End;

vcldeveloper
شنبه 31 شهریور 1386, 23:20 عصر
دو نکته خارج از بحث را بگم:
1- جناب Delphi_CAT؛ وقتی کدی برای یک تابع خارج از context یک کلاس می نویسید، استفاده از Self بی معنی هست، پس باید بجای Self یا nil به Create پاس می کردید، یا اشاره گری به Object ایی که بتونه به عنوان Owner اون شی ساخته شده عمل کنه. البته در این مورد خاص بهتر بود که اصلا وظیفه ساخت شی را به کاربری که قصد استفاده از تابع را دارد واگذار می کردید، و صرفا یک اشاره گر به شی ساخته شده را به عنوان پارامتر ورودی تابع درخواست می کردید.
2- دوستان سعی کنید حتی در Sample های ساده ایی هم که برای روشن شدن یک مبحث میزارید، try-finally را فراموش نکنید. این هم باعث میشه خودتون به استفاده از try-finally بعد از Create یک Object مقید بشید، هم دوستانی که کمتر اطلاع دارند با مطالعه کد شما روش غلط را یاد نمی گیرند.

موفق باشید.

پرواز
یک شنبه 01 مهر 1386, 00:25 صبح
و در تکمیل صحبتهای جناب کشاورز و با اجازه ایشان:
3- در کدنویسی از فرو رفتگی ها برای خوانایی کد استفاده کنید. مثلا کد جناب hossein taghi zadeh رو به جای اینکه اینجوری بنویسیم:

Var
bkMode: Integer;
Bitmap: TBitmap;
Begin
Bitmap := TBitmap.Create;
Bitmap.LoadFromStream(MyStream);
bkMode := SetBkMode(Bitmap.Canvas.Handle, 1);
Bitmap.Canvas.TextOut(2, 2, 'MyString');
If bkMode <> 0 Then
SetBkMode(Bitmap.Canvas.Handle, bkMode);
Bitmap.SaveToStream(MyStream);
End;

بهتره که اینجوری بنویسیم:

Var
bkMode: Integer;
Bitmap: TBitmap;
Begin
Bitmap := TBitmap.Create;
Bitmap.LoadFromStream(MyStream);
bkMode := SetBkMode(Bitmap.Canvas.Handle, 1);
Bitmap.Canvas.TextOut(2, 2, 'MyString');
If bkMode <> 0 Then
SetBkMode(Bitmap.Canvas.Handle, bkMode);
Bitmap.SaveToStream(MyStream);
End;

مصطفی ساتکی
یک شنبه 01 مهر 1386, 12:13 عصر
با عرض سلام به آقای علی کشاورز این کد خارج از context نبود و نخواستم در قسمت اعلان procedure نام فرم خاصی برده شود و زمانی از try-finally در این زمینه استفاده می شود که بخواهیم image مورد نظر را free کنیم ولی ما در اینجا همچین قصدی نداشتیم و تا زمانیکه برنامه در حال اجراست تصویر بایستی بر روی فرم نمایش داده می شد در ضمن من فقط در حد مشکل مورد نظر راهنمایی کردم با تشکر DelphiCAT

ali_abbasi22145
یک شنبه 01 مهر 1386, 12:44 عصر
سلام
درسته که دوستمان گفت از کامپوننت نمی خواهم استفاده کنم!
ImageEN نوشتن متن را روی تصویر به راحتی پشتیبانی میکند، یکی از مثالهای ImageEN این موضوع است در سایتش جستجو کنید.

A.Nemati
یک شنبه 01 مهر 1386, 15:23 عصر
با تشکر از تمامی دوستان به خصوص آقایان Delphi_CAT و کشاورز.
بعد از جوابهای اولیه کمی مطلب را بیشتر پیگیری کردم که به نتایج جالبی دست پیدا کردم و فکر کردم که شاید براتون مفید باشه:
1- Canvas.TextOut در TImage و TBitmap فقط برای تصاویر با فرمت Bitmap کار می‌کنه! و از اونجاییکه تصاویر در دیتابیس معمولا به صورت jpg ذخیره شده‌اند، پس باید ابتدا تصویر را به bmp تبدیل می‌کردم.
2- شاید متنی که نوشته می‌شد بیشتر از عرض تصویر بود پس باید در صورت لزوم Wrap می‌شد. کد لازم را در آدرس http://www.delphi3000.com/articles/article_4389.asp?SK=listBox پیدا کردم.
3- در انتها Alignment رو هم قابل تنظیم کردم و نتیجه نسبتا خوبی به دست اومد.

همه رو در قالب یک برنامه کوچیک براتون پیوست کردم.

البته حتما می‌شه کاملتر و Customizeترش کرد ولی من فعلا نه نیازی بهش داشتم و نه وقتشو.

موفق باشید.

vcldeveloper
یک شنبه 01 مهر 1386, 17:35 عصر
زمانی از try-finally در این زمینه استفاده می شود که بخواهیم image مورد نظر را free کنیم ولی ما در اینجا همچین قصدی نداشتیم و تا زمانیکه برنامه در حال اجراست تصویر بایستی بر روی فرم نمایش داده می شد
به همین دلیل گفتم که بهتر بود Object مربوطه را بصورت پارامتر از کاربر می گرفتید، چون Image ایی که در داخل Procedure بصورت Local ساختید، بعد از خروج از Procedure هیچ Reference ایی بهش وجود نداره که بعدا بشه آزادش کرد، در نتیجه تبدیل به Garbage میشه.


در ضمن من فقط در حد مشکل مورد نظر راهنمایی کردم
کاملا درسته. بنده هم قصدم این نیست که خدای نکرده بخوام اشکال گیری کنم یا اطلاعات شما را زیر سوال ببرم، بلکه هدف اینکه دوستان در خلال مطالعه این کدها با برخی ریزه کاری ها شاید خیلی وقت ها از چشمشون پنهان بمونه آشنا بشند و البته به Copy/Paste کدهایی که در اینجا نوشته میشه عادت نکنند و چند دقیقه ایی روی کد کار کند و بعد در برنامه خودشون ازش استفاده کنند.

موفق باشید

مصطفی ساتکی
دوشنبه 02 مهر 1386, 09:33 صبح
بعد از خروج از Procedure هیچ Reference ایی بهش وجود نداره که بعدا بشه آزادش کرد، در نتیجه تبدیل به Garbage میشه.

آقای کشاورز اینو نوشتم که بگم تصویر مورد نظر Garbage نیست بلکه قابل دسترس هست زمانی Delphi چیزی را garbage در نظر می گیره که هیچ Reference ی به اون وجود نداشته باشه جهت اثبات حرفم کد زیرو نوشتم


procedure TForm1.Button1Click(Sender: TObject);
var i : integer;
begin
for i:=0 to tform(Self).ComponentCount-1 do
if (tform(Self).Components[i] is TImage) then
if( TImage(tform(Self).Components[i]).Canvas.Font.Name='b titr') and
( TImage(tform(Self).Components[i]).Canvas.Font.Size=14) and
( TImage(tform(Self).Components[i]).Canvas.Font.Color=clRed) then
ShowMessage('I am not a garbage Control');
end;

vcldeveloper
دوشنبه 02 مهر 1386, 16:39 عصر
آقای کشاورز اینو نوشتم که بگم تصویر مورد نظر Garbage نیست بلکه قابل دسترس هست زمانی Delphi چیزی را garbage در نظر می گیره که هیچ Reference ی به اون وجود نداشته باشه جهت اثبات حرفم کد زیرو نوشتم
اون زمانی هست که Self ایی وجود داشته باشه و به عنوان Owner کامپوننت مربوطه معرفی شده باشه. قبلا هم گفتم که در کد شما به اون شکلی که نوشته بودید، امکان استفاده از Self وجود نداره. البته شما در پست های بعدی گفتید که نام کلاس فرم را از عنوان تابع حذف کرده بودید، کاربر هیچ ایده ایی که شما نام کلاس را حذف کردید نداره.
همونطور که خودتون هم در پست 12 می بینید، کد شما زمانی که بصورت یک متد تعریف بشه، معنی پیدا میکنه، وگرنه یا کامپایلر error میده (در صورت استفاده از Self)، یا برنامه Garbage درست میکنه، در صورت جایگزین کردن Self با nil.

در پست های قبلی هم توضیح داده شد که چرا به همچین موارد کوچکی گاهی توجه داده میشه.