// File: /workspace/github_c_makefile_star2_O3/enzo1982[P]smooth/classes/graphics/imageloader/png.cpp
// Function: smooth::GUI::ImageLoaderPNG::Load()
const S::GUI::Bitmap &S::GUI::ImageLoaderPNG::Load()
{
	/* Make sure bitmap is initialized.
	 */
	bitmap = NIL;

	/* Check if we either have a file or a buffer to load.
	 */
	if (!gotFileName && !gotBuffer) return bitmap;

	/* Create and initialize the png_struct with the desired error handler
	 * functions.  If you want to use the default stderr and longjump method,
	 * you can supply NULL for the last three parameters.  We also supply the
	 * the compiler header file version, so that we know if the application
	 * was compiled with a compatible version of the library.
	 */
	png_structp	 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NIL, &my_png_error, &my_png_warning);

	if (png_ptr == NULL) return bitmap;

	/* Allocate/initialize the memory for image information.
	 */
	png_infop	 info_ptr = png_create_info_struct(png_ptr);

	if (info_ptr == NULL)
	{
		png_destroy_read_struct(&png_ptr, NULL, NULL);

		return bitmap;
	}

	/* Create input stream for file or buffer.
	 */
	InStream	*in = NIL;

	if	(gotFileName) in = new InStream(STREAM_FILE, fileName, IS_READ);
	else if (gotBuffer)   in = new InStream(STREAM_BUFFER, buffer, buffer.Size());

	if (in->GetLastError() != IO_ERROR_OK || in->InputNumberRaw(8) != (Int64) 0x89504E470D0A1A0ALL)
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

		delete in;

		return bitmap;
	}

	in->Seek(0);

	/* If you are using replacement read functions, instead of calling
	 * png_init_io() here you would call:
	 */
	png_set_read_fn(png_ptr, (void *) in, &my_png_read);

	/* The call to png_read_info() gives us all of the information from the
	 * PNG file before the first IDAT (image data chunk).
	 */
	png_read_info(png_ptr, info_ptr);

	/* Tell libpng to strip 16 bit/color files down to 8 bits/color.
	 */
	png_set_strip_16(png_ptr);

	/* Get basic image information and create bitmap.
	 */
	png_uint_32	 width	    = 0;
	png_uint_32	 height	    = 0;
	int		 bit_depth  = 0;
	int		 color_type = 0;

	png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);

	bitmap.CreateBitmap(Size(width, height), (color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
						  color_type == PNG_COLOR_TYPE_GRAY_ALPHA) ? 32 : 24);

	/* Set background color if the image has an alpha
	 * channel but we only have a non-alpha bitmap.
	 */
	if ((color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
	     color_type == PNG_COLOR_TYPE_GRAY_ALPHA) && bitmap.GetDepth() != 32)
	{
		/* Set the background color to draw transparent and alpha images over.
		 * It is possible to set the red, green, and blue components directly
		 * for paletted images instead of supplying a palette index.
		 */
		png_color_16 my_background;

		my_background.red = Setup::BackgroundColor.GetRed();
		my_background.green = Setup::BackgroundColor.GetGreen();
		my_background.blue = Setup::BackgroundColor.GetBlue();

		png_set_background(png_ptr, &my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);

		if	(color_type == PNG_COLOR_TYPE_RGB_ALPHA)  color_type = PNG_COLOR_TYPE_RGB;
		else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) color_type = PNG_COLOR_TYPE_GRAY;
	}

	/* Get palette information.
	 */
	png_colorp	 palette     = NULL;
	int		 num_palette = 0;

	png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);

	/* The easiest way to read the image.
	 */
	png_bytep *row_pointers = (png_bytep *) malloc(height * sizeof(png_bytep));

	for (unsigned int row = 0; row < height; row++) row_pointers[row] = (png_bytep) malloc(png_get_rowbytes(png_ptr, info_ptr));

	/* Now it's time to read the image.
	 */
	png_read_image(png_ptr, row_pointers);

	for (UnsignedInt y = 0; y < height; y++)
	{
		for (UnsignedInt x = 0; x < width; x++)
		{
			if	(color_type == PNG_COLOR_TYPE_GRAY	 && bit_depth == 1) bitmap.SetPixel(Point(x, y), Color(row_pointers[y][x / 8] & (128 >> (x % 8)) ? 255 : 0, Color::GRAY));
			else if	(color_type == PNG_COLOR_TYPE_GRAY	 && bit_depth == 8) bitmap.SetPixel(Point(x, y), Color(					  row_pointers[y][    x	   ] << 16 | row_pointers[y][	 x    ] << 8 | row_pointers[y][	   x], Color::RGB));
			else if	(color_type == PNG_COLOR_TYPE_GRAY_ALPHA && bit_depth == 8) bitmap.SetPixel(Point(x, y), Color(row_pointers[y][2 * x + 1] << 24 | row_pointers[y][2 * x	   ] << 16 | row_pointers[y][2 * x    ] << 8 | row_pointers[y][2 * x], Color::RGBA));
			else if	(color_type == PNG_COLOR_TYPE_RGB	 && bit_depth == 8) bitmap.SetPixel(Point(x, y), Color(					  row_pointers[y][3 * x + 2] << 16 | row_pointers[y][3 * x + 1] << 8 | row_pointers[y][3 * x], Color::RGB));
			else if	(color_type == PNG_COLOR_TYPE_RGB_ALPHA	 && bit_depth == 8) bitmap.SetPixel(Point(x, y), Color(row_pointers[y][4 * x + 3] << 24 | row_pointers[y][4 * x + 2] << 16 | row_pointers[y][4 * x + 1] << 8 | row_pointers[y][4 * x], Color::RGBA));
			else if (color_type == PNG_COLOR_TYPE_PALETTE	 && bit_depth == 8) bitmap.SetPixel(Point(x, y), Color(palette[row_pointers[y][x]].red, palette[row_pointers[y][x]].green, palette[row_pointers[y][x]].blue, Color::RGB));
		}
	}

	/* Free PNG rows.
	 */
	for (unsigned int row = 0; row < height; row++) free(row_pointers[row]);

	free(row_pointers);

	/* Read rest of file, and get additional chunks in info_ptr.
	 */
	png_read_end(png_ptr, info_ptr);

	/* Clean up after the read, and free any memory allocated.
	 */
	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

	delete in;

	/* That's it.
	 */
	return bitmap;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x78, %rsp
movq %rdi, %r15
addq $0x40, %rdi
movq %rdi, 0x28(%rsp)
xorl %esi, %esi
callq 0x56740
cmpb $0x0, 0x38(%r15)
jne 0x627b1
cmpb $0x1, 0x39(%r15)
jne 0x629d3
leaq 0x90eba(%rip), %rdi     # 0xf3672
leaq -0x66(%rip), %rdx       # 0x62759
leaq -0x6c(%rip), %rcx       # 0x6275a
xorl %esi, %esi
callq 0x585a0
movq %rax, 0x48(%rsp)
testq %rax, %rax
je 0x629d3
movq %rax, %rdi
callq 0x58790
movq %rax, 0x50(%rsp)
testq %rax, %rax
je 0x6281c
cmpb $0x1, 0x38(%r15)
jne 0x6282f
movl $0x108, %edi            # imm = 0x108
callq 0x556b0
movq %rax, %r14
addq $0x8, %r15
movq %rax, %rdi
movl $0x3, %esi
movq %r15, %rdx
movl $0x2, %ecx
callq 0x58730
jmp 0x6285d
leaq 0x48(%rsp), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x561c0
jmp 0x629d3
movl $0x108, %edi            # imm = 0x108
callq 0x556b0
movq %rax, %r14
movq 0x28(%r15), %rax
testq %rax, %rax
je 0x6284a
movq (%rax), %rdx
jmp 0x6284c
xorl %edx, %edx
movslq 0x30(%r15), %rcx
movq %r14, %rdi
movl $0x5, %esi
callq 0x56590
cmpw $0x0, 0xf8(%r14)
jne 0x629b9
movq %r14, %rdi
movl $0x8, %esi
callq 0x55d40
movabsq $-0x76afb1b8f2f5e5f6, %rcx # imm = 0x89504E470D0A1A0A
cmpq %rcx, %rax
jne 0x629b9
movq (%r14), %rax
xorl %ebx, %ebx
movq %r14, %rdi
xorl %esi, %esi
callq *0x28(%rax)
movq 0x48(%rsp), %r12
leaq -0x14a(%rip), %rdx      # 0x6275b
movq %r12, %rdi
movq %r14, %rsi
callq 0x55cd0
movq 0x50(%rsp), %r13
movq %r12, %rdi
movq %r13, %rsi
callq 0x558c0
movq %r12, %rdi
callq 0x58900
leaq 0x58(%rsp), %rbp
movl %ebx, (%rbp)
leaq 0x24(%rsp), %r15
movl %ebx, (%r15)
leaq 0x5c(%rsp), %r8
movl %ebx, (%r8)
leaq 0x44(%rsp), %rax
movl %ebx, (%rax)
movq %rax, %rbx
xorps %xmm0, %xmm0
movups %xmm0, (%rsp)
movq $0x0, 0x10(%rsp)
movq %r12, %rdi
movq %r13, %rsi
movq %rbp, %rdx
movq %r15, %rcx
movq %rax, %r9
callq 0x58340
movl (%rbp), %eax
movl (%r15), %ecx
leaq 0x30(%rsp), %rsi
movl %eax, (%rsi)
movl %ecx, 0x4(%rsi)
movl (%rbx), %eax
andl $-0x3, %eax
xorl %ecx, %ecx
cmpl $0x4, %eax
sete %cl
leal 0x18(,%rcx,8), %edx
movq 0x28(%rsp), %rdi
callq 0x57c20
movl (%rbx), %eax
andl $-0x3, %eax
cmpl $0x4, %eax
jne 0x629ef
movq 0x28(%rsp), %rdi
callq 0x56c20
cmpb $0x20, %al
je 0x629ef
movq 0x108b6d(%rip), %rax    # 0x16b4d0
movl 0x8(%rax), %eax
movl $0xff, %ecx
movl %eax, %edx
andl %ecx, %edx
leaq 0x30(%rsp), %rsi
movw %dx, 0x2(%rsi)
movzbl %ah, %edx
movw %dx, 0x4(%rsi)
shrl $0x10, %eax
andl %ecx, %eax
movw %ax, 0x6(%rsi)
movq 0x48(%rsp), %rdi
movsd 0x909f3(%rip), %xmm0    # 0xf3388
movl $0x1, %edx
xorl %ecx, %ecx
callq 0x58b60
movl 0x44(%rsp), %eax
cmpl $0x4, %eax
je 0x629e7
cmpl $0x6, %eax
jne 0x629ef
movl $0x2, 0x44(%rsp)
jmp 0x629ef
leaq 0x48(%rsp), %rdi
leaq 0x50(%rsp), %rsi
xorl %edx, %edx
callq 0x561c0
movq (%r14), %rax
movq %r14, %rdi
callq *0x8(%rax)
movq 0x28(%rsp), %rax
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl $0x0, 0x44(%rsp)
leaq 0x68(%rsp), %rdx
movq $0x0, (%rdx)
leaq 0x74(%rsp), %rcx
movl $0x0, (%rcx)
movq 0x48(%rsp), %rdi
movq 0x50(%rsp), %rsi
callq 0x55c30
movl 0x24(%rsp), %ebx
leaq (,%rbx,8), %rdi
callq 0x57ff0
movq %rax, %r15
testq %rbx, %rbx
je 0x62a57
xorl %ebx, %ebx
movq 0x48(%rsp), %rdi
movq 0x50(%rsp), %rsi
callq 0x590e0
movq %rax, %rdi
callq 0x57ff0
movq %rax, (%r15,%rbx,8)
incq %rbx
movl 0x24(%rsp), %eax
cmpq %rax, %rbx
jb 0x62a30
movq 0x48(%rsp), %rdi
movq %r15, %rsi
callq 0x55d60
movl 0x24(%rsp), %ecx
testl %ecx, %ecx
je 0x62c9b
movq %r14, 0x60(%rsp)
movl 0x58(%rsp), %eax
xorl %r14d, %r14d
testl %eax, %eax
movl $0x0, %eax
je 0x62c6d
xorl %ebp, %ebp
movl $0x1, %r12d
movl $0x1, %r13d
xorl %ebx, %ebx
movl 0x44(%rsp), %eax
movl 0x5c(%rsp), %ecx
movl %ecx, %edx
xorl $0x1, %edx
orl %eax, %edx
jne 0x62aeb
movl %ebx, 0x1c(%rsp)
movl %r14d, 0x20(%rsp)
movq (%r15,%r14,8), %rax
movq %rbx, %rcx
shrq $0x3, %rcx
movzbl (%rax,%rcx), %eax
movl %ebx, %ecx
andb $0x7, %cl
shll %cl, %eax
testb %al, %al
movl $0xff, %eax
movl $0x0, %ecx
cmovnsq %rcx, %rax
movq %rax, 0x38(%rsp)
movl $0x6, 0x30(%rsp)
jmp 0x62bac
xorl $0x8, %ecx
movl %eax, %edx
orl %ecx, %edx
jne 0x62b1d
movl %ebx, 0x1c(%rsp)
movl %r14d, 0x20(%rsp)
movq (%r15,%r14,8), %rax
movzbl (%rax,%rbx), %eax
movl %eax, %ecx
shll $0x10, %ecx
movl %eax, %edx
shll $0x8, %edx
orl %ecx, %edx
orl %eax, %edx
movq %rdx, 0x38(%rsp)
jmp 0x62ba4
movl %eax, %edx
xorl $0x4, %edx
orl %ecx, %edx
jne 0x62b6a
movl %ebx, 0x1c(%rsp)
movl %r14d, 0x20(%rsp)
movq (%r15,%r14,8), %rax
leal -0x1(%r13), %ecx
movl %r13d, %edx
movzbl (%rax,%rdx), %edx
shll $0x18, %edx
movzbl (%rax,%rcx), %eax
movl %eax, %ecx
shll $0x10, %ecx
movl %eax, %esi
shll $0x8, %esi
movslq %edx, %rdx
orq %rcx, %rdx
orq %rsi, %rdx
orq %rax, %rdx
movq %rdx, 0x38(%rsp)
movl $0x1, 0x30(%rsp)
jmp 0x62bac
movl %eax, %edx
xorl $0x2, %edx
orl %ecx, %edx
jne 0x62be0
movl %ebx, 0x1c(%rsp)
movl %r14d, 0x20(%rsp)
movq (%r15,%r14,8), %rax
leal 0x2(%rbp), %ecx
movzbl (%rax,%rcx), %ecx
shll $0x10, %ecx
leal 0x1(%rbp), %edx
movzbl (%rax,%rdx), %edx
shll $0x8, %edx
orl %ecx, %edx
movl %ebp, %ecx
movzbl (%rax,%rcx), %eax
orq %rdx, %rax
movq %rax, 0x38(%rsp)
movl $0x0, 0x30(%rsp)
movq 0x28(%rsp), %rdi
leaq 0x1c(%rsp), %rsi
leaq 0x30(%rsp), %rdx
callq 0x56080
incq %rbx
movl 0x58(%rsp), %eax
addl $0x2, %r13d
addl $0x3, %ebp
addl $0x4, %r12d
cmpq %rax, %rbx
jb 0x62a99
jmp 0x62c69
movl %eax, %edx
xorl $0x6, %edx
orl %ecx, %edx
jne 0x62c37
movl %ebx, 0x1c(%rsp)
movl %r14d, 0x20(%rsp)
movq (%r15,%r14,8), %rax
leal -0x1(%r12), %ecx
leal 0x2(%r12), %edx
movzbl (%rax,%rdx), %edx
shll $0x18, %edx
leal 0x1(%r12), %esi
movzbl (%rax,%rsi), %esi
shll $0x10, %esi
movslq %edx, %rdx
orq %rsi, %rdx
movl %r12d, %esi
movzbl (%rax,%rsi), %esi
shll $0x8, %esi
orq %rdx, %rsi
movzbl (%rax,%rcx), %eax
orq %rsi, %rax
movq %rax, 0x38(%rsp)
jmp 0x62b60
xorl $0x3, %eax
orl %ecx, %eax
jne 0x62bc0
movl %ebx, 0x1c(%rsp)
movl %r14d, 0x20(%rsp)
movq 0x68(%rsp), %rax
movq (%r15,%r14,8), %rcx
movzbl (%rcx,%rbx), %ecx
leaq (%rcx,%rcx,2), %rcx
movzwl (%rax,%rcx), %edx
movzbl 0x2(%rax,%rcx), %eax
shll $0x10, %eax
jmp 0x62b9c
movl 0x24(%rsp), %ecx
incq %r14
movl %ecx, %edx
cmpq %rdx, %r14
jb 0x62a7c
testl %ecx, %ecx
movq 0x60(%rsp), %r14
je 0x62c9b
xorl %ebx, %ebx
movq (%r15,%rbx,8), %rdi
callq 0x55790
incq %rbx
movl 0x24(%rsp), %eax
cmpq %rax, %rbx
jb 0x62c86
movq %r15, %rdi
callq 0x55790
leaq 0x48(%rsp), %r15
movq (%r15), %rdi
leaq 0x50(%rsp), %r12
movq (%r12), %rsi
callq 0x56100
movq %r15, %rdi
movq %r12, %rsi
jmp 0x629c3
jmp 0x62cc6
movq %rax, %rbx
movl $0x108, %esi            # imm = 0x108
movq %r14, %rdi
callq 0x55480
movq %rbx, %rdi
callq 0x57090
nop