Create your own XnView plugins

Share your advanced PureBasic knowledge/code with the community.
Thorium
Addict
Addict
Posts: 1305
Joined: Sat Aug 15, 2009 6:59 pm

Create your own XnView plugins

Post by Thorium »

XnView is a freeware image viewer: http://www.xnview.com/
The interessting thing about it is that it have a open plugin interface. Very usefull if you create your own image formats or want to view unusual image formats, like images of old games, without the need to write a whole viewer and converter.

I translated the plugin SDK, which is just a uncommented C source, to PureBasic.
Compile it as DLL and change the file name extension to ".usr". Then set the first character of the file name to "X" and copy it to the "PlugIns" folder in the XnView folder.
Here you can download the SDK: http://www.xnview.com/download/plugins/ ... DK-win.zip
It have a test image in it with the extension ".tst". The test plugin can load an save it's format.

Code: Select all

;/------------------------------------------\
;| Plugin example for XnView 1.65 or higher |
;| by Thorium                               |
;|                                          |
;| PureBasic 4.40                           |
;\------------------------------------------/

EnableExplicit

#GFP_RGB = 0
#GFP_BGR = 1

#GFP_READ  = 1
#GFP_WRITE = 2

Structure GFP_COLORMAP
	Red.a[256]
	Green.a[256]
	Blue.a[256]
EndStructure

Structure MYDATA
  fp.i
  Width.i
  Component_Per_Pixel.i
EndStructure

ProcedureDLL gfpGetPluginInfo(Version.i, *Label, Label_Max_Size.i, *Extension, Extension_Max_Size.i, *Support.INTEGER)

  If Version <> 2
    ProcedureReturn #False
  EndIf
  
  PokeS(*Label, "Plugin Example")
  PokeS(*Extension, "tst;test")
  
  *Support\i = #GFP_READ | #GFP_WRITE

  ProcedureReturn #True
  
EndProcedure

ProcedureDLL gfpLoadPictureInit(Filename.s)

  Define *FileData.MYDATA
  
  *FileData = AllocateMemory(SizeOf(MYDATA))
  *FileData\fp = OpenFile(#PB_Any, Filename)
  
  If *FileData\fp = 0
    FreeMemory(*FileData)
    *FileData = 0
  EndIf
  
  ProcedureReturn *FileData

EndProcedure

ProcedureDLL gfpLoadPictureGetInfo(*FileData.MYDATA, *PicType.Integer, *Width.Integer, *Height.INTEGER, *Dpi.INTEGER, *Bits_Per_Pixel.INTEGER, *Bytes_Per_Line.INTEGER, *Has_Colormap.INTEGER, *Label, Label_Max_Size.i)

  *Width\i = ReadLong(*FileData\fp)
  *Height\i = ReadLong(*FileData\fp)
  *Bits_Per_Pixel\i = ReadLong(*FileData\fp)
  
  *FileData\Width = *Width\i
  *FileData\Component_Per_Pixel = *Bits_Per_Pixel\i / 8
  
  *PicType\i = #GFP_RGB
  *Dpi\i = 68
  *Bytes_Per_Line\i = *FileData\Component_Per_Pixel * *Width\i
  
  *Has_Colormap\i = #False

  PokeS(*Label, "Test format")
  
  ProcedureReturn #True
  
EndProcedure

ProcedureDLL gfpLoadPictureGetLine(*FileData.MYDATA, Line.i, *Buffer)

  ReadData(*FileData\fp, *Buffer, *FileData\Width * *FileData\Component_Per_Pixel)

  ProcedureReturn #True
  
EndProcedure

ProcedureDLL gfpLoadPictureGetColormap(*FileData.MYDATA, *cMap.GFP_COLORMAP)

  ProcedureReturn #False

EndProcedure

ProcedureDLL gfpLoadPictureExit(*FileData.MYDATA)

  CloseFile(*FileData\fp)
  FreeMemory(*FileData)

EndProcedure

ProcedureDLL gfpSavePictureIsSupported(Width.i, Height.i, Bits_Per_Pixel.i, Has_Colormap.i)

  If Has_Colormap <> #False Or Bits_Per_Pixel <> 24
    ProcedureReturn #False
  EndIf
  
  ProcedureReturn #True
  
EndProcedure

ProcedureDLL gfpSavePictureInit(*Filename, Width.i, Height.i, Bits_Per_Pixel.i, Dpi.i, *Picture_Type.INTEGER, *Label, Label_Max_Size.i)

  Define *FileData.MYDATA
  
  *FileData = AllocateMemory(SizeOf(MYDATA))
  *FileData\fp = CreateFile(#PB_Any, PeekS(*Filename))
  
  If *FileData\fp = 0
    FreeMemory(*FileData)
    ProcedureReturn #False
  EndIf
  
  *Picture_Type\i = #GFP_RGB
  WriteLong(*FileData\fp, Width)
  WriteLong(*FileData\fp, Height)
  WriteLong(*FileData\fp, Bits_Per_Pixel)
  
  PokeS(*Label, "Test format")
  
  *FileData\Width = Width
  *FileData\Component_Per_Pixel = Bits_Per_Pixel / 8

  ProcedureReturn *FileData

EndProcedure

ProcedureDLL gfpSavePicturePutLine(*FileData.MYDATA, Line.i, *Buffer)

  WriteData(*FileData\fp, *Buffer, *FileData\Width * *FileData\Component_Per_Pixel)
  
  ProcedureReturn #True
  
EndProcedure

ProcedureDLL gfpSavePictureExit(*FileData.MYDATA)

  CloseFile(*FileData\fp)
  FreeMemory(*FileData)

EndProcedure
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Re: Create your own XnView plugins

Post by djes »

Terrific! We could imagine to create a special gfx format for our game, and use the powerful xnview (love it!) to work with them. Nice! 8)
Thorium
Addict
Addict
Posts: 1305
Joined: Sat Aug 15, 2009 6:59 pm

Re: Create your own XnView plugins

Post by Thorium »

djes wrote:Terrific! We could imagine to create a special gfx format for our game, and use the powerful xnview (love it!) to work with them. Nice! 8)
Yes, that is why i translated the example plugin, to work easily with my own game image format.

But there is a problem with XnView and BGRA. If you define the pixel format as BGR and set the components per pixel to 4 you have ABGR and not BGRA. So i needed to convert every pixel in my plugin, because in my file format pixels are saved as BGRA.
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Re: Create your own XnView plugins

Post by Mistrel »

Sweet! I love XnView. Thanks for sharing. :D
Post Reply