// File: /workspace/github_c_makefile_star2_O2/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 0x57880
cmpb $0x0, 0x38(%r15)
jne 0x633f7
cmpb $0x1, 0x39(%r15)
jne 0x6360d
leaq 0x8023c(%rip), %rdi     # 0xe363a
leaq -0x66(%rip), %rdx       # 0x6339f
leaq -0x6c(%rip), %rcx       # 0x633a0
xorl %esi, %esi
callq 0x59890
movq %rax, 0x48(%rsp)
testq %rax, %rax
je 0x6360d
movq %rax, %rdi
callq 0x59a90
movq %rax, 0x50(%rsp)
testq %rax, %rax
je 0x6345e
cmpb $0x1, 0x38(%r15)
jne 0x63471
movl $0x108, %edi            # imm = 0x108
callq 0x56700
movq %rax, %rbx
addq $0x8, %r15
pushq $0x3
popq %rsi
pushq $0x2
popq %rcx
movq %rax, %rdi
movq %r15, %rdx
callq 0x59a20
jmp 0x6349d
leaq 0x48(%rsp), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x572b0
jmp 0x6360d
movl $0x108, %edi            # imm = 0x108
callq 0x56700
movq %rax, %rbx
movq 0x28(%r15), %rax
testq %rax, %rax
je 0x6348c
movq (%rax), %rdx
jmp 0x6348e
xorl %edx, %edx
movslq 0x30(%r15), %rcx
pushq $0x5
popq %rsi
movq %rbx, %rdi
callq 0x576a0
cmpw $0x0, 0xf8(%rbx)
jne 0x635f3
pushq $0x8
popq %rsi
movq %rbx, %rdi
callq 0x56df0
movabsq $-0x76afb1b8f2f5e5f6, %rcx # imm = 0x89504E470D0A1A0A
cmpq %rcx, %rax
jne 0x635f3
movq (%rbx), %rax
movq %rbx, %rdi
xorl %esi, %esi
callq *0x28(%rax)
movq 0x48(%rsp), %r12
leaq -0x13f(%rip), %rdx      # 0x633a1
movq %r12, %rdi
movq %rbx, %rsi
callq 0x56d70
movq 0x50(%rsp), %r13
movq %r12, %rdi
movq %r13, %rsi
callq 0x56920
movq %r12, %rdi
callq 0x59c30
leaq 0x5c(%rsp), %rbp
andl $0x0, (%rbp)
leaq 0x44(%rsp), %r15
andl $0x0, (%r15)
leaq 0x58(%rsp), %r8
andl $0x0, (%r8)
leaq 0x40(%rsp), %r14
andl $0x0, (%r14)
xorps %xmm0, %xmm0
movups %xmm0, (%rsp)
andq $0x0, 0x10(%rsp)
movq %r12, %rdi
movq %r13, %rsi
movq %rbp, %rdx
movq %r15, %rcx
movq %r14, %r9
callq 0x595f0
movl (%rbp), %eax
movl (%r15), %ecx
leaq 0x30(%rsp), %rsi
movl %eax, (%rsi)
movl %ecx, 0x4(%rsi)
movl (%r14), %eax
andl $-0x3, %eax
xorl %ecx, %ecx
cmpl $0x4, %eax
sete %cl
leal 0x18(,%rcx,8), %edx
movq 0x28(%rsp), %rdi
callq 0x58ea0
movl (%r14), %eax
andl $-0x3, %eax
cmpl $0x4, %eax
jne 0x63626
movq 0x28(%rsp), %rdi
callq 0x57da0
cmpb $0x20, %al
je 0x63626
movq 0xfdf31(%rip), %rax     # 0x1614d0
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
pushq $0x1
popq %rdx
movsd 0x7fd9c(%rip), %xmm0    # 0xe3370
xorl %ecx, %ecx
callq 0x59ea0
movl 0x40(%rsp), %eax
cmpl $0x4, %eax
je 0x63621
cmpl $0x6, %eax
jne 0x63626
movl $0x2, 0x40(%rsp)
jmp 0x63626
leaq 0x48(%rsp), %rdi
leaq 0x50(%rsp), %rsi
xorl %edx, %edx
callq 0x572b0
movq (%rbx), %rax
movq %rbx, %rdi
callq *0x8(%rax)
movq 0x28(%rsp), %rax
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
andl $0x0, 0x40(%rsp)
movq %rbx, 0x60(%rsp)
leaq 0x68(%rsp), %rdx
andq $0x0, (%rdx)
leaq 0x74(%rsp), %rcx
andl $0x0, (%rcx)
movq 0x48(%rsp), %rdi
movq 0x50(%rsp), %rsi
callq 0x56cc0
movl 0x44(%rsp), %r14d
movq %r14, %rdi
shlq $0x3, %rdi
callq 0x59280
movq %rax, %r15
xorl %ebx, %ebx
movl %r14d, %eax
movq 0x48(%rsp), %rdi
cmpq %rax, %rbx
jae 0x6368e
movq 0x50(%rsp), %rsi
callq 0x5a460
movq %rax, %rdi
callq 0x59280
movq %rax, (%r15,%rbx,8)
incq %rbx
movl 0x44(%rsp), %r14d
jmp 0x63661
movq %r15, %rsi
callq 0x56e10
xorl %r14d, %r14d
movl 0x44(%rsp), %eax
cmpq %rax, %r14
jae 0x6388e
xorl %ebp, %ebp
pushq $0x1
popq %rax
movl %eax, %ebx
movl %eax, %r12d
xorl %r13d, %r13d
movl 0x5c(%rsp), %eax
cmpq %rax, %r13
jae 0x63886
movl 0x40(%rsp), %eax
movl 0x58(%rsp), %ecx
movl %ecx, %edx
xorl $0x1, %edx
orl %eax, %edx
jne 0x63714
movl %r13d, 0x20(%rsp)
movl %r14d, 0x24(%rsp)
movq (%r15,%r14,8), %rax
movq %r13, %rcx
shrq $0x3, %rcx
movzbl (%rax,%rcx), %eax
movl %r13d, %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 0x637d4
xorl $0x8, %ecx
movl %eax, %edx
orl %ecx, %edx
jne 0x63748
movl %r13d, 0x20(%rsp)
movl %r14d, 0x24(%rsp)
movq (%r15,%r14,8), %rax
movzbl (%rax,%r13), %eax
movl %eax, %ecx
shll $0x10, %ecx
movl %eax, %edx
shll $0x8, %edx
orl %ecx, %edx
orl %eax, %edx
movq %rdx, 0x38(%rsp)
jmp 0x637cf
movl %eax, %edx
xorl $0x4, %edx
orl %ecx, %edx
jne 0x63794
movl %r13d, 0x20(%rsp)
movl %r14d, 0x24(%rsp)
movq (%r15,%r14,8), %rax
leal -0x1(%rbx), %ecx
movl %ebx, %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 0x637d4
movl %eax, %edx
xorl $0x2, %edx
orl %ecx, %edx
jne 0x637fa
movl %r13d, 0x20(%rsp)
movl %r14d, 0x24(%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)
andl $0x0, 0x30(%rsp)
movq 0x28(%rsp), %rdi
leaq 0x20(%rsp), %rsi
leaq 0x30(%rsp), %rdx
callq 0x57160
incq %r13
addl $0x4, %r12d
addl $0x3, %ebp
addl $0x2, %ebx
jmp 0x636b3
movl %eax, %edx
xorl $0x6, %edx
orl %ecx, %edx
jne 0x63852
movl %r13d, 0x20(%rsp)
movl %r14d, 0x24(%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 0x6378a
xorl $0x3, %eax
orl %ecx, %eax
jne 0x637e8
movl %r13d, 0x20(%rsp)
movl %r14d, 0x24(%rsp)
movq 0x68(%rsp), %rax
movq (%r15,%r14,8), %rcx
movzbl (%rcx,%r13), %ecx
leaq (%rcx,%rcx,2), %rcx
movzwl (%rax,%rcx), %edx
movzbl 0x2(%rax,%rcx), %eax
shll $0x10, %eax
jmp 0x637c7
incq %r14
jmp 0x63699
xorl %ebx, %ebx
movq 0x60(%rsp), %r14
movl %eax, %eax
cmpq %rax, %rbx
jae 0x638ae
movq (%r15,%rbx,8), %rdi
callq 0x567f0
incq %rbx
movl 0x44(%rsp), %eax
jmp 0x63895
movq %r15, %rdi
callq 0x567f0
leaq 0x48(%rsp), %r15
movq (%r15), %rdi
leaq 0x50(%rsp), %r12
movq (%r12), %rsi
callq 0x571e0
movq %r15, %rdi
movq %r12, %rsi
xorl %edx, %edx
callq 0x572b0
movq (%r14), %rax
movq %r14, %rdi
jmp 0x6360a
jmp 0x638e6
movq %rbx, %rdi
movq %rax, %rbx
movl $0x108, %esi            # imm = 0x108
callq 0x564c0
movq %rbx, %rdi
callq 0x58260
nop