From 3db8ee02ba24a3f95e24a02f79cd5c1396db34b3 Mon Sep 17 00:00:00 2001 From: Wei-ju Wu Date: Mon, 11 Jan 2016 16:14:55 -0800 Subject: [PATCH] ILBM lib enhancements convert interleaved to plane-by plane data, display in Intuition is changed to consider the imaga data width --- 30years/iffview/Makefile | 4 ++- 30years/iffview/filereq.c | 6 +++++ 30years/iffview/iffview.c | 22 ++++++++++++----- 30years/iffview/ilbm.c | 51 +++++++++++++++++++++++++++++++++++++++ 30years/iffview/ilbm.h | 1 + 5 files changed, 77 insertions(+), 7 deletions(-) diff --git a/30years/iffview/Makefile b/30years/iffview/Makefile index 5837919..dc824bb 100644 --- a/30years/iffview/Makefile +++ b/30years/iffview/Makefile @@ -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 diff --git a/30years/iffview/filereq.c b/30years/iffview/filereq.c index 558197a..74815eb 100644 --- a/30years/iffview/filereq.c +++ b/30years/iffview/filereq.c @@ -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 !!! diff --git a/30years/iffview/iffview.c b/30years/iffview/iffview.c index e05d467..3fc359b 100644 --- a/30years/iffview/iffview.c +++ b/30years/iffview/iffview.c @@ -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(); diff --git a/30years/iffview/ilbm.c b/30years/iffview/ilbm.c index 4a3e782..e5905be 100644 --- a/30years/iffview/ilbm.c +++ b/30years/iffview/ilbm.c @@ -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); } } diff --git a/30years/iffview/ilbm.h b/30years/iffview/ilbm.h index 20daa79..6b5629b 100644 --- a/30years/iffview/ilbm.h +++ b/30years/iffview/ilbm.h @@ -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__ */