Page 1 of 1

Saving .PNG images in Linux

Posted: Sun Jun 03, 2018 1:35 pm
by HarrysLad
I've written a few simple apps that compile and run as expected on macOS and Windows but now I'm attempting to offer Linux versions as well.
There're a few things to sort out but a major problem at the moment centres around saving an image in .PNG format.

Code: Select all

Procedure imageSave(Image.l)

  Define file$, PathPart$, FilePart$, buffer.l, w.i, h.i
  
  file$ = SaveFileRequester("Save Image as PNG", "Image.png", "Images (.png)|*.png", 0)
  If file$ > ""
    w = GadgetWidth(Image)
    h = GadgetHeight(Image)
    PathPart$ = GetPathPart(file$)
    FilePart$ = GetFilePart(file$, #PB_FileSystem_NoExtension)
    file$ = PathPart$ + FilePart$ + ".png"
    CreateImage(buffer, w, h)
    StartDrawing(ImageOutput(buffer))
    DrawImage(GetGadgetAttribute(Image, #PB_Canvas_Image), 0, 0)
    FrontColor($0)
    DrawingMode(#PB_2DDrawing_Outlined)
    Box(0, 0, w, h)
    StopDrawing()
    SaveImage(buffer, file$)          
    FreeImage(buffer) 
    MessageRequester("Image:", "Saved as:" + #CR$ + file$)
  EndIf
    
EndProcedure
This same code works perfectly in macOS and Windows but, while it writes a .png file at the requested destination, Linux reckons "Fatal error reading PNG image file: Not a PNG file" when I try to view it.

Tested on Windows 7, 10, macOS High Sierra ... OK
Ubuntu 16.04 LTS, Mint 18 ... not so good.

Any ideas what I'm doing wrong?

TIA
Dave

Re: Saving .PNG images in Linux

Posted: Sun Jun 03, 2018 2:11 pm
by StarBootics
Did you use the UsePNGImageEncoder() somewhere in your program ?

Code: Select all

Procedure imageSave(Image.l)
  
  Define file$, PathPart$, FilePart$, buffer.l, w.i, h.i
  
  file$ = SaveFileRequester("Save Image as PNG", "Image.png", "Images (.png)|*.png", 0)
  If file$ > ""
    w = GadgetWidth(Image)
    h = GadgetHeight(Image)
    PathPart$ = GetPathPart(file$)
    FilePart$ = GetFilePart(file$, #PB_FileSystem_NoExtension)
    file$ = PathPart$ + FilePart$ + ".png"
    CreateImage(buffer, w, h)
    StartDrawing(ImageOutput(buffer))
    DrawImage(GetGadgetAttribute(Image, #PB_Canvas_Image), 0, 0)
    FrontColor($0)
    DrawingMode(#PB_2DDrawing_Outlined)
    Box(0, 0, w, h)
    StopDrawing()
    SaveImage(buffer, file$, #PB_ImagePlugin_PNG)         
    FreeImage(buffer)
    MessageRequester("Image:", "Saved as:" + #CR$ + file$)
  EndIf
  
EndProcedure

UsePNGImageEncoder()

If OpenWindow(0, 0, 0, 220, 220, "CanvasGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  CanvasGadget(0, 10, 10, 200, 200)
  imageSave(0)
  Repeat
    Event = WaitWindowEvent()
    
    If Event = #PB_Event_Gadget And EventGadget() = 0 
      If EventType() = #PB_EventType_LeftButtonDown Or (EventType() = #PB_EventType_MouseMove And GetGadgetAttribute(0, #PB_Canvas_Buttons) & #PB_Canvas_LeftButton)
        If StartDrawing(CanvasOutput(0))
          x = GetGadgetAttribute(0, #PB_Canvas_MouseX)
          y = GetGadgetAttribute(0, #PB_Canvas_MouseY)
          Circle(X, Y, 10, RGB(Random(255), Random(255), Random(255)))
          StopDrawing()
        EndIf
      EndIf
    EndIf    
    
  Until Event = #PB_Event_CloseWindow
EndIf
The code above work on linux Ubuntu 18.04.

Best regards
StarBootics

Re: Saving .PNG images in Linux

Posted: Sun Jun 03, 2018 2:28 pm
by HarrysLad
StarBootics wrote:Did you use the UsePNGImageEncoder() somewhere in your program ?
Yes but - clutching at straws - I have compiled versions without. Same result as before ... works on Win & macOS, doesn't on Linux.
StarBootics wrote:By the way without a working example it's very hard to tell.
You're right. I just thought (hoped) I was making a silly/obvious error somewhere.
I'll write a little app to demonstrate.

ATB
Dave

Re: Saving .PNG images in Linux

Posted: Sun Jun 03, 2018 3:03 pm
by Marc56us
Always check after create

Not only:

Code: Select all

SaveImage(buffer, file$) 

But:

Code: Select all

If Not SaveImage(buffer, file$) 
  Debug "SaveImage failed :-("
  ProcedureReturn
EndIf
  Debug "Size of file saved: " + FileSize(file$)

FileSize must be > 0
if FileSize = 0 something is wrong (files rights ? directory rights ? user rights ? file exist ? file is directory ?)

Check on shell
$ file <your file>
must be binary file

:wink:

Re: Saving .PNG images in Linux

Posted: Sun Jun 03, 2018 3:34 pm
by Trond
I've written a few simple apps that compile and run as expected on macOS and Windows
...
This same code works perfectly in macOS and Windows
No, it doesn't, it actually works the same under all OSes. The difference lies in how the OSes handle opening a bmp file with a png extension. Because your code saves a bmp file, not a png file. That's why you get the error message "not a png file". :)

New code:

Code: Select all

SaveImage(buffer, file$,  #PB_ImagePlugin_PNG)

Re: Saving .PNG images in Linux

Posted: Sun Jun 03, 2018 3:52 pm
by Marc56us
HarrysLad, Trond and StarBootics are right

Your sample : Image1.png
StarBootics sample: Image2.png

Code: Select all

$ file Image*
Image1.png: PC bitmap, Windows 3.x format, 200 x 200 x 24
Image2.png: PNG image data, 200 x 200, 8-bit/color RGB, non-interlaced
:wink:

https://www.purebasic.com/documentation ... image.html
Without specify plugin, Save the image in BMP (default)

Re: Saving .PNG images in Linux

Posted: Sun Jun 03, 2018 4:00 pm
by HarrysLad
Curiouser and curiouser ...
You might have guessed but I'm new to Linux. :D
I've incorporated all of your suggestions and it works in Win/OSX but not Linux.
However ...
The image opens OK using Gimp and FireFox and ImageMajick (whatever that is) but the Image Viewer stops with the error.
This is with both Umbuntu and Mint.
Trond wrote:
I've written a few simple apps that compile and run as expected on macOS and Windows
...
This same code works perfectly in macOS and Windows
No, it doesn't, it actually works the same under all OSes. The difference lies in how the OSes handle opening a bmp file with a png extension. Because your code saves a bmp file, not a png file. That's why you get the error message "not a png file". :)

New code:

Code: Select all

SaveImage(buffer, file$,  #PB_ImagePlugin_PNG)

Trouble is if I add the '#PB_ImagePlugin_PNG' it doesn't work in Windows, OSX or Linux ..

Code: Select all

; PNGTesting.pb

Enumeration
  
  ; main window
  #WINDOW_MAIN
  ; image buffer
  #IMAGE_BUFFER
  ; image view
  #IMAGE_VIEW
  
EndEnumeration

Procedure ImageSave(Image.l)

  Define file$, PathPart$, FilePart$, buffer.l, w.i, h.i
  
  file$ = SaveFileRequester("Save Reticle as PNG", "Image.png", "Images (.png)|*.png", 0)
  If file$ > ""
    w = GadgetWidth(Image)
    h = GadgetHeight(Image)
    PathPart$ = GetPathPart(file$)
    FilePart$ = GetFilePart(file$, #PB_FileSystem_NoExtension)
    file$ = PathPart$ + FilePart$ + ".png"
    CreateImage(buffer, w, h)
    StartDrawing(ImageOutput(buffer))
      DrawImage(GetGadgetAttribute(Image, #PB_Canvas_Image), 0, 0)
      FrontColor($0)
      DrawingMode(#PB_2DDrawing_Outlined)
      Box(0, 0, w, h)
      StopDrawing()
      If SaveImage(buffer, file$,  #PB_ImagePlugin_PNG)    
        Debug "imageSave OK ("+ FileSize(file$)+" bytes)"
      Else
        Debug "imageSave failed ... "
      EndIf
      FreeImage(buffer) 
    MessageRequester("Image:", "Saved as:" + #CR$ + file$)
  EndIf
    
EndProcedure

;
; main bit
;

UsePNGImageDecoder()

OpenWindow(#WINDOW_MAIN, 0, 0, 410, 410, "PNGTesting",#PB_Window_ScreenCentered) 
CanvasGadget(#IMAGE_VIEW, 5, 5, 400, 400)  
CatchImage(#IMAGE_BUFFER, ?PNGImage)
If StartDrawing(CanvasOutput(#IMAGE_VIEW))
  Box(0, 0, 500, 500, #White)
  DrawAlphaImage(ImageID(#IMAGE_BUFFER), 0, 0)
  DrawingMode(#PB_2DDrawing_Outlined)
  Box(0, 0, 400, 400, #Black)   
  StopDrawing()
EndIf
GadgetToolTip(#IMAGE_VIEW, "Right click to save, Escape to Quit")

AddKeyboardShortcut(#WINDOW_MAIN, #PB_Shortcut_Escape,2)

Repeat
  
  Event = WaitWindowEvent(1) 
  If Event = #PB_Event_CloseWindow Or (Event = #PB_Event_Menu And EventMenu() = 2)
    Quit = #True                    
  EndIf
  Select Event
    Case #PB_Event_Gadget 
      Select EventGadget()
        Case #IMAGE_VIEW
          Select EventType()
            Case #PB_EventType_RightClick
              ImageSave(#IMAGE_VIEW) 
          EndSelect
      EndSelect
  EndSelect

Until Quit = #True   
End 

DataSection

  PNGImage:
  IncludeBinary "HALFMD.png" 
  
EndDataSection
Dave

Re: Saving .PNG images in Linux

Posted: Sun Jun 03, 2018 4:13 pm
by Marc56us
UsePNGImageEncoder()
Not
UsePNGImageDecoder()

(and put it at top of code)

And before modify your code, test StarBootics code, it's a standalone sample.

:wink:

Re: Saving .PNG images in Linux

Posted: Sun Jun 03, 2018 4:27 pm
by HarrysLad
Marc56us wrote:UsePNGImageEncoder()
Not
UsePNGImageDecoder()

(and put it at top of code)

And before modify your code, test StarBootics code, it's a standalone sample.

:wink:
Yup, I thought it must be something simple/stupid - although I actually need both UsePNGImageEncoder() and UsePNGImageDecoder() presumably because I'm reading in and writing out .PNG files.

I'm sure another problem'll be along shortly but for now, thanks for your help.
Dave