Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Звук, графика и видео > Надо написать Мега Пеинт


Автор: ShuVaS 18.1.2005, 22:08
Ну вот опять я...Опять куча вопросов.Решил написать че то типа паинта : с зумом, с палитрами - ну короче со всем и решил добавить новое - тени гаусово размытие ...Вот и прошу помочь мне - с чего мне собственно начать ???Почему не открываються *.jpg или как сделать поддержку *.png .Почему при изменении размеров формы image так сильно мерцает...Короче я так понял это довольно тяжедая тема и прошу помочь кто чем может ... smile

Автор: s-mike 19.1.2005, 00:34
1) Для использования *.jpg подключи модуль JPEG к проекту
2) Поддержку *.png можно сделать с помощью дополнительных компонентов, которые входят в состав JEDI VCL (http://delphi-jedi.org) или возьми с http://pngdelphi.sourceforge.net/. Есть еще некоторые. Юзай поиск и torry.net.
3) Из-за чего мерцает Image? Этот вопрос звучит скорее как риторический. Ведь это не оконный компонент, а графический. То есть он отрисовывается на родительском оконном компоненте. Так что при необходимости его перерисовки сначала перерисовывается компонент под ним, а потом уже сам Image. Вот это и вызывает мерцание.

Какие методы устранения?
Можно попробовать Image.ControlStyle := Image.ControlStyle + [csOpaque], но в ряде случаев мерцание все равно будет заметно. Я вот библиотеку целую сделал, чтобы обойтись без TImage. Мерцания никакого. Загляни сюда: http://forum.vingrad.ru/index.php?showtopic=39908.

Автор: ShuVaS 19.1.2005, 09:53
Библиотеку видел.Стронних компонентов использоваться не хочу .Мерцания избежал даббл буфером.Вопросик - можно ли как то зоом делать ?!А модуль jpeg у меня всегда покключен- но не фига не пашет..

Автор: Штабс 19.1.2005, 10:51
ShuVaS!
Прости я насчет *.png
ну зачем тебе париться
да возьми библиотеку с открытыми кодами
да выдери оттуда работу с png
поверь и по времени и по силам ты сэкономишь
всеравно ничего координально лучшего ты не создашь

напрягает эта библиотека
кинь ссылку на себя пришлю GraphicEx добавка к VirtualTree
вроде там объявили много
вот почитай

GraphicEx is an addendum to Delphi's Graphics.pas in order to enable your application to load many common image formats. This library is primarily designed to load images as background (buttons, forms, toolbars) and textures (DirectX, OpenGL) or for image browsing and editing purposes as long as you don't need to save images. Currently only TTargaGraphic also supports saving an image.
GraphicEx is open source under the Mozilla Public License (MPL). Please read the license agreement before you start using this library.

Portable network graphic images (*.png)byte order: big endian
sample sizes: 1, 2, 4, 8, 16 bits per sample
color spaces: indexed, grayscale (alpha), RGB(A)
compression format: LZ77
specials:
supported chunks: IHDR, IDAT, IEND, PLTE, gAMA, tRNS, bKGD
transparency support partially for RGB, which is stored as 32 bits format

Желаю успехов

Автор: ShuVaS 19.1.2005, 11:39
Ладно но допустим я открываю разные форматы .Png там jpeg и на разные расширения - разные процедуры:привожу пример сосежнего топика :
Код

uses ..., JPEG;

procedure TForm1.Button1Click(Sender: TObject);
var
 JPEG: TJPEGImage;
begin
 JPEG := TJPEGImage.Create;
 try
   JPEG.LoadFromFile('Work2.jpg');
   IMage1.Picture.Bitmap.Assign(JPEG);
 finally
   FreeAndNil(JPEG);
 end;
 //Если нужен прозрачный фон, то раскоментируй эту строчку
 //SetBkMode(Image1.Canvas.Handle, TRANSPARENT);
 Image1.Canvas.TextOut(10, 10, 'bla bla bla');
end;


или свой обработчик открытия бмп:
Код

procedure TForm1.N2Click(Sender: TObject);
var  b : tbitmap;
begin
If OpenDialog1.Execute then
  begin
   try
    b:=tbitmap.Create;
    b.LoadFromFile(OpenDialog1.FileName);
    Caption:=ExtractFileName(OpenDialog1.Filename) + ' - Drawer';
    image1.Picture.Graphic :=b;
   except
     b.Free;
     end;
   end;
end;



Вопрос - одной процедурки то нету для открытия всех типов файлов - как при нажатии на кнопку при выборе изображения сама выбиралась нужная процедура ? smile

Автор: Illusion Dolphin 19.1.2005, 12:05
Код

uses ..., JPEG, {GIF, PNG, PSD...};

var Image:TBitmap;

procedure TForm1.Button1Click(Sender: TObject);
var
pic: TPicture;
begin
pic:= TPicture.Create;
try
  pic.LoadFromFile('File.любое_поддерживаемое_расширение');
finally
  FreeAndNil(pic);
  exit;
end;
Image.assign(pic.graphic);//надеюсь, что Image у нас уже создано
pic.free;
end;

комментарии по поводу данного кода: с jpeg никаких проблем не будет вообще... а с другими форматами (и бмп тоже!) БУДУТ! Вся проблема что GIF, BMP, PNG бывают "прозрачными". Нужно как бы проверять изображения на прозрачность (BMP, PNG - pixelformat = pf24bit, GIF - тут как я понял нужно смотреть все картинки и проверять на прозрачность каждую - выходит надёжнее) и в этом случае загружать нужно в соответствии с особенностями даных форматом и модулей, которые их поддерживают, но в конечном итоге получим Image.pixelformat:=pf32bit!. Теперь вся трудонсть в том, что винда хоть и повсюду юзает 32-битные битмапки, обычным GDI их не выведешь smile... Нужно через scanline их дравить на буфер а потом выводить на экран.

Автор: Штабс 19.1.2005, 12:09
а анализировать название файла не хочешь
перед открытием

типа расширение JPG тогда процедура по открыдию JPG
а если PNG тгогда процедура по открыдию PNG

конечно это упрощенно

можно в дальнейшем создать и абстрактный клас

что то типа
посмотри код

if AnsiLastChar(FDirectory)^ <> '\' then FDirectory := FDirectory + '\';
Picture := TPicture.Create;
Extensions := TStringList.Create;
try
FileFormatList.GetExtensionList(Extensions);
for I := 0 to Extensions.Count - 1 do Extensions[I] := '.' + UpperCase(Extensions[I]);
Extensions.Sort;
if FindFirst(FDirectory + '*.*', faAnyFile, SR) = 0 then
begin
// iterate through the picked folder and collect all known image files
repeat
if SR.Attr <> faDirectory then
begin
// check whether this file is an image file we can show
Ext := ExtractFileExt(SR.Name);
if Extensions.Find(Ext, I) then
begin
// fine, we found an image file, so add it to our internal list
New(Entry);
Entry.Name := SR.Name;
Entry.Bitmap := TBitmap.Create;
try
Picture.LoadFromFile(FDirectory + SR.Name);
if not (Picture.Graphic is TBitmap) then
begin
// Some extra steps needed to keep non TBitmap descentant alive when scaling.
// This is needed because when accessing Picture.Bitmap all non-TBitmap content
// will simply be erased (definitly the wrong action, but we can't do anything
// to prevent this). Hence we must draw the graphic to a bitmap.
with Entry.Bitmap do
begin
PixelFormat := pf24Bit;
Width := Picture.Width;
Height := Picture.Height;
Canvas.Draw(0, 0, Picture.Graphic);
end;
Picture.Bitmap.Assign(Entry.Bitmap);
end;
RescaleImage(Picture.Bitmap, Entry.Bitmap, True);
FFileList.Add(Entry);
Caption := IntToStr(Count) + ' images loaded';
R.Top := YPos + (Count div XCount) * HeightPerLine;
if R.Top < R.Bottom then
begin
InvalidateRect(Handle, @R, False);
UpdateWindow(Handle);
end;
Inc(Count);
except
// no exceptions please, just ignore invalid images
Application.ProcessMessages;
end;

Автор: ShuVaS 19.1.2005, 15:50
Че то не фига не понял я .... короче закидываю на время я создание паинта - теперь мне хотя бы сделать что бы форматы открывало развыне (*.bmp *.jpeg *.png и *.giv и *.ico ).Вот кинул на форму имадже , кнопку - и какой обработчик писать??Желательно без findfirst ...можно по подробнее...

p.s Дельфин ты где ???Я тя в асе уже дней пять выцепляю !

Автор: Guest 19.1.2005, 17:52
Хорошо давай поподробнее
кидаешь на форму
OpenDialog

на событии по нажатию кнопки
пишешь
if OpenDialog1.Execute then { если OpenDialog1.выпониося тогда... дословный перевод}
begin
...
...
end;
весь навар у тебя в том что ты имеешь

OpenDialog1.FileName полное имя открываемого файла

теперь можно написать

Ext := ExtractFileExt(SR.Name);

получить расширение выбранного файла

получаем

if OpenDialog1.Execute then { если OpenDialog1.выпониося тогда... дословный перевод}
begin
Ext := ExtractFileExt(SR.Name);

end;

а уж дальше сваливаешься куда тебе надо.... и как тебе надо


примеры

if Ext='JPG' then ......
если EXT определена как строка

или
case Ext of
'JPG':....
'PNG':...
end;
если EXT определена как типизированая переменная



Автор: Штабс 19.1.2005, 17:56
я там заметил неточность

SR.Name:=OpenDialog1.FileName

это одно и тоже

Автор: Illusion Dolphin 19.1.2005, 20:13
ShuVaS: если хочешь я могу сюда развестить примерчик который открывает BMP JPEG GIF (всё остальное - качай GraphicsEx), но уже завтра...

Автор: ShuVaS 19.1.2005, 20:26
оки ... заранее спасиба ..

Автор: Illusion Dolphin 19.1.2005, 21:49
Хе-хе smile
Paint-demo. Поддержка: BMP (32-битные тоже!) , JPEG, GIF (эксперементально) + скролинг.
Исходники прилагаются. Понятия написанного мною достаточно чтобы довести до ума идею.
Код

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, ExtCtrls, Menus, ExtDlgs, PanelCanvas, jpeg, math, GIFImage,
 StdCtrls;

 type
 TRGB32=record
 b,g,r,l : byte;
 end;
 Type
   ARGB32=array [0..1] of TRGB32;
   PARGB32=^ARGB32;

Type
 TRGB=record
 b,g,r : byte;
 end;

   ARGB=array [0..1] of TRGB;
   PARGB=^ARGB;
   PRGB = ^TRGB;

Type TTool=(ToolNone,ToolPen);

type
 TEditor = class(TForm)
   MainMenu1: TMainMenu;
   File1: TMenuItem;
   Open1: TMenuItem;
   ToolsPanel: TPanel;
   OpenPictureDialog1: TOpenPictureDialog;
   Shape1: TShape;
   ColorDialog1: TColorDialog;
   ScrollBar1: TScrollBar;
   ScrollBar2: TScrollBar;
   procedure Open1Click(Sender: TObject);
   procedure FormCreate(Sender: TObject);
   procedure Panel2Resize(Sender: TObject);
   procedure MakeImage;
   procedure FormPaint(Sender: TObject);
   procedure LoadProgramImageFormat(Pic : TPicture);
   procedure LoadJPEGImage(JPEG : TJPEGImage);
   procedure LoadBMPImage(Bitmap : TBitmap);
   procedure LoadGIFImage(GIF : TGIFImage);
   procedure Shape1MouseDown(Sender: TObject; Button: TMouseButton;
     Shift: TShiftState; X, Y: Integer);
   procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
     Shift: TShiftState; X, Y: Integer);
   procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
     Shift: TShiftState; X, Y: Integer);
   procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
     Y: Integer);
   procedure ScrollBar2Change(Sender: TObject);

 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Editor: TEditor;
 CurrentImage, Buffer : TBitmap;
 Tool : TTool;
 BeginPoint : TPoint;

implementation

{$R *.dfm}

procedure Line(image : TBitmap; x_begin,y_begin,x_end,y_end : integer; Color: Tcolor);
var
 fx,fy,i : integer;
 x,y,tg : real;
 p : Pargb32;
 r,g,b : byte;

Procedure Replace(var x1,x2 : integer);
var
  temp : integer;
begin
 temp:=x1;
 x1:=x2;
 x2:=temp;
end;

begin
image.PixelFormat:=pf32bit;
r:=GetRValue(Color);
g:=GetGValue(Color);
b:=GetBValue(Color);
if ((y_end - y_begin)=0)  and ((x_end - x_begin)=0) then
begin
 if (y_begin<image.Height-1) and (y_begin>=0) then
 begin
 p:=image.ScanLine[y_begin];
  if (x_begin<image.Width-1) and (x_begin>=0) then
  begin
   p[x_begin].r:=r;
   p[x_begin].g:=g;
   p[x_begin].b:=b;
   p[x_begin].l:=255;
  end;
 end;
 exit;
end;
if (abs(x_end-x_begin) < abs(y_end-y_begin)) and ((y_end - y_begin)<>0)  then
begin
 if y_begin>y_end then
 begin
  replace(x_begin,x_end);
  replace(y_begin,y_end);
 end;
 tg:=((x_begin-x_end)/(y_begin-y_end));
 for i:=y_begin to y_end do
 begin
  x:=x_begin+(i-y_begin)*tg;
  fx:=round(x);
  fy:=round(i);
  if (fy<image.Height-1) and (fy>=0) then
  begin
   p:=image.ScanLine[fy];
   if (fx<image.Width-1) and (fx>=0) then
   begin
    p[fx].r:=r;
    p[fx].g:=g;
    p[fx].b:=b;
    p[fx].l:=255;
   end;
  end;
 end;
end;
if  (abs(x_end-x_begin) >= abs(y_end-y_begin)) and ((x_end - x_begin)<>0) then
begin
 if x_begin>x_end then
 begin
  replace(x_begin,x_end);
  replace(y_begin,y_end);
 end;
 tg:=((y_end-y_begin)/(x_end-x_begin));
 for i:=x_begin to x_end do
 begin
  y:=y_begin+(i-x_begin)*tg;
  fx:=round(i);
  fy:=round(y);
  if (fy<image.Height-1) and (fy>=0) then
  begin
   p:=image.ScanLine[fy];
   if (fx<image.Width-1) and (fx>=0) then
   begin
    p[fx].r:=r;
    p[fx].g:=g;
    p[fx].b:=b;
    p[fx].l:=255;
   end;
  end;
 end;
end;
end;

procedure TEditor.Open1Click(Sender: TObject);
var
 pic : TPicture;
begin
if OpenPictureDialog1.Execute then
begin
 pic := TPicture.Create;
 try
  pic.LoadFromFile(OpenPictureDialog1.FileName);
 except
  pic.free;
  exit;
 end;
 LoadProgramImageFormat(pic);
 pic.free;
 MakeImage;
 FormPaint(self);
 Panel2Resize(self)
end;
end;

procedure TEditor.FormCreate(Sender: TObject);
begin
CurrentImage:=TBitmap.Create;
CurrentImage.PixelFormat:=pf32bit; //!!!!
CurrentImage.Width:=0;
CurrentImage.Height:=0;
Buffer:=TBitmap.Create;
Buffer.PixelFormat:=pf24bit;
Tool:=ToolNone;
end;

procedure TEditor.Panel2Resize(Sender: TObject);
begin
Buffer.Width:=Max(1,ClientWidth-ToolsPanel.Width-ScrollBar2.Width);
Buffer.Height:=Max(1,ToolsPanel.Height-ScrollBar1.Height);
ScrollBar1.Width:=ClientWidth-ToolsPanel.Width-ScrollBar2.Width;
ScrollBar1.Top:=ClientHeight-ScrollBar1.Height;
ScrollBar2.left:=ClientWidth-ScrollBar2.Width;
ScrollBar2.Height:=ToolsPanel.Height-ScrollBar1.Height;
ScrollBar1.Max:=Max(0,CurrentImage.Width-Buffer.Width);
ScrollBar2.Max:=Max(0,CurrentImage.Height-Buffer.Height);
MakeImage;
FormPaint(nil);
end;

procedure TEditor.MakeImage;
var
 i, j : integer;
 p : PARGB;
 p32 : PARGB32;
 Color1, Color2 : TColor;
 r1,r2,g1,g2,b1,b2 : byte;
begin
Color1:=$FFFFFF;
Color2:=$A1A1A1;
r1:=GetRValue(Color1);
g1:=GetGValue(Color1);
b1:=GetBValue(Color1);
r2:=GetRValue(Color2);
g2:=GetGValue(Color2);
b2:=GetBValue(Color2);
for i:=0 to Buffer.Height-1 do
begin
 p:=Buffer.ScanLine[i];
 for j:=0 to Buffer.Width-1 do
 begin
  if odd((i*j) div 5) then //фоновый рисунок :)
  begin
   p[j].r:=r1;
   p[j].g:=g1;
   p[j].b:=b1;
  end else
  begin
   p[j].r:=r2;
   p[j].g:=g2;
   p[j].b:=b2;
  end;
 end;
end;
for i:=0 to Math.Min(Buffer.Height-2,CurrentImage.Height-1) do
begin
 p:=Buffer.ScanLine[i+1];
 if i+ScrollBar2.Position>CurrentImage.Height-1 then Break;
 p32:=CurrentImage.ScanLine[i+ScrollBar2.Position];
 for j:=0 to Math.Min(Buffer.Width-2,CurrentImage.Width-1) do
 begin
  if j>CurrentImage.Width-1 then Break;
  p[j+1].r:=Round((p32[j+ScrollBar1.Position].r)*(p32[j+ScrollBar1.Position].l/255)+p[j+1].r*(1-p32[j+ScrollBar1.Position].l/255));
  p[j+1].g:=Round((p32[j+ScrollBar1.Position].g)*(p32[j+ScrollBar1.Position].l/255)+p[j+1].g*(1-p32[j+ScrollBar1.Position].l/255));
  p[j+1].b:=Round((p32[j+ScrollBar1.Position].b)*(p32[j+ScrollBar1.Position].l/255)+p[j+1].b*(1-p32[j+ScrollBar1.Position].l/255));
 end;
end;
for i:=0 to Math.Min(Buffer.Height-1,CurrentImage.Height-1) do
begin
 p:=Buffer.ScanLine[i];
 p[0].r:=0;
 p[0].g:=0;
 p[0].b:=0;
end;
p:=Buffer.ScanLine[0];
for j:=0 to Math.Min(Buffer.Width-2,CurrentImage.Width-1) do
begin
 p[j].r:=0;
 p[j].g:=0;
 p[j].b:=0;
end;
if Buffer.Width-1>CurrentImage.Width-1 then
for i:=0 to Math.Min(Buffer.Height-1,CurrentImage.Height-1) do
begin
 p:=Buffer.ScanLine[i];
 p[CurrentImage.Width].r:=0;
 p[CurrentImage.Width].g:=0;
 p[CurrentImage.Width].b:=0;
end;
if Buffer.Height-1>CurrentImage.Height-1 then
begin
 p:=Buffer.ScanLine[CurrentImage.Height];
 for j:=0 to Math.Min(Buffer.Width-2,CurrentImage.Width-1) do
 begin
  p[j].r:=0;
  p[j].g:=0;
  p[j].b:=0;
 end;
end;
end;

procedure TEditor.FormPaint(Sender: TObject);
begin
Canvas.Draw(ToolsPanel.Width,0,Buffer);
end;

procedure TEditor.LoadProgramImageFormat(Pic: TPicture);
var
 Bitmap : TBitmap;
begin
if Pic.Graphic is TJPEGImage then
begin
 LoadJPEGImage(Pic.Graphic as TJPEGImage);
end;
if Pic.Graphic is TBitmap then
begin
 LoadBMPImage(Pic.Graphic as TBitmap);
end;
if Pic.Graphic is TGIFImage then
begin
 LoadGIFImage(Pic.Graphic as TGIFImage);
end;
end;

procedure TEditor.LoadJPEGImage(JPEG : TJPEGImage);
var
 Temp : TBitmap;
 i, j : integer;
 p : PARGB;
 p32 : PARGB32;
begin
Temp := TBitmap.Create;
Temp.Assign(JPEG);
Temp.PixelFormat:=pf24bit;
CurrentImage.Width:=Temp.Width;
CurrentImage.Height:=Temp.Height;
CurrentImage.PixelFormat:=pf32bit;
for i:=0 to Temp.Height-1 do
begin
 p:=Temp.ScanLine[i];
 p32:=CurrentImage.ScanLine[i];
 for j:=0 to Temp.Width-1 do
 begin
  p32[j].r:=p[j].r;
  p32[j].g:=p[j].g;
  p32[j].b:=p[j].b;
  p32[j].l:=255;
 end;
end;
Temp.Free;
end;

procedure TEditor.LoadBMPImage(Bitmap: TBitmap);
var
 i, j : integer;
 p : PARGB;
 p32 : PARGB32;
begin
CurrentImage.Width:=Bitmap.Width;
CurrentImage.Height:=Bitmap.Height;
CurrentImage.PixelFormat:=pf32bit;
if Bitmap.PixelFormat<>pf32bit then
begin
 Bitmap.PixelFormat:=pf24bit;
 for i:=0 to Bitmap.Height-1 do
 begin
  p:=Bitmap.ScanLine[i];
  p32:=CurrentImage.ScanLine[i];
  for j:=0 to Bitmap.Width-1 do
  begin
   p32[j].r:=p[j].r;
   p32[j].g:=p[j].g;
   p32[j].b:=p[j].b;
   p32[j].l:=255;
  end;
end;
end else
begin
 CurrentImage.Assign(Bitmap);
end;
end;

procedure TEditor.LoadGIFImage(GIF: TGIFImage);
var
 i, j : integer;
 p32 : PARGB32;
begin
CurrentImage.Width:=GIF.Width;
CurrentImage.Height:=GIF.Height;
CurrentImage.Assign(GIF);
CurrentImage.PixelFormat:=pf32bit;
for i:=0 to GIF.Height-1 do
begin
 p32:=CurrentImage.ScanLine[i];
 for j:=0 to GIF.Width-1 do
 begin
  if GIF.Images[0].Pixels[j,i]=GIF.Images[0].GraphicControlExtension.TransparentColorIndex then
  p32[j].l:=0 else p32[j].l:=255;
 end;
end;
end;

procedure TEditor.Shape1MouseDown(Sender: TObject; Button: TMouseButton;
 Shift: TShiftState; X, Y: Integer);
begin
ColorDialog1.Color:=Shape1.Brush.Color;
if ColorDialog1.Execute then
Shape1.Brush.Color:=ColorDialog1.Color;
end;

procedure TEditor.FormMouseDown(Sender: TObject; Button: TMouseButton;
 Shift: TShiftState; X, Y: Integer);
begin
Tool:=ToolPen;
BeginPoint:=Point(x-ToolsPanel.Width,y);
Line(CurrentImage,BeginPoint.X+ScrollBar1.Position,BeginPoint.Y+ScrollBar2.Position,x-ToolsPanel.Width+ScrollBar1.Position,y+ScrollBar2.Position,Shape1.Brush.Color);
end;

procedure TEditor.FormMouseUp(Sender: TObject; Button: TMouseButton;
 Shift: TShiftState; X, Y: Integer);
begin
Tool:=ToolNone;
end;

procedure TEditor.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
 Y: Integer);
begin
if Tool=ToolPen then
begin
 Line(CurrentImage,BeginPoint.X+ScrollBar1.Position,BeginPoint.Y+ScrollBar2.Position,x-ToolsPanel.Width+ScrollBar1.Position,y+ScrollBar2.Position,Shape1.Brush.Color);
 BeginPoint:=Point(x-ToolsPanel.Width,y);
end;
MakeImage;
FormPaint(nil);
end;

procedure TEditor.ScrollBar2Change(Sender: TObject);
begin
MakeImage;
FormPaint(nil);
end;

end.


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)