[SOLVED] SDL2 image rotation Problem lazarus / 39-Graphics ---------------------------------------------------------------------- Pe3s · 2024-12-13 20:54 Hello forumers I am learning SDL and I have encountered a problem after loading the image format “portrait” rotation and fitting the image to the window margins appear at the top and bottom , when loading the image format landscape the problem does not occur how can I correct the error in the code ? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit Unit1; {$mode objfpc}{$H+} interface usesClasses, SysUtils, Forms, Controls, Graphics, Dialogs, ComCtrls, ExtCtrls,  StdCtrls, SDL2, SDL2_image, Math; type   { TForm1 }   TForm1 = class(TForm)    Button1: TButton;    Button2: TButton;    Button3: TButton;    Button4: TButton;    Button5: TButton;    Button6: TButton;    Button7: TButton;    OpenDialog1: TOpenDialog;    Panel1: TPanel;    Panel2: TPanel;    StatusBar1: TStatusBar;    procedure Button1Click(Sender: TObject);    procedure Button2Click(Sender: TObject);    procedure Button3Click(Sender: TObject);    procedure Button4Click(Sender: TObject);    procedure Button5Click(Sender: TObject);    procedure Button6Click(Sender: TObject);    procedure Button7Click(Sender: TObject);    procedure FormDestroy(Sender: TObject);    procedure FormResize(Sender: TObject);    procedure FormShow(Sender: TObject);    procedure Panel1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);    procedure Panel1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);    procedure Panel1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);    procedure Panel1Paint(Sender: TObject);  private    SDLWindow: PSDL_Window;    SDLRenderer: PSDL_Renderer;    CurrentTexture: PSDL_Texture;     OffsetX, OffsetY, ZoomLevel, MinZoom, MaxZoom, FRotationAngle: Double;    IsPanning: Boolean;    LastMouseX, LastMouseY, ImgWidth, ImgHeight: Integer;     procedure InitializeSDL;    procedure ShutdownSDL;    procedure LoadAndDisplayImage(const FileName: string);    procedure RenderImage;    procedure CenterImage;    procedure Zoom(Delta: Double; FocusX, FocusY: Integer);    procedure FitImage;   public   end; var  Form1: TForm1; implementation {$R *.lfm} { TForm1 } procedure TForm1.FormShow(Sender: TObject);begin   InitializeSDL;  ZoomLevel := 1.0;  OffsetX := 0;  OffsetY := 0;  IsPanning := False;    ImgWidth := 0;  // No image loaded yet  ImgHeight := 0; // No image loaded yet  CurrentTexture := nil;end; procedure TForm1.Panel1MouseDown(Sender: TObject; Button: TMouseButton;  Shift: TShiftState; X, Y: Integer);begin  if Button = mbLeft then  begin    IsPanning := True;    LastMouseX := X;    LastMouseY := Y;  end;end; procedure TForm1.Panel1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);begin  if IsPanning then  begin    OffsetX := OffsetX + (X - LastMouseX);    OffsetY := OffsetY + (Y - LastMouseY);     LastMouseX := X;    LastMouseY := Y;     RenderImage;  end;end; procedure TForm1.Panel1MouseUp(Sender: TObject; Button: TMouseButton;  Shift: TShiftState; X, Y: Integer);begin    if Button = mbLeft then    IsPanning := False;end; procedure TForm1.Panel1Paint(Sender: TObject);begin   // Draw a red rectangle (example)  SDL_SetRenderDrawColor(sdlRenderer, 0, 0, 0, 255);  SDL_RenderFillRect(sdlRenderer, nil); // Full screen fill  SDL_RenderPresent(sdlRenderer);    RenderImage;end; procedure TForm1.FormDestroy(Sender: TObject);begin  ShutdownSDL;end; procedure TForm1.FormResize(Sender: TObject); var  PanelWidth, PanelHeight: Integer;begin  PanelWidth := Panel1.Width;  PanelHeight := Panel1.Height;   // Skip fitting or rendering if no image is loaded  if (ImgWidth = 0) or (ImgHeight = 0) then Exit;   // Check for valid dimensions before fitting or rendering  if (PanelWidth > 0) and (PanelHeight > 0) then  begin    FitImage; // Automatically fit the image on resize  end;end; procedure TForm1.Button1Click(Sender: TObject);begin   if OpenDialog1.Execute then    LoadAndDisplayImage(OpenDialog1.FileName);end; procedure TForm1.Button2Click(Sender: TObject);begin Zoom(1, Panel1.Width div 2, Panel1.Height div 2); // Zoom in towards the centerend; procedure TForm1.Button3Click(Sender: TObject);begin   Zoom(-1, Panel1.Width div 2, Panel1.Height div 2); // Zoom out towards the centeend; procedure TForm1.Button4Click(Sender: TObject);begin  ZoomLevel:= 1.0;  CenterImage;  RenderImage;end; procedure TForm1.Button5Click(Sender: TObject);begin     FitImage; // Reset zoom and center the imageend; procedure TForm1.Button6Click(Sender: TObject);begin  FRotationAngle := (FRotationAngle -90) mod 360;  RenderImage;end; procedure TForm1.Button7Click(Sender: TObject);begin  FRotationAngle := (FRotationAngle +90) mod 360;  RenderImage;end; procedure TForm1.InitializeSDL;begin  if SDL_Init(SDL_INIT_VIDEO) < 0 then    raise Exception.Create('Nie udało się zainicjować SDL: ' + SDL_GetError);   SDLWindow := SDL_CreateWindowFrom(Pointer(Panel1.Handle));  if SDLWindow = nil then    raise Exception.Create('Nie udało się utworzyć okna SDL: ' + SDL_GetError);   SDLRenderer := SDL_CreateRenderer(sdlWindow, -1, SDL_RENDERER_ACCELERATED or SDL_RENDERER_PRESENTVSYNC);  if SDLRenderer = nil then    raise Exception.Create('Nie można utworzyć renderowania SDL: ' + SDL_GetError);   ZoomLevel := 1.0; // Initialize zoom level end; procedure TForm1.ShutdownSDL;begin   if CurrentTexture <> nil then    SDL_DestroyTexture(CurrentTexture);  if SDLRenderer <> nil then    SDL_DestroyRenderer(SDLRenderer);  if SDLWindow <> nil then    SDL_DestroyWindow(SDLWindow);  IMG_Quit;  SDL_Quit;end; procedure TForm1.LoadAndDisplayImage(const FileName: string);  var  PanelWidth, PanelHeight: Integer;  FitZoom: Double;begin  if CurrentTexture <> nil then    SDL_DestroyTexture(CurrentTexture);   CurrentTexture := IMG_LoadTexture(SDLRenderer, PChar(FileName));  if CurrentTexture = nil then    raise Exception.Create('Nie udało się wczytać tekstury: ' + IMG_GetError);   // Query the texture for its dimensions  SDL_QueryTexture(CurrentTexture, nil, nil, @ImgWidth, @ImgHeight);    // Calculate initial zoom to fit the image in the panel  PanelWidth := Panel1.Width;  PanelHeight := Panel1.Height;  FitZoom := Min(PanelWidth / ImgWidth, PanelHeight / ImgHeight);   // Set zoom level and center offsets  ZoomLevel := FitZoom;  OffsetX := (PanelWidth - Round(ImgWidth * ZoomLevel)) div 2;  OffsetY := (PanelHeight - Round(ImgHeight * ZoomLevel)) div 2;   // Set zoom limits  MinZoom := FitZoom * 0.5; // Allow zooming out to 50% of fit size  MaxZoom := 3.0; // Allow zooming in up to 300%   RenderImage;  FitImage;end; procedure TForm1.RenderImage;  var    DstRect: TSDL_Rect;    PanelWidth, PanelHeight: Integer;  begin    if CurrentTexture = nil then Exit; // No texture to render     PanelWidth := Panel1.Width;    PanelHeight := Panel1.Height;     if (PanelWidth <= 0) or (PanelHeight <= 0) then Exit; // Avoid rendering if panel is invalid     // Calculate destination rectangle with zoom and offsets  DstRect.w := Round(ImgWidth * ZoomLevel);    DstRect.h := Round(ImgHeight * ZoomLevel);     // Constrain panning to avoid blank spaces    if DstRect.w <= PanelWidth then      OffsetX := (PanelWidth - DstRect.w) / 2    else      OffsetX := Max(Min(OffsetX, 0), PanelWidth - DstRect.w);     if DstRect.h <= PanelHeight then      OffsetY := (PanelHeight - DstRect.h) / 2    else      OffsetY := Max(Min(OffsetY, 0), PanelHeight - DstRect.h);     DstRect.x := Round(OffsetX);    DstRect.y := Round(OffsetY);     SDL_RenderClear(SDLRenderer);     // Render the image    SDL_RenderCopyEx(SDLRenderer, CurrentTexture, nil, @DstRect, FRotationAngle, nil, SDL_FLIP_NONE);    SDL_RenderPresent(SDLRenderer);end; procedure TForm1.CenterImage; var  PanelWidth, PanelHeight: Integer;begin  if (ImgWidth = 0) or (ImgHeight = 0) or (CurrentTexture = nil) then Exit;   PanelWidth := Panel1.Width;  PanelHeight := Panel1.Height;   // Reset offsets to center the image  OffsetX := (PanelWidth - ImgWidth * ZoomLevel) / 2;  OffsetY := (PanelHeight - ImgHeight * ZoomLevel) / 2;   RenderImage;end; procedure TForm1.Zoom(Delta: Double; FocusX, FocusY: Integer); var  OldZoom: Double;  PanelWidth, PanelHeight: Integer;  ImageCenterX, ImageCenterY: Double;begin  if (ImgWidth = 0) or (ImgHeight = 0) or (CurrentTexture = nil) then Exit;   OldZoom := ZoomLevel;  PanelWidth := Panel1.Width;  PanelHeight := Panel1.Height;   // Adjust zoom level with bounds  ZoomLevel := Max(MinZoom, Min(MaxZoom, ZoomLevel + Delta * 0.1));   // Compute focus point scaling  if ZoomLevel <> OldZoom then  begin    ImageCenterX := (FocusX - OffsetX) / OldZoom;    ImageCenterY := (FocusY - OffsetY) / OldZoom;     OffsetX := FocusX - ImageCenterX * ZoomLevel;    OffsetY := FocusY - ImageCenterY * ZoomLevel;  end;   // Update caption  Form1.Caption := Format('Zoom: %.0f%%', [ZoomLevel * 100]);   RenderImage;end; procedure TForm1.FitImage; var  RotatedWidth, RotatedHeight: Double;  ScalingFactor: Double;  AngleRadians: Double;begin  if (ImgWidth = 0) or (ImgHeight = 0) or (CurrentTexture = nil) then Exit;   // Normalize the rotation angle to the range [0, 360)  AngleRadians := DegToRad((FRotationAngle mod 360 + 360) mod 360);   // Calculate rotated bounding box dimensions  RotatedWidth := Abs(ImgWidth * Cos(AngleRadians)) + Abs(ImgHeight * Sin(AngleRadians));  RotatedHeight := Abs(ImgWidth * Sin(AngleRadians)) + Abs(ImgHeight * Cos(AngleRadians));   // Calculate scaling factor to fit the panel's height  ScalingFactor := Panel1.Height / RotatedHeight;   // Update the zoom level to maintain proportional scaling  ZoomLevel := ScalingFactor;   // Recalculate offsets to ensure proper centering  CenterImage;end; end.   Greetings ---------------------------------------------------------------------- bobihot · 2024-12-13 21:31 Try with Lazarus-SDL3.0-Packages_and_Examples https://github.com/sechshelme/Lazarus-SDL3.0-Packages_and_Examples Me also interested, because I was used on Delphi. But I do not try now. Thanks ---------------------------------------------------------------------- Pe3s · 2024-12-14 18:18 This is not an SDL bug rather my code. The loaded image in landscape aspect ratio works , but when I load a portrait there is a problem when rotating. ---------------------------------------------------------------------- Pe3s · 2024-12-18 11:08 How can I dynamically swap the height with the width and update the sdl window ? So that the rotated image will adjust to the window ---------------------------------------------------------------------- Roland57 · 2024-12-19 01:21 Hello! By the way, I can compile your project, but I get this error when I try to run it: [roland@localhost sdl_image]$ ./project1 The program 'project1' received an X Window System error. This probably reflects a bug in the program. The error was 'BadWindow (invalid Window parameter)'.   (Details: serial 88 error_code 3 request_code 20 minor_code 0)   (Note to programmers: normally, X errors are reported asynchronously;    that is, you will receive the error a while after causing it.    To debug your program, run it with the --sync command line    option to change this behavior. You can then get a meaningful    backtrace from your debugger if you break on the gdk_x_error() function.) I took a look at your code. The logic is too complicated for me. ---------------------------------------------------------------------- Pe3s · 2024-12-19 13:30 Under Windows it compiles and runs correctly ---------------------------------------------------------------------- Fred vS · 2024-12-19 14:15 Quote from: Roland57 on December 19, 2024, 02:21:28 amHello! By the way, I can compile your project, but I get this error when I try to run it: [roland@localhost sdl_image]$ ./project1 The program 'project1' received an X Window System error. This probably reflects a bug in the program. The error was 'BadWindow (invalid Window parameter)'.   (Details: serial 88 error_code 3 request_code 20 minor_code 0)   (Note to programmers: normally, X errors are reported asynchronously;    that is, you will receive the error a while after causing it.    To debug your program, run it with the --sync command line    option to change this behavior. You can then get a meaningful    backtrace from your debugger if you break on the gdk_x_error() function.) I took a look at your code. The logic is too complicated for me.  Hello Roland. On Linux, maybe you can try with msegui: https://github.com/mse-org/mseide-msegui/discussions/94 Fre;D ---------------------------------------------------------------------- Pe3s · 2024-12-30 06:40 Below I present a visualization of image rotation as SDL performs it. The problem that I can't solve is this image rotation with swapping image dimensions. ---------------------------------------------------------------------- Pe3s · 2025-01-03 06:52 Below are two images the first loaded not rotated and the second rotated with incorrect proportions which I am trying to fix ---------------------------------------------------------------------- Seenkao · 2025-01-03 23:11 Pe3s, вам ни кто не сможет помочь, хотя бы по простой причине, что непонятно, как вы поворачиваете свой объект. Даже люди использующие SDL вряд ли смогут вам помочь. Поворот может быть выполнен несколькими способами: - повернули весь экран. - повернули текстуру. - повернули объект. - какой-то другой способ? Если вы повернули весь экран, то это означает, что вы не учитываете при повороте ни какого масштаба. И просто повернули экран так, будь-то он  квадратный, а не прямоугольный (надо либо обрезать, либо масштабировать экран), для прямоугольного экрана, при повороте, надо пересчитывать все объекты согласно поворота и согласно центра экрана. Если вы повернули объект или текстуру, то вероятно вы та же проблема что и выше, только тут вам для поворота надо пересчитывать координаты объекта или текстуры соответственно (помнить, что вы поворачиваете не квадрат, а прямоугольник). Без вашего кода, сложно что-то вообще говорить о вашей проблеме. ------------------------------------------------ Google translate: Pe3s, no one can help you, at least for the simple reason that it is not clear how you rotate your object. Even people using SDL are unlikely to be able to help you. Rotation can be done in several ways: - rotated the entire screen. - rotated the texture. - rotated the object. - some other way? If you rotated the entire screen, this means that you do not take into account any scale when rotating. And you simply rotated the screen, whether it is square, and not rectangular (you either need to crop or scale the screen), for a rectangular screen, when rotating, you need to recalculate all objects according to the rotation and according to the center of the screen. If you rotated an object or texture, then you probably have the same problem as above, only here you need to recalculate the coordinates of the object or texture accordingly (remember that you are rotating not a square, but a rectangle). Without your code, it is difficult to say anything about your problem. ---------------------------------------------------------------------- Pe3s · 2025-01-05 07:02 @Seenkao, If you are able to help, please provide the entire code ---------------------------------------------------------------------- Pe3s · 2025-01-11 17:08 Can anyone help or is it over with the code questions ---------------------------------------------------------------------- Fred vS · 2025-01-12 20:05 Quote from: Pe3s on January 11, 2025, 06:08:53 pmCan anyone help or is it over with the code questions Maybe if you add a valid tar it would be easier. (and dont use space " " but "_" instead ) Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i $ tar -xvzf Image_Browser_0.3.rar gzip: stdin: not in gzip formattar: Child returned status 1tar: Error is not recoverable: exiting now About rotation of image, I cannot see your code but if you use that method to load it: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i SDL_LoadBMPFromFile('aimage.bmp');A workaround would be to use BGRABitmap and do the rotation of the original file or already loaded bitmap and save it as tempory bmp. Then reload the new rotated image with SDL_LoadBMPFromFile('arotatedimage.bmp') then delete it. But I agree it is a workaround. Note that I am a new explorer of SDL2 and I tested it only using MSEgui. https://github.com/mse-org/mseide-msegui/discussions/94 ---------------------------------------------------------------------- TRon · 2025-01-12 20:14 Quote from: Fred vS on January 12, 2025, 09:05:55 pmgzip: stdin: not in gzip format tar: Child returned status 1 tar: Error is not recoverable: exiting now You could use either 7z or (un)rar to extract rar archives. tar is not able to do that. ---------------------------------------------------------------------- Fred vS · 2025-01-12 20:30 Quote from: TRon on January 12, 2025, 09:14:15 pmQuote from: Fred vS on January 12, 2025, 09:05:55 pmgzip: stdin: not in gzip format tar: Child returned status 1 tar: Error is not recoverable: exiting now You could use either 7z or (un)rar to extract rar archives. tar is not able to do that. Hello TRon. unrar did the trick, thanks (but 7z failed, all the files have 0kb). ---------------------------------------------------------------------- Pe3s · 2025-01-13 16:07 I found a solution to my problem only that in Delphi there is a component ImageEn however, you have to reckon with the cost of buying a license. However, for graphics it is a great solution. Greetings ---------------------------------------------------------------------- TRon · 2025-01-13 21:00 Quote from: Roland57 on December 19, 2024, 02:21:28 amBy the way, I can compile your project, but I get this error when I try to run it: The SDLCreateWindowFrom function in combination with LCL only works for the Windows platform (other platforms/widgetsets require a special handle that allows for graphics to be drawn onto the canvas). Quote from: Pe3s on January 11, 2025, 06:08:53 pmCan anyone help or is it over with the code questions I order to be able to test your code it needs to be rewritten when doing so for a platform besides Windows. Seenkao's questions are still valid because I also do not have a clue what it is that you are actually trying to achieve. The rotating works with keeping the aspect ratio of the original image. You do not seem to want that but do not mention what the result should become. Should the image be resized to match the canvas, should the image be scaled to match the largest dimensions keeping the original aspect ratio and cut off everything that is out of range, should it resize the size of the canvas to match the (rotated)_ picture etc. etc. No answers means we would have to come up with all possible scenario's while you seem to fancy only one of them (whatever that scenario might be) ---------------------------------------------------------------------- Pe3s · 2025-01-14 07:44 @TRon I want that after rotation the image would fit according to the proportions of the window, plot, etc. Let's take such an example, for example, from the IrfanView viewer if we rotate the image, then the image dimensions swap places and the image is adjusted to the window. In my code if we read an image for example in portrait format then after rotation the image is smaller and does not fit the window. Greetings ---------------------------------------------------------------------- Pe3s · 2025-01-14 09:19 so I wonder if it would not help to dynamically swap the dimensions of the plot, only that sdl permanently holds the dimension of the loaded image. - If we load an image with dimensions: 200x300px then after a 90 degree rotation the dimensions should change to 300x200, after another rotation 200x300, after another 300x200 and finally return to 200x300, and the image should be adjusted to the proportions of the window in the case of large images. ---------------------------------------------------------------------- Fred vS · 2025-01-14 22:18 Hello Pe3s. In case you are not angry with me, here code to rotate image with SDL2. Yes, Grok helps me but I must help him a lot too. There are 2 images rendered, one from the png and the other is a rotation of the first image. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var image_texture: PSDL_Texture = nil; rotated_image_texture: PSDL_Texture = nil; image_rect: TSDL_Rect = (x: 0; y: 0; w: 0; h: 0); rotated_image_rect: TSDL_Rect = (x: 0; y: 0; w: 0; h: 0); ... procedure load_images;varimage_surface: PSDL_Surface;begin  // Load first image  image_surface := IMG_Load('/path/of/image.png');  if image_surface = nil then  begin    WriteLn('Unable to load image! SDL_image Error: ', IMG_GetError());    Exit;  end else  begin    WriteLn('First Image loaded successfully.');  end;   image_texture := SDL_CreateTextureFromSurface(renderer, image_surface);  SDL_QueryTexture(image_texture, nil, nil, @image_rect.w, @image_rect.h);   // Use the same texture for rotation during rendering  rotated_image_texture := image_texture;  SDL_QueryTexture(rotated_image_texture, nil, nil, @rotated_image_rect.w, @rotated_image_rect.h);   SDL_FreeSurface(image_surface);end; procedure render;begin  SDL_SetRenderDrawColor(renderer, 50, 50, 50, 255);  SDL_RenderClear(renderer);   // Draw images first from png  if Assigned(image_texture) then  begin    SDL_RenderCopy(renderer, image_texture, nil, @image_rect);  end;   // Draw rotated image  if Assigned(rotated_image_texture) then  begin    SDL_RenderCopyEx(renderer, rotated_image_texture, nil, @rotated_image_rect, 90, nil, SDL_FLIP_NONE);  end;    SDL_QueryTexture(rotated_image_texture, nil, nil, @rotated_width, @rotated_height);        // Adjust the rectangle for left alignment  rotated_image_rect.x := image_rect.w + 150 ;// Left align    rotated_image_rect.y := 120; // Position as before or adjust vertically if needed    rotated_image_rect.w := rotated_width; // Width stays the same as it was after rotation    rotated_image_rect.h := rotated_height; // Height stays the same as it was after rotationend; ---------------------------------------------------------------------- Pe3s · 2025-01-15 09:12 @Fred vS, I am not angry, I adhere to the principle that a smile is better than anger. I'm just looking for a solution. I am grateful for any comment and help . Thank you and Greetings with a smile. ---------------------------------------------------------------------- Fred vS · 2025-01-15 11:23 Quote from: Pe3s on January 15, 2025, 10:12:11 am@Fred vS, I am not angry, I adhere to the principle that a smile is better than anger. I'm just looking for a solution. I am grateful for any comment and help . Thank you and Greetings with a smile. Hello Pe3s. Nice answer and good feeling. I am in the same boat as you, exploring sdl2. In a previous post I told you about the fantastic graphical tool: BGRABitmap. It can be perfectly used with sdl2 and will allow to do complicated image manipulations. Here is the code that loads a image.png into an sdl2 image and rotates it using BGRABitmap and this rotated bitmap is filled into another sdl2 image. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i uses  SysUtils, SDL2, SDL2_image, BGRABitmap, BGRABitmapTypes; ... var  window: PSDL_Window;  renderer: PSDL_Renderer;  running: Boolean = True;  original_texture, rotated_texture: PSDL_Texture;  original_rect, rotated_rect: TSDL_Rect; ... procedure load_and_process_images;var  surface: PSDL_Surface;  bgraBitmap, rotatedBitmap: TBGRABitmap;  rotated_surface: PSDL_Surface;begin  // Load image with SDL2  surface := IMG_Load('/path/to/image.png');  if surface = nil then  begin    WriteLn('Unable to load image! SDL_image Error: ', IMG_GetError());    Exit;  end;   try    // Convert SDL_Surface to BGRABitmap for manipulation    bgraBitmap := TBGRABitmap.Create(surface^.w, surface^.h, BGRAWhite);    Move(surface^.pixels^, bgraBitmap.Data^, surface^.w * surface^.h * 4);     // Rotate using BGRABitmap    rotatedBitmap := bgraBitmap.RotateCW;    try      // Convert back to SDL textures      original_texture := SDL_CreateTextureFromSurface(renderer, surface);    SDL_QueryTexture(original_texture, nil, nil, @original_rect.w, @original_rect.h);      original_rect.x := 10;      original_rect.y := 10;       // Create a new surface for the rotated image with the same pixel format as the original      rotated_surface := SDL_CreateRGBSurface(0, rotatedBitmap.Width, rotatedBitmap.Height,                                              surface^.format^.BitsPerPixel,                                              surface^.format^.Rmask,                                              surface^.format^.Gmask,                                              surface^.format^.Bmask,                                              surface^.format^.Amask);      if rotated_surface <> nil then    begin        // Copy the bitmap data, making sure color channels are in the correct order        Move(rotatedBitmap.Data^, rotated_surface^.pixels^, rotatedBitmap.NbPixels * 4);        rotated_texture := SDL_CreateTextureFromSurface(renderer, rotated_surface);        SDL_QueryTexture(rotated_texture, nil, nil, @rotated_rect.w, @rotated_rect.h);        rotated_rect.x := 10;      rotated_rect.y := original_rect.y + original_rect.h + 10;        SDL_FreeSurface(rotated_surface);      end else      begin        WriteLn('Failed to create surface for rotated image: ', SDL_GetError());      end;    finally      rotatedBitmap.Free;    end;  finally    bgraBitmap.Free;    SDL_FreeSurface(surface);  end;end; procedure render;begin  SDL_SetRenderDrawColor(renderer, 50, 50, 50, 255);  SDL_RenderClear(renderer);   if Assigned(original_texture) then    SDL_RenderCopy(renderer, original_texture, nil, @original_rect);   if Assigned(rotated_texture) then    SDL_RenderCopy(renderer, rotated_texture, nil, @rotated_rect);   SDL_RenderPresent(renderer);end; ---------------------------------------------------------------------- TRon · 2025-01-15 18:55 Quote from: Pe3s on January 14, 2025, 08:44:26 am@TRon I want that after rotation the image would fit according to the proportions of the window, plot, etc. Ok, in that case you need to be prepared and expect that the image is stretched. But then the question becomes how to treat the contents of the picture itself. In case the dimensions of the graphical content do not match the window then you can either opt for resizing the image to the smallest available window height/width and cut of the other direction or you would have to deal with the fact that there are either horizontal or vertical borders. The other option is the fit the image into the window dimensions but then the image will need to be resized to match those dimensions (in that process the aspect ratio of the contents of the graphics will change accordingly). @Fred: Nice solution (and I did not know that you could mix bgra with sdl) but realize that the original code in the rar archive from TS already rotated the image correctly. The problem lies in how to present the rotated picture in to the available canvas space (window). TS is unclear on how that should behave and there are several situations possible. ---------------------------------------------------------------------- Fred vS · 2025-01-16 00:13 Quote from: TRon on January 15, 2025, 07:55:17 pm@Fred:  (and I did not know that you could mix bgra with sdl) BGRABitmap is fabulous.  There is the full demo with SDL2 pascal headers here. Quote from: TRon on January 15, 2025, 07:55:17 pm@Fred:  but realize that the original code in the rar archive from TS already rotated the image correctly. Yes but the result is stretched using width and length of original picture. With the code I provided it is rotated with width = original height and height = original width. ---------------------------------------------------------------------- TRon · 2025-01-18 23:39 Quote from: Fred vS on January 16, 2025, 01:13:15 amYes but the result is stretched using width and length of original picture. With the code I provided it is rotated with width = original height and height = original width. Leaving out the LCL related code and only focusing on the SDL side of the graphics the code already works correctly. That is what I am trying to tell  PS: in case someone from FPC meets SDL happens to read this: The 2.2 stable release (SDL2-for-Pascal-2.2-stable.tar.gz) seems to be missing SDL_BlitScaled, e.g. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function SDL_BlitScaled(src: PSDL_Surface; const srcrect: PSDL_Rect; dst: PSDL_Surface; dstrect: PSDL_Rect): cint; cdecl; inline;begin  result := SDL_BlitSurfaceScaled(src, srcrect, dst, dstrect);end; ---------------------------------------------------------------------- Pe3s · 2025-02-14 06:28 Thank you for your discussion and help