Reputation: 4008
I'm writing a program that:
1.- Ask the user to select a file, Any kind of image (JPG, PNG, etc)
2.- Let's user pixellate the image and shows the new pixellated image.
Since my test image is a JPG, I'm getting error: Incompatible types: 'TPersistent' and 'TFileName'
Before trying to convert the JPG to Bitmap, I was getting:
Bitmap image is not valid
Code:
unit demo_2;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, Vcl.Imaging.Jpeg;
var
OpenDialog: TOpenDialog;
OpenFolder: TFileOpenDialog;
OriginalImage: TBitmap;
PixellatedImage: TBitmap;
type
TForm1 = class(TForm)
btn1_select_img: TButton;
btn2_select_output_path: TButton;
lbl_selected_file: TLabel;
lbl_output_path: TLabel;
img1: TImage;
pnl_img: TPanel;
pnl_btns: TPanel;
procedure btn1_select_imgClick(Sender: TObject);
procedure btn2_select_output_pathClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.btn1_select_imgClick(Sender: TObject);
begin
OpenDialog := TOpenDialog.Create(nil);
OpenDialog.Filter := 'All Files|*.*';
OpenDialog.Options := [ofPathMustExist, ofFileMustExist];
try
if OpenDialog.Execute then
begin
// Print the selected file's path to the console
//WriteLn(OpenDialog.FileName);
lbl_selected_file.Caption := OpenDialog.FileName;
img1.Picture.LoadFromFile(OpenDialog.FileName);
end;
finally
//OpenDialog.Free;
end;
end;
procedure TForm1.btn2_select_output_pathClick(Sender: TObject);
begin
//OpenFolder := TFileOpenDialog.Create(nil); for folder selection
//OpenFolder.Options := [fdoPickFolders]; for folder selection
try
//if OpenFolder.Execute then
begin
PixellatedImage := TBitmap.Create;
//PixellatedImage.LoadFromFile(OpenDialog.FileName);
PixellatedImage.Assign(OpenDialog.FileName);
// Pixellate the image by setting the Width and Height to a small value
PixellatedImage.Width := 10;
PixellatedImage.Height := 10;
img1.Picture.Bitmap := PixellatedImage;
//lbl_output_path.Caption := OpenFolder.FileName; for folder selection
end;
finally
//OpenFolder.Free;
//OpenDialog.Free;
PixellatedImage.Free;
end;
end;
end.
Upvotes: 0
Views: 371
Reputation: 109068
Since my test image is a JPG, I'm getting error: Incompatible types: 'TPersistent' and 'TFileName'
Actually, that's wrong in the sense that the error has nothing to do with the image being JPG. So while both "my test image is a JPG" and "I'm getting error ..." are correct, the implication ("since") is not.
The TPersistent.Assign
method used in
PixellatedImage.Assign(OpenDialog.FileName);
requires a TPersistent
object. In this case, when you are dealing with graphics, you typically need a TGraphic
instance. Hence, you cannot pass a string, even if that string happens to be a file name of an image file.
So if you want to use the Assign
method on a graphics object, you need to pass it another graphics object -- one you may have loaded from file using its own LoadFromFile
:
procedure TForm1.FormCreate(Sender: TObject);
begin
var JpegImage := TJPEGImage.Create;
try
var OpenDlg := TFileOpenDialog.Create(Self);
try
with OpenDlg.FileTypes.Add do
begin
DisplayName := 'JPEG images';
FileMask := '*.jpg';
end;
if OpenDlg.Execute then
JpegImage.LoadFromFile(OpenDlg.FileName)
else
Exit;
finally
OpenDlg.Free;
end;
var BmpImage := TBitmap.Create;
try
BmpImage.Assign(JpegImage);
// For example: BmpImage.SaveToFile('K:\bitmap.bmp');
finally
BmpImage.Free;
end;
finally
JpegImage.Free;
end;
end;
Also, please note that you must use the idiom
LFrog := TFrog.Create;
try
// use LFrog
finally
LFrog.Free;
end
and never
try
LFrog := TFrog.Create;
// use LFrog
finally // WRONG!
LFrog.Free;
end
assuming LFrog
is a local variable. If LFrog
isn't a local variable, it probably should be made local! Otherwise, it is important to do FreeAndNil
on it and not only Free
.
Update. The Q was changed so it no longer is about JPG -> BMP, but "any" image file to BMP. Then perhaps the best way is to use the Windows Imaging Component:
procedure TForm1.FormCreate(Sender: TObject);
begin
var WicImage := TWICImage.Create;
try
var OpenDlg := TFileOpenDialog.Create(Self);
try
with OpenDlg.FileTypes.Add do
begin
DisplayName := 'All image files';
FileMask := '*.jpg;*.tiff;*.tif;*.png;*.gif;*.bmp';
end;
with OpenDlg.FileTypes.Add do
begin
DisplayName := 'JPEG images';
FileMask := '*.jpg';
end;
with OpenDlg.FileTypes.Add do
begin
DisplayName := 'TIFF images';
FileMask := '*.tiff;*.tif';
end;
with OpenDlg.FileTypes.Add do
begin
DisplayName := 'PNG images';
FileMask := '*.png';
end;
with OpenDlg.FileTypes.Add do
begin
DisplayName := 'GIF images';
FileMask := '*.gif';
end;
with OpenDlg.FileTypes.Add do
begin
DisplayName := 'Bitmap images';
FileMask := '*.bmp';
end;
// etc.
if OpenDlg.Execute then
WicImage.LoadFromFile(OpenDlg.FileName);
finally
OpenDlg.Free;
end;
var BmpImage := TBitmap.Create;
try
BmpImage.Assign(WicImage);
// For example: BmpImage.SaveToFile('K:\bitmap.bmp');
finally
BmpImage.Free;
end;
finally
WicImage.Free;
end;
end;
Finally, I note that you write
// Pixellate the image by setting the Width and Height to a small value PixellatedImage.Width := 10; PixellatedImage.Height := 10;
Although not relevant to your main question about TGraphic.Assign
, I should note that setting a TBitmap
's Width
and Height
very much doesn't pixelate the image in the usual sense of the word. (Algorithmically, pixelation should be done like in this Pixelate
procedure.)
Upvotes: 1