Page 1 of 1

Trying to figure out how to extract an image from a pack file

Posted: Thu Mar 06, 2025 12:47 am
by Carm3D
ok I have a question... And this is perplexing all of the AIs I am trying.

I have a pack file.. it contains 19 PNG images compressed.

I allocate memory to hold the pack data when it is read. Good.

I am able to use NextPackEntry to step through the pack one entry at a time... From here I can glean the filename and the size of each chunk.

I -believe- the goal is to copy a cropped portion of this buffer to a new buffer.. So the first entry starts at 0 and has a size of X. The next entry starts at X and has a size of Y..

I do not see any tool to copy a portion of the buffer to a new buffer starting from a specific location.. Nor do I see any tools to crop memory buffers... What key component am I missing here?

Once I get this sorted, the goal is to take the new buffer, uncompress it, and then use CatchImage to pull the image out, yes?

Re: Trying to figure out how to extract an image from a pack file

Posted: Thu Mar 06, 2025 12:53 am
by idle
you could use EZpack
https://www.purebasic.fr/english/viewtopic.php?t=52586
you can catch files from memory

Re: Trying to figure out how to extract an image from a pack file

Posted: Thu Mar 06, 2025 1:11 am
by Carm3D
I think I may have just found the originally-intended solution... UncompressPackMemory()

Gonna try it out.

Re: Trying to figure out how to extract an image from a pack file

Posted: Thu Mar 06, 2025 1:27 am
by RASHAD
Hi
You can get only any pack file by knowing the file name

Code: Select all

UseZipPacker()

Path$ = #PB_Compiler_Home + "examples/sources/Data/" ; path to the PureBasic examples data/media files
PackFile$ = GetTemporaryDirectory() + "PureBasicTest.zip"  ; path to the pack file which should be created and opened later
If CreatePack(0, PackFile$)
  AddPackFile(0, Path$ + "world.png", "world.png")
  AddPackFile(0, Path$ + "test.pref", "test.pref")
  AddPackFile(0, Path$ + "CdPlayer.ico", "CdPlayer.ico")
  AddPackFile(0, Path$ + "Background.bmp", "Background.bmp")
  ClosePack(0)
  Debug "PackFile successfully created: " + PackFile$
Else
  Debug "Error creating the pack file!"
EndIf

Path$ = GetTemporaryDirectory() + "PureBasicTest/"  ; path to a directory into which the pack files should be extracted
If OpenPack(0, PackFile$)
  If CreateDirectory(Path$) Or FileSize(Path$) = -2
    If ExaminePack(0)
      While NextPackEntry(0)
        text$ = PackEntryName(0)
        If text$ = "CdPlayer.ico"
          UncompressPackFile(0, GetTemporaryDirectory()+ text$)
          Break
        EndIf
      Wend
    EndIf
    ClosePack(0)
  Else
    Debug "Error while creating the folder '" + Path$ + "' to unpack the archive contents!"
  EndIf
Else
  Debug "Error opening the pack file!"
EndIf



Re: Trying to figure out how to extract an image from a pack file

Posted: Thu Mar 06, 2025 1:39 am
by Carm3D
I believe I have successfully used UncompressPackMemory().... if my debug messages can be believed. CatchImage() has not worked so far.

This is what my code looks like so far.

Code: Select all

If ExaminePack(PreloadPack)
			PackEntryStart = 0
			While NextPackEntry(PreloadPack)
				PackEntrySize = PackEntrySize(PreloadPack)
				PackEntryName = PackEntryName(PreloadPack)
				;Debug "PackEntryName: " + PackEntryName
				;Debug "PackEntrySize: " + Str(PackEntrySize)

				*PackEntry = AllocateMemory(PackEntrySize * 3)
				If UncompressPackMemory(PreloadPack, *PackEntry, PackEntrySize) = -1
					MessageRequester("Error", PackEntryName + " could not decompress.", #PB_MessageRequester_Error)
					FreeMemory(*PackEntry)
					FreeMemory(*PreloadBuffer)
					EndProgram()
				Else
					;Debug "Entry:" + PackEntryName + " decompressed."
					If CatchImage(#PB_Any, *PackEntry) = 0
						MessageRequester("Error", PackEntryName + " could not catch image.", #PB_MessageRequester_Error)
						FreeMemory(*PackEntry)
						FreeMemory(*PreloadBuffer)
						EndProgram()
					EndIf
				EndIf
				PackEntryStart = PackEntryStart + PackEntrySize
			Wend
			Else
				MessageRequester("Error", "Failed to examine Preload.bin!", #PB_MessageRequester_Error)
				FreeMemory(*PreloadBuffer)
				EndProgram()
			EndIf

Re: Trying to figure out how to extract an image from a pack file

Posted: Thu Mar 06, 2025 4:42 am
by miso

Code: Select all

;Load and catch an image from a zip

#PACKPLUGIN = #PB_PackerPlugin_Zip
UseZipPacker()
UsePNGImageDecoder()
UsePNGImageEncoder()
Define myimage_id.i

;-PROCEDURE
;****************************************************
;LOADS AND CATCHES A SPECIFIC IMAGE FROM A PACKFILE
;RETURNS :#FALSE ON ERROR
;         VALID IMAGE ID ON SUCCESS
;****************************************************
Procedure.i imageloadfrompack(packname.s,entryname.s)
  Protected packid.i, Size.i, *Buffer, Catched_Image_ID.i,Result.i
  If Not FileSize(packname.s) : Debug "Packfile not found: " + packname.s + "." : ProcedureReturn #False :EndIf
  packid.i = OpenPack(#PB_Any,packname.s,#PACKPLUGIN)
  If Not packid : Debug packname.s + " is not a valid pack file, or corrupted." :  ProcedureReturn #False : EndIf
  If Not ExaminePack(packid) : Debug "Error While examining the pack.":ClosePack(packid) : ProcedureReturn #False : EndIf
  
  While NextPackEntry(packid)
    If PackEntryName(packid) = entryname.s
      Size.i = PackEntrySize(packid,#PB_Packer_UncompressedSize)
      *Buffer = AllocateMemory(Size.i)
      If Not *Buffer : Debug "Could not allocate memory" : ClosePack(packid) : ProcedureReturn #False : EndIf
      result.i = UncompressPackMemory(packid,*Buffer,Size.i,name.s)
      If result <> size : Debug "Something wrong while uncompressing, size differs." : FreeMemory(*Buffer) : ClosePack(packid) : ProcedureReturn #False : EndIf
      Catched_Image_ID = CatchImage(#PB_Any,*Buffer,Size)
      ClosePack(packid)
      FreeMemory(*Buffer)
      If Not IsImage(Catched_Image_ID) : Debug "Packentry might be not an image, or need to use some imageplugin to catch" : ProcedureReturn #False : EndIf
      ProcedureReturn Catched_Image_ID
    EndIf
  Wend
  
  Debug "Could not find "+ entryname.s + " in pack " + packname.s+ "."
  ClosePack(packid)
  ProcedureReturn #False
EndProcedure





;-EXAMPLE USAGE      
;CHANGE THE NAMES TO A CORRECT ZIPFILE AND ENTRYNAME    
myimage_id = imageloadfrompack("MiniWorldSprites.zip","mountains.png")
SaveImage(myimage_id,"hello.png",#PB_ImagePlugin_PNG)


Re: Trying to figure out how to extract an image from a pack file

Posted: Thu Mar 06, 2025 9:08 am
by Carm3D
miso wrote: Thu Mar 06, 2025 4:42 am

Code: Select all

;Load and catch an image from a zip
Thank you Miso. This may work, but I need something that can grab/catch every image in the pack in one sequenced shot. I have a couple of packs of 32 images and I will need to grab them repeatedly and I believe your system requires a single image to be pulled out by name. Do you have a solution that will grab everything in a pack and catch them all in one go?

Re: Trying to figure out how to extract an image from a pack file

Posted: Thu Mar 06, 2025 9:19 am
by miso
May sound silly to open a pack then close it multiple times one after another, but works. I don't know if PB or the Windows OS caches something, but after the first unpack the other ones are lightning fast from the same archive.

Also, you can modify that code to iterate trough and catch everything from your pack in one step, store the id-s in a list or array or map.
Entryname is optional while unpacking in memory.

Re: Trying to figure out how to extract an image from a pack file

Posted: Thu Mar 06, 2025 6:02 pm
by Carm3D
I'm giving up on Packer.. I'm going to arrange my images into a sprite sheet thing and chop them up into images inside my program.

Re: Trying to figure out how to extract an image from a pack file

Posted: Thu Mar 06, 2025 6:22 pm
by Quin
Carm3D wrote: Thu Mar 06, 2025 6:02 pm I'm giving up on Packer.. I'm going to arrange my images into a sprite sheet thing and chop them up into images inside my program.
Why? Have you found a bug with the Packer library? It should be able to do everything you want super efficiently.

Re: Trying to figure out how to extract an image from a pack file

Posted: Thu Mar 06, 2025 6:58 pm
by Carm3D
Quin wrote: Thu Mar 06, 2025 6:22 pm Why? Have you found a bug with the Packer library? It should be able to do everything you want super efficiently.
I don't know if it's a bug or I am just a moron, but I couldn't get it to work... Esp. CatchImage(). I'm now making my images into sprite-sheets and I'll chop them up into image sequences after loading.

Re: Trying to figure out how to extract an image from a pack file

Posted: Thu Mar 06, 2025 7:04 pm
by miso
I don't know why is that good, but here's the code:

Code: Select all

;Load and catch all images from a zip, stores the ID-s in an array.
EnableExplicit
#PACKPLUGIN = #PB_PackerPlugin_Zip
UseZipPacker()
UsePNGImageDecoder()
UsePNGImageEncoder()

Global Dim Images_h(0)

;-PROCEDURE
Procedure.i load_all_images_from_pack(packname.s)
  Protected packid.i, Size.i, *Buffer, Catched_Image_ID.i,Result.i
  If Not FileSize(packname.s) : Debug "Packfile not found: " + packname.s + "." : ProcedureReturn #False :EndIf
  packid.i = OpenPack(#PB_Any,packname.s,#PACKPLUGIN)
  If Not packid : Debug packname.s + " is not a valid pack file, or corrupted." :  ProcedureReturn #False : EndIf
  If Not ExaminePack(packid) : Debug "Error While examining the pack.":ClosePack(packid) : ProcedureReturn #False : EndIf
  
  While NextPackEntry(packid)
      Size.i = PackEntrySize(packid,#PB_Packer_UncompressedSize)
      *Buffer = AllocateMemory(Size.i)
      result.i = UncompressPackMemory(packid,*Buffer,Size.i)
      Images_h(ArraySize(images_h())) = CatchImage(#PB_Any,*Buffer,Size)
      FreeMemory(*Buffer)      
      ReDim Images_h(ArraySize(Images_h())+1)
  Wend
  ClosePack(packid)
EndProcedure

;-EXAMPLE USAGE      
;CHANGE THE NAMES TO A CORRECT ZIPFILE AND ENTRYNAME    
OpenConsole("Test")
load_all_images_from_pack("MiniworldSprites2.zip")

PrintN("ID-s of loaded images")
PrintN("")

Define i.i
For i = 0 To ArraySize(images_h())-1
  PrintN("Image_handle_"+RSet(Str(i),2,"0")+": "+Str(Images_h(i)))
Next i

PrintN(Str(ArraySize(Images_h()))+" images loaded.")

Input()
End

Re: Trying to figure out how to extract an image from a pack file

Posted: Mon Mar 31, 2025 12:58 am
by Mohawk70
RASHAD wrote: Thu Mar 06, 2025 1:27 am Hi
You can get only any pack file by knowing the file name
See this topic for an easy solution for getting file names for a pack file.
The method there even includes a way to check the integrity of the files extracted ( file size and filehash ). PB has built-in hashing functions.

https://www.purebasic.fr/english/viewtopic.php?t=42330