There was a thread on UtilityBase (I think) about how to display bitmap images that are embedded in the executable. Sadly, the site has been dead as a dodo for more than a year now.
What I'm after is this: I have a simple 16-colour image that I want to embed in the program and display in the GUI using ReAction. For certain specific reasons I don't want to use bitmap.image's BITMAP_SourceFile tag to load the image from disk, using datatypes. How would I best go about it? I have the image exported from PPaint as a field of UWORDs plus a corresponding struct Image, but how do I remap its colours for the screen the GUI opens on?
Are you sure there was a working solution in this thread?
IIRC the discussion was about embedding an image file as binary in the executable and then using NewDTObject with DTA_SourceType,DTST_MEMORY and DTA_SourceAddress and DTA_SourceSize.
The problem was that the person did not get it to work while there was an example on the ADCD which appears to work. However, the example fools itself because it supplies the file name to NewDTObject. What happens is that DTST_MEMORY is ignored and the file is loaded from disk instead.
I don't remember a sample program with DTST_MEMORY which really works as intended.
Maybe the support for DTST_MEMORY was widelier spread into datatype subclasses in OS 4, but on OS 3.9 there is not a single picture subclass I know which supports it.
@thomas
I don't think it was related to datatypes at all but I may as well be mistaken.
Anyway, the SDK's ReAction speedbar.gadget example actually uses an embedded image - the only difference is that it doesn't remap any colours but uses the standard few defined for the Workbench screen. What I'd like to know is whether the remapping is possible at all or not, and how should I do it.
AmigaOne X5000-020 / 2GB RAM / Sapphire Pulse Radeon RX 560 / AmigaOS 4.1 Final Edition Update 2
@trixie
I wanted to embed some small images in a little program I was working on and had the same problem. I couldn't find an example that works so I gave up. However, your request set me off on another search and this time I may have found the solution. There is an example on the ADCD_2.1 developer CD that might do the trick. It uses DTST_MEMORY like thomas suggested. It opens an image file, copies it into memory and then displays it from memory. I was surprised that DTST_MEMORY works on an undecoded image file in memory but that seems to be the case. I tested the OS3 binary and it worked with a small IFF file. It displayed a PNG file but the alpha channel didn't work.Take a look at the directory ADCD_2.1/NDK/NDK_3.5/Examples/DataTypes/Memory on the dev CD. It seems to me that if the example can load the file into memory and display it then you should be able to load it into memory from an embeded array in your program. If you succeed, please share :-)
X1000 - OS 4.1FE
@xenic
Thanks very much, I'll give it a try!
AmigaOne X5000-020 / 2GB RAM / Sapphire Pulse Radeon RX 560 / AmigaOS 4.1 Final Edition Update 2
@trixie
I changed the example to use proto/ includes instead of clib/, changed the FileInfoBlock (fib) to use AllocDiskObject, removed the extern library declarations, removed the amigaguide includes, added "PDTA_DestMode,PMODE_V43," & "PDTA_Remap,TRUE," to the NewDTObject function call and compiled the example for OS4 using -D__USE_INLINE__. It loads 32bit IFF files or PNG files and displays them with proper alpha channel blending :-)
X1000 - OS 4.1FE
@xenic
This is exactly the example I mentioned above. Are you really sure that it uses the memory address supplied with DTA_SourceAddress for you? Please change the example so that it does not supply the original file name to NewDTObject. Only then you are able to recognise whether it really works as expected or not.
@thomas
The example did in fact have the filename as the first argument to NewDTObject but when I changed the name argument to NULL the example still works. Whether it works by copying the file from embedded data still remains to be seen. I'll try that as soon as I can.
EDIT: I converted an image file to C source with BinToC, commented out the filereading code and simply inserted the embedded array address in NewDTObject (DTA_SourceAddress, &TESTDT_ARRAY). It works! It's probably a bad idea to pass the address of data embedded in a program but it was just for a quick test and the array should probably be copied to allocated memory.
X1000 - OS 4.1FE
@trixie
A struct Image has no palette specified so it's a but hard to remap pen colours. But, where does PPaint save the palette? The Image palette would depend on the screen it is on and the Image settings determine what bitplanes and thus what pens are written into.
Are you blitting onto an RTG or classic screen? For RTG a bitplane based Image is no so efficient. Apart from datatypes I don't know how one would go about displaying a binary image. We don't seem to have a way of dealing with images otherwise.
@Hypex
There are several programs at Aminet that will (ifftoC, iff2c, image2c etc.) produce palette and pen tables along with the image but that still leaves you with the problem of remapping to get the right colors on the target screen and that is way more complicated than I would want.
There is penmap class which will accept chunky image data and pens or palette. There are several programs (mchunky) at Aminet that will convert an image to a C file containing chunky data & palette needed for penmap class. The penmap example in SDK:Examples/ReAction/os4examples/ uses embedded chunky data to display an image. However, a 956 byte iff file turns into 15,640 of bytes of chunky data in a C file so the datatype method of embedding the original iff file and loading the image from that is a lot more effecient as far as program size is concerned. The only potential problem with that is the 8bit CLUT screen issue reported in the "Strange DataType problem.." topic. Thomas states that setting PDTA_DestMode to PMODE_V42 is needed in that case which I suppose means that you would need to check the screen depth before you display the image with DataTypes.
I've haven't found any programs that will convert a bitmap to a C file that can be loaded with bitmap class but it should be possible. I suspect it will suffer the same program size bloat that using penmap class produces.
X1000 - OS 4.1FE
@xenic
If you're concerned about executable size why not just compress the raw image data with gzip or bzip2 and then in your program you can decompress it using z.library or bz2.library?
@salass00
If by "raw image data" you mean the array data that will be embedded in the program; the embedded image data for the datatatype method of setting DTA_SourceType to DTST_MEMORY can be an embedded PNG file or ILBM bitplane file. I did some testing and bzip2 makes a PNG file larger in some cases.There might be some size advantage to compressing the chunky image data that would be used for the penmap class method of displaying an image but why bother when you can simply use data that is already in a compressed format with the datatype method?? Even if I could figure out how to save a bitmap for embedding in a C language file for use with bitmap class, the same holds true.
X1000 - OS 4.1FE
I've had good success creating images on the fly with DataTypes and PDTM_WRITEPIXELARRAY
With images stored as arrays of 32bit ARGB
All the brush buttons in SketchBlock are genarated that way.
By "raw image data" I mean just that, i.e. just a normal array of ARGB32 or CLUT8 pixels (depending on your needs). Compressing a PNG image of course won't do much as the image data there is already zlib compressed.
@xenic
There are actually some pen functions I remember for obtaining or determining the best pen colour for an RGB value. For true colour it would be exact. But then of course you have your palette and would still need to remap that data to the screen.
That's interesting as the IFF compression isn't considered the best and could lose out by being bitmap based.
One can of course use own or third party compression to bring it down. I once wrote a 68020 optimised run byte compression/decompression routine. I called it Flat. To expand I called it Fat. So you Flatten it then Fatten it later. Hehe. :-D
It would have been easy enough to modernise the routine to use run "pattern" compression instead like the better methods do by storing an offset and length to copy instead of one character that repeats.
That's a bit older than I remember. I've heard of a PMODE_V43 being needed but not an earlier one.
They would need output a format compatible to the class. And needing to expand the graphic data beforehand would complicate it and cause extra overhead.
@Hypex
Unless you're writing a graphics program, doing it that way would a fairly large distraction from the functional goal of the the program.
Yes. The original IFF ILBM compression was not very effective and in the case of small images can be counterproductive. If you create a small brush in PPaint (less that 256x256) with an 8 color palette, saving it as a compressed ILBM will yield a larger file than if you save it uncompressed. However, if you save an IFF ILBM with few colors it can be smaller than a compressed RGB image because it only needs to contain the active bitplanes and not the bitplanes that are all zeros. For example, I saved a document scan as a 2 color (single bitplane) ILBM that has a filesize of 97526 bytes. Saving as an RGB PNG yields a filesize of 81179 bytes which is not that different from the ILBM file.
I'm just quoting someone else's suggestion but I assume it means that you need to use the old remapping method for 8 bit screens.
X1000 - OS 4.1FE
Hi, yep "reusing" this old thread/topic.
I managed to create an image frrom an embedde data image:
...
But it stays always at left border/side, how can I "center" it.
TiA
AOS4.1/SAM460ex/PPC460EX-1155MHZ/2048MB/RadeonHD6570/SSD120GB/DVDRW :-P
Add a space.gadget object on both sides of the banner.
GA_RelWidth is not what you want. If this code works for you, then apparently it is ignored.
GA_RelWidth makes the gadget width relative to the window width. It is only useful with negative values. And it only makes sense if the gadget is added directly to an Intuition window, not to a layout gadget or a window.class object.
In order to scale the banner to a certain size, you should use the PDTM_SCALE method.
Yes, thx. Removed GA_RelWidth and it now it's centered.
AOS4.1/SAM460ex/PPC460EX-1155MHZ/2048MB/RadeonHD6570/SSD120GB/DVDRW :-P
BTW do I need to "DisposeDTObject()"?
Or does "DisposeObject( OBJ(OID_MAINWIN) );" dispose the datatype object too.
AOS4.1/SAM460ex/PPC460EX-1155MHZ/2048MB/RadeonHD6570/SSD120GB/DVDRW :-P
Both window.class and layout.gadget will automatically dispose their children added via WINDOW_Layout resp. LAYOUT_AddChild. So no, you don't need to manually dispose the datatype object. If you do, you will get a "memory freed twice" guru.
ok, thx for confirmation.
I tried to disposeDTobject(), got a crash/GR and. thx for explanation.
AOS4.1/SAM460ex/PPC460EX-1155MHZ/2048MB/RadeonHD6570/SSD120GB/DVDRW :-P