eXec.plMAGAZYN UŻYTKOWNIKÓW KOMPUTERÓW AMIGA
MAGAZYN UŻYTKOWNIKÓW KOMPUTERÓW AMIGA

czwartek, 6. października, 2022, 20:03

Amiga forum / C/C++ / Wczytywanie i konwersja IFFów - realizacja :)

Czytasz wątek: Wczytywanie i konwersja IFFów - realizacja :)

hextreme
Nieaktywny użytkownik starego forum

Wczytywanie i konwersja IFFów - realizacja :) wysłany: 2013-06-17 17:24

Przedstawiam tutaj przykładową realizację ładowania i konwersji IFFów, którą opracowałem. Za pomocą tych procedur można ładować i konwertować dane w locie! Podana przykładowa konwersja do planarnej bitmapy. Można napisać konwersję do bitmapy typu chunky, danych planarnych BOBów, duszków itp.



/*
* IFFLoad :: loading and converting IFF files.
*/

#include
#include
#include
#include
#include

#include
#include
#include
#include

#include "IFFLoad.h"

#define RowBytes(w) ((((w) + 15) >> 4) << 1)

/* ILBMHandle :: auxilliary structure to hold ILBM info. */
struct ILBMHandle
{
struct BitMapHeader *bmhd;
BYTE *buffer, *curbuf;
ULONG bufsize;
};

/* myOpenIFF :: open IFF transaction from DOS file. */
struct IFFHandle *myOpenIFF(char *name)
{
struct IFFHandle *iff;
if (iff = AllocIFF())
{
if (iff->iff_Stream = Open(name, MODE_OLDFILE))
{
InitIFFasDOS(iff);
if (OpenIFF(iff, IFFF_READ) == 0)
{
return iff;
}
}
}
return NULL;
}

/* myCloseIFF :: close IFF transaction of DOS file. */
void myCloseIFF(struct IFFHandle *iff)
{
CloseIFF(iff);
Close(iff->iff_Stream);
FreeIFF(iff);
}

/* preParseILBM :: pre-parse IFF ILBM file. Return ILBMHandle. */
struct ILBMHandle *preParseILBM(struct IFFHandle *iff)
{
LONG result;
ULONG props[]={ ID_ILBM, ID_BMHD, ID_ILBM, ID_CMAP };
struct ILBMHandle *ilbm;
struct StoredProperty *sp;
struct ContextNode *cn;

if (PropChunks(iff, props, 2) == 0 && StopChunk(iff, ID_ILBM, ID_BODY) == 0)
{
if ((result = ParseIFF(iff, IFFPARSE_SCAN)) == 0)
{
if (ilbm = AllocMem(sizeof(struct ILBMHandle), MEMF_PUBLIC|MEMF_CLEAR))
{
if (sp = FindProp(iff, ID_ILBM, ID_BMHD))
{
ilbm->bmhd = (struct BitMapHeader *)sp->sp_Data;
if (cn = CurrentChunk(iff))
{
ilbm->bufsize = cn->cn_Size;
if (ilbm->buffer = AllocMem(ilbm->bufsize, MEMF_PUBLIC))
{
if (ReadChunkBytes(iff, ilbm->buffer, ilbm->bufsize) == ilbm->bufsize)
{
ilbm->curbuf = ilbm->buffer;
printf("ILBM successfully opened: bufsize = %d\n", ilbm->bufsize);
return ilbm;
}
else
printf("Error while reading chunk bytes.\n");
FreeMem(ilbm->buffer, ilbm->bufsize);
}
else
printf("Not enough memory.\n");
}
else
printf("Error while obtaining current chunk.\n");
}
else
printf("Error: file has not BMHD chunk.\n");
FreeMem(ilbm, sizeof(struct ILBMHandle));
}
else
printf("Not enough memory.\n");
}
else
printf("Error %ld has occured during parsing.\n", result);
}
return NULL;
}

/* closeILBM :: close ILBM. */
void closeILBM(struct ILBMHandle *ilbm)
{
FreeMem(ilbm->buffer, ilbm->bufsize);
FreeMem(ilbm, sizeof(struct ILBMHandle));
printf("ILBM closed.\n");
}

/* readILBM :: read ILBM BODY chunk one line. */
int readILBM(struct IFFHandle *iff, struct ILBMHandle *ilbm, BYTE *dest)
{
WORD bpr;
BYTE control, repeat;

bpr = RowBytes(ilbm->bmhd->bmh_Width);
if (ilbm->bmhd->bmh_Compression == cmpNone)
{
CopyMem(ilbm->curbuf, dest, bpr);
ilbm->curbuf += bpr;
return 0;
}
else if (ilbm->bmhd->bmh_Compression == cmpByteRun1)
{
while (bpr > 0)
{
if ((control = *(ilbm->curbuf)++) >= 0)
{
control++;
bpr -= control;
while (control-- > 0)
*dest++ = *(ilbm->curbuf)++;
}
else if (control != -12
{
control = -control + 1;
bpr -= control;
repeat = *(ilbm->curbuf)++;
while (control-- > 0)
*dest++ = repeat;
}
}
}
return 0;
}

/* loadILBMasBitMap :: load ILBM as planar BitMap. */
struct BitMap *loadILBMasBitMap(char *name, UWORD **pal)
{
struct BitMap *bm=NULL;
struct IFFHandle *iff;
struct ILBMHandle *ilbm;
PLANEPTR planes[8];
struct BitMapHeader *bmhd;
WORD width, bpr, depth, height, row, plane, color;
struct StoredProperty *sp;
BYTE *cmap;

if (iff = myOpenIFF(name))
{
if (ilbm = preParseILBM(iff))
{
bmhd = ilbm->bmhd;
width = bmhd->bmh_Width;
bpr = RowBytes(width);
height = bmhd->bmh_Height;
depth = bmhd->bmh_Depth;
if (bm = AllocBitMap(width, height, depth, BMF_CLEAR, NULL))
{
for (plane = 0; plane < depth; plane++)
planes[plane] = bm->Planes[plane];
for (row = 0; row < height; row++)
{
for (plane = 0; plane < depth; plane++)
{
readILBM(iff, ilbm, planes[plane]);
planes[plane] += bpr;
}
}
if (sp = FindProp(iff, ID_ILBM, ID_CMAP))
{
cmap = sp->sp_Data;
if (pal)
{
if ((*pal) = AllocMem((1 << depth) * sizeof(UWORD), MEMF_PUBLIC|MEMF_CLEAR))
{
/* Convert palette from CMAP to RGB 4 bits per gun. */
for (color = 0; color < (1 << depth); color++)
{
(*pal)[color] = ((*cmap++) & 0xF0) << 4;
(*pal)[color] |= ((*cmap++) & 0xF0);
(*pal)[color] |= ((*cmap++) & 0xF0) >> 4;
}
}
}
}
}
closeILBM(ilbm);
}
myCloseIFF(iff);
}
return bm;
}

/* freePalette :: takes care of freeing color palette. Takes amount of colors. */
void freePalette(UWORD *pal, WORD colors)
{
FreeMem(pal, colors * sizeof(UWORD));
}




Odpowiedz

hextreme
Nieaktywny użytkownik starego forum

Re:Wczytywanie i konwersja IFFów - realizacja :... wysłany: 2013-10-19 20:17

A tutaj moja praca nad warsztatem programistycznym. Tym razem logiczny i spójny podział na funkcje. Staram się dzielić duże zadanie na jak najmniejsze pod-zadania. Oto procedura ładowania obrazka i palety kolorów IFF ILBM do struktury planarnej BitMapy.

Czy jest tutaj ktoś obeznany i mógłby mi powiedzieć, czy dobrze kombinuję? Takie rozwiązanie jest na pewno jednym z wielu możliwych, ale mnie coraz bardziej się podoba.
Zalety: krótkie, łatwe do analizowania funkcje, błyskawiczna de-alokacja zasobów w razie napotkania błędu (ciągła kontrola poprawności). Wady: troszkę mała wszechstronność funkcji, ale to da się poprawić w razie potrzeby.

Pozdrawiam serdecznie.




/* makeshape: program to create shapes: IFF loading part. */

#include
#include
#include
#include
#include
#include
#include
#include
#include

#include "IFFload.h"

/*======================================================================*
* depackbuffer: depack buffer into BitMap within ILBMInfo.
* Inputs: pointer to ILBMInfo, pointer to buffer
* Output: result
*======================================================================*/
int depackbuffer(struct ILBMInfo *ii, BYTE *buffer)
{
int result=-1;
WORD row, plane, bpr;
PLANEPTR planes[8];
BYTE c, n;

if (ii->bitmap = AllocBitMap(ii->width, ii->height, ii->depth, 0, NULL)) {
for (plane = 0; plane < ii->depth; plane++)
planes[plane] = ii->bitmap->Planes[plane];
for (row = 0; row < ii->height; row++) {
for (plane = 0; plane < ii->depth; plane++) {
bpr = ii->bpr;
if (ii->compression == cmpNone) {
CopyMem(buffer, planes[plane], bpr);
buffer += bpr;
planes[plane] += bpr;
}
else if (ii->compression == cmpByteRun1) {
while (bpr > 0) {
if ((c = *buffer++) >= 0) {
c++;
bpr -= c;
while (c-- > 0)
*planes[plane]++ = *buffer++;
}
else if (c != -12 {
c = -c + 1;
bpr -= c;
n = *buffer++;
while (c-- > 0)
*planes[plane]++ = n;
}
}
}
}
}
result = 0;
}
return result;
}

/*======================================================================*
* readbody: alloc buffer then depack ILBM BODY into it.
* Inputs: pointer to ILBMInfo, pointer to IFFHandle.
* Output: result
*======================================================================*/
int readbody(struct ILBMInfo *ii, struct IFFHandle *iff)
{
struct ContextNode *cn;
BYTE *buffer;
int result=-1;

if (cn = CurrentChunk(iff)) {
if (buffer = AllocMem(cn->cn_Size, MEMF_PUBLIC)) {
if (ReadChunkBytes(iff, buffer, cn->cn_Size) == cn->cn_Size) {
result = depackbuffer(ii, buffer);
}
FreeMem(buffer, cn->cn_Size);
}
}
return result;
}

/*======================================================================*
* storebmhd: copy contents of BMHD chunk into ILMBInfo.
* Inputs: pointer to ILBMInfo, pointer to BitMapHeader
* Output: none
*======================================================================*/
void storebmhd(struct ILBMInfo *ii, struct BitMapHeader *bmhd)
{
ii->width = bmhd->bmh_Width;
ii->height = bmhd->bmh_Height;
ii->depth = bmhd->bmh_Depth;
ii->bpr = ROWBYTES(ii->width);
ii->compression = bmhd->bmh_Compression;
}

/*======================================================================*
* storecmap: copy contents of CMAP chunk into ILBMInfo.
* Inputs: pointer to ILBMInfo, pointer to CMAP, size of CMAP chunk
* Output: result
*======================================================================*/
int storecmap(struct ILBMInfo *ii, UBYTE *cmap, ULONG size)
{
if (ii->cmap = AllocMem(size, MEMF_PUBLIC)) {
CopyMem(cmap, ii->cmap, size);
return 0;
}
return -1;
}

/*======================================================================*
* readilbm: store data from IFF ILBM file into ILBMInfo.
* Inputs: pointer to ILBMInfo, pointer to IFFHandle
* Output: result
*======================================================================*/
int readilbm(struct ILBMInfo *ii, struct IFFHandle *iff)
{
struct StoredProperty *sp;
int result=-1;

if (sp = FindProp(iff, ID_ILBM, ID_BMHD)) {
storebmhd(ii, (struct BitMapHeader *)sp->sp_Data);
if (sp = FindProp(iff, ID_ILBM, ID_CMAP)) {
storecmap(ii, sp->sp_Data, sp->sp_Size);
}
result = readbody(ii, iff);
}
return result;
}

/*======================================================================*
* parseilbm: parse IFF ILBM file.
* Inputs: pointer to ILBMInfo, pointer to IFFHandle
* Output: result
*======================================================================*/
int parseilbm(struct ILBMInfo *ii, struct IFFHandle *iff)
{
int result;

result = PropChunk(iff, ID_ILBM, ID_BMHD);
result |= PropChunk(iff, ID_ILBM, ID_CMAP);
result |= StopChunk(iff, ID_ILBM, ID_BODY);
if (result == 0 && ParseIFF(iff, IFFPARSE_SCAN) == 0) {
result = readilbm(ii, iff);
}
return result;
}

/*======================================================================*
* openiff: begin transaction with IFF file and begin parsing.
* Inputs: pointer to ILBMInfo, pointer to IFFHandle
* Output: result
*======================================================================*/
int openiff(struct ILBMInfo *ii, struct IFFHandle *iff)
{
int result=-1;

if (OpenIFF(iff, IFFF_READ) == 0) {
result = parseilbm(ii, iff);
CloseIFF(iff);
}
return result;
}

/*======================================================================*
* openilbm: open IFF file and store contents into ILBMInfo.
* Inputs: pointer to ILBMInfo, pointer to IFFHandle, name
* Output: result
*======================================================================*/
int openilbm(struct ILBMInfo *ii, struct IFFHandle *iff, char *name)
{
int result=-1;

if (iff->iff_Stream = Open(name, MODE_OLDFILE)) {
InitIFFasDOS(iff);
result = openiff(ii, iff);
Close(iff->iff_Stream);
}
return result;
}

/*======================================================================*
* fillilbminfo: fill ILBMInfo structure with data from IFF file.
* Inputs: pointer to ILBMInfo, name
* Output: result
*======================================================================*/
int fillilbminfo(struct ILBMInfo *ii, char *name)
{
struct IFFHandle *iff;
int result=-1;

if (iff = AllocIFF()) {
result = openilbm(ii, iff, name);
FreeIFF(iff);
}
return result;
}

/*======================================================================*
* loadilbm: load IFF ILBM named name.
* Inputs: name
* Output: pointer to ILBMInfo
*======================================================================*/
struct ILBMInfo *loadilbm(char *name)
{
struct ILBMInfo *ii;

if (ii = AllocMem(sizeof(struct ILBMInfo), MEMF_PUBLIC|MEMF_CLEAR)) {
if (fillilbminfo(ii, name) == 0) {
return ii;
}
FreeMem(ii, sizeof(struct ILBMInfo));
}
return NULL;
}




Odpowiedz

AmigaOS.pl