// File: /workspace/github_c_makefile_star2_O0/jsummers[P]deark/modules/ilbm.c
// Function: write_frame
static void write_frame(deark *c, lctx *d, struct imgbody_info *ibi, struct frame_ctx *frctx)
{
	de_bitmap *img = NULL;
	i64 j;
	u32 *rowbuf = NULL; // The current row of pixel (palette or RGB) values
	u8 *rowbuf_trns = NULL; // The current row's 1-bit transparency mask values
	UI rowbuf_size;
	int bypp;
	de_finfo *fi = NULL;
	UI createflags = 0;
	u32 pixelval[8];
	u8 pixeltrnsval[8];

	if(d->errflag) goto done;
	if(!frctx) goto done;
	if(!frctx->frame_buffer) {
		d->errflag = 1;
		goto done;
	}
	if(ibi->colortype==COLORTYPE_RGB24) {
		if(ibi->planes_fg!=24) goto done;
	}
	else if(ibi->planes_fg<1 || ibi->planes_fg>8) {
		goto done;
	}

	if(d->debug_frame_buffer) {
		de_finfo *fi_fb;

		fi_fb = de_finfo_create(c);
		de_finfo_set_name_from_sz(c, fi_fb, "fb", 0, DE_ENCODING_LATIN1);
		de_convert_and_write_image_bilevel(frctx->frame_buffer, 0,
			ibi->bits_per_row_per_plane * ibi->planes_total,
			ibi->height, ibi->frame_buffer_rowspan, 0, fi_fb, 0);
		de_finfo_destroy(c, fi_fb);
	}

	rowbuf_size = (UI)ibi->width;
	rowbuf = de_mallocarray(c, rowbuf_size, sizeof(rowbuf[0]));
	rowbuf_trns = de_mallocarray(c, rowbuf_size, sizeof(rowbuf_trns[0]));

	if(ibi->is_rgb24) {
		bypp = 3;
	}
	else if(d->found_cmap && d->pal_is_grayscale && d->planes_raw<=8 && !d->is_ham6 && !d->is_ham8) {
		bypp = 1;
	}
	else {
		bypp = 3;
	}

	if(ibi->use_colorkey_transparency || ibi->masking_code==MASKINGTYPE_1BITMASK) {
		bypp++;
	}

	img = de_bitmap_create(c, ibi->width, ibi->height, bypp);

	if(ibi->is_pbm) {
		de_convert_image_paletted(frctx->frame_buffer, 0, 8, ibi->frame_buffer_rowspan,
			d->pal, img, 0);
		goto after_render;
	}
	else if(ibi->is_rgb24) {
		de_convert_image_rgb(frctx->frame_buffer, 0, ibi->bytes_per_row_per_plane, 3,
			img, 0);
		goto after_render;
	}

	for(j=0; j<ibi->height; j++) {
		i64 z;
		i64 plane;
		UI k;

		// Process 8 pixels at a time
		for(z=0; z<ibi->bytes_per_row_per_plane; z++) {
			de_zeromem(pixelval, sizeof(pixelval));
			de_zeromem(pixeltrnsval, sizeof(pixeltrnsval));

			// Read the zth byte in each plane
			for(plane=0; plane<ibi->planes_total; plane++) {
				u8 b;

				b = dbuf_getbyte(frctx->frame_buffer,
					j*ibi->frame_buffer_rowspan +
					plane*ibi->bytes_per_row_per_plane + z);

				for(k=0; k<8; k++) {
					if(b & (1U<<(7-k))) {
						if(plane < ibi->planes_fg) {
							pixelval[k] |= 1U<<(UI)plane;
						}
						else {
							// The only way this can happen is if this plane is a
							// 1-bit transparency mask.
							pixeltrnsval[k] = 1;
						}
					}
				}
			}

			for(k=0; k<8; k++) {
				UI idx;

				idx = (UI)z*8+k;
				if(idx < rowbuf_size) {
					rowbuf[idx] = pixelval[k];
					rowbuf_trns[idx] = pixeltrnsval[k];
				}
			}
		}

		if(ibi->colortype==COLORTYPE_RGB24) {
			render_pixel_row_rgb24(c, d, ibi, j, rowbuf, rowbuf_size, img);
		}
		else if(d->is_ham6) {
			render_pixel_row_ham6(c, d, j, rowbuf, rowbuf_size, img);
		}
		else if(d->is_ham8) {
			render_pixel_row_ham8(c, d, j, rowbuf, rowbuf_size, img);
		}
		else {
			render_pixel_row_normal(c, d, ibi, j, rowbuf, rowbuf_size, img);
		}

		// Handle 1-bit transparency masks here, for all color types.
		if(ibi->masking_code==MASKINGTYPE_1BITMASK) {
			i64 i;

			for(i=0; i<rowbuf_size; i++) {
				u32 clr;

				if(rowbuf_trns[i]==0) {
					clr = de_bitmap_getpixel(img, i, j);
					clr = DE_SET_ALPHA(clr, 0);
					de_bitmap_setpixel_rgba(img, i, j, clr);
				}
			}
		}
	}

after_render:
	if(d->trans_setting==TRANS_AUTO) {
		if(ibi->masking_code==MASKINGTYPE_1BITMASK) {
			de_bitmap_optimize_alpha(img, 0x2|0x4);
		}
	}
	else if(d->trans_setting==TRANS_REMOVE) {
		de_bitmap_remove_alpha(img);
	}

	fi = de_finfo_create(c);
	set_finfo_data(c, d, ibi, fi);
	if(ibi->is_thumb) {
		createflags |= DE_CREATEFLAG_IS_AUX;
	}
	if(!d->is_anim) {
		// TODO: Enable this for ANIM?
		createflags |= DE_CREATEFLAG_OPT_IMAGE;
	}

	de_bitmap_write_to_file_finfo(img, fi, createflags);

done:
	de_bitmap_destroy(img);
	de_finfo_destroy(c, fi);
	de_free(c, rowbuf);
	de_free(c, rowbuf_trns);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xd0, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq $0x0, -0x28(%rbp)
movq $0x0, -0x38(%rbp)
movq $0x0, -0x40(%rbp)
movq $0x0, -0x50(%rbp)
movl $0x0, -0x54(%rbp)
movq -0x10(%rbp), %rax
cmpl $0x0, 0x1c(%rax)
je 0xb3011
jmp 0xb3642
cmpq $0x0, -0x20(%rbp)
jne 0xb301d
jmp 0xb3642
movq -0x20(%rbp), %rax
cmpq $0x0, 0x20(%rax)
jne 0xb3038
movq -0x10(%rbp), %rax
movl $0x1, 0x1c(%rax)
jmp 0xb3642
movq -0x18(%rbp), %rax
cmpl $0x1, 0x58(%rax)
jne 0xb3054
movq -0x18(%rbp), %rax
cmpq $0x18, 0x10(%rax)
je 0xb3052
jmp 0xb3642
jmp 0xb3071
movq -0x18(%rbp), %rax
cmpq $0x1, 0x10(%rax)
jl 0xb306a
movq -0x18(%rbp), %rax
cmpq $0x8, 0x10(%rax)
jle 0xb306f
jmp 0xb3642
jmp 0xb3071
movq -0x10(%rbp), %rax
cmpl $0x0, 0x28(%rax)
je 0xb3104
movq -0x8(%rbp), %rdi
callq 0x15d230
movq %rax, -0x90(%rbp)
movq -0x8(%rbp), %rdi
movq -0x90(%rbp), %rsi
leaq 0xf2414(%rip), %rdx     # 0x1a54b5
xorl %ecx, %ecx
movl $0x5, %r8d
callq 0x15d4c0
movq -0x20(%rbp), %rax
movq 0x20(%rax), %rdi
movq -0x18(%rbp), %rax
movq 0x38(%rax), %rdx
movq -0x18(%rbp), %rax
imulq 0x18(%rax), %rdx
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rcx
movq -0x18(%rbp), %rax
movq 0x48(%rax), %r8
movq -0x90(%rbp), %rax
xorl %esi, %esi
xorl %r9d, %r9d
movq %rax, (%rsp)
movl $0x0, 0x8(%rsp)
callq 0x16bf50
movq -0x8(%rbp), %rdi
movq -0x90(%rbp), %rsi
callq 0x15d260
movq -0x18(%rbp), %rax
movq (%rax), %rax
movl %eax, -0x44(%rbp)
movq -0x8(%rbp), %rdi
movl -0x44(%rbp), %eax
movl %eax, %esi
movl $0x4, %edx
callq 0x15c450
movq %rax, -0x38(%rbp)
movq -0x8(%rbp), %rdi
movl -0x44(%rbp), %eax
movl %eax, %esi
movl $0x1, %edx
callq 0x15c450
movq %rax, -0x40(%rbp)
movq -0x18(%rbp), %rax
cmpb $0x0, 0x61(%rax)
je 0xb314f
movl $0x3, -0x48(%rbp)
jmp 0xb319a
movq -0x10(%rbp), %rax
movzbl 0x33(%rax), %eax
cmpl $0x0, %eax
je 0xb3191
movq -0x10(%rbp), %rax
cmpl $0x0, 0xd0(%rax)
je 0xb3191
movq -0x10(%rbp), %rax
cmpq $0x8, 0x60(%rax)
jg 0xb3191
movq -0x10(%rbp), %rax
cmpb $0x0, 0x39(%rax)
jne 0xb3191
movq -0x10(%rbp), %rax
cmpb $0x0, 0x3a(%rax)
jne 0xb3191
movl $0x1, -0x48(%rbp)
jmp 0xb3198
movl $0x3, -0x48(%rbp)
jmp 0xb319a
movq -0x18(%rbp), %rax
movzbl 0x22(%rax), %eax
cmpl $0x0, %eax
jne 0xb31b4
movq -0x18(%rbp), %rax
movzbl 0x21(%rax), %eax
cmpl $0x1, %eax
jne 0xb31bd
movl -0x48(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x48(%rbp)
movq -0x8(%rbp), %rdi
movq -0x18(%rbp), %rax
movq (%rax), %rsi
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rdx
movl -0x48(%rbp), %ecx
callq 0x16b750
movq %rax, -0x28(%rbp)
movq -0x18(%rbp), %rax
cmpb $0x0, 0x60(%rax)
je 0xb3221
movq -0x20(%rbp), %rax
movq 0x20(%rax), %rdi
movq -0x18(%rbp), %rax
movq 0x48(%rax), %rcx
movq -0x10(%rbp), %r8
addq $0x4d4, %r8             # imm = 0x4D4
movq -0x28(%rbp), %r9
xorl %eax, %eax
movl %eax, %esi
movl $0x8, %edx
xorl %eax, %eax
movl $0x0, (%rsp)
callq 0x16c520
jmp 0xb35a9
movq -0x18(%rbp), %rax
cmpb $0x0, 0x61(%rax)
je 0xb3255
movq -0x20(%rbp), %rax
movq 0x20(%rax), %rdi
movq -0x18(%rbp), %rax
movq 0x40(%rax), %rdx
movq -0x28(%rbp), %r8
xorl %eax, %eax
movl %eax, %esi
movl $0x3, %ecx
xorl %r9d, %r9d
callq 0x16c8b0
jmp 0xb35a9
jmp 0xb3257
movq $0x0, -0x30(%rbp)
movq -0x30(%rbp), %rax
movq -0x18(%rbp), %rcx
cmpq 0x8(%rcx), %rax
jge 0xb35a7
movq $0x0, -0x98(%rbp)
movq -0x98(%rbp), %rax
movq -0x18(%rbp), %rcx
cmpq 0x40(%rcx), %rax
jge 0xb3446
leaq -0x80(%rbp), %rdi
xorl %esi, %esi
movl $0x20, %edx
callq 0x19140
leaq -0x88(%rbp), %rdi
xorl %esi, %esi
movl $0x8, %edx
callq 0x19140
movq $0x0, -0xa0(%rbp)
movq -0xa0(%rbp), %rax
movq -0x18(%rbp), %rcx
cmpq 0x18(%rcx), %rax
jge 0xb33b5
movq -0x20(%rbp), %rax
movq 0x20(%rax), %rdi
movq -0x30(%rbp), %rsi
movq -0x18(%rbp), %rax
imulq 0x48(%rax), %rsi
movq -0xa0(%rbp), %rax
movq -0x18(%rbp), %rcx
imulq 0x40(%rcx), %rax
addq %rax, %rsi
addq -0x98(%rbp), %rsi
callq 0x165060
movb %al, -0xa5(%rbp)
movl $0x0, -0xa4(%rbp)
cmpl $0x8, -0xa4(%rbp)
jae 0xb339c
movzbl -0xa5(%rbp), %eax
movl $0x7, %ecx
subl -0xa4(%rbp), %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
andl %ecx, %eax
cmpl $0x0, %eax
je 0xb3386
movq -0xa0(%rbp), %rax
movq -0x18(%rbp), %rcx
cmpq 0x10(%rcx), %rax
jge 0xb3376
movq -0xa0(%rbp), %rax
movl %eax, %ecx
movl $0x1, %eax
shll %cl, %eax
movl %eax, %ecx
movl -0xa4(%rbp), %eax
orl -0x80(%rbp,%rax,4), %ecx
movl %ecx, -0x80(%rbp,%rax,4)
jmp 0xb3384
movl -0xa4(%rbp), %eax
movb $0x1, -0x88(%rbp,%rax)
jmp 0xb3386
jmp 0xb3388
movl -0xa4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa4(%rbp)
jmp 0xb3318
jmp 0xb339e
movq -0xa0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xa0(%rbp)
jmp 0xb32bf
movl $0x0, -0xa4(%rbp)
cmpl $0x8, -0xa4(%rbp)
jae 0xb342d
movq -0x98(%rbp), %rax
shll $0x3, %eax
addl -0xa4(%rbp), %eax
movl %eax, -0xac(%rbp)
movl -0xac(%rbp), %eax
cmpl -0x44(%rbp), %eax
jae 0xb341a
movl -0xa4(%rbp), %eax
movl -0x80(%rbp,%rax,4), %edx
movq -0x38(%rbp), %rax
movl -0xac(%rbp), %ecx
movl %edx, (%rax,%rcx,4)
movl -0xa4(%rbp), %eax
movb -0x88(%rbp,%rax), %dl
movq -0x40(%rbp), %rax
movl -0xac(%rbp), %ecx
movb %dl, (%rax,%rcx)
jmp 0xb341c
movl -0xa4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa4(%rbp)
jmp 0xb33bf
jmp 0xb342f
movq -0x98(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x98(%rbp)
jmp 0xb327c
movq -0x18(%rbp), %rax
cmpl $0x1, 0x58(%rax)
jne 0xb3477
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
movq -0x30(%rbp), %rcx
movq -0x38(%rbp), %r8
movl -0x44(%rbp), %r9d
movq -0x28(%rbp), %rax
movq %rax, (%rsp)
callq 0xb3ec0
jmp 0xb34f2
movq -0x10(%rbp), %rax
cmpb $0x0, 0x39(%rax)
je 0xb34a0
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x30(%rbp), %rdx
movq -0x38(%rbp), %rcx
movl -0x44(%rbp), %r8d
movq -0x28(%rbp), %r9
callq 0xb3f70
jmp 0xb34f0
movq -0x10(%rbp), %rax
cmpb $0x0, 0x3a(%rax)
je 0xb34c9
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x30(%rbp), %rdx
movq -0x38(%rbp), %rcx
movl -0x44(%rbp), %r8d
movq -0x28(%rbp), %r9
callq 0xb40c0
jmp 0xb34ee
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
movq -0x30(%rbp), %rcx
movq -0x38(%rbp), %r8
movl -0x44(%rbp), %r9d
movq -0x28(%rbp), %rax
movq %rax, (%rsp)
callq 0xb4230
jmp 0xb34f0
jmp 0xb34f2
movq -0x18(%rbp), %rax
movzbl 0x21(%rax), %eax
cmpl $0x1, %eax
jne 0xb3594
movq $0x0, -0xb8(%rbp)
movq -0xb8(%rbp), %rax
movl -0x44(%rbp), %ecx
cmpq %rcx, %rax
jge 0xb3592
movq -0x40(%rbp), %rax
movq -0xb8(%rbp), %rcx
movzbl (%rax,%rcx), %eax
cmpl $0x0, %eax
jne 0xb3579
movq -0x28(%rbp), %rdi
movq -0xb8(%rbp), %rsi
movq -0x30(%rbp), %rdx
callq 0x16b540
movl %eax, -0xbc(%rbp)
movl -0xbc(%rbp), %eax
andl $0xffffff, %eax         # imm = 0xFFFFFF
orl $0x0, %eax
movl %eax, -0xbc(%rbp)
movq -0x28(%rbp), %rdi
movq -0xb8(%rbp), %rsi
movq -0x30(%rbp), %rdx
movl -0xbc(%rbp), %ecx
callq 0x16b350
jmp 0xb357b
movq -0xb8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xb8(%rbp)
jmp 0xb350e
jmp 0xb3594
jmp 0xb3596
movq -0x30(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x30(%rbp)
jmp 0xb325f
jmp 0xb35a9
movq -0x10(%rbp), %rax
movzbl 0x2c(%rax), %eax
cmpl $0x2, %eax
jne 0xb35d3
movq -0x18(%rbp), %rax
movzbl 0x21(%rax), %eax
cmpl $0x1, %eax
jne 0xb35d1
movq -0x28(%rbp), %rdi
movl $0x6, %esi
callq 0x16d190
jmp 0xb35eb
movq -0x10(%rbp), %rax
movzbl 0x2c(%rax), %eax
cmpl $0x0, %eax
jne 0xb35e9
movq -0x28(%rbp), %rdi
callq 0x16d070
jmp 0xb35eb
movq -0x8(%rbp), %rdi
callq 0x15d230
movq %rax, -0x50(%rbp)
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
movq -0x50(%rbp), %rcx
callq 0xb42b0
movq -0x18(%rbp), %rax
cmpl $0x0, 0x5c(%rax)
je 0xb3620
movl -0x54(%rbp), %eax
orl $0x1, %eax
movl %eax, -0x54(%rbp)
movq -0x10(%rbp), %rax
cmpl $0x0, (%rax)
jne 0xb3632
movl -0x54(%rbp), %eax
orl $0x2, %eax
movl %eax, -0x54(%rbp)
movq -0x28(%rbp), %rdi
movq -0x50(%rbp), %rsi
movl -0x54(%rbp), %edx
callq 0x16afa0
movq -0x28(%rbp), %rdi
callq 0x16af60
movq -0x8(%rbp), %rdi
movq -0x50(%rbp), %rsi
callq 0x15d260
movq -0x8(%rbp), %rdi
movq -0x38(%rbp), %rsi
callq 0x15b820
movq -0x8(%rbp), %rdi
movq -0x40(%rbp), %rsi
callq 0x15b820
addq $0xd0, %rsp
popq %rbp
retq
nopl (%rax,%rax)