Imported raw bitmap displays mirrored (upside-down) lazarus / 39-Graphics ---------------------------------------------------------------------- Hitnrun · 2007-06-15 18:30 Hello! I am trying to port an application from windows, where I have a pointer to bitmap data in BGR24 format (default windows DIB). In windows I do: Code: [Select] procedure display(pData: Pointer); var   b: TBitmap;   bi: TBitmapInfo; begin      FillChar(bi, sizeof(bi), 0);      bi.bmiHeader.biWidth := FWindowWidth;      bi.bmiHeader.biHeight := -FWindowHeight;      bi.bmiHeader.biPlanes := 1;      bi.bmiHeader.biBitCount := 24;      bi.bmiHeader.biSizeImage := 0;      bi.bmiHeader.biSize := sizeof(TBitmapInfoHeader);      bi.bmiHeader.biClrUsed := 0;      bi.bmiHeader.biClrImportant := 0;      b := TBitmap.Create;      b.Height := 0;      b.Width := FWindowWidth;      b.Height := FWindowHeight;      if SetDIBits(b.Canvas.Handle, b.Handle, 0, FWindowHeight, pData, bi, DIB_RGB_COLORS) = 0 then raise Exception.Create('error');       FWindow.Canvas.StretchDraw(Rect(0, 0, FDisplayWidth, FDisplayHeight), b);       b.Free; end; Note that on windows, I pass the parameter      bi.bmiHeader.biHeight := -FWindowHeight; as negative, so the SetDIBits function displays the image right. If I leave it positive, the image displays mirrored just like I am getting with lazarus. On lazarus, my code looks like: Code: [Select] procedure display(pData: Pointer); var   B: HBITMAP;   bmp: TBitmap; begin      bmp := TBitmap.Create;      B := CreateBitmap(FWindowWidth, FWindowHeight, 1, 24, pData);      if B = 0 then         raise Exception('Error creating bitmap');          bmp.CreateFromBitmapHandles(B, 0, Rect(0, 0, FWindowWidth, FWindowHeight));         FWindow.Canvas.StretchDraw(Rect(0, 0, FDisplayWidth, FDisplayHeight), FOffscreen);          DeleteObject(B);    bmp.Free; end; but the image displays mirrored. Is there an equivallent parameter of the negative parameter of SetDIBits? What is wrong, my image was inverted, or the CreateBitmap inverts it? Thanks! ---------------------------------------------------------------------- Marc · 2007-06-18 08:49 windows bitmaps are stored in a reversed order. So when crating one you need to pass the image lines in a reversed order. For DIBs you can indeed tell windows that the ordering is from top to bottom. ---------------------------------------------------------------------- Hitnrun · 2007-06-18 12:31 Quote from: "Marc"windows bitmaps are stored in a reversed order. So when crating one you need to pass the image lines in a reversed order. For DIBs you can indeed tell windows that the ordering is from top to bottom. Ok, in Windows I pass the height as a negative value, so how I do this in Lazarus/FPC? I tried passing the height as negative in various funcions, all of them gave errors... ---------------------------------------------------------------------- Marc · 2007-06-18 12:46 what functions did you use ? The easiest way to load raw image data into a bitmap is using TRawImage. There you can setup a description which matches exactly your data. ---------------------------------------------------------------------- Hitnrun · 2007-06-18 13:01 The ones I posted on the first post!  :wink: Code: [Select] procedure display(pData: Pointer); var   B: HBITMAP;   bmp: TBitmap; begin      bmp := TBitmap.Create;      B := CreateBitmap(FWindowWidth, FWindowHeight, 1, 24, pData);      if B = 0 then         raise Exception('Error creating bitmap');          bmp.CreateFromBitmapHandles(B, 0, Rect(0, 0, FWindowWidth, FWindowHeight));         FWindow.Canvas.StretchDraw(Rect(0, 0, FDisplayWidth, FDisplayHeight), FOffscreen);          DeleteObject(B);    bmp.Free; end; pData is a pointer to image bytes, the width, height and depth I know from previous funcions calls. ---------------------------------------------------------------------- Marc · 2007-06-19 10:56 Ah, Create bitmap creates the (original) windows bitmaps, with the scanlines reversed. There is no way to tell what the layout or yuor data is. It is faster (removes 2 conversions) to use TBitmap.LoadFromIntfImage(IntfImage: TLazIntfImage); Code: [Select] procedure display(pData: Pointer); var   bmp: TBitmap;   IntfImage: TLazIntfImage; begin   FillByte(IntfImage, SizeOf(IntfImage), 0);     // fill in parts of IntfImage.Description   with IntfImage.Description do   begin     Format := ricfRGBA;     Depth := 24; // used bits per pixel     Width := FWindowWidth;     Height := FWindowHeight;     BitOrder := riboBitsInOrder;     ByteOrder := DefaultByteOrder;     LineOrder := riloTopToBottom; // here you can set the direction of lines     BitsPerPixel := 24; // bits per pixel. can be greater than Depth.                                 // (dont know if pixels are represented by RGB or RGBx otherwise it should be 32     LineEnd := rileWordBoundary;     RedPrec:=8; // red precision. bits for red     RedShift:=16;     GreenPrec:=8;     GreenShift:=8; // bitshift. Direction: from least to most significant     BluePrec:=8; //    BlueShift:=0; //    AlphaPrec:=0; //    MaskBitsPerPixel:=0;   end;   IntfImage.Data := pData;   IntfImage.DataSize := FWindowWidth * FWindowHeight * 3; (see BitsPerPixel remark)   bmp := TBitmap.Create;   bmp.LoadFromIntfImage(IntfImage); end; ---------------------------------------------------------------------- Hitnrun · 2007-06-19 12:18 In doing this, I get this exception: "TGtkWidgetSet.CreateBitmapFromRawImage Incompatible BitsPerPixel" Tracing into the sourcecode, I saw that the call Visual:=gdk_visual_get_best_with_depth(ImgDepth); Returns a depth of 32 bpp (instead if my image's 24 bpp), and compares with my image's depth         if (RawImage.Description.BitsPerPixel<>GetPGdkImageBitsPerPixe l(GdkImage))         then begin           RaiseGDBException('TGtkWidgetSet.CreateBitmapFromRawImage Incompatible BitsPerPixel');         end; And of course they are different... why is it changing my format do 32 bits, if I told that it is 24? (my pixel data is in real 24 bpp) Ah for the code you provided to compile, I had to make a few changes: Code: [Select] var   bmp: TBitmap;   RI: TRawImage;   IntfImage: TLazIntfImage; begin   FillChar(RI, SizeOf(RI), 0);   // fill in parts of IntfImage.Description   with RI.Description do   begin     Format := ricfRGBA;     Depth := 24; // used bits per pixel     Width := FWindowWidth;     Height := FWindowHeight;     BitOrder := riboBitsInOrder;     ByteOrder := DefaultByteOrder;     LineOrder := riloTopToBottom; // here you can set the direction of lines     BitsPerPixel := 24; // bits per pixel. can be greater than Depth.                                 // (dont know if pixels are represented by RGB or RGBx otherwise it should be 32     LineEnd := rileWordBoundary;     RedPrec:=8; // red precision. bits for red     RedShift:=16;     GreenPrec:=8;     GreenShift:=8; // bitshift. Direction: from least to most significant     BluePrec:=8; //    BlueShift:=0; //    AlphaPrec:=0; //    MaskBitsPerPixel:=0;   end;   RI.Data := pData   RI.DataSize := FFrameSize; // FWindowWidth * FWindowHeight * 3; {see BitsPerPixel remark}   IntfImage := TLazIntfImage.Create(FWindowWidth, FWindowHeight);   IntfImage.SetRawImage(RI);   bmp := TBitmap.Create;   bmp.LoadFromIntfImage(IntfImage); ---------------------------------------------------------------------- Marc · 2007-06-19 13:00 Quote from: "Hitnrun"In doing this, I get this exception: "TGtkWidgetSet.CreateBitmapFromRawImage Incompatible BitsPerPixel" Tracing into the sourcecode, I saw that the call Visual:=gdk_visual_get_best_with_depth(ImgDepth); Returns a depth of 32 bpp Interesting. I've spend some time to find a 32bpp X server, but couldn't find any to test with. What Xserver do you use ? Quote (instead if my image's 24 bpp), and compares with my image's depth And of course they are different... why is it changing my format do 32 bits, if I told that it is 24? (my pixel data is in real 24 bpp) Ehm... that is one of the problems that Paul and I are currently trying to solve (in a separate branch). The way the bitmap code works now is that it always creates a bitmap in the depth of your device. And unlike windows, X only accepts 1bpp or device bpp depths. So there is no conversion done yet. You could use another intfimage to convert your image to a device depth, but I admit that's something you nomally don't want. Quote Ah for the code you provided to compile, I had to make a few changes: Ah, I didn't test it. I only wrote it down here, but you got the idea. ---------------------------------------------------------------------- Hitnrun · 2007-06-20 16:43 Quote from: "Marc"Interesting. I've spend some time to find a 32bpp X server, but couldn't find any to test with. What Xserver do you use ? According to dpkg -l (on Ubuntu 7.04): xserver-xorg   7.2-0ubuntu11  the X.Org X server