Module: Automatic image upload to ImgBB.com

Applications, Games, Tools, User libs and useful stuff coded in PureBasic
User avatar
Kurzer
Enthusiast
Enthusiast
Posts: 664
Joined: Sun Jun 11, 2006 12:07 am
Location: Near Hamburg

Module: Automatic image upload to ImgBB.com

Post by Kurzer »

Hello,

because I was tired of manually uploading the screenshots to an image hoster for my forum posts, this module was created.

Module ImgBBUploader:

The module makes it possible to automatically upload an image to the webspace of the image hoster http://www.ImgBB.com and returns the following three links if transfer was successful:
- Link to the image (in the ImgBB web page preview)
- Link to image (direct link)
- Link to delete the image

The module offers the following public procedure for this purpose:

Code: Select all

   Procedure.i ImgBBUpload(sImageFile.s, sAPIKey.s, *stOutImgBBResult.ImgBBResult)
      ; +-----------------------------------------------------------------
      ; |Description  : Automatically uploads an image to the image hoster www.ImgBB.com
      ; |               The Imagehoster supports the image formats JPG, PNG, BMP and GIF with a maximum size of 16 MB.
      ; |Arguments    : sImageFile      : The full path and filename of the image
      ; |               sAPIKey         : The ImgBB.com API key, wich is necessary for the upload to work
      ; |               stOutImgBBResult: A structured return variable of type ImgBBResult containing
      ; |                                 the links to the uploaded image (preview link, direct link, delete link)
      ; |Results      : 1, if the upload was successful, otherwise 0.
      ; |Remarks      : -
      ; +-----------------------------------------------------------------
The result variable in which the links to the image are transferred after a successful image upload must be of type ImgBBResult:

Code: Select all

   Structure ImgBBResult
      sFileStatus.s                     ; "Ok" = ok
      sHttpStatus.s                     ; "200" = ok
      sUploadSuccessfull.s            ; true / false
      sViewerLink.s
      sDirectLink.s
      sDeleteLink.s
   EndStructure
I chose ImgBB.com because this image hoster offers an API to upload. So I can easily upload a Base64 encoded image with HTTPReqeust and get back a JSON result with the necessary links and status values.

To be able to use the API you have to register a user account and then you can get an API key in your profile. The API key can be displayed at the push of a button and used immediately. I can reassure paranoid people like me, because you can also create the account with a funny disposable email address and a fictional username. 8)

There is also a checkbox [x] private mode in the profile. I didn't find a function on ImgBB that would allow you to view pictures of other users, but to be on the safe side you should set this checkbox. :-)
Image

At the end of the module I added an example program, which is encapsulated by CompilerIf #PB_Compiler_IsMainFile. The example program is actually a full-fledged upload program. I intentionally made it a bit more extensive, because I can use it as an uploader for myself. :-)

The example program uses a demo API key registered by me (yes of course, the account was created with a fantasy email address). You should, however, request your own API key if you use the module permanently. It is possible that the demo API key will be blocked very quickly if too many people use it or if some jokers upload inappropriate images. According to ImgBB.com, the images are checked by humans and must comply with ImgBB.com's terms of use (see also https://imgbb.com/tos).

Here is a screenshot of the example program...
Image

Changelog:

Code: Select all

;* 1.01 - rel 01.05.2019: 
;*        fix - A closeFile() command was missing in the error handling (in line 174)
... and the sourcecode:

Code: Select all

;*************************************************************************
;* ImgBBUploader (c) Kurzer
;*************************************************************************
;*
;* Modulname         : ImgBBUploader
;* Filename          : mod_ImgBBUploader.pbi
;* Filetype          : Module [MainApp, Formular, Include, Module, Data]
;* Programming lang. : Purebasic 5.70+ Minimum because of HTTPRequest()
;* String-Format     : Unicode [Ascii, Unicode, All]
;* Platform          : Windows [Windows, Mac, Linux, All]
;* Processor         : All [x86, x64, All]
;* Compileroptions   : -
;* Version           : 1.01
;* Date              : 01.05.2019
;* Autor             : Kurzer
;* Dependencies      :
;* -----------------------------------------------------------------------
;* Description:
;*
;* Uploads an image to the image hoster www.ImgBB.com
;*
;* Attention: You need an own API key from www.ImgBB.com and have to register
;* a user account. The example at the end of this module uses an API key which
;* will be probably blocked if it is used too often. So you better get your
;* own API key at https://api.imgbb.com/
;*
;* The image hoster supports the image formats JPG, PNG, BMP and GIF with a
;* maximum size of 16 MB.
;*
;* Please respect the ImgBB's terms of use: https://imgbb.com/tos
;*
;* For legal consequences arising from the use of this module (especially if
;* the user uploads non-compliant images), the user of this module alone is
;* responsible and in no way the author of the module!
;* -----------------------------------------------------------------------
;* Changelog:
;* 1.01 - rel 01.05.2019: 
;*        fix - A closeFile() command was missing in the error handling (in line 174)
;* 1.00 - rel 22.04.2019: 
;*        add - First release
;* -----------------------------------------------------------------------
;* English-Forum     : https://www.purebasic.fr/english/viewtopic.php?f=27&t=72696
;* French-Forum      :
;* German-Forum      : https://www.purebasic.fr/german/viewtopic.php?f=8&t=31417
;* -----------------------------------------------------------------------
;* License: MIT License
;* 
;* Copyright (c) 2016/19 Kurzer
;* 
;* Permission is hereby granted, free of charge, to any person obtaining a copy
;* of this software and associated documentation files (the "Software"), to deal
;* in the Software without restriction, including without limitation the rights
;* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
;* copies of the Software, and to permit persons to whom the Software is
;* furnished to do so, subject to the following conditions:
;*
;* The above copyright notice and this permission notice shall be included in all
;* copies or substantial portions of the Software.
;* 
;* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
;* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
;* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
;* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
;* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
;* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
;* SOFTWARE.
;* 
;* ---------------- German translation of the MIT License ----------------
;*
;* MIT Lizenz:
;*
;* Hiermit wird unentgeltlich jeder Person, die eine Kopie der Software und der
;* zugehörigen Dokumentationen (die "Software") erhält, die Erlaubnis erteilt,
;* sie uneingeschränkt zu nutzen, inklusive und ohne Ausnahme mit dem Recht, sie
;* zu verwenden, zu kopieren, zu verändern, zusammenzufügen, zu veröffentlichen,
;* zu verbreiten, zu unterlizenzieren und/oder zu verkaufen, und Personen, denen
;* diese Software überlassen wird, diese Rechte zu verschaffen, unter den folgenden
;* Bedingungen:
;* 
;* Der obige Urheberrechtsvermerk und dieser Erlaubnisvermerk sind in allen Kopien
;* oder Teilkopien der Software beizulegen.
;* 
;* DIE SOFTWARE WIRD OHNE JEDE AUSDRÜCKLICHE ODER IMPLIZIERTE GARANTIE BEREITGESTELLT,
;* EINSCHLIEßLICH DER GARANTIE ZUR BENUTZUNG FÜR DEN VORGESEHENEN ODER EINEM BESTIMMTEN
;* ZWECK SOWIE JEGLICHER RECHTSVERLETZUNG, JEDOCH NICHT DARAUF BESCHRÄNKT. IN KEINEM
;* FALL SIND DIE AUTOREN ODER COPYRIGHTINHABER FÜR JEGLICHEN SCHADEN ODER SONSTIGE
;* ANSPRÜCHE HAFTBAR ZU MACHEN, OB INFOLGE DER ERFÜLLUNG EINES VERTRAGES, EINES DELIKTES
;* ODER ANDERS IM ZUSAMMENHANG MIT DER SOFTWARE ODER SONSTIGER VERWENDUNG DER SOFTWARE
;* ENTSTANDEN.
;*************************************************************************

DeclareModule ImgBBUpload
	;- --- [Module declaration / public elements] ------------------------------------------
	;-
	
	;*************************************************************************
	;- Compiler directives
	;*************************************************************************
	EnableExplicit
	
	;*************************************************************************
	;- Structures
	;*************************************************************************
	Structure ImgBBResult
		sFileStatus.s								; "Ok" = ok
		sHttpStatus.s								; "200" = ok
		sUploadSuccessfull.s				; true / false
		sViewerLink.s
		sDirectLink.s
		sDeleteLink.s
	EndStructure
	
	;*************************************************************************
	;- Public Procedures (dec)
	;*************************************************************************
	Declare.i ImgBBUpload(sImageFile.s, sAPIKey.s, *stOutImgBBResult.ImgBBResult)
	
EndDeclareModule

Module ImgBBUpload
	;-
	;- --- [Module implementation / private elements] -----------------------------------------
	;-
	
	;*************************************************************************
	;- Constants
	;*************************************************************************
	#IMGBB_URL										= "https://api.imgbb.com/1/upload?key=#APIKEY#"
	#IMGBB_PARAMS									= "image="
	
	;*************************************************************************
	;- Private Procedures (imp)
	;*************************************************************************
	
	;*************************************************************************
	;- Public Procedures (imp)
	;*************************************************************************
	Procedure.i ImgBBUpload(sImageFile.s, sAPIKey.s, *stOutImgBBResult.ImgBBResult)
		; +-----------------------------------------------------------------
		; |Description  : Automatically uploads an image to the image hoster www.ImgBB.com
		; |               The Imagehoster supports the image formats JPG, PNG, BMP and GIF with a maximum size of 16 MB.
		; |Arguments    : sImageFile      : The full path and filename of the image
		; |               sAPIKey         : The ImgBB.com API key, wich is necessary for the upload to work
		; |               stOutImgBBResult: A structured return variable of type ImgBBResult containing
		; |                                 the links to the uploaded image (preview link, direct link, delete link)
		; |Results      : 1, if the upload was successful, otherwise 0.
		; |Remarks      : -
		; +-----------------------------------------------------------------
		Protected.i *Buffer, iImgFile, iLength, iHttpRequest, iJson
		Protected.s sUrl, sParams, sImageB64, sResponse
		
		; Check file extension
		Select LCase(GetExtensionPart(sImageFile))
			Case "jpg", "png", "bmp", "gif"
				; Do nothing, because format is okay
			Default
				*stOutImgBBResult\sFileStatus = "File format error"
				ProcedureReturn 0
		EndSelect
		
		; Open Image file
		iImgFile = ReadFile(#PB_Any, sImageFile)
		If iImgFile = 0
			*stOutImgBBResult\sFileStatus = "File open error"
			ProcedureReturn 0
		EndIf
		
		iLength = Lof(iImgFile)
		If iLength < 1
			*stOutImgBBResult\sFileStatus = "File length error"
			CloseFile(iImgFile)
			ProcedureReturn 0
		EndIf		
		
		; Allocate a memory buffer, load the image into the buffer and encode it to Base64
		*Buffer = AllocateMemory(iLength)
		If *Buffer = 0 
			*stOutImgBBResult\sFileStatus = "File buffer error"
			CloseFile(iImgFile)
			ProcedureReturn 0
		EndIf
		
		iLength = ReadData(iImgFile, *Buffer, iLength)
		CloseFile(iImgFile)
		If iLength = 0
			*stOutImgBBResult\sFileStatus = "File read error"
			FreeMemory(*Buffer)
			ProcedureReturn 0
		EndIf
		
		sImageB64 = Base64Encoder(*Buffer, iLength)
		FreeMemory(*Buffer)
		*stOutImgBBResult\sFileStatus = "Ok"

		; Send image to image hoster
		sURL = #IMGBB_URL
		sURL = ReplaceString(sURL, "#APIKEY#", sAPIKey)
		sParams = URLEncoder(#IMGBB_PARAMS + sImageB64, #PB_UTF8)
		iHttpRequest = HTTPRequest(#PB_HTTP_Post, sURL, sParams)
		If iHttpRequest = 0
			*stOutImgBBResult\sHttpStatus = "HTTPRequest error"
			ProcedureReturn 0
		EndIf
		
		; Check status code of the Http request
		*stOutImgBBResult\sHttpStatus = HTTPInfo(iHttpRequest, #PB_HTTP_StatusCode)
		If *stOutImgBBResult\sHttpStatus <> "200"
			FinishHTTP(iHttpRequest)
			ProcedureReturn 0
		EndIf
		
		sResponse = HTTPInfo(iHttpRequest, #PB_HTTP_Response)
		sResponse = ReplaceString(sResponse, "\/", "/")
		FinishHTTP(iHttpRequest)
		
		; Extract JSON data
		iJson = ParseJSON(#PB_Any, sResponse)
		If iJson = 0
			*stOutImgBBResult\sUploadSuccessfull = "false"
			ProcedureReturn 0
		EndIf
		
		; Check if the upload is flagged as successfully by the image hoster
		If GetJSONBoolean(GetJSONMember(JSONValue(iJson), "success")) = 1
			*stOutImgBBResult\sUploadSuccessfull = "true"
		Else
			*stOutImgBBResult\sUploadSuccessfull = "false"
			FreeJSON(iJson)
			ProcedureReturn 0
		EndIf
		
		*stOutImgBBResult\sViewerLink = GetJSONString(GetJSONMember(GetJSONMember(JSONValue(iJson), "data"), "url_viewer"))
		*stOutImgBBResult\sDirectLink = GetJSONString(GetJSONMember(GetJSONMember(JSONValue(iJson), "data"), "url"))
		*stOutImgBBResult\sDeleteLink = GetJSONString(GetJSONMember(GetJSONMember(JSONValue(iJson), "data"), "delete_url"))
		FreeJSON(iJson)
		ProcedureReturn 1
		
	EndProcedure
EndModule

;-------------------------------------------------------------------------------
;- Main
CompilerIf #PB_Compiler_IsMainFile
	EnableExplicit
	
	#StatusMsg 		= "Drag 'n drop an image file into the red circle"
	#DemoAPIKey 	=	"33f1af445879b680577710583e8ec7b0" ; 33f1af445879b680577710583e8ec7b0
	
	Enumeration 
		#Window = 0
		#Image = 0
		#ImageGadget = 0
		#TextStatus
		#TextViewer
		#StringViewer
		#ButtonViewer
		#TextDirect
		#StringDirect
		#ButtonDirect
		#TextDelete
		#StringDelete
		#ButtonDelete
		#TextAPI
		#StringAPI
	EndEnumeration
	
	Global.i iImageSize = DesktopScaledX(100)
	
	Procedure UploadFile()
		UseModule ImgBBUpload
		Protected stImgBBResult.ImgBBResult
		Protected.s sFileName, sMessage
		
		sFileName = EventDropFiles()
		If FileSize(sFileName) > 0
			TextGadget(#TextStatus, 5, 112, 250, 20, "Uploading image, please wait...")
			If ImgBBUpload(sFilename, #DemoAPIKey, stImgBBResult)
				Debug "File status: " + stImgBBResult\sFileStatus
				Debug "Http status: " + stImgBBResult\sHttpStatus
				Debug "Upload status: " + stImgBBResult\sUploadSuccessfull
				SetGadgetText(#StringViewer, stImgBBResult\sViewerLink)
				SetGadgetText(#StringDirect, stImgBBResult\sDirectLink)
				SetGadgetText(#StringDelete, stImgBBResult\sDeleteLink)
			Else
				TextGadget(#TextStatus, 5, 112, 250, 20, "Error during image upload!")
				sMessage + "File status: " + #TAB$ + stImgBBResult\sFileStatus + #LF$
				sMessage + "Http status: " + #TAB$ + stImgBBResult\sHttpStatus + #LF$
				sMessage + "Upload status: " + #TAB$ + stImgBBResult\sUploadSuccessfull
				MessageRequester("Upload failed - Image upload to ImgBB.com", sMessage, #PB_MessageRequester_Error|#PB_MessageRequester_Ok)
			EndIf
			TextGadget(#TextStatus, 5, 112, 250, 20, #StatusMsg)
		EndIf
		UnuseModule ImgBBUpload
	EndProcedure
	Procedure Copy()
		Select EventGadget()
			Case #ButtonViewer
				SetClipboardText(GetGadgetText(#StringViewer))
			Case #ButtonDirect
				SetClipboardText(GetGadgetText(#StringDirect))
			Case #ButtonDelete
				SetClipboardText(GetGadgetText(#StringDelete))
		EndSelect
	EndProcedure
	Procedure.i CreateDropImage(iImageNo.i)
    If CreateImage(iImageNo, iImageSize, iImageSize) And StartDrawing(ImageOutput(iImageNo))
    Box(0, 0, iImageSize, iImageSize, $ffffff)
      Circle(iImageSize/2, iImageSize/2, iImageSize/2.2, $0000ee)
      Circle(iImageSize/2, iImageSize/2, iImageSize/3.2, $ffffff)
      Circle(iImageSize/2, iImageSize/2, iImageSize/6, $0000ee)
      StopDrawing() 
      ProcedureReturn 1
  EndIf
	ProcedureReturn 0
	EndProcedure
	
	Procedure Main()
		InitNetwork()
		
		If OpenWindow(#Window, 600, 100, 410, 130, "Image upload to ImgBB.com by Kurzer", #PB_Window_MinimizeGadget)
			StickyWindow(#Window, 1)
			If CreateDropImage(#Image)
				ImageGadget(#ImageGadget, 5, 5, iImageSize, iImageSize, ImageID(#Image), #PB_Image_Border)
				EnableGadgetDrop(#ImageGadget, #PB_Drop_Files, #PB_Drag_Copy)
				
				TextGadget(#TextStatus, 5, 112, 250, 20, #StatusMsg)
				TextGadget(#TextViewer, 120, 7, 70, 20, "Viewer link:")
				StringGadget(#StringViewer, 190, 5, 165, 20, "", #PB_String_ReadOnly)
				ButtonGadget(#ButtonViewer, 360, 5, 45, 20, "Copy")
				
				TextGadget(#TextDirect, 120, 30, 70, 20, "Direct link:")
				StringGadget(#StringDirect, 190, 28, 165, 20, "", #PB_String_ReadOnly)
				ButtonGadget(#ButtonDirect, 360, 30, 45, 20, "Copy")
				
				TextGadget(#TextDelete, 120, 53, 70, 20, "Delete link:")
				StringGadget(#StringDelete, 190, 51, 165, 20, "", #PB_String_ReadOnly)
				ButtonGadget(#ButtonDelete, 360, 53, 45, 20, "Copy")
				
				TextGadget(#TextAPI, 120, 82, 70, 20, "Your API key:")
				StringGadget(#StringAPI, 190, 80, 215, 20, #DemoAPIKey, #PB_String_ReadOnly)
				
				BindEvent(#PB_Event_GadgetDrop, @UploadFile(), 0, 0)
				BindGadgetEvent(#ButtonViewer, @Copy(), #PB_EventType_LeftClick)
				BindGadgetEvent(#ButtonDirect, @Copy(), #PB_EventType_LeftClick)
				BindGadgetEvent(#ButtonDelete, @Copy(), #PB_EventType_LeftClick)
				
				Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
				
				UnbindEvent(#PB_Event_GadgetDrop, @UploadFile(), 0, 0)
				UnbindGadgetEvent(#ButtonViewer, @Copy(), #PB_EventType_LeftClick)
				UnbindGadgetEvent(#ButtonDirect, @Copy(), #PB_EventType_LeftClick)
				UnbindGadgetEvent(#ButtonDelete, @Copy(), #PB_EventType_LeftClick)
				FreeImage(#Image)
				FreeGadget(#PB_All)
			EndIf
			CloseWindow(#Window)
		EndIf
	EndProcedure
	
	Main()
	End
CompilerEndIf
Have fun with this module

Greetings Kurzer
Last edited by Kurzer on Fri May 03, 2019 9:22 am, edited 3 times in total.
PB 6.02 x64, OS: Win 7 Pro x64 & Win 11 x64, Desktopscaling: 125%, CPU: I7 6500, RAM: 16 GB, GPU: Intel Graphics HD 520, User age in 2023: 56y
"Happiness is a pet." | "Never run a changing system!"
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5342
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Module: Automatic image upload to ImgBB.com

Post by Kwai chang caine »

Very usefull idea :idea:
Works great here, simpler would be indecent :D
Thanks for sharing 8)
ImageThe happiness is a road...
Not a destination
Little John
Addict
Addict
Posts: 4519
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: Module: Automatic image upload to ImgBB.com

Post by Little John »

Cool idea, thanks for sharing!
kvitaliy
Enthusiast
Enthusiast
Posts: 162
Joined: Mon May 10, 2010 4:02 pm

Re: Module: Automatic image upload to ImgBB.com

Post by kvitaliy »

Works great!
Thanks for sharing!
User avatar
Kurzer
Enthusiast
Enthusiast
Posts: 664
Joined: Sun Jun 11, 2006 12:07 am
Location: Near Hamburg

Re: Module: Automatic image upload to ImgBB.com

Post by Kurzer »

Thank you very much for your feedback. Image

I just fixed a small bug. The code in the first post has been updated.

Code: Select all

;* 1.01 - rel 01.05.2019: 
;*        fix - A closeFile() command was missing in the error handling (in line 174)
PB 6.02 x64, OS: Win 7 Pro x64 & Win 11 x64, Desktopscaling: 125%, CPU: I7 6500, RAM: 16 GB, GPU: Intel Graphics HD 520, User age in 2023: 56y
"Happiness is a pet." | "Never run a changing system!"
jsampo
New User
New User
Posts: 1
Joined: Tue Dec 17, 2019 11:33 pm

Re: Module: Automatic image upload to ImgBB.com

Post by jsampo »

Great program Kurzer!

Just would like to provide this modification/suggestion to pass the filename. Just change the line that sets sParams to:

sParams = URLEncoder("name=" + Left(GetFilePart(sImageFile),Len(GetFilePart(sImageFile))-4) + "&" + #IMGBB_PARAMS + sImageB64, #PB_UTF8)

-Jose
Post Reply