Search code examples
delphifiremonkey

Why uploaded photo is much smaller than saved - Delphi 10.3.2, firemonkey


I have Delphi 10.3.2 I do not understand this situations:

1) Uploading photo about 1M

image1.Bitmap.LoadFromFile('test.jpg');

Then I save the same photo

image1.Bitmap.SaveToFile('test_new.jpg');

and test_new.jpg is about 3M. Why ???

2)

I want to send a photo from the TImage (test1.jpg - 1MB) object using IdHTTP and POST request to server. I use the function Base64_Encoding_stream to encode image. Image size (string) after encoding the function is 20 MB! ? Why if the original file has 1MB ?

function Base64_Encoding_stream(_image:Timage): string;
var
  base64: TIdEncoderMIME;
  output: string;
  stream_image : TStream;
begin
    try
      begin
        base64 := TIdEncoderMIME.Create(nil);
        stream_image := TMemoryStream.Create;
        _image.Bitmap.SaveToStream(stream_image);
        stream_image.Position := 0;
        output := TIdEncoderMIME.EncodeStream(stream_image);
        stream_image.Free;
        base64.Free;
        if not(output = '') then
        begin
          Result := output;
        end
        else
        begin
          Result := 'Error';
        end;
      end;
    except
      begin
        Result := 'Error'
      end;
    end;
 end;


....

img_encoded := Base64_Encoding_stream(Image1);

.....

procedure Send(_json:String );
var
  lHTTP             : TIdHTTP;
  PostData          : TStringList;
begin
  PostData := TStringList.Create;
  lHTTP := TIdHTTP.Create(nil);
  try
      PostData.Add('dane='  + _json );
      lHTTP.Request.UserAgent   :=   'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0';
      lHTTP.Request.Connection  := 'keep-alive';
      lHTTP.Request.ContentType := 'application/x-www-form-urlencoded';
      lHTTP.Request.Charset     := 'utf-8';
      lHTTP.Request.Method      := 'POST';

    _dane := lHTTP.Post('http://......./add_photo.php',PostData);

  finally
    lHTTP.Free;
    PostData.Free;
end;



Solution

  • To post your original file using base64 you can basically use your own code. You only need to change the used stream inside your base64 encoding routine like this:

    function Base64_Encoding_stream(const filename: string): string;
    var
      stream_image : TStream;
    begin
      try
        // create read-only stream to access the file data
        stream_image := TFileStream.Create(filename, fmOpenRead or fmShareDenyWrite);
        // the stream position will be ‘0’, so no need to set that
        Try
          Result := TIdEncoderMIME.EncodeStream(stream_image);
        Finally
          stream_image.Free;
        End;
        if length(result) = 0 then
        begin
          Result := 'Error';
        end;
      except
        Result := 'Error'
      end;
    end;
    

    Also, I refactored your code a bit with some try/finally sections, to ensure no memory leaks when errors occur. And I removed the begin/end inside the try/except as those are not needed.

    Also removed the local string variable to avoid double string allocation and the unnecessary construction of the TIdEncoderMIME base64 object.