Introduction
The datatypes.library was introduced to decode file formats (#?.png #?.jpg etc.) easily using different classes which can be installed as they are needed.
The descriptors in devs/datatypes contain the information how to identify a file type. Usually the file is opened only once by datatypes.library and a small buffer is used for comparisons which contains the first few bytes of the file (64 bytes IIRC).
dt descriptor is related to the struct DataTypeHeader dth_Name, dth_BaseName, etc.
Most datatype descriptors are held very simple, for example "compare the first 12 bytes with the pattern FORM????ILBM". The comparison is done by datatypes.library, there is no foreign code involved.
Only very few descriptors actually contain code. In this code everything can be done, though. For example, the code can close and reopen the file and read it entirely if needed. But this should not be done because identification needs to be very fast.
Dtdesc tool (and accompanied documentation) createdtdesc package is aimed at creating (picture) datatypes (as a whole, including makefiles). dtdescr is aimed at (only) viewing and creating the descriptor.
Once the file type is identified and the application wants to load the file, the class library from classes/datatypes is called. This library contains the code to decode the file contents and to make it available to datatypes.library.
Datatypes consist of a few libraries that exposes a couple of methods to load and save f.e. pictures of a certain type. Internally there is a 'common' storage method of the pixels that is used by the picture datatype, and so each 'library' that can handle its own type is able to 'convert' this common storage method into a specific format or load to this specific format.
The datatypes system itself exposes methods for the developer/user that allows for easy loading and saving by just calling some functions.
So, as long (and in theory) as there are 'libraries' that support a certain file-type (in this case pictures) you can very simply convert from one picture format to another picture format.
First you should learn about BOOPSI. If you understand BOOPSI, it's easy to understand datatypes, ReAction, MUI, ...
The only problem with AmigaOS implementation of datatypes is that they aren't really bidirectional. You can generally only save in IFF.
The ideal implementation would allow each datatype superclass (picture.datatype, sound.datatype etc.) to provide a list of all currently known sub-classes that support encoding. You'd then be able to pick one and encode data for that datatype and write it out to disk in that format.
Wanderer (AROS WB replacement) does not utilise the datatype subsystem directly "except" for loading window background imagery. The datatype system cannot deal with progressive loading and streaming yet.
assume you are trying to manipulate images? Load images using datatypes but read image data to ARGB array using ReadPixelArray methods and dispose source object. For images, to get the raw data use PDTM_READPIXELARRAY (that's the uncompressed data).
concerning Sounds ? Should it be better to use DTMethod to uncompress on a buffer and then use this uncompressed buffer ? For sound, get the data using the SDTA_Sample (or SDTA_LeftSample/SDTA_RightSample) attributes. You can retrieve sample data using SDTA_Sample tag but AmigaOS lacks support for SDTA_SampleType so you can get only 8-bit sample data there. AROS and MorphOS are more advanced there but generally it is better drop datatypes and write your own wave loader.
Setting SDTA_BitsPerSample, 16 will make SDTA_(Left|Right|%) Sample be in 16-bits (32-bit is also supported).
How to
create a Datatype Object, use the NewDTObject function ...
gd->gd_DisplayObject = NewDTObject ((IPTR)gd->gd_Unit, DTA_SourceType, DTST_CLIPBOARD, GA_Immediate, TRUE, GA_RelVerify, TRUE, DTA_TextAttr, (ULONG) & gd->gd_TextAttr, TAG_DONE))
The parameters of this functions uses Tags as defined in datatypes/datatypesclasses.h and intuition/gadgetclass.h
gf->gd_Unit = the Clipboard unit number DTST_Clipboard = the Clipboard is the data source GA_Immediate = Should the object be active when displayed GA_RelVerify = Verify that the pointer is over the object when it is selected gd_->gd_TextAttr = Pointer to text font attributes
Once a datatype object is no longer required, it is disposed of and memory released: e.g.
DisposeDTObject (gd->gd_DisplayObject);
To get attributes from a datatype object, you can use the GetDTAttrs function e.g.
GetDTAttrs (gd->gd_DisplayObject, DTA_DataType, (ULONG)&dtn, TAG_DONE);
and examining the results from the dtn structure you can retrieve:
dtn->dtn_Header->dth_Name = Descriptive name of the datatype dtn->dtn_Header->dth_GroupID = The group the datatype belongs to
The function GetDTString returns a localised Datatypes string of the id given. This string could be syst, text, docu, soun, inst, musi, pict, anim or movi (see datatypes.h). e.g.
GetDTString (dtn->dtn_Header->dth_GroupID)
Change State - Set/Get
what you usually do is, to create an object (initial state), get/set some attributes (attribute change) and then do layout or extract a type.
in that case there many programs that call remap but doesn't have a gpinfo structure.
is there some info what remap have on initial state ?
AROS dt set it to true.
pd->Remap = TRUE;
when a program have no gpinfo with screen, then i think remap should be set to false.maybe AOS do that somewhere.
same can happen on AROS dt too, maybe on AOS dt bitmap (state change and get/set); however it is not clearly defined in which way state changes may affect attributes (screen, colors) or what happens in case some attributes have not been set prior triggering the state change; it's not even exactly clear which states are possible
Refresh
Your application can find out when a refresh is appropriate by using the Boopsi ICATarget attribute with the ICTargetIDCMP value. This causes the datatype (gadget) to send an IDCMP_IDCMPUpdate IntuiMessage to the window port on certain status changes. That message carries a pointer to one or more attributes and if DTA_Sync is in that list with a value of 1 then the datatype object is ready for refresh.
You get one of these on attaching the datatype object to your window, and also a stream of them when the window is resized.
Creating datatype object of specified subclass
In order to create a jpeg datatype object (jpeg subclass of picture class)
DTImage = NewDTObject(NULL, DTA_SourceType, DTST_RAM, DTA_BaseName, "jpeg", PDTA_DestMode, PMODE_V43, TAG_DONE);
Examples
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/datatypes.h>
#include <datatypes/pictureclass.h>
int main (void)
{
struct RDArgs *rdargs;
struct {
char *file;
char *pubscreen;
} args = {0};
int rc = RETURN_FAIL;
struct Screen *scr;
Object *dto;
struct BitMapHeader *bmhd;
struct BitMap *bm;
WORD winw,winh;
struct Window *win;
struct IntuiMessage *imsg;
BOOL cont;
rdargs = ReadArgs ("FILE/A,PUBSCREEN/K",(LONG *)&args,NULL);
if (!rdargs)
{
PrintFault (IoErr(),NULL);
return (RETURN_FAIL);
}
if (scr = LockPubScreen (args.pubscreen))
{
if (dto = NewDTObject (args.file,DTA_GroupID,GID_PICTURE,PDTA_Remap,TRUE,PDTA_Screen,scr,TAG_END))
{
DoDTMethod (dto,NULL,NULL,DTM_PROCLAYOUT,NULL,TRUE);
GetDTAttrs (dto,(ULONG) PDTA_BitMapHeader,&bmhd,(ULONG) PDTA_BitMap,&bm,TAG_END);
if (bm && bmhd)
{
winw = bmhd->bmh_Width + scr->WBorLeft + scr->WBorRight;
winh = bmhd->bmh_Height + scr->WBorTop + scr->RastPort.TxHeight + 1 + scr->WBorBottom;
if (win = OpenWindowTags (NULL,
WA_Left, (scr->Width - winw) / 2,
WA_Top, (scr->Height - winh) / 2,
WA_Width, winw,
WA_Height, winh,
WA_Title, args.file,
WA_Flags, WFLG_CLOSEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_ACTIVATE | WFLG_NOCAREREFRESH,
WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY,
TAG_END))
{
rc = RETURN_OK;
BltBitMapRastPort (bm,0,0,win->RPort,win->BorderLeft,win->BorderTop,win->GZZWidth,win->GZZHeight,0xc0);
cont = TRUE;
do {
if (Wait ((1L << win->UserPort->mp_SigBit) | SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
cont = FALSE;
while (imsg = (struct IntuiMessage *) GetMsg (win->UserPort))
{
switch (imsg->Class)
{
case IDCMP_VANILLAKEY:
if (imsg->Code == 0x1b) /* Esc */
cont = FALSE;
break;
case IDCMP_CLOSEWINDOW:
cont = FALSE;
break;
}
ReplyMsg ((struct Message *) imsg);
}
}
while (cont);
CloseWindow (win);
}
}
else
Printf ("image cannot be rendered into the named pubscreen\n");
DisposeDTObject (dto);
}
else
{
Printf (GetDTString (IoErr()),args.file);
Printf ("\n");
}
UnlockPubScreen (NULL,scr);
}
else
Printf ("cannot lock pubscreen\n");
return (rc);
}
that's code of diskobjpngio.c.read
icon->iconPNG.handle = PNG_LoadImageMEM(icon->iconPNG.filebuffer, filesize, chunknames, chunkpointer, TRUE);
if (!icon->iconPNG.handle)
{
FreeIconPNG(&icon->dobj, IconBase);
return FALSE;
}
{
LONG width, height;
PNG_GetImageInfo(icon->iconPNG.handle, &width, &height, NULL, NULL);
icon->iconPNG.width = width;
icon->iconPNG.height = height;
icon->iconPNG.transparency = 0xffffffff;
PNG_GetImageData(icon->iconPNG.handle, (APTR *)&icon->iconPNG.img1, NULL);
dt2thumb application
#include <dos/dos.h>
#include <dos/dosasl.h>
#include <dos/dosextens.h>
#include <dos/exall.h>
#include <dos/rdargs.h>
#include <exec/memory.h>
#include <exec/types.h>
#include <utility/utility.h>
#include <proto/arossupport.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/cybergraphics.h>
#include <proto/datatypes.h>
#include <proto/icon.h>
#include <workbench/workbench.h>
#include <workbench/icon.h>
#include <datatypes/pictureclass.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CTRL_C (SetSignal(0L,0L) & SIGBREAKF_CTRL_C)
#define isDir(fib) ((fib)->fib_DirEntryType >= 0)
#define ARG_TEMPLATE "FILE/A,ALL/S,QUIET/S,W=WIDTH/N,H=HEIGHT/N,F=FORCEASPECT/S,M=METHOD,DEFTOOL"
enum
{
ARG_FILE = 0,
ARG_ALL,
ARG_QUIET,
ARG_WIDTH,
ARG_HEIGHT,
ARG_FORCEASPECT,
ARG_METHOD,
ARG_DEFTOOL,
NOOFARGS
};
/* Maximum file path length */
#define MAX_PATH_LEN 2048
const TEXT version[] = "$VER: dt2thumb 1.1 (10.12.2010)\n";
static char cmdname[] = "dt2thumb";
typedef struct rgbImage
{
UWORD Width;
UWORD Height;
UBYTE *Data;
}
RGBImage;
int doThumbs(struct AnchorPath *ap, STRPTR files, BOOL all, BOOL quiet,
ULONG destwidth, ULONG destheight, BOOL keepaspect, STRPTR deftool, STRPTR method);
BOOL CreateThumb(STRPTR infile, ULONG destwidth, ULONG destheight, BOOL keepaspect, STRPTR deftool, STRPTR method);
BOOL readpic_by_datatype(RGBImage *pic, char *file_name);
BOOL savepic_by_datatype(RGBImage *pic, char *file_name);
RGBImage *resizeBilinear(RGBImage *pic, ULONG w2, ULONG h2);
RGBImage *resizeNearest(RGBImage *pic, ULONG w2, ULONG h2);
RGBImage *resizeAverage(RGBImage *pic, ULONG w2, ULONG h2);
int main(void)
{
struct RDArgs *rda = NULL;
struct AnchorPath *ap = NULL;
int retval = RETURN_OK;
STRPTR files = "#?";
BOOL all = FALSE;
BOOL quiet = FALSE;
ULONG destwidth = 128;
ULONG destheight = 128;
BOOL keepaspect = TRUE;
STRPTR method = NULL;
STRPTR deftool = NULL;
IPTR args[NOOFARGS] = { (IPTR)files, all, quiet, (IPTR)&destwidth, (IPTR)&destheight, !keepaspect ,(IPTR)method ,(IPTR)deftool};
ap = AllocVec(sizeof(struct AnchorPath) + MAX_PATH_LEN, MEMF_ANY | MEMF_CLEAR);
if (ap != NULL)
{
ap->ap_Strlen = MAX_PATH_LEN;
rda = ReadArgs(ARG_TEMPLATE, args, NULL);
if (rda != NULL)
{
/* Convert arguments into (less complex) variables */
if (args[ARG_FILE]) files = (STRPTR)args[ARG_FILE];
if (args[ARG_ALL]) all = TRUE;
if (args[ARG_QUIET]) quiet = TRUE;
if (args[ARG_WIDTH]) destwidth = (ULONG)*((IPTR *)args[ARG_WIDTH]);
if (args[ARG_HEIGHT]) destheight = (ULONG)*((IPTR *)args[ARG_HEIGHT]);
if (args[ARG_FORCEASPECT]) keepaspect = FALSE;
if (args[ARG_METHOD]) method = (STRPTR)args[ARG_METHOD];
if (args[ARG_DEFTOOL]) deftool = (STRPTR)args[ARG_DEFTOOL];
if (!all &&IsDosEntryA(files, LDF_VOLUMES | LDF_DEVICES))
{
Printf("Can't create thumb for %s - ", files);
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
PrintFault(IoErr(), NULL);
retval = RETURN_FAIL;
}
else
retval = doThumbs(ap, files, all, quiet, destwidth, destheight, keepaspect, deftool, method);
FreeArgs(rda);
}
else
{
PrintFault(IoErr(), cmdname);
retval = RETURN_FAIL;
}
if (ap!=NULL) FreeVec(ap);
}
else
{
retval = RETURN_FAIL;
}
return retval;
} /* main */
int doThumbs(struct AnchorPath *ap, STRPTR files, BOOL all, BOOL quiet,
ULONG destwidth, ULONG destheight, BOOL keepaspect, STRPTR deftool, STRPTR method)
{
LONG match;
int retval = RETURN_OK;
LONG indent = 0;
int i; /* Loop variable */
BOOL error;
for (match = MatchFirst(files, ap);
match == 0 && retval == RETURN_OK;// && !CTRL_C;
match = MatchNext(ap))
{
if (isDir(&ap->ap_Info))
{
if (ap->ap_Flags & APF_DIDDIR)
{
indent--;
ap->ap_Flags &= ~APF_DIDDIR; /* Should not be necessary */
continue;
}
else if (all)
{
ap->ap_Flags |= APF_DODIR;
indent++;
}
}
error = CreateThumb(ap->ap_Buf, destwidth, destheight, keepaspect, deftool, method);
if (!quiet)
{
/* Fix indentation level */
for (i = 0; i < indent; i++)
{
PutStr(" ");
}
if (!isDir(&ap->ap_Info))
{
PutStr(" ");
}
PutStr(ap->ap_Info.fib_FileName);
if (isDir(&ap->ap_Info))
{
PutStr(" (dir)");
}
if (error)
{
PutStr(" ..Not a known picture file\n");
}
else
{
PutStr(" ..Thumbnail created\n");
}
}
}
MatchEnd(ap);
return retval;
}
STRPTR get_ext(char *filename)
{
static char extension[32];
int position=strlen((char *)filename)-1;
strcpy(extension,"");
while(position > -1 && filename[position] != '.') position--;
if (position > -1)
{
strncpy(extension,&filename[position+1],32);
}
return extension;
}
BOOL CreateThumb(STRPTR infile, ULONG destwidth, ULONG destheight, BOOL keepaspect, STRPTR deftool, STRPTR method)
{
RGBImage *in_pic = NULL, *out_pic = NULL;
char outfile[MAX_PATH_LEN];
BOOL retval = TRUE;
// do not create thumb for info files
if (strnicmp(get_ext(infile),"info",4)==0) return retval;
sprintf(outfile,"%s.info",infile);
if (in_pic = (RGBImage *)AllocVec(sizeof(RGBImage),MEMF_ANY))
{
in_pic->Data = NULL;
if (readpic_by_datatype(in_pic, infile))
{
if (keepaspect)
{
int arw = in_pic->Width / destwidth;
int arh = in_pic->Height / destheight;
if (arw > arh) destheight = in_pic->Height / arw;
else if (arh > arw) destwidth = in_pic->Width / arh;
}
if (method != NULL)
{
if (strnicmp(method,"BI",2)==0)
out_pic = resizeBilinear(in_pic, destwidth, destheight);
else if (strnicmp(method,"AV",2)==0)
out_pic = resizeAverage(in_pic, destwidth, destheight);
else
out_pic = resizeNearest(in_pic, destwidth, destheight);
}
else
out_pic = resizeNearest(in_pic, destwidth, destheight);
if (out_pic)
{
if (savepic_by_datatype(out_pic, outfile))
{
// Write default tool
struct DiskObject *icon = GetIconTags
(
infile, ICONGETA_FailIfUnavailable, FALSE, TAG_DONE
);
if (icon != NULL)
{
STRPTR oldDefaultTool = icon->do_DefaultTool;
if (deftool)
icon->do_DefaultTool = deftool;
else
{
static STRPTR tool = "multiview";
icon->do_DefaultTool = tool;
}
if (!PutIconTags(infile, icon, TAG_DONE))
{
Printf("ERROR: Failed to write icon.\n");
}
icon->do_DefaultTool = oldDefaultTool;
FreeDiskObject(icon);
retval = FALSE;
}
else
{
Printf("ERROR: Failed to open icon for file\n");
retval = TRUE;;
}
}
}
}
if (in_pic)
{
if (in_pic->Data) FreeVec(in_pic->Data);
FreeVec(in_pic);
}
if (out_pic)
{
if (out_pic->Data) FreeVec(out_pic->Data);
FreeVec(out_pic);
}
}
return retval;
}
BOOL readpic_by_datatype(RGBImage *pic, char *file_name)
{
Object *DTImage = NULL;
struct BitMapHeader *bmh;
struct pdtBlitPixelArray bpa;
DTImage = NewDTObject( file_name,
(DTA_SourceType), DTST_FILE,
(DTA_GroupID), GID_PICTURE,
(PDTA_Remap), FALSE,
(OBP_Precision), PRECISION_EXACT,
TAG_DONE);
if (DTImage)
{
if (GetDTAttrs( DTImage,
PDTA_BitMapHeader, (ULONG)&bmh,
TAG_END ) == 1)
{
/* Picture struct and buffer mem allocation */
pic->Data = (UBYTE *)AllocVec(bmh->bmh_Width * bmh->bmh_Height * 4, MEMF_ANY);
if (pic->Data)
{
bpa.MethodID = PDTM_READPIXELARRAY;
bpa.pbpa_PixelData = (APTR)pic->Data;
bpa.pbpa_PixelFormat = PBPAFMT_ARGB;
bpa.pbpa_PixelArrayMod = bmh->bmh_Width * 4;
bpa.pbpa_Left = 0;
bpa.pbpa_Top = 0;
bpa.pbpa_Width = bmh->bmh_Width;
bpa.pbpa_Height = bmh->bmh_Height;
DoMethodA( DTImage, (Msg)&bpa );
pic->Width = bmh->bmh_Width;
pic->Height = bmh->bmh_Height;
DisposeDTObject( DTImage );
return TRUE;
}
}
DisposeDTObject( DTImage );
}
return FALSE;
}
/**
* Nearest Neighbor resizing algorithm
* In case of thumbnail generation the loss of quality
* should be minimal vs the bilinear algorithm
*/
RGBImage *resizeNearest(RGBImage *pic, ULONG w2, ULONG h2)
{
ULONG *temp = NULL;
RGBImage *outpic = NULL;
ULONG *pixels = (ULONG *)pic->Data;
ULONG x_ratio = (ULONG)((pic->Width<<16)/w2) +1;
ULONG y_ratio = (ULONG)((pic->Height<<16)/h2) +1;
ULONG x2,y2,i,j;
if (outpic = (RGBImage *)AllocVec(sizeof(RGBImage),MEMF_ANY))
{
outpic->Data = NULL;
if (outpic->Data = (UBYTE *)AllocVec(w2*h2*4, MEMF_ANY))
{
outpic->Width = w2;
outpic->Height = h2;
temp = (ULONG *)outpic->Data;
for (i=0;i<h2;i++)
{
y2 = ((i*y_ratio)>>16) ;
for (j=0;j<w2;j++)
{
x2 = ((j*x_ratio)>>16) ;
temp[(i*w2)+j] = pixels[(y2*pic->Width)+x2] ;
}
}
}
}
return outpic;
}
#define max(x,y) (x)>(y)?(x):(y)
#define min(x,y) (x)<(y)?(x):(y)
/**
* Averaging resizing algorithm
*
*
*/
RGBImage *resizeAverage(RGBImage *pic, ULONG w2, ULONG h2)
{
ULONG *temp = NULL;
RGBImage *outpic = NULL;
ULONG *pixels = (ULONG *)pic->Data;
ULONG xpixels = min(256,max((ULONG)(pic->Width/w2),1));
ULONG ypixels = min(256,max((ULONG)(pic->Height/h2),1));
ULONG x_ratio = (ULONG)((pic->Width<<16)/w2) +1;
ULONG y_ratio = (ULONG)((pic->Height<<16)/h2) +1;
ULONG r,g,b,a,index;
ULONG x2,y2,i,j,x,y;
if (outpic = (RGBImage *)AllocVec(sizeof(RGBImage),MEMF_ANY))
{
outpic->Data = NULL;
if (outpic->Data = (UBYTE *)AllocVec(w2*h2*4, MEMF_ANY))
{
outpic->Width = w2;
outpic->Height = h2;
temp = (ULONG *)outpic->Data;
for (i=0;i<h2;i++)
{
y2 = ((i*y_ratio)>>16) ;
for (j=0;j<w2;j++)
{
x2 = ((j*x_ratio)>>16) ;
r = 0;
g = 0;
b = 0;
a = 0;
for (y=0;y<ypixels;y++)
for (x=0;x<xpixels;x++)
{
index = ((y2+y)*pic->Width+(x2+x));
b += (pixels[index]&0xff);
g += ((pixels[index]>>8)&0xff);
r += ((pixels[index]>>16)&0xff);
a += ((pixels[index]>>24)&0xff);
}
r /= (ypixels*xpixels);
g /= (ypixels*xpixels);
b /= (ypixels*xpixels);
a /= (ypixels*xpixels);
temp[(i*w2)+j] = ((((ULONG)a)<<24) & 0xff000000) |
((((ULONG)r)<<16) & 0x00ff0000) |
((((ULONG)g)<<8) & 0x0000ff00) |
((ULONG)b) ;
}
}
}
}
return outpic;
}
/**
* Bilinear resize ARGB image.
* pixels is an array of size w * h.
* Target dimension is w2 * h2.
* w2 * h2 cannot be zero.
*/
RGBImage *resizeBilinear(RGBImage *pic, ULONG w2, ULONG h2)
{
ULONG *temp = NULL;
RGBImage *outpic = NULL;
ULONG *pixels = (ULONG *)pic->Data;
ULONG a, b, c, d, x, y, index ;
float x_ratio = ((float)(pic->Width-1))/w2 ;
float y_ratio = ((float)(pic->Height-1))/h2 ;
float x_diff, y_diff, blue, red, green, alpha ;
ULONG offset = 0 ;
int i,j;
if (outpic = (RGBImage *)AllocVec(sizeof(RGBImage),MEMF_ANY))
{
if (outpic->Data = (UBYTE *)AllocVec(w2*h2*4, MEMF_ANY))
{
outpic->Width = w2;
outpic->Height = h2;
temp = (ULONG *)outpic->Data;
if ((pic->Width==w2) && (pic->Height=h2))
{
CopyMem(pixels, temp, pic->Width * pic->Height * 4);
return outpic;
}
for (i=0;i<h2;i++)
{
for (j=0;j<w2;j++)
{
x = (ULONG)(x_ratio * j) ;
y = (ULONG)(y_ratio * i) ;
x_diff = (x_ratio * j) - x ;
y_diff = (y_ratio * i) - y ;
index = (y*pic->Width+x) ;
a = pixels[index] ;
b = pixels[index+1] ;
c = pixels[index+pic->Width] ;
d = pixels[index+pic->Width+1] ;
// blue element
// Yb = Ab(1-w)(1-h) + Bb(w)(1-h) + Cb(h)(1-w) + Db(wh)
blue = (a&0xff)*(1-x_diff)*(1-y_diff) + (b&0xff)*(x_diff)*(1-y_diff) +
(c&0xff)*(y_diff)*(1-x_diff) + (d&0xff)*(x_diff*y_diff);
// green element
// Yg = Ag(1-w)(1-h) + Bg(w)(1-h) + Cg(h)(1-w) + Dg(wh)
green = ((a>>8)&0xff)*(1-x_diff)*(1-y_diff) + ((b>>8)&0xff)*(x_diff)*(1-y_diff) +
((c>>8)&0xff)*(y_diff)*(1-x_diff) + ((d>>8)&0xff)*(x_diff*y_diff);
// red element
// Yr = Ar(1-w)(1-h) + Br(w)(1-h) + Cr(h)(1-w) + Dr(wh)
red = ((a>>16)&0xff)*(1-x_diff)*(1-y_diff) + ((b>>16)&0xff)*(x_diff)*(1-y_diff) +
((c>>16)&0xff)*(y_diff)*(1-x_diff) + ((d>>16)&0xff)*(x_diff*y_diff);
// alpha element
// Yr = Ar(1-w)(1-h) + Br(w)(1-h) + Cr(h)(1-w) + Dr(wh)
alpha = ((a>>24)&0xff)*(1-x_diff)*(1-y_diff) + ((b>>24)&0xff)*(x_diff)*(1-y_diff) +
((c>>24)&0xff)*(y_diff)*(1-x_diff) + ((d>>24)&0xff)*(x_diff*y_diff);
temp[offset++] = ((((ULONG)alpha)<<24) & 0xff000000) |
((((ULONG)red) <<16) & 0x00ff0000) |
((((ULONG)green)<<8) & 0x0000ff00) |
((ULONG)blue) ;
}
}
}
}
return outpic ;
}
BOOL savepic_by_datatype(RGBImage *pic, char *file_name)
{
Object *DTImage = NULL;
struct BitMapHeader *bmhd;
struct dtWrite dtw;
struct pdtBlitPixelArray dtb;
FILE *file = NULL;
BOOL retval = FALSE;
DTImage = NewDTObject( (APTR)NULL,
DTA_SourceType, DTST_RAM,
DTA_BaseName, (IPTR)"png",
PDTA_DestMode, PMODE_V43,
TAG_DONE);
if (!DTImage) return(FALSE);
if (GetDTAttrs(DTImage,PDTA_BitMapHeader,(IPTR)&bmhd,TAG_DONE))
{
dtb.MethodID = PDTM_WRITEPIXELARRAY;
dtb.pbpa_PixelData = pic->Data;
dtb.pbpa_PixelFormat = PBPAFMT_ARGB;
dtb.pbpa_PixelArrayMod = pic->Width*4;
dtb.pbpa_Left = 0;
dtb.pbpa_Top = 0;
dtb.pbpa_Width = pic->Width;
dtb.pbpa_Height = pic->Height;
bmhd->bmh_Width = pic->Width;
bmhd->bmh_Height = pic->Height;
bmhd->bmh_Depth = 24;
bmhd->bmh_PageWidth = 320;
bmhd->bmh_PageHeight = 240;
DoMethodA(DTImage, (Msg) &dtb);
//write datatype object to file
if (file = Open (file_name,MODE_NEWFILE))
{
dtw.MethodID = DTM_WRITE;
dtw.dtw_GInfo = NULL;
dtw.dtw_FileHandle = file;
dtw.dtw_Mode = DTWM_RAW;
dtw.dtw_AttrList = NULL;
if (DoMethodA(DTImage, (Msg) &dtw)) retval = TRUE;
}
}
if (file) Close (file);
if (DTImage) DisposeDTObject(DTImage);
return retval;
}
sound function
void do_sound()
{
soundnow = "sounds/bingobongo.aiff";
cout << "do sound!"<<endl;
int frq, vol, pan, state;
if (soundobject)DisposeDTObject(soundobject);
if ((soundobject = NewDTObject(soundnow,
DTA_SourceType, DTST_FILE,
DTA_GroupID, GID_SOUND,
DTA_Repeat, TRUE,
SDTA_SignalTask, (ULONG) FindTask(NULL),
SDTA_SignalBit, (ULONG) SIGBREAKF_CTRL_C,
TAG_DONE)))
{
DoDTMethod(soundobject, NULL, NULL, DTM_TRIGGER, NULL, STM_PLAY, NULL);
}
else
{
cout << "can't create sound"<<endl;
}
}
STATIC IPTR DT_SetMethod(struct IClass *cl, struct Gadget *g, struct opSet *msg)
{
struct Picture_Data *pd;
const struct TagItem *tl = msg->ops_AttrList;
struct TagItem *ti;
IPTR RetVal;
struct RastPort *rp;
pd=(struct Picture_Data *) INST_DATA(cl, g);
RetVal=0;
while((ti=NextTagItem(&tl)))
{
switch (ti->ti_Tag)
{
case DTA_VisibleHoriz:
case DTA_VisibleVert:
RetVal = 1;
break;
case PDTA_ModeID:
pd->ModeID = (ULONG) ti->ti_Data;
DGS(bug("picture.datatype/OM_SET: Tag PDTA_ModeID: 0x%lx\n",(long)pd->ModeID));
break;
case PDTA_ClassBitMap:
pd->KeepSrcBM = TRUE;
DGS(bug("picture.datatype/OM_GET: Tag PDTA_ClassBitMap: Handled as PDTA_BitMap\n"));
case PDTA_BitMap:
pd->SrcBM = (struct BitMap *) ti->ti_Data;
DGS(bug("picture.datatype/OM_SET: Tag PDTA_BitMap: 0x%lx\n",(long)pd->SrcBM));
break;
case PDTA_Screen:
pd->DestScreen = (struct Screen *) ti->ti_Data;
DGS(bug("picture.datatype/OM_SET: Tag PDTA_Screen: 0x%lx\n",(long)pd->DestScreen));
break;
case PDTA_NumColors:
pd->NumColors = (UWORD) ti->ti_Data;
DGS(bug("picture.datatype/OM_SET: Tag PDTA_NumColors:%ld\n", (long)pd->NumColors));
break;
case PDTA_Grab:
{
Point *ThePoint;
DGS(bug("picture.datatype/OM_SET: Tag PDTA_Grab\n"));
ThePoint = (Point *) ti->ti_Data;
if(!ThePoint)
{
break;
}
pd->Grab.x = ThePoint->x;
pd->Grab.y = ThePoint->y;
break;
}
case PDTA_SourceMode:
DGS(bug("picture.datatype/OM_SET: Tag PDTA_SourceMode (ignored): %ld\n", (long)ti->ti_Data));
break;
case PDTA_DestMode:
pd->DestMode = (BOOL) ti->ti_Data;
DGS(bug("picture.datatype/OM_SET: Tag PDTA_DestMode: %ld\n",(long)pd->DestMode));
break;
case PDTA_FreeSourceBitMap:
pd->FreeSource = (BOOL) ti->ti_Data;
DGS(bug("picture.datatype/OM_SET: Tag PDTA_FreeSourceBitMap:%ld\n", (long)pd->FreeSource));
break;
case PDTA_UseFriendBitMap:
pd->UseFriendBM = (BOOL) ti->ti_Data;
DGS(bug("picture.datatype/OM_SET: Tag PDTA_UseFriendBitMap:%ld\n", (long)pd->UseFriendBM));
break;
case PDTA_MaxDitherPens:
pd->MaxDitherPens = (UWORD) ti->ti_Data;
DGS(bug("picture.datatype/OM_SET: Tag PDTA_MaxDitherPens:%ld\n", (long)pd->MaxDitherPens));
break;
case PDTA_DitherQuality:
pd->DitherQuality = (UWORD) ti->ti_Data;
DGS(bug("picture.datatype/OM_SET: Tag PDTA_DitherQuality:%ld\n", (long)pd->DitherQuality));
break;
case PDTA_ScaleQuality:
pd->ScaleQuality = (UWORD) ti->ti_Data;
DGS(bug("picture.datatype/OM_SET: Tag PDTA_ScaleQuality:%ld\n", (long)pd->ScaleQuality));
break;
case PDTA_Remap:
pd->Remap = (BOOL) ti->ti_Data;
DGS(bug("picture.datatype/OM_SET: Tag ID PDTA_Remap: %ld\n",(long)pd->Remap));
break;
#ifdef __AROS__
case PDTA_DelayedRead:
pd->DelayedRead = (BOOL) ti->ti_Data;
DGS(bug("picture.datatype/OM_SET: Tag PDTA_DelayedRead:
%ld\n", (long)pd->DelayedRead));
break;
#endif
#ifdef MYDEBUG
default:
{
register int i;
int Known;
Known=FALSE;
for(i=0; i<NumAttribs; i++)
{
if(ti->ti_Tag==KnownAttribs[i])
{
Known=TRUE;
DGS(bug("picture.datatype/OM_SET: Tag %s: 0x%lx (%ld)\n",AttribNames[i], (long)ti->ti_Data, (long)ti->ti_Data));
}
}
if(!Known)
{
DGS(bug("picture.datatype/OM_SET: Tag ID 0x%lx: 0x%lx\n",(long)ti->ti_Tag, (long)ti->ti_Data));
}
}
#endif /* MYDEBUG */
}
}
#if 0
if(msg->ops_GInfo)
{
DoMethod((Object *) g, GM_LAYOUT, msg->ops_GInfo, TRUE);
}
#endif
/* Do not call the SuperMethod if you come from OM_NEW! */
if(!(msg->MethodID == OM_NEW))
{
RetVal += (IPTR) DoSuperMethodA(cl, (Object *) g, (Msg) msg);
}
if(msg->ops_GInfo)
{
#if 1
if (RetVal)
#else
if(OCLASS((Object *) g) == cl)
#endif
{
rp=ObtainGIRPort(msg->ops_GInfo);
if(rp)
{
DoMethod((Object *) g, GM_RENDER, (IPTR) msg->ops_GInfo,(IPTR) rp, GREDRAW_UPDATE);
ReleaseGIRPort (rp);
}
}
#if 0 /* stegerg: ?? */
if(msg->MethodID == OM_UPDATE)
{
DoMethod((Object *) g, OM_NOTIFY, msg->ops_AttrList,
msg->ops_GInfo, 0);
}
#endif
}
return(RetVal);
}
---------------------------------------------------
STATIC IPTR DT_Render(struct IClass *cl, struct Gadget *g, struct gpRender *msg)
{
struct Picture_Data *pd;
struct DTSpecialInfo *si;
struct IBox *domain;
IPTR TopVert, TopHoriz;
long SrcX, SrcY, DestX, DestY, SizeX, SizeY;
pd = (struct Picture_Data *) INST_DATA(cl, g);
si = (struct DTSpecialInfo *) g->SpecialInfo;
if(!pd->Layouted)
{
D(bug("picture.datatype/GM_RENDER: No layout done yet !\n"));
return FALSE;
}
if(si->si_Flags & DTSIF_LAYOUT)
{
D(bug("picture.datatype/GM_RENDER: In layout process !\n"));
return FALSE;
}
if(!(GetDTAttrs((Object *) g, DTA_Domain, (IPTR) &domain,
DTA_TopHoriz, (IPTR) &TopHoriz,
DTA_TopVert, (IPTR) &TopVert,
TAG_DONE) == 3))
{
D(bug("picture.datatype/GM_RENDER: Couldn't get dimensions\n"));
return FALSE;
}
ObtainSemaphore(&(si->si_Lock));
D(bug("picture.datatype/GM_RENDER: Domain: left %ld top %ld width %ld height %ld\n", domain->Left, domain->Top, domain->Width, domain->Height));
D(bug("picture.datatype/GM_RENDER: TopHoriz %ld TopVert %ld Width %ld Height %ld\n", (long)TopHoriz, (long)TopVert, (long)pd->DestWidth, (long)pd->DestHeight));
if( pd->DestBM )
{
SrcX = MIN( TopHoriz, pd->DestWidth );
SrcY = MIN( TopVert, pd->DestHeight );
DestX = domain->Left;
DestY = domain->Top;
SizeX = MIN( pd->DestWidth - SrcX, domain->Width );
SizeY = MIN( pd->DestHeight - SrcY, domain->Height );
D(bug("picture.datatype/GM_RENDER: SizeX/Y %ld/%ld\n SrcX/Y %ld/%ld DestX/Y %ld/%ld\n",
SizeX, SizeY, SrcX, SrcY, DestX, DestY));
render_on_rastport(pd, g, SrcX, SrcY, msg->gpr_RPort, DestX, DestY, SizeX, SizeY);
}
else /* if(pd->DestBuffer) || if(pd->DestBM) */
{
D(bug("picture.datatype/GM_RENDER: No destination picture present !\n"));
return FALSE;
}
ReleaseSemaphore(&(si->si_Lock));
return TRUE;
}
How to compile datatypes
Build dtdesc tool, this is what you need. The source is located in tools/dtdesc. This tool is used in order to make a datatype descriptor from .dtd file. Class library is built in a usual way, using a usual crosscompiler.
A package so that it will be easy to build datatypes independently of the whole build system. Compiled createdtdesc and examinedtdesc for native AROS. One other tool that is needed is genmodule.
What is needed is a READ/WRITEPIXELARRAY interface, that replaces the former SET PDTA_BitMap and GET PDTA_DestBitMap interface. If a Bitmap was SET (legacy interface), it gets converted to LUT8 format during layout. A destination BitMap is only created, if this is set by Prefs or an applications requests it by GET PDTA_DestBitMap.
RENDER Method chooses one of these functions for displaying
- cgfx/WritePixelArray: Truecolor pic -> Truecolor screen
- cgfx/WriteLUTPixelArray: Colormapped pic -> Truecolor screen
- graphics/WriteChunkyPixels: Colormapped pic -> Colormapped chunky screen
- graphics/BltBitMapRastPort: Colormapped pic -> Colormapped planar screen
Truecolor pic -> Colormapped screen is handled during layout, with a fixed colormap and some simple but fast dithering algorithm (one dimensional error propagation). Floyd-Steinberg dithering algorithm could be used for slightly better results (two dimensional error propagation). Much better results could be obtained by a calculated colormap (e.g. median cut algorithm), but this is much slower.
Colormapped data is always stored in LUT8 format, or BitMap format for legacy. Truecolor data is always stored in ARGB format. This isn't memory effective, but makes things more simple and faster. Some optimization could be done here.
Created a template for new graphic datatypes here.
/*
Copyright © 1995-2005, The AROS Development Team. All rights reserved.
$Id: bmpclass.c 30902 2009-03-14 13:38:20Z mazze $
*/
/**********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dostags.h>
#include <graphics/gfxbase.h>
#include <graphics/rpattr.h>
#include <cybergraphx/cybergraphics.h>
#include <intuition/imageclass.h>
#include <intuition/icclass.h>
#include <intuition/gadgetclass.h>
#include <intuition/cghooks.h>
#include <datatypes/datatypesclass.h>
#include <datatypes/pictureclass.h>
#include <clib/alib_protos.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/utility.h>
#include <proto/iffparse.h>
#include <proto/datatypes.h>
#include <aros/symbolsets.h>
#include "debug.h"
#include "methods.h"
/* Open superclass */
ADD2LIBS("datatypes/picture.datatype", 0, struct Library *, PictureBase);
/**************************************************************************************************/
#define FILEBUFSIZE 65536
#define MAXCOLORS 256
typedef struct {
struct IFFHandle *filehandle;
UBYTE *filebuf;
UBYTE *filebufpos;
long filebufbytes;
long filebufsize;
UBYTE *linebuf;
UBYTE *linebufpos;
long linebufbytes;
long linebufsize;
APTR codecvars;
} BmpHandleType;
typedef struct
{
WORD bfType; // 0 ASCII "BM"
ULONG bfSize; // 2 Size in bytes of the file
WORD bfReserved1; // 6 Zero
WORD bfReserved2; // 8 Zero
ULONG bfOffBits; // 10 Byte offset in files where image begins
} FileBitMapHeader __attribute__((packed)); // 14
typedef struct
{
ULONG biSize; // 0 Size of this header, 40 bytes
LONG biWidth; // 4 Image width in pixels
LONG biHeight; // 8 Image height in pixels
WORD biPlanes; // 12 Number of image planes, must be 1
WORD biBitCount; // 14 Bits per pixel, 1, 4, 8, 24, or 32
ULONG biCompression; // 16 Compression type, below
ULONG biSizeImage; // 20 Size in bytes of compressed image, or zero
LONG biXPelsPerMeter; // 24 Horizontal resolution, in pixels/meter
LONG biYPelsPerMeter; // 28 Vertical resolution, in pixels/meter
ULONG biClrUsed; // 32 Number of colors used, below
ULONG biClrImportant; // 36 Number of "important" colors
} BitmapInfoHeader __attribute__((packed)); // 40
/* "BM" backwards, due to LE byte order */
#define BITMAP_ID "MB"
/**************************************************************************************************/
static void BMP_Exit(BmpHandleType *bmphandle, LONG errorcode)
{
D(if (errorcode) bug("bmp.datatype/BMP_Exit() --- IoErr %ld\n", errorcode));
if (bmphandle->filebuf)
{
FreeMem(bmphandle->filebuf, bmphandle->filebufsize);
}
if (bmphandle->linebuf)
{
FreeMem(bmphandle->linebuf, bmphandle->linebufsize);
}
if (bmphandle->codecvars)
{
FreeVec(bmphandle->codecvars);
}
SetIoErr(errorcode);
}
/**************************************************************************************************/
/* buffered file access, useful for RLE */
BOOL SaveBMP_EmptyBuf(BmpHandleType *bmphandle, long minbytes)
{
long bytes, bytestowrite;
bytestowrite = bmphandle->filebufsize - (bmphandle->filebufbytes + minbytes);
D(bug("bmp.datatype/SaveBMP_EmptyBuf() --- minimum %ld bytes, %ld bytes to write\n", (long)minbytes, (long)bytestowrite));
bytes = Write(bmphandle->filehandle, bmphandle->filebuf, bytestowrite);
if ( bytes < bytestowrite )
{
D(bug("bmp.datatype/SaveBMP_EmptyBuf() --- writing failed, wrote %ld bytes\n", (long)bytes));
return FALSE;
}
bmphandle->filebufpos = bmphandle->filebuf;
bmphandle->filebufbytes = bmphandle->filebufsize - minbytes;
D(bug("bmp.datatype/SaveBMP_EmptyBuf() --- wrote %ld bytes\n", (long)bytes));
return TRUE;
}
/* buffered file access, useful for RLE */
BOOL LoadBMP_FillBuf(BmpHandleType *bmphandle, long minbytes)
{
long i, bytes;
//D(bug("bmp.datatype/LoadBMP_FillBuf() --- minimum %ld bytes of %ld (%ld) bytes\n", (long)minbytes, (long)bmphandle->filebufbytes, (long)(bmphandle->filebufsize-(bmphandle->filebufpos-bmphandle->filebuf)) ));
if ( bmphandle->filebufbytes >= 0 )
return TRUE;
bytes = bmphandle->filebufbytes + minbytes;
//D(bug("bmp.datatype/LoadBMP_FillBuf() --- %ld bytes requested, %ld bytes left\n", (long)minbytes, (long)bytes));
if (bytes > 0)
{
//D(bug("bmp.datatype/LoadBMP_FillBuf() --- existing %ld old bytes\n", (long)bytes));
for (i=0; i<bytes; i++) /* copy existing bytes to start of buffer */
bmphandle->filebuf[i] = bmphandle->filebufpos[i];
}
bmphandle->filebufpos = bmphandle->filebuf;
bytes = Read(bmphandle->filehandle, bmphandle->filebuf + bytes, bmphandle->filebufsize - bytes);
if (bytes < 0 ) bytes = 0;
bmphandle->filebufbytes += bytes;
//D(bug("bmp.datatype/LoadBMP_FillBuf() --- read %ld bytes, remaining new %ld bytes\n", (long)bytes, (long)bmphandle->filebufbytes));
//D(bug("bmp.datatype/LoadBMP_FillBuf() --- >minimum %ld bytes of %ld (%ld) bytes\n", (long)minbytes, (long)bmphandle->filebufbytes, (long)(bmphandle->filebufsize-(bmphandle->filebufpos-bmphandle->filebuf)) ));
if (bmphandle->filebufbytes >= 0)
return TRUE;
return FALSE;
}
static BOOL LoadBMP_Colormap(BmpHandleType *bmphandle, int numcolors,
struct ColorRegister *colormap, ULONG *colregs)
{
unsigned int i, j;
if (numcolors && numcolors <= MAXCOLORS)
{
j = 0;
for (i = 0; i < numcolors; i++)
{
if ( (bmphandle->filebufbytes -= 4) < 0 && !LoadBMP_FillBuf(bmphandle, 4) )
{
D(bug("bmp.datatype/LoadBMP_Colormap() --- colormap loading failed\n"));
return FALSE;
}
/* BGR0 format for MS Win files, BGR format for OS/2 files */
colormap[i].blue = *(bmphandle->filebufpos)++;
colormap[i].green = *(bmphandle->filebufpos)++;
colormap[i].red = *(bmphandle->filebufpos)++;
bmphandle->filebufpos++;
colregs[j++] = ((ULONG)colormap[i].red)<<24;
colregs[j++] = ((ULONG)colormap[i].green)<<24;
colregs[j++] = ((ULONG)colormap[i].blue)<<24;
// D(if (i<5) bug("gif r %02lx g %02lx b %02lx\n", colormap[i].red, colormap[i].green, colormap[i].blue));
}
D(bug("bmp.datatype/LoadBMP_Colormap() --- %d colors loaded\n", numcolors));
}
return TRUE;
}
/**************************************************************************************************/
static BOOL LoadBMP(struct IClass *cl, Object *o)
{
BmpHandleType *bmphandle;
UBYTE *filebuf;
IPTR sourcetype;
ULONG bfSize, bfOffBits;
ULONG biSize, biWidth, biHeight, biCompression;
ULONG biClrUsed, biClrImportant;
UWORD biPlanes, biBitCount;
ULONG alignwidth, alignbytes, pixelfmt;
long x, y;
int cont, byte;
struct BitMapHeader *bmhd;
struct ColorRegister *colormap;
ULONG *colorregs;
STRPTR name;
D(bug("bmp.datatype/LoadBMP()\n"));
if( !(bmphandle = AllocMem(sizeof(BmpHandleType), MEMF_ANY)) )
{
SetIoErr(ERROR_NO_FREE_STORE);
return FALSE;
}
bmphandle->filebuf = NULL;
bmphandle->linebuf = NULL;
bmphandle->codecvars = NULL;
if( GetDTAttrs(o, DTA_SourceType , (IPTR)&sourcetype ,
DTA_Handle , (IPTR)&(bmphandle->filehandle),
PDTA_BitMapHeader , (IPTR)&bmhd,
TAG_DONE) != 3 )
{
BMP_Exit(bmphandle, ERROR_OBJECT_NOT_FOUND);
return FALSE;
}
if ( sourcetype == DTST_RAM && bmphandle->filehandle == NULL && bmhd )
{
D(bug("bmp.datatype/LoadBMP() --- Creating an empty object\n"));
BMP_Exit(bmphandle, 0);
return TRUE;
}
if ( sourcetype != DTST_FILE || !bmphandle->filehandle || !bmhd )
{
D(bug("bmp.datatype/LoadBMP() --- unsupported mode\n"));
BMP_Exit(bmphandle, ERROR_NOT_IMPLEMENTED);
return FALSE;
}
/* initialize buffered file reads */
bmphandle->filebufbytes = 0;
bmphandle->filebufsize = FILEBUFSIZE;
if( !(bmphandle->filebuf = bmphandle->filebufpos = AllocMem(bmphandle->filebufsize, MEMF_ANY)) )
{
BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
return FALSE;
}
/* load FileBitmapHeader from file, make sure, there are at least 14 bytes in buffer */
if ( (bmphandle->filebufbytes -= 14) < 0 && !LoadBMP_FillBuf(bmphandle, 14) )
{
D(bug("bmp.datatype/LoadBMP() --- filling buffer with header failed\n"));
BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
return FALSE;
}
filebuf = bmphandle->filebufpos; /* this makes things easier */
bmphandle->filebufpos += 14;
if( filebuf[0] != 'B' && filebuf[1] != 'M' )
{
D(bug("bmp.datatype/LoadBMP() --- header type mismatch\n"));
BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
return FALSE;
}
/* byte-wise access isn't elegant, but it is endianess-safe */
bfSize = (filebuf[5]<<24) | (filebuf[4]<<16) | (filebuf[3]<<8) | filebuf[2];
bfOffBits = (filebuf[13]<<24) | (filebuf[12]<<16) | (filebuf[11]<<8) | filebuf[10];
D(bug("bmp.datatype/LoadBMP() --- bfSize %ld bfOffBits %ld\n", bfSize, bfOffBits));
/* load BitmapInfoHeader from file, make sure, there are at least 40 bytes in buffer */
if ( (bmphandle->filebufbytes -= 40) < 0 && !LoadBMP_FillBuf(bmphandle, 40) )
{
D(bug("bmp.datatype/LoadBMP() --- filling buffer with header 2 failed\n"));
BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
return FALSE;
}
filebuf = bmphandle->filebufpos; /* this makes things easier */
bmphandle->filebufpos += 40;
/* get image size attributes */
biSize = (filebuf[3]<<24) | (filebuf[2]<<16) | (filebuf[1]<<8) | filebuf[0];
biWidth = (filebuf[7]<<24) | (filebuf[6]<<16) | (filebuf[5]<<8) | filebuf[4];
biHeight = (filebuf[11]<<24) | (filebuf[10]<<16) | (filebuf[9]<<8) | filebuf[8];
biPlanes = (filebuf[13]<<8) | filebuf[12];
biBitCount = (filebuf[15]<<8) | filebuf[14];
biCompression = (filebuf[19]<<24) | (filebuf[18]<<16) | (filebuf[17]<<8) | filebuf[16];
biClrUsed = (filebuf[35]<<24) | (filebuf[34]<<16) | (filebuf[33]<<8) | filebuf[32];
biClrImportant = (filebuf[39]<<24) | (filebuf[38]<<16) | (filebuf[37]<<8) | filebuf[36];
D(bug("bmp.datatype/LoadBMP() --- BMP-Screen %ld x %ld x %ld, %ld (%ld) colors, compression %ld, type %ld\n",
biWidth, biHeight, (long)biBitCount, biClrUsed, biClrImportant, biCompression, biSize));
if (biSize != 40 || biPlanes != 1 || biCompression != 0)
{
D(bug("bmp.datatype/LoadBMP() --- Image format not supported\n"));
BMP_Exit(bmphandle, ERROR_NOT_IMPLEMENTED);
return FALSE;
}
/* check color mode */
pixelfmt = PBPAFMT_LUT8;
switch (biBitCount)
{
case 1:
alignwidth = (biWidth + 31) & ~31UL;
alignbytes = alignwidth / 8;
break;
case 4:
alignwidth = (biWidth + 7) & ~7UL;
alignbytes = alignwidth / 2;
break;
case 8:
alignwidth = (biWidth + 3) & ~3UL;
alignbytes = alignwidth;
break;
case 24:
alignbytes = (biWidth + 3) & ~3UL;
alignwidth = alignbytes * 3;
pixelfmt = PBPAFMT_RGB;
break;
default:
D(bug("bmp.datatype/LoadBMP() --- unsupported color depth\n"));
BMP_Exit(bmphandle, ERROR_NOT_IMPLEMENTED);
return FALSE;
}
D(bug("bmp.datatype/LoadBMP() --- align: pixels %ld bytes %ld\n", alignwidth, alignbytes));
/* set BitMapHeader with image size */
bmhd->bmh_Width = bmhd->bmh_PageWidth = biWidth;
bmhd->bmh_Height = bmhd->bmh_PageHeight = biHeight;
bmhd->bmh_Depth = biBitCount;
/* get empty colormap, then fill in colormap to use*/
if (biBitCount != 24)
{
if( !(GetDTAttrs(o, PDTA_ColorRegisters, (IPTR)&colormap,
PDTA_CRegs, (IPTR)&colorregs,
TAG_DONE ) == 2) ||
!(colormap && colorregs) )
{
D(bug("bmp.datatype/LoadBMP() --- got no colormap\n"));
BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
return FALSE;
}
if( !LoadBMP_Colormap(bmphandle, biClrUsed, colormap, colorregs) )
{
BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
return FALSE;
}
}
/* skip offset */
bfOffBits = bfOffBits - 14 - 40 - biClrUsed*4;
D(bug("bmp.datatype/LoadBMP() --- remaining offset %ld\n", bfOffBits));
if ( bfOffBits < 0 ||
( (bmphandle->filebufbytes -= bfOffBits ) < 0 && !LoadBMP_FillBuf(bmphandle, bfOffBits) ) )
{
D(bug("bmp.datatype/LoadBMP() --- cannot skip offset\n"));
BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
return FALSE;
}
bmphandle->filebufpos += bfOffBits;
/* Pass attributes to picture.datatype */
GetDTAttrs( o, DTA_Name, (IPTR)&name, TAG_DONE );
SetDTAttrs(o, NULL, NULL, PDTA_NumColors, biClrUsed,
DTA_NominalHoriz, biWidth,
DTA_NominalVert , biHeight,
DTA_ObjName , (IPTR)name,
TAG_DONE);
/* Now decode the picture data into a chunky buffer; and pass it to Bitmap line-by-line */
bmphandle->linebufsize = bmphandle->linebufbytes = alignwidth;
if (! (bmphandle->linebuf = bmphandle->linebufpos = AllocMem(bmphandle->linebufsize, MEMF_ANY)) )
{
BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
return FALSE;
}
//D(bug("bmp.datatype/LoadBMP() --- bytes of %ld (%ld) bytes\n", (long)bmphandle->filebufbytes, (long)(bmphandle->filebufsize-(bmphandle->filebufpos-bmphandle->filebuf)) ));
cont = 1;
for (y=biHeight-1; y>=0 && cont; y--)
{
int r, g, b;
bmphandle->linebufpos = bmphandle->linebuf;
if (biBitCount == 24)
{
if ( (bmphandle->filebufbytes -= alignwidth) < 0 && !LoadBMP_FillBuf(bmphandle, alignwidth) )
{
D(bug("bmp.datatype/LoadBMP() --- early end of bitmap data, x %ld y %ld\n", x, y));
//BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
//return FALSE;
cont = 0;
}
for (x=0; x<alignbytes; x++)
{
b = *(bmphandle->filebufpos)++;
g = *(bmphandle->filebufpos)++;
r = *(bmphandle->filebufpos)++;
*(bmphandle->linebufpos)++ = r;
*(bmphandle->linebufpos)++ = g;
*(bmphandle->linebufpos)++ = b;
}
}
else
{
for (x=0; x<alignbytes; x++)
{
if ( (bmphandle->filebufbytes -= 1) < 0 && !LoadBMP_FillBuf(bmphandle, 1) )
{
D(bug("bmp.datatype/LoadBMP() --- early end of bitmap data, x %ld y %ld\n", x, y));
//BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
//return FALSE;
cont = 0;
break;
}
byte = *(bmphandle->filebufpos)++;
switch (biBitCount)
{
case 1:
for (b=0; b<8; b++)
{
*(bmphandle->linebufpos)++ = (byte & 0x80) ? 1 : 0;
byte <<= 1;
}
break;
case 4:
*(bmphandle->linebufpos)++ = (byte & 0xf0) >> 4;
*(bmphandle->linebufpos)++ = (byte & 0x0f);
break;
case 8:
*(bmphandle->linebufpos)++ = byte;
break;
case 24:
*(bmphandle->linebufpos)++ = byte;
break;
}
}
}
if
(
!DoSuperMethod(cl, o,
PDTM_WRITEPIXELARRAY, /* Method_ID */
(IPTR)bmphandle->linebuf, /* PixelData */
pixelfmt, /* PixelFormat */
alignwidth, /* PixelArrayMod (number of bytes per row) */
0, /* Left edge */
y, /* Top edge */
biWidth, /* Width */
1 /* Height (here: one line) */
)
)
{
D(bug("bmp.datatype/LoadBMP() --- WRITEPIXELARRAY failed !\n"));
BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
return FALSE;
}
}
//D(bug("bmp.datatype/LoadBMP() --- bytes of %ld (%ld) bytes\n", (long)bmphandle->filebufbytes, (long)(bmphandle->filebufsize-(bmphandle->filebufpos-bmphandle->filebuf)) ));
D(bug("bmp.datatype/LoadBMP() --- Normal Exit\n"));
BMP_Exit(bmphandle, 0);
return TRUE;
}
/**************************************************************************************************/
static BOOL SaveBMP(struct IClass *cl, Object *o, struct dtWrite *dtw )
{
BmpHandleType *bmphandle;
UBYTE *filebuf;
unsigned int width, height, widthxheight, numplanes, numcolors;
struct BitMapHeader *bmhd;
struct BitMap *bm;
struct RastPort rp;
long *colorregs;
int i, j, ret;
D(bug("bmp.datatype/SaveBMP()\n"));
if( !(bmphandle = AllocMem(sizeof(BmpHandleType), MEMF_ANY)) )
{
SetIoErr(ERROR_NO_FREE_STORE);
return FALSE;
}
bmphandle->filebuf = NULL;
bmphandle->linebuf = NULL;
bmphandle->codecvars = NULL;
/* A NULL file handle is a NOP */
if( !dtw->dtw_FileHandle )
{
D(bug("bmp.datatype/SaveBMP() --- empty Filehandle - just testing\n"));
BMP_Exit(bmphandle, 0);
return TRUE;
}
bmphandle->filehandle = dtw->dtw_FileHandle;
/* Get BitMap and color palette */
if( GetDTAttrs( o, PDTA_BitMapHeader, (IPTR)&bmhd,
PDTA_BitMap, (IPTR)&bm,
PDTA_CRegs, (IPTR)&colorregs,
PDTA_NumColors, (IPTR)&numcolors,
TAG_DONE ) != 4UL ||
!bmhd || !bm || !colorregs || !numcolors)
{
D(bug("bmp.datatype/SaveBMP() --- missing attributes\n"));
BMP_Exit(bmphandle, ERROR_OBJECT_NOT_FOUND);
return FALSE;
}
#if 0
/* Check if this is a standard BitMap */
if( !( GetBitMapAttr(bm, BMA_FLAGS) & BMF_STANDARD ) )
{
D(bug("bmp.datatype/SaveBMP() --- wrong BitMap type\n"));
BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
return FALSE;
}
#endif
/* initialize buffered file reads */
bmphandle->filebufsize = FILEBUFSIZE;
bmphandle->filebufbytes = bmphandle->filebufsize;
if( !(bmphandle->filebuf = bmphandle->filebufpos = AllocMem(bmphandle->filebufsize, MEMF_ANY)) )
{
BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
return FALSE;
}
/* write BMP 87a header to file, make sure, there are at least 13 bytes in buffer */
if ( (bmphandle->filebufbytes -= 13) < 0 && !SaveBMP_EmptyBuf(bmphandle, 13) )
{
D(bug("bmp.datatype/SaveBMP() --- filling buffer with header failed\n"));
BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
return FALSE;
}
filebuf = bmphandle->filebufpos; /* this makes things easier */
bmphandle->filebufpos += 13;
/* set screen descriptor attributes (from BitMapHeader) */
width = bmhd->bmh_PageWidth;
height = bmhd->bmh_PageHeight;
numplanes = bmhd->bmh_Depth - 1;
numcolors = 1 << (numplanes + 1);
D(bug("bmp.datatype/SaveBMP() --- BMP-Image %d x %d x %d, cols %d\n", width, height, numplanes+1, numcolors));
filebuf[6] = width & 0xff;
filebuf[7] = width >> 8;
filebuf[8] = height & 0xff;
filebuf[9] = height >> 8;
filebuf[10] = 0x80 | ((numplanes & 0x07) << 4) | (numplanes & 0x07) ; /* set numplanes, havecolmap=1 */
filebuf[11] = 0; /* this is fillcolor */
filebuf[12] = 0; /* this is pixel aspect ratio, 0 means unused */
/* write screen colormap, we don't use an image colormap */
for (i = 0; i < numcolors*3; i += 3)
{
if ( (bmphandle->filebufbytes -= 3) < 0 && !SaveBMP_EmptyBuf(bmphandle, 3) )
{
BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
return FALSE;
}
*(bmphandle->filebufpos)++ = colorregs[i] >> 24;
*(bmphandle->filebufpos)++ = colorregs[i+1] >> 24;
*(bmphandle->filebufpos)++ = colorregs[i+2] >> 24;
}
/* write image header, image has same size as screen */
if ( (bmphandle->filebufbytes -= 10) < 0 && !SaveBMP_EmptyBuf(bmphandle, 10) )
{
BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
return FALSE;
}
filebuf = bmphandle->filebufpos; /* this makes things easier */
bmphandle->filebufpos += 10;
filebuf[0] = ','; /* header ID */
filebuf[1] = filebuf[2] = 0; /* no left edge */
filebuf[3] = filebuf[4] = 0; /* no top edge */
filebuf[5] = width & 0xff;
filebuf[6] = width >> 8;
filebuf[7] = height & 0xff;
filebuf[8] = height >> 8;
filebuf[9] = numplanes & 0x07; /* set numplanes, havecolmap=0, interlaced=0 */
/* Now read the picture data from the bitplanes and write it to a chunky buffer */
/* For now, we use a full picture pixel buffer, not a single line */
widthxheight = width*height;
bmphandle->linebufsize = bmphandle->linebufbytes = widthxheight;
if (! (bmphandle->linebuf = bmphandle->linebufpos = AllocMem(bmphandle->linebufsize, MEMF_ANY)) )
{
BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
return FALSE;
}
InitRastPort(&rp);
rp.BitMap=bm;
for (j=0; j<height; j++)
{
for (i=0; i<width; i++)
{
ret = (UBYTE)ReadPixel(&rp, i, j); /* very slow, to be changed */
*(bmphandle->linebufpos)++ = ret;
}
}
bmphandle->linebufpos = bmphandle->linebuf;
/* write the chunky buffer to file, after encoding */
/* write end-of-BMP marker */
if ( !bmphandle->filebufbytes-- && !SaveBMP_EmptyBuf(bmphandle, 1) )
{
BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
return FALSE;
}
*(bmphandle->filebufpos)++ = ';';
/* flush write buffer to file and exit */
SaveBMP_EmptyBuf(bmphandle, 0);
D(bug("bmp.datatype/SaveBMP() --- Normal Exit\n"));
BMP_Exit(bmphandle, 0);
return TRUE;
}
/**************************************************************************************************/
IPTR BMP__OM_NEW(Class *cl, Object *o, Msg msg)
{
Object *newobj;
D(bug("bmp.datatype/DT_Dispatcher: Method OM_NEW\n"));
newobj = (Object *)DoSuperMethodA(cl, o, msg);
if (newobj)
{
if (!LoadBMP(cl, newobj))
{
CoerceMethod(cl, newobj, OM_DISPOSE);
newobj = NULL;
}
}
return (IPTR)newobj;
}
/**************************************************************************************************/
IPTR BMP__DTM_WRITE(Class *cl, Object *o, struct dtWrite *dtw)
{
D(bug("bmp.datatype/DT_Dispatcher: Method DTM_WRITE\n"));
if( (dtw -> dtw_Mode) == DTWM_RAW )
{
/* Local data format requested */
return SaveBMP(cl, o, dtw );
}
else
{
/* Pass msg to superclass (which writes an IFF ILBM picture)... */
return DoSuperMethodA( cl, o, (Msg)dtw );
}
}
/*
Copyright © 1995-2001, The AROS Development Team. All rights reserved.
$Id: ppmclass.c 30902 2009-03-14 13:38:20Z mazze $
*/
/**********************************************************************/
#define DEBUGMETHODS 0
/**********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dostags.h>
#include <graphics/gfxbase.h>
#include <graphics/rpattr.h>
#include <intuition/imageclass.h>
#include <intuition/icclass.h>
#include <intuition/gadgetclass.h>
#include <intuition/cghooks.h>
#include <datatypes/datatypesclass.h>
#include <datatypes/pictureclass.h>
#include <clib/alib_protos.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/utility.h>
#include <proto/iffparse.h>
#include <proto/datatypes.h>
#include <aros/symbolsets.h>
ADD2LIBS("datatypes/picture.datatype", 0, struct Library *, PictureBase);
#include "debug.h"
#include "methods.h"
/**************************************************************************************************/
IPTR PPM__OM_NEW(Class *cl, Object *o, struct opSet *msg)
{
IPTR RetVal;
char *Title;
IPTR sourcetype;
BPTR FileHandle;
struct BitMapHeader *bmhd;
char LineBuffer[128];
long Width, Height, NumChars;
unsigned int i;
unsigned char *RGBBuffer;
D(bug("ppm.datatype/OM_NEW: Entering\n"));
D(bug("ppm.datatype/OM_NEW: cl: 0x%lx o: 0x%lx msg: 0x%lx\n", (unsigned long) cl, (unsigned long) o, (unsigned long) msg));
RetVal=DoSuperMethodA(cl, o, (Msg) msg);
if(!RetVal)
{
D(bug("ppm.datatype/OM_NEW: DoSuperMethod failed\n"));
return(0);
}
D(bug("ppm.datatype/OM_NEW: DoSuperMethod: 0x%lx\n", (unsigned long) RetVal));
if( GetDTAttrs((Object *) RetVal,
DTA_SourceType , (IPTR)&sourcetype ,
DTA_Handle , (IPTR)&FileHandle,
DTA_Name , (IPTR)&Title,
PDTA_BitMapHeader , (IPTR)&bmhd,
TAG_DONE) != 4 )
{
D(bug("ppm.datatype/OM_NEW: GetDTAttrs(DTA_Handle, DTA_BitMapHeader) error !\n"));
CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
SetIoErr(ERROR_OBJECT_NOT_FOUND);
return FALSE;
}
D(bug("ppm.datatype/OM_NEW: GetDTAttrs(DTA_Handle, DTA_BitMapHeader) successful\n"));
if ( sourcetype == DTST_RAM && FileHandle == NULL )
{
D(bug("ppm.datatype/OM_NEW: Creating an empty object\n"));
return TRUE;
}
if ( sourcetype != DTST_FILE || !FileHandle || !bmhd )
{
D(bug("ppm.datatype/OM_NEW: Unsupported sourcetype mode\n"));
SetIoErr(ERROR_NOT_IMPLEMENTED);
return FALSE;
}
D(bug("ppm.datatype/OM_NEW: Title: %s\n", Title?Title:"[none]"));
Seek(FileHandle, 0, OFFSET_BEGINNING);
D(bug("ppm.datatype/OM_NEW: Seek successful\n"));
if(!FGets(FileHandle, LineBuffer, 128))
{
D(bug("ppm.datatype/OM_NEW: FGets line 1 failed\n"));
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
return(0);
}
if(!(LineBuffer[0]=='P' && LineBuffer[1]=='6'))
{
D(bug("ppm.datatype/OM_NEW: Not a P6 PPM\n"));
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
return(0);
}
D(bug("ppm.datatype/OM_NEW: It's a P6 PPM\n"));
if(!FGets(FileHandle, LineBuffer, 128))
{
D(bug("ppm.datatype/OM_NEW: FGets line 2 failed\n"));
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
return(0);
}
if(LineBuffer[0]=='#')
{
D(bug("ppm.datatype/OM_NEW: Line 2 is a comment\n"));
if(!FGets(FileHandle, LineBuffer, 128))
{
D(bug("ppm.datatype/OM_NEW: FGets line 3 after comment failed\n"));
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
return(0);
}
}
NumChars=StrToLong(LineBuffer, (LONG *)&Width);
if(!((NumChars>0) && (Width>0)))
{
D(bug("ppm.datatype/OM_NEW: StrToLong(Width) failed\n"));
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
return(0);
}
D(bug("ppm.datatype/OM_NEW: Width: %ld\n", (long) Width));
D(bug("ppm.datatype/OM_NEW: NumChars: %ld\n", (long) NumChars));
NumChars=StrToLong(LineBuffer+NumChars, (LONG *)&Height);
if(!((NumChars>0) && (Height>0)))
{
D(bug("ppm.datatype/OM_NEW: StrToLong(Height) failed\n"));
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
return(0);
}
D(bug("ppm.datatype/OM_NEW: Height: %ld\n", (long) Height));
D(bug("ppm.datatype/OM_NEW: NumChars: %ld\n", (long) NumChars));
if(!FGets(FileHandle, LineBuffer, 128))
{
D(bug("ppm.datatype/OM_NEW: FGets line 3 (4) failed\n"));
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
return(0);
}
if(!(LineBuffer[0]=='2' && LineBuffer[1]=='5' && LineBuffer[2]=='5'))
{
D(bug("ppm.datatype/OM_NEW: Wrong depth\n"));
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
return(0);
}
D(bug("ppm.datatype/OM_NEW: Header successful read\n"));
bmhd->bmh_Width = Width;
bmhd->bmh_Height = Height;
bmhd->bmh_PageWidth = bmhd->bmh_Width;
bmhd->bmh_PageHeight = bmhd->bmh_Height;
D(bug("ppm.datatype/OM_NEW: Using 24 bit colors\n"));
bmhd->bmh_Depth = 24;
/* Get a buffer for one line of RGB triples */
RGBBuffer=AllocVec(Width*3, MEMF_ANY | MEMF_CLEAR);
if(!RGBBuffer)
{
D(bug("ppm.datatype/OM_NEW: AllocVec(RGBBuffer) failed\n"));
CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
SetIoErr(ERROR_NO_FREE_STORE);
return(0);
}
D(bug("ppm.datatype/OM_NEW: RGBBuffer successfully allocated\n"));
/* Flush filehandle, so that unbuffered Read() can be used after buffered FGets() */
Flush(FileHandle);
/* Copy picture line by line to picture.datatype using WRITEPIXELARRAY method */
for(i=0; i<Height; i++)
{
if(!(Read(FileHandle, RGBBuffer, (Width*3))==(Width*3)))
{
D(bug("ppm.datatype/OM_NEW: Read(RGBBuffer) failed, maybe file too short\n"));
FreeVec(RGBBuffer);
CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
return(0);
}
if(!DoSuperMethod(cl, (Object *) RetVal,
PDTM_WRITEPIXELARRAY, /* Method_ID */
(IPTR) RGBBuffer, /* PixelData */
PBPAFMT_RGB, /* PixelFormat */
Width*3, /* PixelArrayMod (number of bytes per row) */
0, /* Left edge */
i, /* Top edge */
Width, /* Width */
1)) /* Height (here: one line) */
{
D(bug("ppm.datatype/OM_NEW: WRITEPIXELARRAY failed\n"));
FreeVec(RGBBuffer);
CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
return(0);
}
}
D(bug("ppm.datatype/OM_NEW: WRITEPIXELARRAY of whole picture done\n"));
FreeVec(RGBBuffer);
SetDTAttrs((Object *) RetVal, NULL, NULL, DTA_ObjName, (IPTR) Title,
DTA_NominalHoriz, Width,
DTA_NominalVert, Height,
TAG_DONE);
D(bug("ppm.datatype/OM_NEW: Leaving. (24 bit mode)\n"));
return(RetVal);
} /* PPM_New() */
/**************************************************************************************************/
static BOOL PPM_Save(struct IClass *cl, Object *o, struct dtWrite *dtw )
{
BPTR filehandle;
unsigned int width, height, numplanes, y;
UBYTE *linebuf;
struct BitMapHeader *bmhd;
long *colorregs;
D(bug("ppm.datatype/PPM_Save()\n"));
/* A NULL file handle is a NOP */
if( !dtw->dtw_FileHandle )
{
D(bug("ppm.datatype/PPM_Save() --- empty Filehandle - just testing\n"));
return TRUE;
}
filehandle = dtw->dtw_FileHandle;
/* Get BitMapHeader and color palette */
if( GetDTAttrs( o, PDTA_BitMapHeader, (IPTR) &bmhd,
PDTA_CRegs, (IPTR) &colorregs,
TAG_DONE ) != 2UL ||
!bmhd || !colorregs )
{
D(bug("ppm.datatype/PPM_Save() --- missing attributes\n"));
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
return FALSE;
}
width = bmhd->bmh_Width;
height = bmhd->bmh_Height;
numplanes = bmhd->bmh_Depth;
if( numplanes != 24 )
{
D(bug("ppm.datatype/PPM_Save() --- color depth %d, can save only depths of 24\n", numplanes));
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
return FALSE;
}
D(bug("ppm.datatype/PPM_Save() --- Picture size %d x %d (x %d bit)\n", width, height, numplanes));
/* Write header to file */
if( FPrintf( filehandle, "P6\n#Created by AROS ppm.datatype aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n%ld %ld\n255\n",
(long)width, (long)height ) == -1 )
{
D(bug("ppm.datatype/PPM_Save() --- writing header failed\n"));
return FALSE;
}
/* Now read the picture data line by line and write it to a chunky buffer */
if( !(linebuf = AllocVec(width*3, MEMF_ANY)) )
{
SetIoErr(ERROR_NO_FREE_STORE);
return FALSE;
}
D(bug("ppm.datatype/PPM_Save() --- copying picture with READPIXELARRAY\n"));
for (y=0; y<height; y++)
{
if(!DoSuperMethod(cl, o,
PDTM_READPIXELARRAY, /* Method_ID */
(IPTR)linebuf, /* PixelData */
PBPAFMT_RGB, /* PixelFormat */
width, /* PixelArrayMod (number of bytes per row) */
0, /* Left edge */
y, /* Top edge */
width, /* Width */
1)) /* Height */
{
D(bug("ppm.datatype/PPM_Save() --- READPIXELARRAY line %d failed !\n", y));
FreeVec(linebuf);
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
return FALSE;
}
if( FWrite( filehandle, linebuf, width*3, 1 ) != 1 )
{
D(bug("ppm.datatype/PPM_Save() --- writing picture data line %d failed !\n", y));
FreeVec(linebuf);
return FALSE;
}
}
D(bug("ppm.datatype/PPM_Save() --- Normal Exit\n"));
FreeVec(linebuf);
SetIoErr(0);
return TRUE;
}
/**************************************************************************************************/
IPTR PPM__DTM_WRITE(struct IClass *cl, Object *o, struct dtWrite *dtw)
{
if( (dtw -> dtw_Mode) == DTWM_RAW )
{
/* Local data format requested */
return PPM_Save(cl, o, dtw );
}
else
{
/* Pass msg to superclass (which writes an IFF ILBM picture)... */
return DoSuperMethodA( cl, o, (Msg)dtw );
}
}
/**************************************************************************************************/
#if DEBUGMETHODS
STATIC IPTR DT_NotifyMethod(struct IClass *cl, struct Gadget *g, struct opUpdate *msg)
{
return(DoSuperMethodA(cl, (Object *) g, (Msg) msg));
}
/**************************************************************************************************/
STATIC IPTR DT_SetMethod(struct IClass *cl, struct Gadget *g, struct opSet *msg)
{
IPTR RetVal;
D(bug("ppm.datatype/OM_SET: Entering\n"));
RetVal=DoSuperMethodA(cl, (Object *) g, (Msg) msg);
return(RetVal);
}
/**************************************************************************************************/
STATIC IPTR DT_GetMethod(struct IClass *cl, struct Gadget *g, struct opGet *msg)
{
IPTR RetVal;
D(bug("ppm.datatype/OM_GET: Entering\n"));
RetVal=DoSuperMethodA(cl, (Object *) g, (Msg) msg);
return(RetVal);
}
/**************************************************************************************************/
STATIC IPTR DT_LayoutMethod(struct IClass *cl, struct Gadget *g, struct gpLayout *msg)
{
IPTR RetVal;
const char L[]="GM_LAYOUT";
const char P[]="DTM_PROCLAYOUT";
const char A[]="DTM_ASYNCLAYOUT";
const char U[]="Unknown Method";
char *MethodName;
RetVal=DoSuperMethodA(cl, (Object *) g, (Msg) msg);
D(bug("ppm.datatype/%s: RetVal 0x%lx\n", MethodName, (unsigned int) RetVal));
D(bug("ppm.datatype/%s: Leaving\n", MethodName));
return(RetVal);
}
#endif /* DEBUGMETHODS */
Creating New Datatypes
IPTR DTD__OM_NEW(Class *cl, Object *o, struct opSet *msg) { } /* DTD_OM_New() */ /**************************************************************************************************/ static BOOL DTD_Load(struct IClass *cl, Object *o) { } static BOOL DTD_Save(struct IClass *cl, Object *o, struct dtWrite *dtw ) { } IPTR DTD__DTM_WRITE(struct IClass *cl, Object *o, struct dtWrite *dtw) { } /**************************************************************************************************/ STATIC IPTR DT_SetMethod(struct IClass *cl, struct Gadget *g, struct opSet *msg) { } STATIC IPTR DT_GetMethod(struct IClass *cl, struct Gadget *g, struct opGet *msg) { } STATIC IPTR DT_LayoutMethod(struct IClass *cl, struct Gadget *g, struct gpLayout *msg) { }
init
/* Programmheader
Name: init.c
Main: reko
Versionstring: $VER: init.c 1.1 (18.10.1999)
Author: SDI
Distribution: Freeware
Description: all the datatype initialization stuff
1.0 19.09.99 : first version
1.1 18.10.99 : fixed the stuff a bit
*/
#include <proto/exec.h>
#include <proto/intuition.h>
#include <dos/dos.h>
#include <exec/resident.h>
#include <exec/initializers.h>
#include <exec/execbase.h>
#include "SDI_compiler.h"
#include "reko.h"
struct LibInitData {
UBYTE i_Type; UBYTE o_Type; UBYTE d_Type; UBYTE p_Type;
UBYTE i_Name; UBYTE o_Name; STRPTR d_Name;
UBYTE i_Flags; UBYTE o_Flags; UBYTE d_Flags; UBYTE p_Flags;
UBYTE i_Version; UBYTE o_Version; UWORD d_Version;
UBYTE i_Revision; UBYTE o_Revision; UWORD d_Revision;
UBYTE i_IdString; UBYTE o_IdString; STRPTR d_IdString;
ULONG endmark;
};
/************************************************************************/
/* First executable routine of this library; must return an error
to the unsuspecting caller */
LONG ReturnError(void)
{
return -1;
}
/************************************************************************/
/* The mandatory reserved library function */
ULONG LibReserved(void)
{
return 0;
}
/************************************************************************/
ASM(struct Library *) LibInit(REG(d0, struct ClassBase *cb), REG(a0, BPTR seglist), REG(a6, struct ExecBase * SysBase))
{
#ifdef _M68060
if(!(SysBase->AttnFlags & AFF_68060))
return 0;
#elif defined (_M68040)
if(!(SysBase->AttnFlags & AFF_68040))
return 0;
#elif defined (_M68030)
if(!(SysBase->AttnFlags & AFF_68030))
return 0;
#elif defined (_M68020)
if(!(SysBase->AttnFlags & AFF_68020))
return 0;
#endif
InitSemaphore(&cb->cb_Lock);
cb->cb_SegList = seglist;
cb->cb_SysBase = SysBase;
if((cb->cb_IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",39)))
{
if((cb->cb_GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 39)))
{
if((cb->cb_DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 39)))
{
if((cb->cb_UtilityBase = (struct UtilityBase *) OpenLibrary ("utility.library", 39)))
return (struct Library *) cb;
CloseLibrary((struct Library *) cb->cb_DOSBase);
}
CloseLibrary((struct Library *) cb->cb_GfxBase);
}
CloseLibrary((struct Library *) cb->cb_IntuitionBase);
}
FreeMem((STRPTR) cb - cb->cb_Lib.lib_NegSize, cb->cb_Lib.lib_NegSize + cb->cb_Lib.lib_PosSize);
return 0;
}
ASM(struct ClassBase *) LibOpen(REG(a6, struct ClassBase *cb))
{
struct ExecBase *SysBase = cb->cb_SysBase;
struct ClassBase *ret = cb;
ObtainSemaphore(&cb->cb_Lock);
cb->cb_Lib.lib_Flags &= ~LIBF_DELEXP;
cb->cb_Lib.lib_OpenCnt++;
if(!cb->cb_Class)
{
if((cb->cb_DataTypesBase = OpenLibrary ("datatypes.library", 39)))
{
if((cb->cb_SuperClassBase = OpenLibrary ("datatypes/picture.datatype", 39)))
{
if((cb->cb_Class = initClass(cb)))
{
ReleaseSemaphore(&cb->cb_Lock);
return ret;
}
CloseLibrary(cb->cb_SuperClassBase);
}
CloseLibrary(cb->cb_DataTypesBase);
}
cb->cb_Lib.lib_OpenCnt--;
ret = 0;
}
ReleaseSemaphore(&cb->cb_Lock);
return ret;
}
ASM(LONG) LibExpunge(REG(a6, struct ClassBase *cb))
{
struct ExecBase *SysBase = cb->cb_SysBase;
if(!cb->cb_Lib.lib_OpenCnt)
{
if(cb->cb_Class) /* security, should never happen */
{
struct IntuitionBase *IntuitionBase = cb->cb_IntuitionBase;
if(FreeClass(cb->cb_Class))
{
cb->cb_Class = 0;
CloseLibrary(cb->cb_SuperClassBase);
CloseLibrary(cb->cb_DataTypesBase);
}
}
if(!cb->cb_Class)
{
BPTR seg = cb->cb_SegList;
Remove((struct Node *) cb);
CloseLibrary((struct Library *) cb->cb_UtilityBase);
CloseLibrary((struct Library *) cb->cb_DOSBase);
CloseLibrary((struct Library *) cb->cb_GfxBase);
CloseLibrary((struct Library *) cb->cb_IntuitionBase);
FreeMem((STRPTR) cb - cb->cb_Lib.lib_NegSize, cb->cb_Lib.lib_NegSize + cb->cb_Lib.lib_PosSize);
return seg;
}
}
cb->cb_Lib.lib_Flags |= LIBF_DELEXP;
return 0;
}
ASM(LONG) LibClose(REG(a6, struct ClassBase *cb))
{
struct ExecBase *SysBase = cb->cb_SysBase;
ObtainSemaphore(&cb->cb_Lock);
if(cb->cb_Lib.lib_OpenCnt)
cb->cb_Lib.lib_OpenCnt--;
if(!cb->cb_Lib.lib_OpenCnt && cb->cb_Class)
{
struct IntuitionBase *IntuitionBase = cb->cb_IntuitionBase;
if(FreeClass(cb->cb_Class))
{
cb->cb_Class = 0;
CloseLibrary(cb->cb_SuperClassBase);
CloseLibrary(cb->cb_DataTypesBase);
}
}
ReleaseSemaphore(&cb->cb_Lock);
/* A bit dangerous, but we cannot release a semaphore after expunging! */
return (cb->cb_Lib.lib_Flags & LIBF_DELEXP) ? LibExpunge(cb) : 0;
}
/************************************************************************/
ASM(Class *) ObtainEngine(REG(a6, struct ClassBase *cb))
{
return cb->cb_Class;
}
/************************************************************************/
/* This is the table of functions that make up the library. The first
four are mandatory, everything following it are user callable
routines. The table is terminated by the value -1. */
static const APTR LibVectors[] = {
LibOpen,
LibClose,
LibExpunge,
LibReserved,
ObtainEngine,
(APTR)-1
};
static const struct LibInitData LibInitData = {
0xA0, (UBYTE) OFFSET(Node, ln_Type), NT_LIBRARY, 0,
0x80, (UBYTE) OFFSET(Node, ln_Name), CLASSNAME,
0xA0, (UBYTE) OFFSET(Library, lib_Flags), LIBF_SUMUSED|LIBF_CHANGED, 0,
0x90, (UBYTE) OFFSET(Library, lib_Version), VERSION,
0x90, (UBYTE) OFFSET(Library, lib_Revision), REVISION,
0x80, (UBYTE) OFFSET(Library, lib_IdString), IDSTRING,
0
};
/* The following data structures and data are responsible for
setting up the Library base data structure and the library
function vector. */
static const ULONG LibInitTable[4] = {
(ULONG)sizeof(struct ClassBase), /* Size of the base data structure */
(ULONG)LibVectors, /* Points to the function vector */
(ULONG)&LibInitData, /* Library base data structure setup table */
(ULONG)LibInit /* The address of the routine to do the setup */
};
/************************************************************************/
/* The library loader looks for this marker in the memory
the library code and data will occupy. It is responsible
setting up the Library base data structure.
*/
static const struct Resident RomTag = {
RTC_MATCHWORD, /* Marker value. */
(struct Resident *)&RomTag, /* This points back to itself. */
(struct Resident *)&RomTag+1, /* This points behind this marker. */
RTF_AUTOINIT, /* The Library should be set up according to the given table. */
VERSION, /* The version of this Library. */
NT_LIBRARY, /* This defines this module as a Library. */
0, /* Initialization priority of this Library; unused. */
CLASSNAME, /* Points to the name of the Library. */
IDSTRING, /* The identification string of this Library. */
(APTR)&LibInitTable /* This table is for initializing the Library. */
};
Dispatcher
/* Programmheader
Name: dispatch.c
Main: reko
Versionstring: $VER: dispatch.c 1.11 (13.07.2003)
Author: SDI
Distribution: Freeware
Description: the real stuff
1.0 19.09.99 : first version
1.1 02.10.99 : added PC stuff
1.2 03.10.99 : some optimizations
1.3 10.10.99 : added HAM conversion
1.4 14.10.99 : added ENV variable support
1.5 17.10.99 : now passes ModeID in HighColor system
1.6 20.10.99 : added HAM6 mode and card clear
1.7 11.11.99 : Now the data is told to be 24 bit!
1.8 10.12.99 : added 16BIT/24BIT keywords
1.9 04.11.01 : added support for layout of older reko datatypes
1.10 18.12.01 : fixed Preview for RKP8 and RKP16
1.11 13.07.03 : added WizSolitaire cardset type
*/
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/datatypes.h>
#include <proto/utility.h>
#include <clib/alib_protos.h>
#include <datatypes/pictureclass.h>
#include <libraries/iffparse.h>
#include <exec/memory.h>
#include <datatypes/pictureclass.h>
#include "SDI_compiler.h"
#include "reko.h"
#define DOSBase cb->cb_DOSBase
#define SysBase cb->cb_SysBase
#define DataTypesBase cb->cb_DataTypesBase
#define UtilityBase cb->cb_UtilityBase
#define GfxBase cb->cb_GfxBase
#define IntuitionBase cb->cb_IntuitionBase
#define REKOFLAG_SOLITON (1<<0)
#define REKOFLAG_PREVIEW (1<<1)
#define REKOFLAG_HAMDIRECT (1<<2)
#define REKOFLAG_16BIT (1<<3)
#define REKOFLAG_REKODT39 (1<<4)
#define REKOFLAG_MREKO (1<<5)
#define REKOFLAG_PCMODE (1<<6)
#define REKOFLAG_WIZMODE (1<<7)
struct RekoHeader /* REKO file header */
{
ULONG rh_ID;
ULONG rh_BodySize;
ULONG rh_CardSize;
UWORD rh_Height;
UWORD rh_Width;
ULONG rh_ModeID;
UBYTE rh_Depth;
UBYTE rh_CardsCnt;
};
struct PCRekoHeader /* PCREKO file header */
{ /* all in INTEL format */
UWORD rh_PCID;
ULONG rh_ID;
UWORD rh_ID2;
ULONG rh_BodySize; /* FileSize-22 */
ULONG rh_CardSize;
UWORD rh_Width;
UWORD rh_Height;
UBYTE rh_Depth;
UBYTE rh_CardsCnt;
};
struct WizData
{
ULONG Unknown;
ULONG Width;
ULONG Height;
UBYTE Order; /* 1 to 13 */
UBYTE Color; /* 0 to 3 */
ULONG JPEGSize;
};
struct WizHeader
{
UBYTE ID[16];
UBYTE Empty[4];
/* We read 2 bytes too much, as reko header has 2 more bytes */
};
#define ID_REKO MAKE_ID('R','E','K','O')
#define ID_PC 0x5043
#define ID_WIZ 0x57697A53
#define HEADER_SIZE sizeof(struct RekoHeader)
#define WIZDATA_SIZE sizeof(struct WizData)
#define FULLHEIGHT 4 /* Number of cards vertically */
#define NORMWIDTH 14
#define FULLWIDTH 17
#define REKO_I 55 /* Cards in REKO I cardset */
#define REKO_II 59 /* Cards in REKO II cardset */
#define REKO_III 68 /* Cards in REKO III cardset */
#define BORDERCOL 0xF0
#define BACKCOL 0
static const UBYTE Mapping[REKO_III][2] = {
{13,2}, {13,1}, {13,0},
{ 0,0}, { 0,1}, { 0,2}, { 0,3},
{ 1,0}, { 1,1}, { 1,2}, { 1,3},
{ 2,0}, { 2,1}, { 2,2}, { 2,3},
{ 3,0}, { 3,1}, { 3,2}, { 3,3},
{ 4,0}, { 4,1}, { 4,2}, { 4,3},
{ 5,0}, { 5,1}, { 5,2}, { 5,3},
{ 6,0}, { 6,1}, { 6,2}, { 6,3},
{ 7,0}, { 7,1}, { 7,2}, { 7,3},
{ 8,0}, { 8,1}, { 8,2}, { 8,3},
{ 9,0}, { 9,1}, { 9,2}, { 9,3},
{10,0}, {10,1}, {10,2}, {10,3},
{11,0}, {11,1}, {11,2}, {11,3},
{12,0}, {12,1}, {12,2}, {12,3},
{13,3}, {14,3}, {15,3}, {16,3},
{14,0}, {15,0}, {16,0},
{14,1}, {15,1}, {16,1},
{14,2}, {15,2}, {16,2}
};
static const UBYTE WizMapping[REKO_III][2] = {
{13,0},
{ 0,0}, { 1,0}, { 2,0}, { 3,0}, { 4,0}, { 5,0}, { 6,0}, { 7,0}, { 8,0}, { 9,0}, {10,0}, {11,0}, {12,0},
{ 0,1}, { 1,1}, { 2,1}, { 3,1}, { 4,1}, { 5,1}, { 6,1}, { 7,1}, { 8,1}, { 9,1}, {10,1}, {11,1}, {12,1},
{ 0,2}, { 1,2}, { 2,2}, { 3,2}, { 4,2}, { 5,2}, { 6,2}, { 7,2}, { 8,2}, { 9,2}, {10,2}, {11,2}, {12,2},
{ 0,3}, { 1,3}, { 2,3}, { 3,3}, { 4,3}, { 5,3}, { 6,3}, { 7,3}, { 8,3}, { 9,3}, {10,3}, {11,3}, {12,3},
{13,3}, {14,3}, {15,3}, {16,3},
{13,1}, /* empty card */
{13,2}, {14,0}, {14,1}, {14,2}, {15,0}, {15,1}, {15,2}, {16,0}, {16,1}, {16,2}
};
ASM(Object *) Dispatch(REG(a0, Class *cl), REG(a2, Object *o), REG(a1, Msg msg));
Class *initClass(struct ClassBase *cb)
{
Class *CL;
/* Create our class (no instance) */
if((CL=MakeClass(CLASSNAME,PICTUREDTCLASS,NULL,NULL,0)))
{
CL->cl_Dispatcher.h_Entry=(HOOKFUNC)Dispatch;
CL->cl_UserData=(ULONG) cb;
AddClass(CL);
}
return CL;
}
/* Calculate number of cards horizontally */
static ULONG GetFullWidth(ULONG cards)
{
ULONG HCnt;
if(cards <= REKO_I) /* REKO-I cardset */
HCnt=NORMWIDTH;
else if(cards <= REKO_III) /* REKO-II or REKO-III cardset */
HCnt=FULLWIDTH;
else /* Unknown cardset */
HCnt=cards/FULLHEIGHT+(cards%FULLHEIGHT>0);
return HCnt;
}
ASM(static void) putfunc(REG(d0, UBYTE data), REG(a3, STRPTR *a))
{
*((*a)++) = data;
}
static void SPrintF(struct ClassBase *cb, STRPTR buf, STRPTR format, ...)
{
STRPTR buf2 = buf;
RawDoFmt(format, (APTR) ((ULONG)&format+sizeof(STRPTR)),
(void(*)()) putfunc, &buf2);
}
static void MakeBackCard(STRPTR buf, ULONG width, ULONG height)
{
ULONG j;
STRPTR b;
b = buf;
for(j = width*height*3; j; --j) /* clear background */
*(b++) = BACKCOL;
b = buf+3;
for(j = (width-2)*3; j; --j) /* upper border */
*(b++) = BORDERCOL;
b = buf+((width*(height-1))+1)*3;
for(j = (width-2)*3; j; --j) /* bottom border */
*(b++) = BORDERCOL;
b = buf + width*3;
for(j = height-2; j ; --j) /* side borders */
{
b[0] = b[1] = b[2] = BORDERCOL;
b += width*3;
*(b-3) = *(b-2) = *(b-1) = BORDERCOL;
}
b = buf + width*3;
b[3] = b[4] = b[5] = BORDERCOL;
b += width*3;
*(b-6) = *(b-5) = *(b-4) = BORDERCOL;
b = buf + width*(height-2)*3;
b[3] = b[4] = b[5] = BORDERCOL;
b += width*3;
*(b-6) = *(b-5) = *(b-4) = BORDERCOL;
}
static void GetXY(ULONG num, ULONG *x, ULONG *y, ULONG flags)
{
if(flags & REKOFLAG_PREVIEW)
{
*x = *y = 0;
}
else if(flags & REKOFLAG_WIZMODE)
{
*x = WizMapping[num][0];
*y = WizMapping[num][1];
}
else if(num < REKO_III)
{
*x = Mapping[num][0];
*y = Mapping[num][1];
if(num < 3)
{
if(flags & REKOFLAG_MREKO)
{
switch(num)
{
case 0: *y = 1; break;
case 1: *y = 2; break;
case 2: *y = 3; break;
};
}
else if(flags & REKOFLAG_REKODT39)
{
*y = 1;
switch(num)
{
case 0: *x = 13; break;
case 1: *x = 14; break;
case 2: *x = 15; break;
}
}
}
else if(num >= REKO_I && (flags & (REKOFLAG_MREKO|REKOFLAG_REKODT39)))
{
if(num < REKO_II) /* stack cards */
*y = 0;
else if((flags & REKOFLAG_REKODT39) && num < REKO_II+2)
{
*x = 13; *y = num-REKO_II+2;
}
else
(*y)++;
}
}
else
{
*x = num/FULLHEIGHT;
*y = num%FULLHEIGHT;
}
}
static void ClearCards(ULONG cnt, struct ClassBase *cb, Class *cl, Object *o, APTR buf, ULONG w, ULONG h, ULONG flags)
{
ULONG maxcnt, x, y;
STRPTR b;
if(flags & REKOFLAG_PREVIEW)
return;
b = (STRPTR) buf;
for(maxcnt = w*h*3; maxcnt; --maxcnt) /* clear card */
*(b++) = BACKCOL;
maxcnt = GetFullWidth(cnt)*FULLHEIGHT;
if(flags & REKOFLAG_PCMODE)
{
GetXY(0, &x, &y, flags);
DoSuperMethod(cl, o, PDTM_WRITEPIXELARRAY, (ULONG) buf, PBPAFMT_RGB, w*3, x*w, y*h, w, h);
}
while(cnt < maxcnt)
{
GetXY(cnt++, &x, &y, flags);
if(!(flags & REKOFLAG_SOLITON) || x <= 13)
DoSuperMethod(cl, o, PDTM_WRITEPIXELARRAY, (ULONG) buf, PBPAFMT_RGB, w*3, x*w, y*h, w, h);
}
}
#define EndConvI32(a) (((a)>>24)|(((a)>>8)&0xFF00)|(((a)<<8)&0xFF0000)|((a)<<24))
#define EndConvI16(a) ((UWORD)(((a)>>8)|((a)<<8)))
static LONG GetPCREKO(struct ClassBase *cb, Class *cl, Object *o, BPTR fh,
struct BitMapHeader *bmhd, struct PCRekoHeader *h, STRPTR Title, ULONG flags)
{
register ULONG CSize;
LONG result = ERROR_OBJECT_WRONG_TYPE;
flags |= REKOFLAG_PCMODE;
h->rh_CardSize = EndConvI32(h->rh_CardSize);
h->rh_Width = EndConvI16(h->rh_Width);
h->rh_Height = EndConvI16(h->rh_Height);
if(flags & REKOFLAG_SOLITON)
{
if(h->rh_CardsCnt > REKO_I-2)
h->rh_CardsCnt = REKO_I-2;
}
else if(flags & REKOFLAG_PREVIEW)
h->rh_CardsCnt = 5;
/* Calculate sizes */
CSize = h->rh_Width*h->rh_Height*(h->rh_Depth>>3);
if(h->rh_CardsCnt && CSize && (h->rh_Depth == 8 || h->rh_Depth == 16) && h->rh_CardSize == CSize)
{
LONG ErrorLevel = 0, ErrorNumber = 0;
ULONG ModeID;
/* Fill in BitMapHeader information */
bmhd->bmh_Width = bmhd->bmh_PageWidth = h->rh_Width*(flags & REKOFLAG_PREVIEW ? 1 : GetFullWidth(h->rh_CardsCnt));
bmhd->bmh_Height = bmhd->bmh_PageHeight = h->rh_Height*(flags & REKOFLAG_PREVIEW ? 1 : FULLHEIGHT);
bmhd->bmh_Depth = flags & REKOFLAG_16BIT ? 16 : 24;
ModeID=BestModeID(BIDTAG_DesiredWidth, bmhd->bmh_Width, BIDTAG_DesiredHeight, bmhd->bmh_Height,
BIDTAG_Depth, bmhd->bmh_Depth, TAG_DONE);
SetDTAttrs(o, 0, 0, DTA_ObjName, Title, DTA_NominalHoriz, bmhd->bmh_Width, DTA_NominalVert, bmhd->bmh_Height,
PDTA_SourceMode, PMODE_V43, PDTA_ModeID, ModeID, DTA_ErrorLevel, &ErrorLevel, DTA_ErrorNumber, &ErrorNumber, TAG_DONE);
if(ErrorLevel)
result = ErrorNumber;
else if(h->rh_Depth == 16)
{
register UBYTE *d, *e;
CSize = h->rh_Width*h->rh_Height*2+4;
if((d = (UBYTE *) AllocVec(CSize+h->rh_Width*h->rh_Height*3, MEMF_PUBLIC)))
{
ULONG x, y;
register ULONG i, j, card = 0;
result = 0;
e = d + CSize;
while(!result && card < h->rh_CardsCnt)
{
if(Read(fh, d, CSize) != CSize)
result = ERROR_OBJECT_WRONG_TYPE;
else
{
j = 0;
for(i = 4; i < CSize; i += 2)
{
e[j++] = (d[i+1]<<1)&0xF8; /* red */
e[j++] = (d[i+1]<<6 | d[i]>>2)&0xF8; /* green */
e[j++] = (d[i]<<3)&0xF8; /* blue */
}
GetXY(card+2, &x, &y, flags);
DoSuperMethod(cl, o, PDTM_WRITEPIXELARRAY, (ULONG) e, PBPAFMT_RGB,
h->rh_Width*3, x*h->rh_Width, y*h->rh_Height, h->rh_Width, h->rh_Height);
}
++card;
}
if(!result && !(flags & REKOFLAG_PREVIEW))
{
MakeBackCard(e, h->rh_Width, h->rh_Height);
GetXY(1, &x, &y, flags);
DoSuperMethod(cl, o, PDTM_WRITEPIXELARRAY, (ULONG) e, PBPAFMT_RGB,
h->rh_Width*3, x*h->rh_Width, y*h->rh_Height, h->rh_Width, h->rh_Height);
ClearCards(h->rh_CardsCnt+2, cb, cl, o, e, h->rh_Width, h->rh_Height, flags);
}
FreeVec(d);
} /* AllocVec */
else
result = ERROR_NO_FREE_STORE;
}
else if(h->rh_Depth == 8)
{
register UBYTE *d, *e, *f, *g;
CSize = h->rh_Width*h->rh_Height;
if((d = (UBYTE *) AllocVec(CSize+256*3+h->rh_Width*h->rh_Height*3, MEMF_PUBLIC)))
{
ULONG x, y;
register ULONG i, j, card = 0;
result = 0;
e = d + 256*3 + CSize;
f = d + CSize;
while(!result && card < h->rh_CardsCnt)
{
if(Read(fh, d, 256*2+4) != 256*2+4)
result = ERROR_OBJECT_WRONG_TYPE;
else
{
j = 0;
for(i = 4; i < (256)*2+4; i += 2)
{
f[j++] = (d[i+1]<<1)&0xF8; /* red */
f[j++] = (d[i+1]<<6 | d[i]>>2)&0xF8; /* green */
f[j++] = (d[i]<<3)&0xF8; /* blue */
}
if(Read(fh, d, CSize) != CSize)
result = ERROR_OBJECT_WRONG_TYPE;
else
{
for(i = j = 0; i < CSize; ++i)
{
g = f + 3*d[i];
e[j++] = *(g++);
e[j++] = *(g++);
e[j++] = *g;
}
GetXY(card+2, &x, &y, flags);
DoSuperMethod(cl, o, PDTM_WRITEPIXELARRAY, (ULONG) e, PBPAFMT_RGB,
h->rh_Width*3, x*h->rh_Width, y*h->rh_Height, h->rh_Width, h->rh_Height);
}
}
++card;
} /* while */
if(!result && !(flags & REKOFLAG_PREVIEW))
{
MakeBackCard(e, h->rh_Width, h->rh_Height);
GetXY(1, &x, &y, flags);
DoSuperMethod(cl, o, PDTM_WRITEPIXELARRAY, (ULONG) e, PBPAFMT_RGB,
h->rh_Width*3, x*h->rh_Width, y*h->rh_Height, h->rh_Width, h->rh_Height);
ClearCards(h->rh_CardsCnt+2, cb, cl, o, e, h->rh_Width, h->rh_Height, flags);
}
FreeVec(d);
} /* AllocVec */
else
result = ERROR_NO_FREE_STORE;
} /* Error ? */
} /* data checks */
return result;
}
static LONG GetWiz(struct ClassBase *cb, Class *cl, Object *o, BPTR fh,
struct BitMapHeader *bmhd, STRPTR Title, ULONG flags)
{
LONG result = 0;
flags |= REKOFLAG_WIZMODE;
if(Seek(fh, -2, OFFSET_CURRENT) == -1)
result = IoErr();
else
{
int i;
ULONG width=0, height=0, add = 0, x, y;
struct Task* t;
STRPTR e = 0;
STRPTR mem;
struct WizData wd;
t = FindTask(0);
for(i = 0; i < 13*4+1+add && !result; ++i)
{
if(Read(fh, &wd, WIZDATA_SIZE) == WIZDATA_SIZE)
{
wd.Width = EndConvI32(wd.Width);
wd.Height = EndConvI32(wd.Height);
wd.JPEGSize = EndConvI32(wd.JPEGSize);
if(!i)
{
LONG ErrorLevel = 0, ErrorNumber = 0;
ULONG ModeID;
width = wd.Width;
height = wd.Height;
if(!(e = (STRPTR) AllocVec(width*height*3, MEMF_PUBLIC)))
result = ERROR_NO_FREE_STORE;
else
{
/* Fill in BitMapHeader information */
bmhd->bmh_Width = bmhd->bmh_PageWidth = width*(flags & REKOFLAG_PREVIEW ? 1 :
(flags & REKOFLAG_SOLITON ? NORMWIDTH : FULLWIDTH));
bmhd->bmh_Height = bmhd->bmh_PageHeight = height*(flags & REKOFLAG_PREVIEW ? 1 : FULLHEIGHT);
bmhd->bmh_Depth = flags & REKOFLAG_16BIT ? 16 : 24;
ModeID=BestModeID(BIDTAG_DesiredWidth, bmhd->bmh_Width, BIDTAG_DesiredHeight, bmhd->bmh_Height,
BIDTAG_Depth, bmhd->bmh_Depth, TAG_DONE);
SetDTAttrs(o, 0, 0, DTA_ObjName, Title, DTA_NominalHoriz, bmhd->bmh_Width, DTA_NominalVert,
bmhd->bmh_Height, PDTA_SourceMode, PMODE_V43, PDTA_ModeID, ModeID, DTA_ErrorLevel, &ErrorLevel,
DTA_ErrorNumber, &ErrorNumber, TAG_DONE);
if(ErrorLevel)
{
result = ErrorNumber;
break;
}
}
}
if(!(flags & REKOFLAG_PREVIEW) || i == 1+3*13)
{
if(!(mem = AllocVec(wd.JPEGSize+30, MEMF_ANY)))
result = ERROR_NO_FREE_STORE;
else /* uses temporary file, does MEM-access work for all JPEG datatypes? */
{
if(Read(fh, mem+30, wd.JPEGSize) == wd.JPEGSize)
{
BPTR fh2;
SPrintF(cb, mem, "T:REKODT_%08lx.jpg", t);
if((fh2 = Open(mem, MODE_NEWFILE)))
{
if((Write(fh2, mem+30, wd.JPEGSize) == wd.JPEGSize))
{
Object *obj;
struct BitMap *bmp;
Close(fh2); fh2 = 0;
if((obj = NewDTObject(mem,
DTA_GroupID , GID_PICTURE,
OBP_Precision , PRECISION_IMAGE,
DTA_SourceType , DTST_FILE,
PDTA_DestMode , PMODE_V43,
TAG_DONE)))
{
DoMethod(obj, DTM_PROCLAYOUT, NULL, 1);
GetDTAttrs(obj, PDTA_DestBitMap, &bmp, TAG_DONE);
GetXY(i, &x, &y, flags);
DoMethod(obj, PDTM_READPIXELARRAY, (ULONG) e, PBPAFMT_RGB,
width*3, 0, 0, width, height);
DoSuperMethod(cl, o, PDTM_WRITEPIXELARRAY, (ULONG) e, PBPAFMT_RGB,
width*3, x*width, y*height, width, height);
DisposeDTObject(obj);
}
else
result = IoErr();
}
else
result = IoErr();
if(fh2)
Close(fh2);
DeleteFile(mem); /* remove the temporary file */
}
else
result = IoErr();
}
else
result = IoErr();
FreeVec(mem);
}
} /* preview card? */
else
{
if(Seek(fh, wd.JPEGSize, OFFSET_CURRENT) == -1)
result = IoErr();
}
if(!result && i == 13*4 && !(flags & REKOFLAG_SOLITON)) /* additional cards */
{
if(Read(fh, &add, 4) == 4)
{
add = EndConvI32(add);
if(add > 4)
add = 0;
}
else
add = 0;
}
} /* read header */
else
result = IoErr();
}
if(!result && !(flags & REKOFLAG_PREVIEW))
{
MakeBackCard(e, width, height);
GetXY(57, &x, &y, flags);
DoSuperMethod(cl, o, PDTM_WRITEPIXELARRAY, (ULONG) e, PBPAFMT_RGB,
width*3, x*width, y*height, width, height);
ClearCards(58, cb, cl, o, e, width, height, flags);
}
if(e)
FreeVec(e);
}
return result;
}
static LONG MakeHAM(struct ClassBase *cb, Class *cl, Object *o, BPTR fh,
struct BitMapHeader *bmhd, struct RekoHeader *h, STRPTR Title, ULONG flags)
{
ULONG CSize;
LONG result = ERROR_OBJECT_WRONG_TYPE;
/* Calculate sizes */
CSize = (h->rh_Width*h->rh_Height*h->rh_Depth)>>3;
if(h->rh_CardsCnt && CSize && h->rh_CardSize == CSize)
{
LONG ErrorLevel = 0, ErrorNumber = 0;
ULONG ModeID;
/* Fill in BitMapHeader information */
bmhd->bmh_Width = bmhd->bmh_PageWidth = h->rh_Width*(flags & REKOFLAG_PREVIEW ? 1 : GetFullWidth(h->rh_CardsCnt));
bmhd->bmh_Height = bmhd->bmh_PageHeight = h->rh_Height*(flags & REKOFLAG_PREVIEW ? 1 : FULLHEIGHT);
bmhd->bmh_Depth = flags & REKOFLAG_16BIT ? 16 : 24;
ModeID=BestModeID(BIDTAG_DesiredWidth, bmhd->bmh_Width, BIDTAG_DesiredHeight, bmhd->bmh_Height,
BIDTAG_Depth, bmhd->bmh_Depth, TAG_DONE);
SetDTAttrs(o, 0, 0, DTA_ObjName, Title, DTA_NominalHoriz, bmhd->bmh_Width, DTA_NominalVert, bmhd->bmh_Height,
PDTA_SourceMode, PMODE_V43, PDTA_ModeID, ModeID, DTA_ErrorLevel, &ErrorLevel, DTA_ErrorNumber, &ErrorNumber, TAG_DONE);
if(ErrorLevel)
result = ErrorNumber;
else if(h->rh_Depth == 8 || h->rh_Depth == 6)
{
UBYTE *Cr;
ULONG i, dep;
dep = h->rh_Depth;
i = (1<<(dep-2))*3;
if((Cr = (UBYTE *) AllocVec(i, MEMF_PUBLIC)))
{
if(Read(fh, Cr, i) == i)
{
register UBYTE *d, *e;
if((d = (UBYTE *) AllocVec(CSize+h->rh_Width*h->rh_Height*3, MEMF_PUBLIC)))
{
ULONG j, k, l, m, card = 0, u;
result = 0;
l = h->rh_Width >> 3;
u = dep*l;
while(!result && card < h->rh_CardsCnt)
{
if(Read(fh, d, CSize) != CSize)
result = ERROR_OBJECT_WRONG_TYPE;
else
{
ULONG x, y, v;
UBYTE *planar[8], image, last[3];
e = d + CSize;
for(j = v = 0; j < h->rh_Height; ++j, v += u)
{
for(k = m = 0; k < dep; ++k, m += l)
planar[k] = d + m + v;
last[0] = Cr[0];
last[1] = Cr[1];
last[2] = Cr[2];
for(m = l; m; --m)
{
for(i = (1<<7); i; i >>= 1)
{
image = 0;
for(k = 0; k < dep; ++k)
{
image >>= 1;
image |= (*planar[k] & i) ? (1<<7) : 0;
}
k = image >> 6;
image <<= 2;
switch(k)
{
case 0: image >>= (8-dep+2); last[0] = Cr[image*3]; last[1] = Cr[image*3+1]; last[2] = Cr[image*3+2]; break;
case 1: last[2] = image; break;
case 2: last[0] = image; break;
case 3: last[1] = image; break;
}
*(e++) = last[0];
*(e++) = last[1];
*(e++) = last[2];
}
for(k = 0; k < dep; k++)
planar[k]++;
}
}
GetXY(card, &x, &y, flags);
DoSuperMethod(cl, o, PDTM_WRITEPIXELARRAY, (ULONG) (d+CSize), PBPAFMT_RGB,
h->rh_Width*3, x*h->rh_Width, y*h->rh_Height, h->rh_Width, h->rh_Height);
}
++card;
}
if(!result)
ClearCards(h->rh_CardsCnt, cb, cl, o, d+CSize, h->rh_Width, h->rh_Height, flags);
FreeVec(d);
} /* AllocVec */
else
result = ERROR_NO_FREE_STORE;
} /* Read */
} /* AllocVec */
else
result = ERROR_NO_FREE_STORE;
}
} /* data checks */
return result;
}
static LONG GetREKO(struct ClassBase *cb, Class *cl, Object *o, struct TagItem *attrs, ULONG flags)
{
struct RekoHeader Header;
LONG result = ERROR_OBJECT_WRONG_TYPE;
struct BitMapHeader *bmhd = 0;
BPTR fh = 0;
STRPTR Title; /* Picture name */
ULONG LSize, CSize, NumCol, ModeID;
ULONG *MethodArray;
Title = (STRPTR)GetTagData(DTA_Name, 0, attrs);
GetDTAttrs(o, DTA_Handle, &fh, PDTA_BitMapHeader, &bmhd, DTA_Methods, &MethodArray, TAG_DONE);
/* Now we search for the new PDTM_WRITEPIXELARRAY method to determine
if it's the new V43 picture.datatype */
while(*MethodArray != ~0 && *MethodArray != PDTM_WRITEPIXELARRAY)
++MethodArray;
if(fh && bmhd)
{
if(Seek(fh, 0, OFFSET_BEGINNING)>=0)
{
if(Read(fh, &Header, HEADER_SIZE) == HEADER_SIZE)
{
if((((struct PCRekoHeader *) &Header)->rh_PCID == ID_PC) && (((struct PCRekoHeader *) &Header)->rh_ID == ID_REKO)
&& (*MethodArray == PDTM_WRITEPIXELARRAY))
result = GetPCREKO(cb, cl, o, fh, bmhd, (struct PCRekoHeader *) &Header, Title, flags);
else if(Header.rh_ID == ID_WIZ)
result = GetWiz(cb, cl, o, fh, bmhd, Title, flags);
else if(Header.rh_ID == ID_REKO)
{
if(flags & REKOFLAG_SOLITON)
{
if(Header.rh_CardsCnt > REKO_I)
Header.rh_CardsCnt = REKO_I;
}
else if(flags & REKOFLAG_REKODT39)
{
if(Header.rh_CardsCnt > REKO_II)
Header.rh_CardsCnt = REKO_II;
}
else if(flags & REKOFLAG_PREVIEW)
Header.rh_CardsCnt = 7;
if(Header.rh_ModeID & HAM_KEY)
{
if((*MethodArray == PDTM_WRITEPIXELARRAY) && !(flags & REKOFLAG_HAMDIRECT))
return MakeHAM(cb, cl, o, fh, bmhd, &Header, Title, flags);
else if(flags & REKOFLAG_SOLITON)
return 0;
}
/* Calculate sizes */
NumCol = 1<<((Header.rh_ModeID & HAM_KEY) ? Header.rh_Depth-2 : Header.rh_Depth);
LSize = Header.rh_Width>>3; /* Width in bytes */
CSize = LSize*Header.rh_Height*Header.rh_Depth; /* Card size in bytes */
if(Header.rh_CardsCnt && CSize && Header.rh_Depth>=3 && Header.rh_CardSize == CSize)
{
/* Fill in BitMapHeader information */
bmhd->bmh_Width = bmhd->bmh_PageWidth = Header.rh_Width*(flags & REKOFLAG_PREVIEW ? 1 :
GetFullWidth(Header.rh_CardsCnt));
bmhd->bmh_Height = bmhd->bmh_PageHeight = Header.rh_Height*(flags & REKOFLAG_PREVIEW ? 1 : FULLHEIGHT);
bmhd->bmh_Depth = Header.rh_Depth;
/* Get display mode id */
if((ModeID=BestModeID(Header.rh_ModeID & HAM_KEY ? BIDTAG_DIPFMustHave : TAG_IGNORE, DIPF_IS_HAM,
BIDTAG_DesiredWidth, bmhd->bmh_Width, BIDTAG_DesiredHeight, bmhd->bmh_Height,
BIDTAG_Depth, Header.rh_Depth, TAG_DONE)) != INVALID_ID)
{
UBYTE *CMap = 0; /* in real "struct ColorRegister *" */
ULONG *CRegs = 0;
/* Set colors */
SetDTAttrs(o,NULL,NULL,PDTA_NumColors,NumCol,TAG_DONE);
GetDTAttrs(o,PDTA_ColorRegisters,&CMap,PDTA_CRegs,&CRegs,TAG_DONE);
if(CMap && CRegs)
{
NumCol *= 3;
if(Read(fh,CMap,NumCol)==NumCol)
{
register ULONG i;
struct BitMap *bm;
register ULONG *a;
register UBYTE *b;
a = CRegs;
b = CMap;
while(NumCol--)
{
i = *(b++);
i = (i<<8)+i;
*(a++) = (i<<16)+i;
}
/* Prepare bitmap */
if((bm=AllocBitMap(bmhd->bmh_Width, bmhd->bmh_Height, Header.rh_Depth,
(BMF_CLEAR | BMF_INTERLEAVED | BMF_DISPLAYABLE), 0)))
{
STRPTR Buffer;
/* Allocate temporary buffer */
if((Buffer = (STRPTR) AllocVec(CSize, MEMF_PUBLIC)))
{
result = 0;
/* Read data in 1-card chunks */
for(i=0; !result && i < Header.rh_CardsCnt; ++i)
{
if(Read(fh,Buffer,CSize) != CSize)
result = ERROR_OBJECT_WRONG_TYPE;
else
{
ULONG x,y;
register ULONG k, j, DstOffs, bpr, h;
bpr = bm->BytesPerRow;
b = Buffer;
h = Header.rh_Height;
GetXY(i,&x,&y, flags);
DstOffs=y*h*bpr+x*LSize;
while(h--)
{
for(k=0; k < Header.rh_Depth; k++)
{
for(j = 0; j < LSize; ++j)
bm->Planes[k][DstOffs+j] = *(b++);
}
DstOffs += bpr;
}
}
}
FreeVec(Buffer);
/* Set attributes of destination picture */
if(!result)
SetDTAttrs(o, 0, 0, DTA_ObjName, Title, DTA_NominalHoriz, bmhd->bmh_Width,
DTA_NominalVert, bmhd->bmh_Height, PDTA_BitMap, bm, PDTA_ModeID, ModeID,
PDTA_SourceMode, PMODE_V42, PDTA_DestMode, PMODE_V42, TAG_DONE);
} /* AllocVec */
else
result = ERROR_NO_FREE_STORE;
if(result)
FreeBitMap(bm);
} /* AllocBitmap */
} /* Read colortable */
} /* CMap && CRegs */
} /* BestModeID */
} /* data checks */
} /* ID_REKO ? */
} /* read header */
} /* seek to begin */
} /* fh && bmhd */
return result;
}
ASM(Object *) Dispatch(REG(a0, Class *cl), REG(a2, Object *o), REG(a1, Msg msg))
{
struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData;
Object *Obj;
switch(msg->MethodID)
{
case OM_NEW: /* We know this method */
if((Obj = (Object *)DoSuperMethodA(cl,o,msg)))
{
UBYTE dtmode[50] = "NORMAL", *ptr;
ULONG flags = 0;
GetVar("REKODTMODE", (STRPTR) &dtmode, 50, GVF_GLOBAL_ONLY);
ptr = dtmode;
while(*ptr)
{
switch(*ptr)
{
case 'm': case 'M': flags |= REKOFLAG_MREKO; break; /* MREKOMODE */
case 'r': case 'R': flags |= REKOFLAG_REKODT39; break; /* REKODT39MODE */
case 'p': case 'P': flags |= REKOFLAG_PREVIEW; break; /* PREVIEW */
case 's': case 'S': flags |= REKOFLAG_SOLITON; break; /* SOLITON */
case 'h': case 'H': flags |= REKOFLAG_HAMDIRECT; break; /* HAMDIRECT */
case '1': flags |= REKOFLAG_16BIT; break; /* 16BIT */
/* case '2': */ /* 24BIT */
/* case 'n': case 'N': */ /* NORMAL */
}
while(*ptr && *(ptr++) != ',')
;
}
if(flags & REKOFLAG_SOLITON)
flags &= ~(REKOFLAG_HAMDIRECT|REKOFLAG_MREKO|REKOFLAG_REKODT39|REKOFLAG_PREVIEW);
else if(flags & REKOFLAG_PREVIEW)
flags &= ~(REKOFLAG_REKODT39|REKOFLAG_MREKO);
else if(flags & REKOFLAG_MREKO)
flags &= ~(REKOFLAG_REKODT39);
if((flags = GetREKO(cb, cl, Obj, ((struct opSet *)msg)->ops_AttrList, flags)))
{
SetIoErr(flags);
CoerceMethod(cl, Obj, OM_DISPOSE);
return 0;
}
else
SetIoErr(0);
}
break;
default: /* Let the superclass handle it */
Obj = (Object *)DoSuperMethodA(cl, o, msg);
break;
}
return Obj;
}
Decoder
References
Picture.class 41.00
OM_DISPOSE function DT_DisposeMethod OM_GET function DT_GetMethod OM_NEW function DT_NewMethod OM_SET alias OM_UPDATE or function DT_SetMethod GM_GOACTIVE function DT_GoActiveMethod GM_HANDLEINPUT function DT_HandleInputMethod GM_LAYOUT function DT_Layout GM_RENDER function DT_Render DTM_ASYNCLAYOUT function DT_AsyncLayout DTM_DRAW function DT_Draw DTM_FRAMEBOX function DT_FrameBox DTM_OBTAINDRAWINFO function DT_ObtainDrawInfo DTM_PROCLAYOUT function DT_ProcLayout DTM_RELEASEDRAWINFO function DT_ReleaseDrawInfo PDTM_READPIXELARRAY function PDT_ReadPixelArray PDTM_SCALE function PDT_Scale PDTM_WRITEPIXELARRAY function PDT_WritePixelArray
sound.class 41.11
OM_DISPOSE function Sound_DISPOSE OM_GET function Sound_GET OM_NEW function Sound_NEW OM_SET function Sound_SET OM_UPDATE function Sound_UPDATE GM_DOMAIN function Sound_DOMAIN GM_GOINACTIVE function Sound_GOINACTIVE GM_HANDLEINPUT function Sound_HANDLEINPUT alias GM_GOACTIVE GM_HITTEST function Sound_HITTEST alias GM_HELPTEST GM_LAYOUT function Sound_LAYOUT alias DTM_PROCLAYOUT GM_RENDER function Sound_RENDER DTM_CLEARSELECTED function Sound_CLEARSELECTED DTM_WRITE function Sound_WRITE alias DTM_COPY DTM_DRAW function Sound_DRAW DTM_OBTAINDRAWINFO function Sound_OBTAINDRAWINFO DTM_RELEASEDRAWINFO function Sound_RELEASEDRAWINFO DTM_REMOVEDTOBJECT function Sound_REMOVEDTOBJECT DTM_SELECT function Sound_SELECT DTM_TRIGGER function Sound_TRIGGER