// Generated by Sichem at 12/24/2021 8:28:15 PM

using Hebron.Runtime;

namespace StbImageBeef
{
	extension StbImage
	{
		public static int32 stbi__psd_decode_rle(stbi__context s, uint8 *pInput, int32 pixelCount)
		{
			var p = pInput;
			int32 count = 0;
			int32 nleft = 0;
			int32 len = 0;
			count = 0;
			while ((nleft = pixelCount - count) > 0)
			{
				len = stbi__get8(s);
				if (len == 128)
				{
				}
				else if (len < 128)
				{
					len++;
					if (len > nleft)
						return 0;
					count += len;
					while (len != 0)
					{
						*p = stbi__get8(s);
						p += 4;
						len--;
					}
				}
				else if (len > 128)
				{
					uint8 val = 0;
					len = 257 - len;
					if (len > nleft)
						return 0;
					val = stbi__get8(s);
					count += len;
					while (len != 0)
					{
						*p = val;
						p += 4;
						len--;
					}
				}
			}

			return 1;
		}

		public static int32 stbi__psd_info(stbi__context s, int32* xInput, int32* yInput, int32* compInput)
		{
			int32 *x = xInput;
			int32 *y = yInput;
			int32 *comp = compInput;
			int32 channelCount = 0;
			int32 dummy = 0;
			int32 depth = 0;
			if (x == null)
				x = &dummy;
			if (y == null)
				y = &dummy;
			if (comp == null)
				comp = &dummy;
			if (stbi__get32be(s) != 0x38425053)
			{
				stbi__rewind(s);
				return 0;
			}

			if (stbi__get16be(s) != 1)
			{
				stbi__rewind(s);
				return 0;
			}

			stbi__skip(s, 6);
			channelCount = stbi__get16be(s);
			if (channelCount < 0 || channelCount > 16)
			{
				stbi__rewind(s);
				return 0;
			}

			*y = (int32)stbi__get32be(s);
			*x = (int32)stbi__get32be(s);
			depth = stbi__get16be(s);
			if (depth != 8 && depth != 16)
			{
				stbi__rewind(s);
				return 0;
			}

			if (stbi__get16be(s) != 3)
			{
				stbi__rewind(s);
				return 0;
			}

			*comp = 4;
			return 1;
		}

		public static int32 stbi__psd_is16(stbi__context s)
		{
			int32 channelCount = 0;
			int32 depth = 0;
			if (stbi__get32be(s) != 0x38425053)
			{
				stbi__rewind(s);
				return 0;
			}

			if (stbi__get16be(s) != 1)
			{
				stbi__rewind(s);
				return 0;
			}

			stbi__skip(s, 6);
			channelCount = stbi__get16be(s);
			if (channelCount < 0 || channelCount > 16)
			{
				stbi__rewind(s);
				return 0;
			}

			depth = stbi__get16be(s);
			if (depth != 16)
			{
				stbi__rewind(s);
				return 0;
			}

			return 1;
		}

		public static void* stbi__psd_load(stbi__context s, int32* x, int32* y, int32* comp, int32 req_comp,
			stbi__result_info* ri, int32 bpc)
		{
			int32 pixelCount = 0;
			int32 channelCount = 0;
			int32 compression = 0;
			int32 channel = 0;
			int32 i = 0;
			int32 bitdepth = 0;
			int32 w = 0;
			int32 h = 0;
			uint8* _out_;
			if (stbi__get32be(s) != 0x38425053)
				return (uint8*)(stbi__err("not PSD") != 0 ? null : null);
			if (stbi__get16be(s) != 1)
				return (uint8*)(stbi__err("wrong version") != 0 ? null : null);
			stbi__skip(s, 6);
			channelCount = stbi__get16be(s);
			if (channelCount < 0 || channelCount > 16)
				return (uint8*)(stbi__err("wrong channel count") != 0 ? null : null);
			h = (int32)stbi__get32be(s);
			w = (int32)stbi__get32be(s);
			if (h > 1 << 24)
				return (uint8*)(stbi__err("too large") != 0 ? null : null);
			if (w > 1 << 24)
				return (uint8*)(stbi__err("too large") != 0 ? null : null);
			bitdepth = stbi__get16be(s);
			if (bitdepth != 8 && bitdepth != 16)
				return (uint8*)(stbi__err("unsupported bit depth") != 0 ? null : null);
			if (stbi__get16be(s) != 3)
				return (uint8*)(stbi__err("wrong color format") != 0 ? null : null);
			stbi__skip(s, (int32)stbi__get32be(s));
			stbi__skip(s, (int32)stbi__get32be(s));
			stbi__skip(s, (int32)stbi__get32be(s));
			compression = stbi__get16be(s);
			if (compression > 1)
				return (uint8*)(stbi__err("bad compression") != 0 ? null : null);
			if (stbi__mad3sizes_valid(4, w, h, 0) == 0)
				return (uint8*)(stbi__err("too large") != 0 ? null : null);
			if (compression == 0 && bitdepth == 16 && bpc == 16)
			{
				_out_ = (uint8*)stbi__malloc_mad3(8, w, h, 0);
				ri.bits_per_channel = 16;
			}
			else
			{
				_out_ = (uint8*)stbi__malloc(4 * w * h);
			}

			if (_out_ == null)
				return (uint8*)(stbi__err("outofmem") != 0 ? null : null);
			pixelCount = w * h;
			if (compression != 0)
			{
				stbi__skip(s, h * channelCount * 2);
				for (channel = 0; channel < 4; channel++)
				{
					uint8* p;
					p = _out_ + channel;
					if (channel >= channelCount)
					{
						for (i = 0; i < pixelCount; i++, p += 4) *p = (uint8)(channel == 3 ? 255 : 0);
					}
					else
					{
						if (stbi__psd_decode_rle(s, p, pixelCount) == 0)
						{
							CRuntime.free(_out_);
							return (uint8*)(stbi__err("corrupt") != 0 ? null : null);
						}
					}
				}
			}
			else
			{
				for (channel = 0; channel < 4; channel++)
					if (channel >= channelCount)
					{
						if (bitdepth == 16 && bpc == 16)
						{
							var q = (uint16*)_out_ + channel;
							var val = (uint16)(channel == 3 ? 65535 : 0);
							for (i = 0; i < pixelCount; i++, q += 4) *q = val;
						}
						else
						{
							var p = _out_ + channel;
							var val = (uint8)(channel == 3 ? 255 : 0);
							for (i = 0; i < pixelCount; i++, p += 4) *p = val;
						}
					}
					else
					{
						if (ri.bits_per_channel == 16)
						{
							var q = (uint16*)_out_ + channel;
							for (i = 0; i < pixelCount; i++, q += 4) *q = (uint16)stbi__get16be(s);
						}
						else
						{
							var p = _out_ + channel;
							if (bitdepth == 16)
								for (i = 0; i < pixelCount; i++, p += 4)
									*p = (uint8)(stbi__get16be(s) >> 8);
							else
								for (i = 0; i < pixelCount; i++, p += 4)
									*p = stbi__get8(s);
						}
					}
			}

			if (channelCount >= 4)
			{
				if (ri.bits_per_channel == 16)
					for (i = 0; i < w * h; ++i)
					{
						var pixel = (uint16*)_out_ + 4 * i;
						if (pixel[3] != 0 && pixel[3] != 65535)
						{
							var a = pixel[3] / 65535.0f;
							var ra = 1.0f / a;
							var inv_a = 65535.0f * (1 - ra);
							pixel[0] = (uint16)(pixel[0] * ra + inv_a);
							pixel[1] = (uint16)(pixel[1] * ra + inv_a);
							pixel[2] = (uint16)(pixel[2] * ra + inv_a);
						}
					}
				else
					for (i = 0; i < w * h; ++i)
					{
						var pixel = _out_ + 4 * i;
						if (pixel[3] != 0 && pixel[3] != 255)
						{
							var a = pixel[3] / 255.0f;
							var ra = 1.0f / a;
							var inv_a = 255.0f * (1 - ra);
							pixel[0] = (uint8)(pixel[0] * ra + inv_a);
							pixel[1] = (uint8)(pixel[1] * ra + inv_a);
							pixel[2] = (uint8)(pixel[2] * ra + inv_a);
						}
					}
			}

			if (req_comp != 0 && req_comp != 4)
			{
				if (ri.bits_per_channel == 16)
					_out_ = (uint8*)stbi__convert_format16((uint16*)_out_, 4, req_comp, w, h);
				else
					_out_ = stbi__convert_format(_out_, 4, req_comp, w, h);
				if (_out_ == null)
					return _out_;
			}

			if (comp != null)
				*comp = 4;
			*y = h;
			*x = w;
			return _out_;
		}

		public static int32 stbi__psd_test(stbi__context s)
		{
			int32 r = stbi__get32be(s) == 0x38425053 ? 1 : 0;
			stbi__rewind(s);
			return r;
		}
	}
}