Image encode Base64 for use in HTML

Share your advanced PureBasic knowledge/code with the community.
kvitaliy
Enthusiast
Enthusiast
Posts: 162
Joined: Mon May 10, 2010 4:02 pm

Image encode Base64 for use in HTML

Post by kvitaliy »

Generates base-64 encoded from a given image file.
Encoded images is to wrap into html img tags.

Code: Select all

file$ = OpenFileRequester("Select a file","","Images (BMP,GIF,JPG,ICO,PNG) | *.bmp;*.gif;*.jpg;*.jpeg;*.png;*.ico",0)
  If file$
    If ReadFile(0, file$)
      length = Lof(0)                           
      *MemoryID = AllocateMemory(length)        
      If *MemoryID
        bytes = ReadData(0, *MemoryID, length)  
      EndIf
      CloseFile(0)
      Extension$ = GetExtensionPart(file$)
         Else
            End
    EndIf
  Else
    End
  EndIf

  Size = length * 1.35
  If Size < 64
    Size = 64
  EndIf
  
  *EncodeBuffer = AllocateMemory(Size)
  Size = Base64EncoderBuffer(*MemoryID, length, *EncodeBuffer, MemorySize(*EncodeBuffer))
  Encoded$ = PeekS(*EncodeBuffer, Size, #PB_Ascii)
  Debug Encoded$
  
  testHTML$+ "<html>"+ #CRLF$ +
             "<head>"+ #CRLF$ +
             "<title>BaseImage</title>"+ #CRLF$+
             "</head>"+ #CRLF$+
             "<body bgcolor='FFFFFF' text='#000000'>"+ #CRLF$+
             "<h1>BaseImage Demo</h1>"+ #CRLF$+
             "<h2>Created With PureBasic v.5.6x </h2>"+ #CRLF$+
             "<br /><br />"+ #CRLF$+
             "<img src='Data:image/"+Extension$+";base64," +Encoded$ + "'  />"+ #CRLF$+
             "<h3>Base 64 encoded image file wrapped in image tags</h3>"+ #CRLF$+
             "<br />"+ #CRLF$+
             "</body>"+ #CRLF$+
             "</html>"
  CreateFile(0,GetTemporaryDirectory()+"testB64.html")
  WriteString(0,testHTML$)
  CloseFile(0)
  RunProgram(GetTemporaryDirectory()+"testB64.html")
 
infratec
Always Here
Always Here
Posts: 6874
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Image encode Base64 for use in HTML

Post by infratec »

Why not:

Code: Select all

Encoded$ = Base64Encoder(*MemoryID, length)
Makes life easier :wink:
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5353
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Image encode Base64 for use in HTML

Post by Kwai chang caine »

Very useful for save a full HTML page with all his pictures in only one file, a little bit like the "MHT" format of IE :wink:
The pluggin for FF, "Save page WE" use this tips and do that perfectly...it's a real miracle, before i install him, i don't know it's possible :shock:
Thanks a lot for sharing KVITALIY 8)
ImageThe happiness is a road...
Not a destination
kvitaliy
Enthusiast
Enthusiast
Posts: 162
Joined: Mon May 10, 2010 4:02 pm

Re: Image encode Base64 for use in HTML

Post by kvitaliy »

infratec wrote:Why not:

Code: Select all

Encoded$ = Base64Encoder(*MemoryID, length)
Makes life easier :wink:
Ok!
The main thing is the principle of work. The implementation method may be different.
Seymour Clufley
Addict
Addict
Posts: 1233
Joined: Wed Feb 28, 2007 9:13 am
Location: London

Re: Image encode Base64 for use in HTML

Post by Seymour Clufley »

A much more extensive tool for Base64'ing all resources called by an HTML file can be found here.
JACK WEBB: "Coding in C is like sculpting a statue using only sandpaper. You can do it, but the result wouldn't be any better. So why bother? Just use the right tools and get the job done."
User avatar
tikidays
User
User
Posts: 43
Joined: Tue Oct 24, 2023 6:47 am
Location: New Zealand
Contact:

Re: Image encode Base64 for use in HTML

Post by tikidays »

Thanks for this code kvitally,

Are you able to show me how to use the encoding part of this to encode a PNG in memory to a string? Im a noob and tried and failed. I want to be able to write this string to a file Im using for my app and to include images, and back again.

Code: Select all

Procedure.s encodePNG(image.i)
  *memoryID = image
  length = SizeOf(image)
  size = length * 1.35
  If size < 64 : size = 64 : EndIf
  *encodeBuffer = AllocateMemory(size)
  size = Base64EncoderBuffer(*memoryID, length, *encodeBuffer, MemorySize(*encodeBuffer))
  encoded.s = PeekS(*encodeBuffer, size, #PB_Ascii)
  ProcedureReturn encoded
 EndProcedure
Debug gives me : size of image: 0 encoded : IE1XAwBgAAA=
ZX80
Enthusiast
Enthusiast
Posts: 331
Joined: Mon Dec 12, 2016 1:37 pm

Re: Image encode Base64 for use in HTML

Post by ZX80 »

tikidays,

I think you need something like this:

Code: Select all

Define.i img, *mem, Base64Size
Define encoded$

img = LoadImage(#PB_Any, #PB_Compiler_Home + "Examples\Sources\Data\PureBasicLogo.bmp")
If img
  If StartDrawing(ImageOutput(img))
    *mem = DrawingBuffer()
    imgsize = DrawingBufferPitch() * ImageHeight(img) ; Wrong size !
    StopDrawing()
  EndIf
  Base64Size = Int(1.35 * imgsize)
  encoded$ = Base64Encoder(*mem, Base64Size)
  FreeImage(img)
EndIf

Debug encoded$
but...
It does not work. :(

Sorry.
infratec
Always Here
Always Here
Posts: 6874
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Image encode Base64 for use in HTML

Post by infratec »

You need EncodeImage()

This was already pointed out here:
https://www.purebasic.fr/english/viewto ... 94#p613694
infratec
Always Here
Always Here
Posts: 6874
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Image encode Base64 for use in HTML

Post by infratec »

Code: Select all

Procedure.s ImageToBase64(Image.i, Format.i=#PB_ImagePlugin_JPEG)
  
  Protected *ImgBuffer, Base64$
  
  
  If IsImage(Image)
    *ImgBuffer = EncodeImage(Image, Format)
    If *ImgBuffer
      Base64$ = Base64Encoder(*ImgBuffer, MemorySize(*ImgBuffer))
      FreeMemory(*ImgBuffer)
    EndIf
  EndIf
  
  ProcedureReturn Base64$
  
EndProcedure
ZX80
Enthusiast
Enthusiast
Posts: 331
Joined: Mon Dec 12, 2016 1:37 pm

Re: Image encode Base64 for use in HTML

Post by ZX80 »

infratec, it works !
Thank you so much !

Tell me, please, in order to correctly decode an image, I need to know the original size of the image ?
I just tried STARGÅTE code from here. And... I was unable to obtain the original image. It is three+ times larger in size and also distorted. Even if I manually write the original image size (buffersize = 7812). It still doesn't work properly.

Thank you in advance !

Code: Select all

Procedure.s ImageToBase64(Image.i, Format.i=#PB_ImagePlugin_JPEG)
  
  Protected *ImgBuffer, Base64$
  
  
  If IsImage(Image)
    *ImgBuffer = EncodeImage(Image, Format)
    If *ImgBuffer
      Base64$ = Base64Encoder(*ImgBuffer, MemorySize(*ImgBuffer))
      FreeMemory(*ImgBuffer)
    EndIf
  EndIf
  
  ProcedureReturn Base64$
  
EndProcedure

Procedure base64catchimage(buffer$) ; Create a new image from a base64 string.
  
  Protected buffersize = 64
  
  If Len(buffer$) > buffersize
    buffersize = Len(buffer$) * 0.7 ; buffer can by smaller.
  EndIf
  
  *output = AllocateMemory(buffersize) ; Allocate a memory block the size of the string (buffer$)
  
  Debug "buffersize =  " + Str(buffersize)
  buffersize = Base64Decoder(buffer$, *output , buffersize) ; Decode the string (buffer$) into memory (*output) with the size provided
  ; buffersize is now the real size of the decoded string, useful in CatchImage.
  
  Debug "buffersize =  " + Str(buffersize) ; why buffersize is zero ???
  buffersize = 7812
  image = CatchImage(#PB_Any, *output, buffersize) ; Output an ImageID from Base64 decoded memory
  
  FreeMemory(*output)
  
  ProcedureReturn image
  
EndProcedure


img = LoadImage(#PB_Any, #PB_Compiler_Home+"Examples\Sources\Data\PureBasicLogo.bmp")
If img
  Encoded$ = ImageToBase64(img, #PB_ImagePlugin_BMP)
  FreeImage(img)
EndIf

Debug Encoded$
; -----------------------------------------------------------------------------  
img = base64catchimage(Encoded$)
If SaveImage(img, GetTemporaryDirectory()+"testB64.bmp", #PB_ImagePlugin_BMP)
  FreeImage(img)
  RunProgram(GetTemporaryDirectory()+"testB64.bmp")
EndIf
infratec
Always Here
Always Here
Posts: 6874
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Image encode Base64 for use in HTML

Post by infratec »

Full working example:

Code: Select all

EnableExplicit

Procedure.s ImageToBase64(Image.i, Format.i=#PB_ImagePlugin_JPEG)
  
  Protected *ImgBuffer, Base64$
  
  
  If IsImage(Image)
    *ImgBuffer = EncodeImage(Image, Format)
    If *ImgBuffer
      Base64$ = Base64Encoder(*ImgBuffer, MemorySize(*ImgBuffer))
      FreeMemory(*ImgBuffer)
    EndIf
  EndIf
  
  ProcedureReturn Base64$
  
EndProcedure


Procedure.i Base64ToImage(Base64$)
  
  Protected *Base64, *Image, Size.i, Image.i
  
  
  *Base64 = Ascii(Base64$)
  If *Base64
    *Image = AllocateMemory(MemorySize(*Base64) * 0.7, #PB_Memory_NoClear)
    If *Image
      Size = Base64DecoderBuffer(*Base64, MemorySize(*Base64), *Image, MemorySize(*Image))
      If Size > 0
        Image = CatchImage(#PB_Any, *Image, Size)
      EndIf
      FreeMemory(*Image)
    EndIf
    FreeMemory(*Base64)
  EndIf
  
  ProcedureReturn Image
  
EndProcedure


#Filename$ = "c:\tmp\base64.jpg"

Define Base64$, Image.i


UseJPEGImageEncoder()
UseJPEGImageDecoder()


CreateImage(0, 200, 200)
If StartDrawing(ImageOutput(0))
  Box(0, 0, 200, 200, #Red)
  StopDrawing()
  
  If CreateFile(1, #Filename$)
    WriteString(1, ImageToBase64(0, #PB_ImagePlugin_JPEG), #PB_Ascii)
    CloseFile(1)
  EndIf
EndIf

If FileSize(#Filename$) > 0
  If ReadFile(1, #Filename$)
    Base64$ = ReadString(1, #PB_Ascii|#PB_File_IgnoreEOL)
    CloseFile(1)
  EndIf
EndIf

If Base64$ <> ""
  Image = Base64ToImage(Base64$)
  If IsImage(Image)
    Debug "Image loaded"
    
    OpenWindow(0, 0, 0, 200, 200, "Base64Image", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
    ImageGadget(0, 0, 0, 0, 0, ImageID(Image))
    
    Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
    
    FreeImage(Image)
  Else
    Debug "Image failed"
  EndIf
EndIf

DeleteFile(#Filename$)
ZX80
Enthusiast
Enthusiast
Posts: 331
Joined: Mon Dec 12, 2016 1:37 pm

Re: Image encode Base64 for use in HTML

Post by ZX80 »

infratec, thank you very much again !
I'll look your code in detail tomorrow.

This is a very useful piece of code to send image over a network.
Thank you !
ZX80
Enthusiast
Enthusiast
Posts: 331
Joined: Mon Dec 12, 2016 1:37 pm

Re: Image encode Base64 for use in HTML

Post by ZX80 »

infratec, I did a little test now and...
YES :!: Checksums are OK ! Сontent is ok.

I was a confused by the difference in file sizes between the original and decoded ones. But now I'm sure everything is fine ! I confirm !
Thank you !
Post Reply