Search code examples
imagedelphiimage-quality

Image quality poor after loading into Image control in comparison to original


I got an app that loads images into the Zimage(graphcontrol). One issue I am having is the original image is a lot better quality than the one that ends up showing in the component. The one showing looks like it has random black marks on it. So what I do:

  • Load the image from a folder into TJpegimage

  • Assign jpg to a bitmap

  • Save bitmap to object list

  • Repeat that above until all images are loaded into object list

  • Then I create a bitmap

  • Assign the first image in the object list to it

  • Draw the bitmap on canvas

But it just looks a lot worse than the original. Any help or idea on this?

This is the loading code.

procedure TForm1.LoadImages(const Dir: string);
var
  i: Integer;
  CurFileName: string;
  JpgIn: TJPEGImage;
  BmpOut: TBitmap;
begin

//set up progress bar
 progressbar1.Min := 0;
 progressbar1.Max := GetFilesCount(dir,'*.*');
 Label3.Visible := true;
 progressbar1.Visible := true;
//sets array for length
  SetLength(hwArray,GetFilesCount(dir,'*.*'));
//sets index for object list
  CurIdx := -1;
  i := 0;
  while True do
  begin
//gets file name out of current folder
    CurFileName := Format('%s%d.jpg',
                          [IncludeTrailingPathDelimiter(Dir), i]);
    if not FileExists(CurFileName) then
      Break;
//count files in folder for progress bar.
     progressbar1.StepBy(1);
//creates jpgin
    JpgIn := TJPEGImage.Create;
    try
//loads jpgin with file
      JpgIn.LoadFromFile(CurFileName);
//creates TBitmap and sets width to same as jpgs
      BmpOut := TBitmap.Create;
      bmpout.Width := jpgin.Width;
      bmpout.Height := jpgin.Height;
     try
         BmpOut.Assign(JpgIn);
//adds 1 to index for object list. thus starting at 0
         curIdx := curIdx+1;
//add bitmap to objectlist
         CurIdx:= mylist.Add(TBitmap(bmpout));
         hwArray[CurIdx][0]:=jpgin.Width;
         hwArray[CurIdx][1]:=jpgin.height;

      finally
      end;
    finally
      JpgIn.Free;
    end;
    Inc(i);
  end;
//makes sure cout is above 0 thus files added
  if mylist.Count > 0 then
  begin
      try
      CurIdx := 0;
      getBitmapfromList(CurIdx,bmpout);
      ZImage1.Bitmap.Assign(bmpout);
       //image1.Canvas.Assign(bmpout);
    finally
       BmpOut.Free;
    end;
  end;
  Label3.Visible := false;
  progressbar1.Visible := false;
  page:= '0';
  zimage1.DblClick;
end;

function get bit map from list

procedure Tform1.getBitmapfromList(index:integer;var Bitm:TBitmap);
begin
     Bitm.Assign(TBitmap(mylist[index]));
     if (Bitm.Width<>hwArray[index][0]) OR (Bitm.Height<>hwArray[index][1]) then begin
        ShowMessage('Size differs');
        Bitm.Width:=hwArray[index][0];
        Bitm.Height:=hwArray[index][1];
     end;
end;

Button to view the next image:

procedure TForm1.Button3Click(Sender: TObject);
var
  BmpOut: TBitmap;
begin
  bmpout := TBitmap.Create;
  CurIdx:= strtoint(page);
  getBitmapfromList(CurIdx,bmpout);
  ZImage1.Bitmap.Assign(bmpout);
  //image1.Canvas.Assign(bmpout);
  page := inttostr(strtoint(page) +1);      //this should show next item in list?
  zimage1.Repaint;
end;

Thanks for any help or suggestions.

Here are the images:

Image loaded into my app using Delphi Programming Code on the left and original image on the rifht


EDIT:

It seems like once I zoom in on an image it gets better. the worst quality is when it's full screen/zoomed all the way out.. original size.


Solution

    • a) I assume that all images have a different size. If the displayed image "ZImage1" should have always the same height or width (one of two things, or it is made ​​with stretch fit == low quality) must be determined ratio (orginal.height / original.width).Then "ZImage1" (either height or width) must calculated in the new relationship.
    • b) Set ZImage1.AutoSize:=false;
    • c) Set ZImage1.Stretch:=false;

    • d) bmpout.Width and Height must set to the current mylist[CurIdx] size.

    bmpout.Assign(TBitmap(mylist[CurIdx]));
    Zimage1.Bitmap.Width := bmpout.Width;
    Zimage1.Bitmap.Height := bmpout.Height;
    ZImage1.Bitmap.Assign(bmpout);
    

    NOTE:

    You did NOT *assign* to mylist .. you store it CurIdx:= mylist.Add(TBitmap(bmpout));

    I can not see how you have created "mylist".

    Maybe that's the reason, if you want it back with bmpout.Assign(TBitmap(mylist[CurIdx]));, perhaps there is no automatic set bmpout.Width and bmpout.Height.

    TIP:

    create an extra array to store height and width.

    ....
    JpgIn.LoadFromFile(CurFileName);
    BmpOut := TBitmap.Create;
    bmpout.Width := jpgin.Width;
    bmpout.Height := jpgin.Height;
    ....
    CurIdx:= mylist.Add(TBitmap(bmpout));
    hwArray[CurIdx][0]:=jpgin.Width;
    hwArray[CurIdx][1]:=jpgin.height;
    ....
    

    make a procedure EDIT: put a test into it;

    procedure getBitmapfromList(index:integer;var Bitm:TBitmap);
    begin
         Bitm.Assign(TBitmap(mylist[index]));
         if (Bitm.Width<>hwArray[index][0]) OR (Bitm.Height<>hwArray[index][1]) then begin
            ShowMessage('Size differs');
            Bitm.Width:=hwArray[index][0];
            Bitm.Height:=hwArray[index][1];
         end;
    end;
    

    call it with:

    ....
    getBitmapfromList(CurIdx,bmpout);
    ....
    ZImage1.Bitmap.Assign(bmpout);
    ....  
    

    EDIT: Create hwArray

    type
      Tarray2size = Array[0..1] of integer;
    .... 
    
    var
      hwArray : Array of Tarray2size;
    ....
    
    procedure TForm1.LoadImages(const Dir: string);
    ....
    begin
     //set up progress bar
     progressbar1.Min := 0;
     showmessage(inttostr(GetFilesCount(dir,'*.*')));
     SetLength(hwArray,GetFilesCount(dir,'*.*'));
    ....