Amiga.org
Operating System Specific Discussions => Amiga OS => Amiga OS -- Development => Topic started by: EDanaII on August 06, 2007, 06:55:10 PM
-
I posted this over on UtilityBase, but thought I'd post it here too to see if I can find the answer more quickly:
========================================
Alright, I'm goofing around again, messing around with ancient Amiga programs. I have an old program that displays images to a WB window. Naturally, it's limited to a very low color depth. The Workbench I'm running, however, is RTG (UAE) so colors are unlimited.
I've spent most of the evening searching aminet for any kind of example that would allow me to draw images that are not limited to a low color WB but with no success. It's now tired, and I'm getting late, so am appealing to UB for clues to the right direction.
So, what's the best approach to draw non-pen dependent images in a workbench window? Does any one know of any tutorials? Example programs? As always, any and all clues appreciated. :)
Thomas responded:Use WritePixelArray
To which, I replied:
Thanks, Thomas, that helps but leaves me with more questions.
Looking at Olaf Barthel's ViewILBM (Aminet), I found an example of how to do that but it's so complex I'm having a tough time figuring out what to do.
WritePixelArray needs a BitPlaneData structure which ViewILBM initializes with an routine called OpenAsync that appears to be assembler and leaves me clueless.
What's the best (and easiest) way to populate this BitPlaneData structure?
Keep them clues coming...
Thanks,
Ed.
========================================
So, can anyone else offer me some clues here? All help appreciated. :)
-
Look into the autodoc?
cybergraphics.library/WritePixelArray cybergraphics.library/WritePixelArray
NAME
WritePixelArray -- write the color value of a rectangular array of
pixels starting at a specified x,y location and continuing through
to another x,y location within a certain RastPort
SYNOPSIS
count = WritePixelArray(srcRect,SrcX ,SrcY ,SrcMod,RastPort,DestX,
D0 A0 D0:16 D1:16 D2:16 A1 D3:16
DestY,SizeX,SizeY,SrcFormat)
D4:16 D5:16 D6:16 D7
LONG WritePixelArray(APTR,UWORD,UWORD,UWORD,struct RastPort *,UWORD,
UWORD,UWORD,UWORD,UBYTE)
FUNCTION
For each pixel in a rectangular region, write the color value from a
linear array of color values into the bitmap used to describe a
particular rastport.
INPUTS
srcRect - pointer to an array of pixels from which to fetch the
pixel data. The pixel format is specified in SrcFormat
(SrcX,SrcY) - starting point in the source rectangle
SrcMod - The number of bytes per row in the source rectangle.
RastPort - pointer to a RastPort structure
(DestX,DestY) - starting point in the RastPort
(SizeX,SizeY) - size of the rectangle that should be transfered
SrcFormat - pixel format in the source rectangle
Currently supported formats are:
RECTFMT_RGB 3 bytes per pixel, one byte red, one blue
and one byte green component
RECTFMT_RGBA 4 bytes per pixel, one byte red, one
blue, one byte green component and the
last byte is alpha channel information.
If you do not use alpha channel set this
byte to 0!!!
RECTFMT_ARGB 4 bytes per pixel, one byte red, one
blue, one byte green component and the
first byte is alpha channel information.
If you do not use alpha channel set this
byte to 0!!!
RECTFMT_LUT8 1 byte per pixel, specifying the pen
number. On screen depths > 8 bits the
data is converted using the actual color
lookup table.
RECTFMT_GREY8 1 byte per pixel, specifying grey scale
value.
RESULT
count will be set to the number of pixels plotted
NOTES
Only RECTFMT_LUT8 can be used on screen depths <= 8 bits.
For > 8 bit rastport RECTFMT_LUT8 uses the actual colormap "attached"
to the bitmap. If the bitmap is a friend bitmap of a screen bitmap
or the screen bitmap itself, it uses the screen's viewport colormap.
BUGS
The count value returned is totally wrong.
SEE ALSO
ReadPixelArray(), WriteLUTPixelArray(),
graphics.library/WritePixelArray()
-
Thanks, Piru, I did look at the AutoDoc, but, unfortunately, I don't know how to read it (yet). At the moment, I'm looking for some advice, and/or simple examples of how to accomplish this. To me, that's by far more understandable than the AutoDoc. :-)
Ed.
-
All right, checking the examples on UtilityBase, I found this. It's not WritePixelArray, but it looks like it would accomplish my purposes: ex01_p96WriteTrueColorData.c (http://utilitybase.com/ref/FUNCTIONS/Picasso96/p96WriteTrueColorData/ex01_p96WriteTrueColorData.c).
If I use this, what are the compatibility issues with other Amigas? Just curious.
Ed.
-
#include <cybergraphx/cybergraphics.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/cybergraphics.h>
#define WIDTH 320
#define HEIGHT 240
int main(int argc, char **argv)
{
struct ExecBase *SysBase = *(struct ExecBase **) 4;
struct IntuitionBase *IntuitionBase;
struct Library *CyberGfxBase;
IntuitionBase = (APTR) OpenLibrary("intuition.library", 37);
CyberGfxBase = OpenLibrary(CYBERGFXNAME, 40);
if (IntuitionBase && CyberGfxBase)
{
ULONG *array;
array = AllocMem(WIDTH * HEIGHT * 4, MEMF_ANY);
if (array)
{
struct Window *win;
int x, y;
for (y = 0; y < HEIGHT; y++)
{
for (x = 0; x < WIDTH; x++)
{
UBYTE r = 255 * x / WIDTH;
UBYTE g = 255 * y / HEIGHT;
UBYTE b = 255 * (x + y) / HEIGHT;
array[y * WIDTH + x] = (r << 16) | (g << 8) | b;
}
}
win = OpenWindowTags(NULL,
WA_Left, 0,
WA_Top, 0,
WA_Width, WIDTH,
WA_Height, HEIGHT,
WA_DragBar, TRUE,
WA_Borderless, TRUE,
WA_SmartRefresh, TRUE,
WA_Activate, TRUE,
WA_CloseGadget, TRUE,
WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_RAWKEY,
TAG_DONE);
if (win)
{
BOOL running = TRUE;
WritePixelArray(array, 0, 0, WIDTH * 4,
win->RPort, 0, 0, WIDTH, HEIGHT, RECTFMT_ARGB);
while (running)
{
struct IntuiMessage *imsg;
Wait(1 << win->UserPort->mp_SigBit);
while ((imsg = (APTR) GetMsg(win->UserPort)))
{
switch (imsg->Class)
{
case IDCMP_CLOSEWINDOW:
running = FALSE;
break;
case IDCMP_RAWKEY:
if (imsg->Code == (0x45 | IECODE_UP_PREFIX))
{
running = FALSE;
}
break;
}
ReplyMsg(&imsg->ExecMessage);
}
}
CloseWindow(win);
}
FreeMem(array, WIDTH * HEIGHT * 4);
}
}
if (CyberGfxBase)
{
CloseLibrary(CyberGfxBase);
}
if (IntuitionBase)
{
CloseLibrary(&IntuitionBase->LibNode);
}
return 0;
}
-
Dude! Excellent. Simple and concise. I owe you one. :-) I'll give it a try later when I have a second.
Ed.
-
@EDanall
If I use this, what are the compatibility issues with other Amigas
If you want to stay compatible do not use Picasso96 API.
CyberGraphX is the universally supported API, Picasso96 emulates it.
-
Turns out I didn't have to take off as quickly as I thought...
So, I tried the example Piru provided but it won't compile. The compiler complains "can't find '#include ' and '#include '."
I'm using NDK 3.9 and AmiDevCpp. Any clues what I'm might be doing wrong here?
Ed.
-
Downloaded a CG Library from this link: http://aweb.sunsite.dk/files/dev/cgfx-sdk.lha
The program compiles but does not link. I get this error: Unresolved error to _IntutionBase.
Bare with me. C is not my first (programming) language. ;)
Ed.
-
Bah, AmiDevCpp doesn't appear to have have libauto then... that sucks donkey round-objects...
I'll workaround the src in a moment.
[EDIT] done [/EDIT]
-
I got it to compile. :banana:
The problem wasn't with AmiDevCpp; my system needed a reboot, apparently.
Thanks for the help, Piru. May I upload your example to UtilityBase so that there actually is an example there? :-)
A couple quick questions before I move on. Do you know if there are there similar routines for BOBS and Sprites? What are they?
Now I need to figure out how to load a PNG or an IFF into the array you provided. I'll spend some time trying to figure that out, but if you want to clue me in on that one too, I won't complain to loudly. ;-)
Ed.
-
@EDanaII
May I upload your example to UtilityBase so that there actually is an example there?
I guess.
Do you know if there are there similar routines for BOBS and Sprites?
BOBs or Blitter OBjects are just rectangular gfx drawn by the system. With gfxcard you can use BltBitMap family routines (see graphics.doc). Note that you'll need to handle background restoration yourself (if you need any).
Graphics cards typically support only one sprite, the mouse pointer, so sprites are out I'm afraid.
Now I need to figure out how to load a PNG or an IFF into the array you provided.
You should look into datatype.library examples. Note however that stock AmigaOS install doesn't include png datatype. You could always use libpng (http://www.libpng.org/pub/png/libpng.html), though.
-
I'd like to learn datatypes but right now I'm trying to keep this simple.
I don't necessarily need to read png, I just want to load an image for now. I've learned that PPaint, for example, will save to C datatypes, but this is clearly not the format needed by your example. I found another tool that saves to "raw" which I'm not familiar with, but assume it is the RGB values used by your example. If I read a raw image straight into an array, should it work? Curious as always.
Ed.
-
@EDanaII
If I read a raw image straight into an array, should it work?
Assuming the raw file is ARGB and has the correct dimensions, sure.
The current code just fills the array with test-pattern.
-
BOBs or Blitter OBjects are just rectangular gfx drawn by the system. With gfxcard you can use BltBitMap family routines (see graphics.doc). Note that you'll need to handle background restoration yourself (if you need any).
In fact with modern gfx boards BOBs are faster and more versatile than sprites. But I know you knew this already :-)
-
@ Piru
There's a tool on Aminet (and included with Amikit) called GfxCon that converts between many different formats, including what it calls "RGB-Raw." I've no clue if this is ARGB or RGBA format, but I suspect I'll find out once I begin to experiment with it.
Ed.
-
All right, following up on this, I took Piru's example and changed the part where he populated the array variable with this bit of code:
while(!done) {
UBYTE a; if (!done) if (!(a = fgetc(test))) done = TRUE;
UBYTE r; if (!done) if (!(r = fgetc(test))) done = TRUE;
UBYTE g; if (!done) if (!(g = fgetc(test))) done = TRUE;
UBYTE b; if (!done) if (!(b = fgetc(test))) done = TRUE;
if (!done) array[y * WIDTH + x] = (r << 16) | (g << 8) | b;
}
Unfortunately, and not unexpectedly, all I got was garbage. I even switched the "UBYTE a" variable from first to last to account for the differences between ARGB and RGBA. I may be approaching this completely wrong and may have made a number of bad assumptions. As always, if ya gots some clues, please enlighten me. :-)
Ed.
-
I figured it out... The raw format I was using has no alpha channel, so it was simple RGB, not RGBA or ARGB. Also, I needed to redefine char to UBYTE, like so:
UBYTE r = (UBYTE)fgetc(test);
UBYTE g = (UBYTE)fgetc(test);
UBYTE b = (UBYTE)fgetc(test);
Ed.