A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/iOrange/QoiFileTypeNet/commit/05239401037a4291f7dabbbe0451cc8e1cd86d34 below:

+ added source files · iOrange/QoiFileTypeNet@0523940 · GitHub

1 +

using System;

2 +

using System.IO;

3 +

using System.Runtime.InteropServices;

4 + 5 + 6 +

// my bad C# translation of this - https://github.com/phoboslab/qoi/blob/master/qoi.h

7 +

namespace QoiFileTypeNet {

8 +

[StructLayout(LayoutKind.Sequential)]

9 +

internal struct QoiRgba : IEquatable<QoiRgba> {

10 +

public byte r;

11 +

public byte g;

12 +

public byte b;

13 +

public byte a;

14 + 15 +

public override bool Equals(object obj) => obj is QoiRgba other && this.Equals(other);

16 + 17 +

public bool Equals(QoiRgba other) {

18 +

return this.r == other.r &&

19 +

this.g == other.g &&

20 +

this.b == other.b &&

21 +

this.a == other.a;

22 +

}

23 + 24 +

public override int GetHashCode() => (r, g, b, a).GetHashCode();

25 + 26 +

public static bool operator ==(QoiRgba a, QoiRgba b) => a.Equals(b);

27 +

public static bool operator !=(QoiRgba a, QoiRgba b) => !a.Equals(b);

28 +

}

29 + 30 +

internal struct QoiDesc {

31 +

public const int QOI_SRGB = 0x00;

32 +

public const int QOI_SRGB_LINEAR_ALPHA = 0x01;

33 +

public const int QOI_LINEAR = 0x0F;

34 + 35 +

public int width;

36 +

public int height;

37 +

public int channels;

38 +

public int colorspace;

39 +

}

40 + 41 +

internal static class QoiFile {

42 +

private const int QOI_INDEX = 0x00; // 00xxxxxx

43 +

private const int QOI_RUN_8 = 0x40; // 010xxxxx

44 +

private const int QOI_RUN_16 = 0x60; // 011xxxxx

45 +

private const int QOI_DIFF_8 = 0x80; // 10xxxxxx

46 +

private const int QOI_DIFF_16 = 0xC0; // 110xxxxx

47 +

private const int QOI_DIFF_24 = 0xE0; // 1110xxxx

48 +

private const int QOI_COLOR = 0xF0; // 1111xxxx

49 + 50 +

private const int QOI_MASK_2 = 0xC0; // 11000000

51 +

private const int QOI_MASK_3 = 0xE0; // 11100000

52 +

private const int QOI_MASK_4 = 0xF0; // 11110000

53 + 54 +

private const int QOI_MAGIC = (((int)'q') << 24 | ((int)'o') << 16 | ((int)'i') << 8 | ((int)'f'));

55 + 56 +

private const int QOI_HEADER_SIZE = 14;

57 +

private const int QOI_PADDING = 4;

58 + 59 +

private static int ColorHash(ref QoiRgba c) {

60 +

return c.r ^ c.g ^ c.b ^ c.a;

61 +

}

62 + 63 +

private static uint SwapBytes(uint x) {

64 +

return ((x & 0x000000ff) << 24) |

65 +

((x & 0x0000ff00) << 8) |

66 +

((x & 0x00ff0000) >> 8) |

67 +

((x & 0xff000000) >> 24);

68 +

}

69 + 70 +

private static int SwapBytes(int x) {

71 +

return (int)SwapBytes((uint)x);

72 +

}

73 + 74 +

public static QoiRgba[] Load(Stream input, ref QoiDesc desc) {

75 +

QoiRgba[] result = null;

76 +

desc.width = 0;

77 +

desc.height = 0;

78 + 79 +

int fileSize = (int)input.Length;

80 +

if (fileSize < (QOI_HEADER_SIZE + QOI_PADDING)) {

81 +

return result;

82 +

}

83 + 84 +

using (BinaryReader reader = new BinaryReader(input)) {

85 +

uint headerMagic = SwapBytes(reader.ReadUInt32());

86 +

if (headerMagic != QOI_MAGIC) {

87 +

return result;

88 +

}

89 + 90 +

desc.width = SwapBytes(reader.ReadInt32());

91 +

desc.height = SwapBytes(reader.ReadInt32());

92 +

desc.channels = reader.ReadByte();

93 +

desc.colorspace = reader.ReadByte();

94 + 95 +

if (desc.width == 0 || desc.height == 0 || desc.channels < 3 || desc.channels > 4) {

96 +

return null;

97 +

}

98 + 99 +

int numPixels = (int)(desc.width * desc.height);

100 +

result = new QoiRgba[numPixels];

101 + 102 +

QoiRgba px = new QoiRgba { r = 0, g = 0, b = 0, a = 255 };

103 +

QoiRgba[] index = new QoiRgba[64];

104 + 105 +

int run = 0;

106 +

int chunksLen = fileSize - QOI_PADDING;

107 +

for (int i = 0; i < numPixels; ++i) {

108 +

if (run > 0) {

109 +

run--;

110 +

} else if (reader.BaseStream.Position < chunksLen) {

111 +

byte b1 = reader.ReadByte();

112 + 113 +

if ((b1 & QOI_MASK_2) == QOI_INDEX) {

114 +

px = index[b1 ^ QOI_INDEX];

115 +

} else if ((b1 & QOI_MASK_3) == QOI_RUN_8) {

116 +

run = b1 & 0x1F;

117 +

} else if ((b1 & QOI_MASK_3) == QOI_RUN_16) {

118 +

byte b2 = reader.ReadByte();

119 +

run = (((b1 & 0x1f) << 8) | (b2)) + 32;

120 +

} else if ((b1 & QOI_MASK_2) == QOI_DIFF_8) {

121 +

px.r += (byte)(((b1 >> 4) & 0x03) - 2);

122 +

px.g += (byte)(((b1 >> 2) & 0x03) - 2);

123 +

px.b += (byte)((b1 & 0x03) - 2);

124 +

} else if ((b1 & QOI_MASK_3) == QOI_DIFF_16) {

125 +

byte b2 = reader.ReadByte();

126 +

px.r += (byte)((b1 & 0x1f) - 16);

127 +

px.g += (byte)((b2 >> 4) - 8);

128 +

px.b += (byte)((b2 & 0x0f) - 8);

129 +

} else if ((b1 & QOI_MASK_4) == QOI_DIFF_24) {

130 +

byte b2 = reader.ReadByte();

131 +

byte b3 = reader.ReadByte();

132 +

px.r += (byte)((((b1 & 0x0f) << 1) | (b2 >> 7)) - 16);

133 +

px.g += (byte)(((b2 & 0x7c) >> 2) - 16);

134 +

px.b += (byte)((((b2 & 0x03) << 3) | ((b3 & 0xe0) >> 5)) - 16);

135 +

px.a += (byte)((b3 & 0x1f) - 16);

136 +

} else if ((b1 & QOI_MASK_4) == QOI_COLOR) {

137 +

if ((b1 & 8) == 8) { px.r = reader.ReadByte(); }

138 +

if ((b1 & 4) == 4) { px.g = reader.ReadByte(); }

139 +

if ((b1 & 2) == 2) { px.b = reader.ReadByte(); }

140 +

if ((b1 & 1) == 1) { px.a = reader.ReadByte(); }

141 +

}

142 + 143 +

index[ColorHash(ref px) % 64] = px;

144 +

}

145 + 146 +

result[i] = px;

147 +

}

148 +

}

149 + 150 +

return result;

151 +

}

152 + 153 +

public static void Save(Stream output, ref QoiDesc desc, QoiRgba[] pixels) {

154 +

BinaryWriter writer = new BinaryWriter(output);

155 + 156 +

writer.Write(SwapBytes(QOI_MAGIC));

157 +

writer.Write(SwapBytes(desc.width));

158 +

writer.Write(SwapBytes(desc.height));

159 +

writer.Write((byte)desc.channels);

160 +

writer.Write((byte)desc.colorspace);

161 + 162 +

QoiRgba px = new QoiRgba { r = 0, g = 0, b = 0, a = 255 };

163 +

QoiRgba pxPrev = px;

164 +

QoiRgba[] index = new QoiRgba[64];

165 + 166 +

int run = 0;

167 +

int numPixels = desc.width * desc.height;

168 +

for (int i = 0; i < numPixels; ++i) {

169 +

px = pixels[i];

170 + 171 +

if (px == pxPrev) {

172 +

run++;

173 +

}

174 + 175 +

if (run > 0 && (run == 0x2020 || px != pxPrev || i == (numPixels - 1))) {

176 +

if (run < 33) {

177 +

run -= 1;

178 +

writer.Write((byte)(QOI_RUN_8 | run));

179 +

} else {

180 +

run -= 33;

181 +

writer.Write((byte)(QOI_RUN_16 | run >> 8));

182 +

writer.Write((byte)run);

183 +

}

184 +

run = 0;

185 +

}

186 + 187 +

if (px != pxPrev) {

188 +

int indexPos = ColorHash(ref px) % 64;

189 + 190 +

if (index[indexPos] == px) {

191 +

writer.Write((byte)(QOI_INDEX | indexPos));

192 +

} else {

193 +

index[indexPos] = px;

194 + 195 +

int vr = px.r - pxPrev.r;

196 +

int vg = px.g - pxPrev.g;

197 +

int vb = px.b - pxPrev.b;

198 +

int va = px.a - pxPrev.a;

199 + 200 +

if (vr > -17 && vr < 16 &&

201 +

vg > -17 && vg < 16 &&

202 +

vb > -17 && vb < 16 &&

203 +

va > -17 && va < 16) {

204 +

if (va == 0 &&

205 +

vr > -3 && vr < 2 &&

206 +

vg > -3 && vg < 2 &&

207 +

vb > -3 && vb < 2) {

208 +

writer.Write((byte)(QOI_DIFF_8 | ((vr + 2) << 4) | (vg + 2) << 2 | (vb + 2)));

209 +

} else if (va == 0 &&

210 +

vr > -17 && vr < 16 &&

211 +

vg > -9 && vg < 8 &&

212 +

vb > -9 && vb < 8 ) {

213 +

writer.Write((byte)(QOI_DIFF_16 | (vr + 16)));

214 +

writer.Write((byte)((vg + 8) << 4 | (vb + 8)));

215 +

} else {

216 +

writer.Write((byte)(QOI_DIFF_24 | (vr + 16) >> 1));

217 +

writer.Write((byte)((vr + 16) << 7 | (vg + 16) << 2 | (vb + 16) >> 3));

218 +

writer.Write((byte)((vb + 16) << 5 | (va + 16)));

219 +

}

220 +

} else {

221 +

writer.Write((byte)(QOI_COLOR | ((vr != 0) ? 8 : 0) | ((vg != 0) ? 4 : 0) | ((vb != 0) ? 2 : 0) | ((va != 0) ? 1 : 0)));

222 +

if (vr != 0) { writer.Write(px.r); }

223 +

if (vg != 0) { writer.Write(px.g); }

224 +

if (vb != 0) { writer.Write(px.b); }

225 +

if (va != 0) { writer.Write(px.a); }

226 +

}

227 +

}

228 +

}

229 + 230 +

pxPrev = px;

231 +

}

232 + 233 +

for (int i = 0; i < QOI_PADDING; ++i) {

234 +

writer.Write((byte)0);

235 +

}

236 +

}

237 +

}

238 +

}


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4