Transparent PNG showed inverted in Wine ( TImage problem ) lazarus / 39-Graphics ---------------------------------------------------------------------- alejol0 · 2010-08-29 15:29 When a PNG picture with transparent color is loaded in a TImage, the image is showed correctly in Windows XP, but is showed vertically mirrored in Wine. Tested in Wine 1.2 in Puppy Linux 5 and in WineXO in XO-1 (Fedora + Sugar). The application was compiled using Lazarus 0.9.29 under Windows XP SP3. PNG images without transparent color are showed correctly in all systems. The same transparent PNG image is showed correctly in Wine 1.2 and in WineXO when opened by Firefox. This occurs with all PNG images with transparent background. Can anyone give a workaround? Thanks in advance. ---------------------------------------------------------------------- Marc · 2010-08-29 17:08 This is IMO a bug in wine. The problem is that there is no windows function which tells me if the bitmap data in a dibsection is upside down or not. So I use a trick by inverting the first databyte. if the topleft pixel is not changed, the data is upside down. Somehow wine fails this check resulting in a wrong orientation ---------------------------------------------------------------------- alejol0 · 2010-08-30 12:21 Hi, Marc! Because Firefox and AbiWord shows correctly these PNG transparent in Wine 1.2 and in WineXO, this is a bug in your implementation in Lazarus, IMO. ---------------------------------------------------------------------- Marc · 2010-08-30 22:20 That other apps show them correctly doesn't prove wine is 100% windows compatible. They simply don't use the winapi functions I use. If my implementation works on all windows versions (win95-win7), without special version dependent code, why do you think, wine is correct and my implementation is wrong ? ---------------------------------------------------------------------- alejol0 · 2010-08-31 00:17 Marc, I appreciate your work as a volunteer. But, the other apps work OK, and only Lazarus have problem. This is because you have implemented the transparent PNG in a wrong way. Maybe you can improve your code, and not use the part of Windows API that causes this problem. Lazarus goal is to be operating system independent. and Lazarus users (programmers) are in disadvantage if applications maded with Lazarus do not work , and applications made with other languages work. In the Wine bug report, only Lazarus have this problem, no other application. And this is dated from 2008, maybe 2 years is too much time.  Think as a oppurtunity for fixing a bug. ---------------------------------------------------------------------- José Mejuto · 2010-08-31 10:35 Quote from: Marc on August 29, 2010, 07:08:27 pmThis is IMO a bug in wine. The problem is that there is no windows function which tells me if the bitmap data in a dibsection is upside down or not. So I use a trick by inverting the first databyte. if the topleft pixel is not changed, the data is upside down. Somehow wine fails this check resulting in a wrong orientation Hello, Is not the height (negative or positive) of DIBSection signaling the upside of the lines array ? Anyway the bug in Wine should be in GetPixel or the function that you use to get the 0,0 pixel do not ? ---------------------------------------------------------------------- Marc · 2010-08-31 23:10 Quote from: JoshyFun on August 31, 2010, 12:35:09 pmQuote from: Marc on August 29, 2010, 07:08:27 pmThis is IMO a bug in wine. The problem is that there is no windows function which tells me if the bitmap data in a dibsection is upside down or not. So I use a trick by inverting the first databyte. if the topleft pixel is not changed, the data is upside down. Somehow wine fails this check resulting in a wrong orientation Hello, Is not the height (negative or positive) of DIBSection signaling the upside of the lines array ? Yes, according to the MSDN yes. That's theory, in reality they are always reported positive. Why do you think I added that check ? I spent weeks reading, searching for official ways, undocumented ways to retrieve this info. All you find is that getDIBinfo should report the height negative for top to bottom images. Should... but it doesnt. QuoteAnyway the bug in Wine should be in GetPixel or the function that you use to get the 0,0 pixel do not ? I readread the code and I thought I used a GetPixel. But the test is more trickier than I thought. in short: Through the GetObject() function I get the BITMAP info of a given HBITMAP If the HBITMAP was created as DIBsection, the BITMAP.bmBits will point to the data of the bitmap. On "real" windows you are allowed to manipulate this data. For these bmBits I want to know if they are bottom-up or top-down. With the GetDIBits() function I request the first scanline/pixel in bottom-up order (so it is the last line of the bitmap). I cannot compare it to the value I found in bmBits, since top and bottom may have the same pixelvalue. Now I invert the first pixel of bmBits and I request again the first scanline in bottom-up order. If the first pixel did change, then the data was bottom-up. It the pixel didn't change, I was manipulating the top of the bitmap There can be a few issues with wine: 1) bmBits points to a copy of the bitmap data 2) GetDIBits doesn't honor the requested scanline order (== doesn't reorder if bottom-up is requested while the image is top-down) 3) Wine does report a negative height, and I think I request a bottom- up but I get a top-down Only point 3 is something I can fix. I'll add an extra check. ---------------------------------------------------------------------- Marc · 2010-08-31 23:25 Quote from: alejol0 on August 31, 2010, 02:17:12 amMarc, I appreciate your work as a volunteer. But, the other apps work OK, and only Lazarus have problem. For simply displaying images you don't need this tricks. For normal applications you know what you get as input. Normal applications don't have to extract the image data from a bitmap handle, simply because they create the handle themselves and know the data. Since the LCL is a library, anyone can create their bitmap handles as they like and still something like bmp.Handle := SomeHandle; bmp.Pixels[1,2] := someColor is supposed to work. QuoteThis is because you have implemented the transparent PNG in a wrong way. This has nothing to do with neither PNG nor transparency. QuoteMaybe you can improve your code, and not use the part of Windows API that causes this problem. See my other reply. If you think it is so simple, please send me a patch fixing this. QuoteLazarus goal is to be operating system independent. and Lazarus users (programmers) are in disadvantage if applications made with Lazarus do not work , and applications made with other languages work. Correct. But wine is not a different operating system. It is an emulation of a operating system based on public available documentation. It sure is possible that there are incompatibilities. Lazarus is cross platform. There is from a Lazarus point of view no reason to use an emulator while you can run a native application. QuoteIn the Wine bug report, only Lazarus have this problem, no other application. And this is dated from 2008, maybe 2 years is too much time. It's a problem from day one and only recently reported in mantis. QuoteThink as a oppurtunity for fixing a bug. I've enough other issues to solve. I see no need in running lazarus apps in an Emulator. ---------------------------------------------------------------------- alejol0 · 2010-08-31 23:36 Marc, there are reasons for running a Lazarus app in an emulator. This is because XO do not have a desktop like Windows. And childrens are in disadvantage if the only desktop they can use is Sugar. And, other Windows applications are running in Wine, without problem. Off course, these applications are not written in Lazarus. You say that Lazarus is not suitable for developping in wine? Why? And, why your implementation is so dependent of Windows API?? How about OS independency? You claim that "This has nothing to do with neither PNG nor transparency. " But, using a BMP and Image1.Transparent:=TRUE  works OK in Wine. Compile my example and run in Wine. Only transparent PNG has problem. Opaque PNG are OK. If nobody uses the check that you use, and they show correctly PNG images, maybe you can rethink about your implementation. And PNG files are well documented, only your code inverts this. You use a trick when the trick is no needed, and this causes trouble, because the PNG is loaded at design time and added to the executable at compilation. The Lazarus compiler has all the information to store correctly the image and then display this. I know that is a volonteer work, maybe you can delegate in someone the fix, or add a workaround. I do not have sufficient knowledge, but if I can help you or other to fix, I like to help. ---------------------------------------------------------------------- Ocye · 2010-09-01 09:18 Your issue becomes relevant for me in case of ToolButtons and a DragImages  created from BMP. So it's not only related to PNG and, even if so, I would agree with Marc that it has low priority. But it should kept in mind and, perhaps, some strange ifdef rotation could help. ---------------------------------------------------------------------- jixian.yang · 2010-09-01 09:27 Ubuntu 9.10, turbo delphi program, pngimage, without problem. The reverse code related to PNG was not found by me. ---------------------------------------------------------------------- felipemdc · 2010-09-01 12:21 Did you already report this bug in the Wine bug tracker? If yes, please post a link here to it for reference. Marc is correct. Wine simulates Windows. If something works in Windows and not in Wine then logically the bug can only be in Wine. Quote from: alejol0 on September 01, 2010, 01:36:51 amMarc, there are reasons for running a Lazarus app in an emulator. This is because XO do not have a desktop like Windows. And childrens are in disadvantage if the only desktop they can use is Sugar. Can't you run some apps under Wine and Lazarus apps natively? QuoteAnd, other Windows applications are running in Wine, without problem. Off course, these applications are not written in Lazarus. This just proves that the Wine developers tested more with other applications. They will start testing wine against Lazarus if people start reporting bugs for wine about Lazarus apps. QuoteYou say that Lazarus is not suitable for developping in wine? Why? To me the only thing proven here is that Wine is too buggy to run Lazarus apps. And by insisting that Lazarus developers should find a work around for the bug in Wine you are depriving the Wine developers from the possibility to fix a bug in their Wine implementation. QuoteAnd, why your implementation is so dependent of Windows API?? How about OS independency? lol!!! This statement is so dramatically missguided that I decided to draw some diagrams to explain how Pascal applications work: http://wiki.freepascal.org/Overview_of_Free_Pascal_and_Lazarus#Lazarus _Architecture ---------------------------------------------------------------------- Marc · 2010-09-01 15:03 Quote from: alejol0 on September 01, 2010, 01:36:51 amYou say that Lazarus is not suitable for developping in wine? Why? where did I say that ? QuoteAnd, why your implementation is so dependent of Windows API?? On some point in time on windows, you must call winapi. Windows wont draw graphics by just reading my mind. QuoteYou claim that "This has nothing to do with neither PNG nor transparency. " But, using a BMP and Image1.Transparent:=TRUE  works OK in Wine. Compile my example and run in Wine. Only transparent PNG has problem. Opaque PNG are OK. Possible. Let me explain how graphics in the lcl work. When you read a graphic format, then that format is decoded to pixels by one ot the fcl-image graphic readers. This results in a basic TRasterImage. at that point the format (png/gif/tiff/bmp/...) is irrelevant. This is all LCL code independent of the widgetset (win32/gtk2/carbon/...) The final drawing of this raster image is done by widgetset specific code. This specific code draws your image upside down on wine. But you made an important remark about the type of PNG. It has a alpha channel. To draw images with an alpha channel, windows has one function: AlphaBlend() But this function is not implemented (or wrong implemented) on some versions of windows. For those cases we have our own implementation. Since this function has exact the same parameters as the windows function, we get the same info. This means that we in this case must extract the imagedata from the passed devicecontexts. Inside that function, wine fails. QuoteIf nobody uses the check that you use, and they show correctly PNG images, maybe you can rethink about your implementation. If I had only to display PNG images, then yes, the code would be a lot simpler. Unfortunately, there is more than only displaying a PNG. QuoteAnd PNG files are well documented, only your code inverts this. You use a trick when the trick is no needed, and this causes trouble, because the PNG is loaded at design time and added to the executable at compilation. The Lazarus compiler has all the information to store correctly the image and then display this. As I explained, the moment a image gets displayed, it is already reduced to a bunch of pixeldata. ---------------------------------------------------------------------- felipemdc · 2010-09-01 20:01 Linking to related Lazarus bug tracker item for reference: http://bugs.freepascal.org/view.php?id=17299 Link to related WINE bug tracker item: http://bugs.winehq.org/show_bug.cgi?id=10885 ---------------------------------------------------------------------- José Mejuto · 2010-09-01 22:22 Quote from: Marc on September 01, 2010, 01:10:59 am Yes, according to the MSDN yes. That's theory, in reality they are always reported positive. Why do you think I added that check ? Hello, That's exactly the answer You added the check because sometimes (maybe some windows) not always report the negative height in bottom- up. I was reading about this a long time ago, but never implemented nothing related. Quotein short: In short ? The trick is quite complex, yes. QuoteThere can be a few issues with wine: 1) bmBits points to a copy of the bitmap data 2) GetDIBits doesn't honor the requested scanline order (== doesn't reorder if bottom-up is requested while the image is top-down) 3) Wine does report a negative height, and I think I request a bottom- up but I get a top-down Only point 3 is something I can fix. I'll add an extra check. I vote for 3 also, but there is also a possibility of only incorrect scanline report in presence of transparent layer :-? ---------------------------------------------------------------------- Marc · 2010-09-02 21:30 Quote from: JoshyFun on September 02, 2010, 12:22:23 am I vote for 3 also, but there is also a possibility of only incorrect scanline report in presence of transparent layer :-? The same code is used at different places too, but you probably wont hit it. There might also be an error in our own alphablend code. Need to check that with win95. ---------------------------------------------------------------------- Marc · 2010-09-02 22:43 I did some debugging on a testapp under wine. It looks like alphablending a top-to-bottom dibsection results in a upsidedown image. the alpha image is created at TWin32WidgetSet.StretchMaskBlt - CreatePremultipliedBitmap (win32api.inc:3420) and is blended at line 3513. the AlphaBlend routine is native wine. I'll investigate more with some direct api calls, not using the lcl. ---------------------------------------------------------------------- alejol0 · 2010-09-03 04:01 Marc, I appreciate your effort. Thanks!! I have reported this bug to Wine developers too. Good luck!!