Page 1 of 2
Knowing file size of saved BMP, JPG and PNG images
Posted: Sun Jan 13, 2008 2:34 am
by PB
Hi,
I want my app to be able to save images in BMP, JPG and PNG formats, but
I'd like to tell the user what file size (on disk) each image will be, so he can
choose the format based on size accordingly.
So, is there a way to work out the resulting file size, preferably WITHOUT
saving test files to disk first? Because if I write test files to disk, then get
their file sizes, and then delete the tests, there will be two problems:
(1) A potential performance hit (eg. small delay while 3 are being saved).
(2) A security risk if the image is sensitive, because the test images could
be undeleted later from their temp location if someone scans the drive.
Although I guess I could save them without a file extension and then write
over the entire image file with random data, so the images wouldn't look
obvious, and not able to be loaded. Hmm. Performance hit again.
This is why I loved the Amiga; you could save them to RAM: and then just
delete them, with no performance hit or risk of undeletion. How I miss it.
Anyway, any ideas on this? Thanks.
Posted: Sun Jan 13, 2008 3:02 am
by pdwyer
THis is not an OS issue though, (not sure if that's what you meant). It's just a feature lacking in the built in plugins.
Not sure if there's a way to trick it by using some sort of memory mapped file but the alternative would be 1) put in a feature request 2) use some other module.
You'll still get the CPU perf hit though as these algorithms need to run across the actual data and compress them to find out what the size will be. I see your point though, disk i/o will slow this down and possibly leave ressidue
Posted: Sun Jan 13, 2008 3:25 am
by PB
> THis is not an OS issue though, (not sure if that's what you meant)
The Amiga has a RAM disk as part of the OS, and you can read/write to it at
any time, without any loss of performance because it's not a physical disk.

Posted: Sun Jan 13, 2008 4:03 am
by pdwyer
go with some other module then, seems a little excessive to be wanting to use a ram disk for something like this anyway. There's no reason a gfx compression module can't let you at the memory before it writes it to disk.
Posted: Sun Jan 13, 2008 4:21 am
by Fluid Byte
For BMP it's easy, just calculate the header + pixeldata (depending on bit depth). But for PNG and JPG it a little difficult. You have to take into account the various color pallete adaption methods for 8-bit images as well as the compression levels of a JPG image. Altough I can tell you for sure that it can be done you won't get very far with PB's internal image en - / decoders because you need to integrate the image formats yourself. If you don't you will not have the needed control to calculate the specific image size.
There maybe some libraries like
FreeImage that will give you the option to calculate the size on image data stored temporarily in memory.
Posted: Sun Jan 13, 2008 12:30 pm
by Trond
Posted: Sun Jan 13, 2008 1:57 pm
by srod
A named pipe is mapped to a disc file anyhow!

Posted: Sun Jan 13, 2008 2:20 pm
by Trond
Are you sure?
Posted: Sun Jan 13, 2008 2:29 pm
by srod
Yes, I did some reading around on named pipes some time ago and at the lowest level; they are mapped to a disc file. Of course, all this is transparent to us lowly developers!

Posted: Sun Jan 13, 2008 2:56 pm
by PB
Thanks for the suggestion anyway, Trond.

Posted: Sun Jan 13, 2008 11:01 pm
by waldschrath
This is not tested, just an Idea. Use Gdi+ to save the Image to an IStream and the call IStream\Stat.
http://www.purebasic.fr/english/viewtopic.php?t=28290 gives an example of saving an Image using Gdi+. Instead of ""GdipSaveImageToFile" you use "GdipSaveImageToStream" and "StringToBStr(filenameout)" has to be replaced by the IStream Object.
The IStream Object is created by CreateStreamOnHGlobal, see short Example below:
Code: Select all
Structure STATSTG
*pwcsName
type.l
cbSize.q
mtime.q
ctime.q
atime.q
grfMode.l
grfLocksSupported.l
clsid.b[16]
grfStateBits.l
reserved.l
EndStructure
If CreateStreamOnHGlobal_(0, 1, @stream.IStream) = #S_OK
*p = AllocateMemory(2000)
If *p <> #Null
If stream\Write(*p, 2000, @written.l) = #S_OK
Debug written
If stream\Stat(@stat.STATSTG, 1) = #S_OK
Debug StrQ(stat\cbSize)
EndIf
EndIf
FreeMemory(*p)
EndIf
stream\Release()
EndIf
Posted: Mon Jan 14, 2008 9:46 am
by thefool
SROD are you sure about that?
Named pipes store data in memory and retrieve it when requested, in a way that is similar to reading from and writing to a file system.
http://publib.boulder.ibm.com/infocente ... min146.htm
Sure enough you can use basic file handling api commands to communicate with it, but that doesn't mean its not stored in memory.
I suppose the only way to get a real answer is to monitor disk
usage while writing and reading from pipes.
Posted: Mon Jan 14, 2008 9:47 am
by Mistrel
What if the file you're writing can't fit into memory twice? What then? :roll:
Posted: Mon Jan 14, 2008 9:50 am
by thefool
Mistrel wrote:What if the file you're writing can't fit into memory twice? What then? :roll:
Then the system will use the page file?
Or else just do a checking on how the raw image data is.
Posted: Mon Jan 14, 2008 9:54 am
by thefool
Whenever a pipe write operation occurs, the system first tries to charge the memory against the pipe write quota. If the remaining pipe write quota is enough to fulfill the request, the write operation completes immediately. If the remaining pipe write quota is too small to fulfill the request, the system will try to expand the buffers to accommodate the data using nonpaged pool reserved for the process. The write operation will block until the data is read from the pipe so that the additional buffer quota can be released. Therefore, if your specified buffer size is too small, the system will grow the buffer as needed, but the downside is that the operation will block. If the operation is overlapped, a system thread is blocked; otherwise, the application thread is blocked.
Sounds like memory to me?
http://msdn2.microsoft.com/en-us/library/aa365150.aspx