mirror of
https://github.com/weiju/amiga-stuff
synced 2026-09-11 19:26:01 +00:00
ILBM lib enhancements
convert interleaved to plane-by plane data, display in Intuition is changed to consider the imaga data width
This commit is contained in:
@@ -11,5 +11,7 @@ iffview: iffview.o ilbm.o filereq.o
|
||||
$(CC) $(CFLAGS) $^ -lamiga -lauto -o $@
|
||||
|
||||
# Mostly for testing
|
||||
# interestingly, when defining std=c99, LITTLE_ENDIAN disappears as a definition
|
||||
# in gcc, so we define it explicitly
|
||||
ilbm: ilbm.c
|
||||
gcc -o $@ $< -DSTANDALONE -DDEBUG
|
||||
gcc -o $@ $< -DSTANDALONE -DDEBUG -std=c99 -DLITTLE_ENDIAN
|
||||
|
||||
@@ -100,6 +100,12 @@ struct Requester *open_file(struct Window *window)
|
||||
requester.ReqText = &labels[0];
|
||||
|
||||
/* scan current directory */
|
||||
/*
|
||||
on AmigaOS versions before 36 (essentially all 1.x versions), the
|
||||
function GetCurrentDirName() does not exist, but it's obtainable
|
||||
by calling Cli() and querying the returned CommandLineInterface
|
||||
structure
|
||||
*/
|
||||
puts("scanning directory...");
|
||||
/*
|
||||
// on AmigaOS 1.x, this function does not exist !!!
|
||||
|
||||
@@ -172,22 +172,32 @@ void setup_menu()
|
||||
|
||||
struct Image image = { 0, 0, 0, 0, 0, NULL, 0, 0, NULL};
|
||||
|
||||
/* Defined automatically in VBCC */
|
||||
extern struct Library *DOSBase;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
/* version: e.g. 34, revision e.g. 3 for Kickstart 1.3 */
|
||||
printf("DOS, version: %d, revision: %d\n",
|
||||
(int) DOSBase->lib_Version, (int) DOSBase->lib_Revision);
|
||||
ILBMData *ilbm_data = NULL;
|
||||
if (window = OpenWindow(&newwin)) {
|
||||
int wordwidth, finalsize;
|
||||
setup_menu();
|
||||
ilbm_data = parse_file("examples/Kickstart13.iff");
|
||||
image.Width = ilbm_data->bmheader->w;
|
||||
image.Height = ilbm_data->bmheader->h;
|
||||
image.Depth = ilbm_data->bmheader->nPlanes;
|
||||
wordwidth = (image.Width + 16) / 16;
|
||||
finalsize = wordwidth * image.Height * image.Depth * sizeof(UWORD);
|
||||
image.ImageData = AllocMem(finalsize, MEMF_CHIP);
|
||||
printf("loaded size: %d, final size: %d\n", ilbm_data->data_bytes, finalsize);
|
||||
memcpy(image.ImageData, ilbm_data->imgdata, ilbm_data->data_bytes);
|
||||
int wordwidth = (image.Width + 16) / 16;
|
||||
int finalsize = wordwidth * image.Height * image.Depth * sizeof(UWORD);
|
||||
image.ImageData = AllocMem(finalsize, MEMF_CHIP|MEMF_CLEAR);
|
||||
ilbm_to_image_data((char *) image.ImageData, ilbm_data, wordwidth * 16, image.Height);
|
||||
image.PlanePick = (1 << image.Depth) - 1;
|
||||
/*
|
||||
Note that the image width is now set to the data's image width.
|
||||
Displayed correctly now.
|
||||
*/
|
||||
image.Width = wordwidth * 16;
|
||||
|
||||
// Note: rastport is the entire window, including title bars
|
||||
DrawImage(window->RPort, &image, 5, 10);
|
||||
handle_events();
|
||||
|
||||
@@ -196,8 +196,10 @@ ILBMData *parse_file(const char *path)
|
||||
if (!strncmp("FORM", buffer, 4)) {
|
||||
|
||||
#ifdef LITTLE_ENDIAN
|
||||
puts("little endian");
|
||||
filesize = __bswap_32(*((ULONG *) &buffer[4])) + CHUNK_HEADER_SIZE;
|
||||
#else
|
||||
puts("big endian");
|
||||
filesize = *((ULONG *) &buffer[4]) + CHUNK_HEADER_SIZE;
|
||||
#endif
|
||||
|
||||
@@ -235,6 +237,46 @@ void print_ilbm_info(ILBMData *data)
|
||||
data->num_colors);
|
||||
}
|
||||
|
||||
/*
|
||||
* ILBM interleaved bit maps -> Intuition Image data
|
||||
* ILBM is interleaved
|
||||
* - plane 0/row 0 -> plane 1/row 0 -> ... plane 0/row 1 -> plane 1/row 1 ->...
|
||||
* - rows are multiples of 8
|
||||
*
|
||||
* but Intuition Image expects its data
|
||||
* - plane-by-plane
|
||||
* - as a multiple of 16
|
||||
*/
|
||||
void ilbm_to_image_data(char *dest, ILBMData *data, int dest_width, int dest_height)
|
||||
{
|
||||
if (data->bmheader->w % 8 != 0) {
|
||||
puts("ERROR: source width must be multiple of 8");
|
||||
return;
|
||||
}
|
||||
if (dest_width % 16 != 0) {
|
||||
puts("ERROR: destination width must be multiple of 16");
|
||||
return;
|
||||
}
|
||||
if (dest_width < data->bmheader->w || dest_height < data->bmheader->h) {
|
||||
puts("ERROR: destination dimensions are smaller than source");
|
||||
return;
|
||||
}
|
||||
int src_bytes_per_row = data->bmheader->w / 8;
|
||||
int dest_bytes_per_row = dest_width / 8;
|
||||
char *src_ptr = data->imgdata;
|
||||
int src_offset, img_height = data->bmheader->h, num_planes = data->bmheader->nPlanes;
|
||||
int row_data_size = num_planes * src_bytes_per_row;
|
||||
|
||||
for (int plane = 0; plane < num_planes; plane++) {
|
||||
// copy row-by-row
|
||||
for (int row = 0; row < img_height; row++) {
|
||||
src_offset = (row * row_data_size) + (plane * src_bytes_per_row);
|
||||
memcpy(dest, src_ptr + src_offset, src_bytes_per_row);
|
||||
dest += dest_bytes_per_row;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef STANDALONE
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
@@ -243,6 +285,15 @@ int main(int argc, char **argv)
|
||||
} else {
|
||||
ILBMData *data = parse_file(argv[1]);
|
||||
print_ilbm_info(data);
|
||||
|
||||
int wordwidth = (data->bmheader->w + 16) / 16;
|
||||
int destWidth = wordwidth * 16;
|
||||
int destHeight = data->bmheader->h;
|
||||
int finalsize = wordwidth * data->bmheader->h * data->bmheader->nPlanes * 2;
|
||||
printf("loaded size: %d, final size: %d\n", data->data_bytes, finalsize);
|
||||
char *dest = calloc(finalsize, sizeof(char));
|
||||
ilbm_to_image_data(dest, data, destWidth, destHeight);
|
||||
free(dest);
|
||||
free_ilbm_data(data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,4 +89,5 @@ typedef struct _ILBMData {
|
||||
|
||||
extern ILBMData *parse_file(const char *path);
|
||||
extern void free_ilbm_data(ILBMData *data);
|
||||
extern void ilbm_to_image_data(char *dest, ILBMData *data, int dest_width, int dest_height);
|
||||
#endif /* __ILBM_H__ */
|
||||
|
||||
Reference in New Issue
Block a user