Skip to content

Commit 9110cdb

Browse files
stub GIF/JPEG decoders
1 parent 3bdd7ff commit 9110cdb

File tree

5 files changed

+160
-37
lines changed

5 files changed

+160
-37
lines changed

MCGalaxy/MCGalaxy_.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,8 +672,10 @@
672672
<Compile Include="util\Formatting\Wildcard.cs" />
673673
<Compile Include="util\DotnetBackend.cs" />
674674
<Compile Include="util\Imaging\Bitmap2D.cs" />
675+
<Compile Include="util\Imaging\GifDecoder.cs" />
675676
<Compile Include="util\Imaging\ImageDecoder.cs" />
676677
<Compile Include="util\Imaging\ImageUtils.cs" />
678+
<Compile Include="util\Imaging\JpegDecoder.cs" />
677679
<Compile Include="util\Imaging\PngDecoder.cs" />
678680
<Compile Include="util\NumberUtils.cs" />
679681
<Compile Include="util\OperatingSystem.cs" />
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
Copyright 2015-2024 MCGalaxy
3+
4+
Dual-licensed under the Educational Community License, Version 2.0 and
5+
the GNU General Public License, Version 3 (the "Licenses"); you may
6+
not use this file except in compliance with the Licenses. You may
7+
obtain a copy of the Licenses at
8+
9+
https://opensource.org/license/ecl-2-0/
10+
https://www.gnu.org/licenses/gpl-3.0.html
11+
12+
Unless required by applicable law or agreed to in writing,
13+
software distributed under the Licenses are distributed on an "AS IS"
14+
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
15+
or implied. See the Licenses for the specific language governing
16+
permissions and limitations under the Licenses.
17+
*/
18+
using System;
19+
using System.IO;
20+
using System.IO.Compression;
21+
using MCGalaxy.Util;
22+
23+
namespace MCGalaxy.Util.Imaging
24+
{
25+
public class GifDecoder : ImageDecoder
26+
{
27+
static byte[] gifSig = new byte[] { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 }; // "GIF89a"
28+
29+
public static bool DetectHeader(byte[] data) {
30+
return MatchesSignature(data, gifSig);
31+
}
32+
33+
public override SimpleBitmap Decode(byte[] src) {
34+
Fail("GIF decoder unfinished");
35+
return null;
36+
}
37+
}
38+
}

MCGalaxy/util/Imaging/ImageDecoder.cs

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,26 @@
1-
using System;
1+
/*
2+
Copyright 2015-2024 MCGalaxy
3+
4+
Dual-licensed under the Educational Community License, Version 2.0 and
5+
the GNU General Public License, Version 3 (the "Licenses"); you may
6+
not use this file except in compliance with the Licenses. You may
7+
obtain a copy of the Licenses at
8+
9+
https://opensource.org/license/ecl-2-0/
10+
https://www.gnu.org/licenses/gpl-3.0.html
11+
12+
Unless required by applicable law or agreed to in writing,
13+
software distributed under the Licenses are distributed on an "AS IS"
14+
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
15+
or implied. See the Licenses for the specific language governing
16+
permissions and limitations under the Licenses.
17+
*/
18+
using System;
219
using System.IO;
320
using System.IO.Compression;
421
using MCGalaxy.Util;
522

6-
namespace MCGalaxy
23+
namespace MCGalaxy.Util.Imaging
724
{
825
public sealed class SimpleBitmap //: IBitmap2D
926
{
@@ -29,6 +46,8 @@ protected static void Fail(string reason) {
2946
throw new InvalidDataException(reason);
3047
}
3148

49+
/// <summary> Checks if starting bytes of data match given signature </summary>
50+
/// <remarks> Ignores parts of sig that are &lt; 0 values </remarks>
3251
protected static bool MatchesSignature(byte[] data, byte[] sig) {
3352
if (data.Length < sig.Length) return false;
3453

@@ -41,10 +60,20 @@ protected static bool MatchesSignature(byte[] data, byte[] sig) {
4160

4261

4362
public static SimpleBitmap DecodeFrom(byte[] src) {
44-
if (PngDecoder.DetectHeader(src))
45-
return new PngDecoder().Decode(src);
63+
ImageDecoder decoder = DetectFrom(src);
64+
if (decoder != null) return decoder.Decode(src);
4665

4766
throw new InvalidDataException("Unsupported or invalid image format");
4867
}
68+
69+
static ImageDecoder DetectFrom(byte[] src) {
70+
if ( PngDecoder.DetectHeader(src)) return new PngDecoder();
71+
if ( GifDecoder.DetectHeader(src)) return new GifDecoder();
72+
if (JpegDecoder.DetectHeader(src)) return new JpegDecoder();
73+
74+
return null;
75+
}
76+
77+
public abstract SimpleBitmap Decode(byte[] src);
4978
}
5079
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
Copyright 2015-2024 MCGalaxy
3+
4+
Dual-licensed under the Educational Community License, Version 2.0 and
5+
the GNU General Public License, Version 3 (the "Licenses"); you may
6+
not use this file except in compliance with the Licenses. You may
7+
obtain a copy of the Licenses at
8+
9+
https://opensource.org/license/ecl-2-0/
10+
https://www.gnu.org/licenses/gpl-3.0.html
11+
12+
Unless required by applicable law or agreed to in writing,
13+
software distributed under the Licenses are distributed on an "AS IS"
14+
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
15+
or implied. See the Licenses for the specific language governing
16+
permissions and limitations under the Licenses.
17+
*/
18+
using System;
19+
using System.IO;
20+
using System.IO.Compression;
21+
using MCGalaxy.Util;
22+
23+
namespace MCGalaxy.Util.Imaging
24+
{
25+
public class JpegDecoder : ImageDecoder
26+
{
27+
static byte[] jfifSig = new byte[] { 0xFF, 0xD8, 0xFF, 0xE8 }; // "SOI", "APP0"
28+
29+
public static bool DetectHeader(byte[] data) {
30+
return MatchesSignature(data, jfifSig);
31+
}
32+
33+
public override SimpleBitmap Decode(byte[] src) {
34+
Fail("JPEG decoder unfinished");
35+
return null;
36+
}
37+
}
38+
}

MCGalaxy/util/Imaging/PngDecoder.cs

Lines changed: 49 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,26 @@
1-
using System;
1+
/*
2+
Copyright 2015-2024 MCGalaxy
3+
4+
Dual-licensed under the Educational Community License, Version 2.0 and
5+
the GNU General Public License, Version 3 (the "Licenses"); you may
6+
not use this file except in compliance with the Licenses. You may
7+
obtain a copy of the Licenses at
8+
9+
https://opensource.org/license/ecl-2-0/
10+
https://www.gnu.org/licenses/gpl-3.0.html
11+
12+
Unless required by applicable law or agreed to in writing,
13+
software distributed under the Licenses are distributed on an "AS IS"
14+
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
15+
or implied. See the Licenses for the specific language governing
16+
permissions and limitations under the Licenses.
17+
*/
18+
using System;
219
using System.IO;
320
using System.IO.Compression;
421
using MCGalaxy.Util;
522

6-
namespace MCGalaxy
23+
namespace MCGalaxy.Util.Imaging
724
{
825
public unsafe class PngDecoder : ImageDecoder
926
{
@@ -16,13 +33,12 @@ public unsafe class PngDecoder : ImageDecoder
1633
*#########################################################################################################################*/
1734
const int IHDR_SIZE = 13;
1835
const int MAX_PALETTE = 256;
19-
const int PNG_SIG_SIZE = 8;
2036
const int MAX_PNG_DIMS = 32768;
2137

2238

39+
// PNG spec - 5.2 PNG signature
2340
static byte[] pngSig = new byte[] { 137, 80, 78, 71, 13, 10, 26, 10 };
2441

25-
/* 5.2 PNG signature */
2642
public static bool DetectHeader(byte[] data) {
2743
return MatchesSignature(data, pngSig);
2844
}
@@ -49,7 +65,7 @@ static Pixel ExpandRGB(byte bitsPerSample, int r, int g, int b) {
4965
static byte[] samplesPerPixel = new byte [] { 1, 0, 3, 1, 2, 0, 4 };
5066
static Pixel BLACK = new Pixel(0, 0, 0, 255);
5167

52-
public SimpleBitmap Decode(byte[] src) {
68+
public override SimpleBitmap Decode(byte[] src) {
5369
byte colorspace = 0xFF;
5470
byte bitsPerSample = 0;
5571

@@ -64,7 +80,7 @@ public SimpleBitmap Decode(byte[] src) {
6480
buf_length = src.Length;
6581

6682
if (!DetectHeader(src)) Fail("sig invalid");
67-
AdvanceOffset(PNG_SIG_SIZE);
83+
AdvanceOffset(pngSig.Length);
6884
bool reachedEnd = false;
6985

7086
while (!reachedEnd)
@@ -89,7 +105,7 @@ public SimpleBitmap Decode(byte[] src) {
89105
colorspace = src[offset + 9];
90106
if (bitsPerSample == 16) Fail("16 bpp");
91107

92-
rowExpander = Png_GetExpander(colorspace, bitsPerSample);
108+
rowExpander = GetRowExpander(colorspace, bitsPerSample);
93109
if (rowExpander == null) Fail("Colorspace/bpp combination");
94110

95111
if (src[offset + 10] != 0) Fail("Compression method");
@@ -214,7 +230,7 @@ void DecompressImage(Stream src, SimpleBitmap bmp, Pixel[] palette, Pixel trnsCo
214230
if (method > PNG_FILTER_PAETH) Fail("Scanline");
215231
StreamUtils.ReadFully(src, line, 0, scanline_size);
216232

217-
Png_Reconstruct(method, bytesPerPixel, line, prior, scanline_size);
233+
ReconstructRow(method, bytesPerPixel, line, prior, scanline_size);
218234
rowExpander(bmp.Width, palette, line, dst + y * bmp.Width);
219235

220236
// Swap current and prior line
@@ -262,7 +278,7 @@ void SkipZLibHeader(byte[] src) {
262278
const int PNG_FILTER_AVERAGE = 3;
263279
const int PNG_FILTER_PAETH = 4;
264280

265-
static void Png_Reconstruct(byte type, int bytesPerPixel, byte[] line, byte[] prior, int lineLen) {
281+
static void ReconstructRow(byte type, int bytesPerPixel, byte[] line, byte[] prior, int lineLen) {
266282
int i, j;
267283

268284
switch (type) {
@@ -338,39 +354,39 @@ static int Get_4BPP(byte[] src, int i) {
338354
const byte SCALE_2BPP = 85;
339355
const byte SCALE_4BPP = 17;
340356

341-
static void Png_Expand_GRAYSCALE_1(int width, Pixel[] palette, byte[] src, Pixel* dst) {
357+
static void Expand_GRAYSCALE_1(int width, Pixel[] palette, byte[] src, Pixel* dst) {
342358
for (int i = 0; i < width; i++)
343359
{
344360
byte rgb = (byte)(Get_1BPP(src, i) * SCALE_1BPP);
345361
dst[i] = new Pixel(rgb, rgb, rgb, 255);
346362
}
347363
}
348364

349-
static void Png_Expand_GRAYSCALE_2(int width, Pixel[] palette, byte[] src, Pixel* dst) {
365+
static void Expand_GRAYSCALE_2(int width, Pixel[] palette, byte[] src, Pixel* dst) {
350366
for (int i = 0; i < width; i++)
351367
{
352368
byte rgb = (byte)(Get_2BPP(src, i) * SCALE_2BPP);
353369
dst[i] = new Pixel(rgb, rgb, rgb, 255);
354370
}
355371
}
356372

357-
static void Png_Expand_GRAYSCALE_4(int width, Pixel[] palette, byte[] src, Pixel* dst) {
373+
static void Expand_GRAYSCALE_4(int width, Pixel[] palette, byte[] src, Pixel* dst) {
358374
for (int i = 0; i < width; i++)
359375
{
360376
byte rgb = (byte)(Get_4BPP(src, i) * SCALE_4BPP);
361377
dst[i] = new Pixel(rgb, rgb, rgb, 255);
362378
}
363379
}
364380

365-
static void Png_Expand_GRAYSCALE_8(int width, Pixel[] palette, byte[] src, Pixel* dst) {
381+
static void Expand_GRAYSCALE_8(int width, Pixel[] palette, byte[] src, Pixel* dst) {
366382
for (int i = 0; i < width; i++)
367383
{
368384
byte rgb = src[i];
369385
dst[i] = new Pixel(rgb, rgb, rgb, 255);
370386
}
371387
}
372388

373-
static void Png_Expand_RGB_8(int width, Pixel[] palette, byte[] src, Pixel* dst) {
389+
static void Expand_RGB_8(int width, Pixel[] palette, byte[] src, Pixel* dst) {
374390
for (int i = 0; i < width; i++)
375391
{
376392
byte r = src[i * 3 + 0];
@@ -380,23 +396,23 @@ static void Png_Expand_RGB_8(int width, Pixel[] palette, byte[] src, Pixel* dst)
380396
}
381397
}
382398

383-
static void Png_Expand_INDEXED_1(int width, Pixel[] palette, byte[] src, Pixel* dst) {
399+
static void Expand_INDEXED_1(int width, Pixel[] palette, byte[] src, Pixel* dst) {
384400
for (int i = 0; i < width; i++) { dst[i] = palette[Get_1BPP(src, i)]; }
385401
}
386402

387-
static void Png_Expand_INDEXED_2(int width, Pixel[] palette, byte[] src, Pixel* dst) {
403+
static void Expand_INDEXED_2(int width, Pixel[] palette, byte[] src, Pixel* dst) {
388404
for (int i = 0; i < width; i++) { dst[i] = palette[Get_2BPP(src, i)]; }
389405
}
390406

391-
static void Png_Expand_INDEXED_4(int width, Pixel[] palette, byte[] src, Pixel* dst) {
407+
static void Expand_INDEXED_4(int width, Pixel[] palette, byte[] src, Pixel* dst) {
392408
for (int i = 0; i < width; i++) { dst[i] = palette[Get_4BPP(src, i)]; }
393409
}
394410

395-
static void Png_Expand_INDEXED_8(int width, Pixel[] palette, byte[] src, Pixel* dst) {
411+
static void Expand_INDEXED_8(int width, Pixel[] palette, byte[] src, Pixel* dst) {
396412
for (int i = 0; i < width; i++) { dst[i] = palette[src[i]]; }
397413
}
398414

399-
static void Png_Expand_GRAYSCALE_A_8(int width, Pixel[] palette, byte[] src, Pixel* dst) {
415+
static void Expand_GRAYSCALE_A_8(int width, Pixel[] palette, byte[] src, Pixel* dst) {
400416
for (int i = 0; i < width; i++)
401417
{
402418
byte rgb = src[i * 2 + 0];
@@ -405,7 +421,7 @@ static void Png_Expand_GRAYSCALE_A_8(int width, Pixel[] palette, byte[] src, Pix
405421
}
406422
}
407423

408-
static void Png_Expand_RGB_A_8(int width, Pixel[] palette, byte[] src, Pixel* dst) {
424+
static void Expand_RGB_A_8(int width, Pixel[] palette, byte[] src, Pixel* dst) {
409425
for (int i = 0; i < width; i++)
410426
{
411427
byte r = src[i * 4 + 0];
@@ -417,41 +433,41 @@ static void Png_Expand_RGB_A_8(int width, Pixel[] palette, byte[] src, Pixel* ds
417433
}
418434

419435

420-
static RowExpander Png_GetExpander(byte col, byte bitsPerSample) {
421-
switch (col) {
436+
static RowExpander GetRowExpander(byte colorspace, byte bitsPerSample) {
437+
switch (colorspace) {
422438
case PNG_COLOR_GRAYSCALE:
423439
switch (bitsPerSample) {
424-
case 1: return Png_Expand_GRAYSCALE_1;
425-
case 2: return Png_Expand_GRAYSCALE_2;
426-
case 4: return Png_Expand_GRAYSCALE_4;
427-
case 8: return Png_Expand_GRAYSCALE_8;
440+
case 1: return Expand_GRAYSCALE_1;
441+
case 2: return Expand_GRAYSCALE_2;
442+
case 4: return Expand_GRAYSCALE_4;
443+
case 8: return Expand_GRAYSCALE_8;
428444
}
429445
return null;
430446

431447
case PNG_COLOR_RGB:
432448
switch (bitsPerSample) {
433-
case 8: return Png_Expand_RGB_8;
449+
case 8: return Expand_RGB_8;
434450
}
435451
return null;
436452

437453
case PNG_COLOR_INDEXED:
438454
switch (bitsPerSample) {
439-
case 1: return Png_Expand_INDEXED_1;
440-
case 2: return Png_Expand_INDEXED_2;
441-
case 4: return Png_Expand_INDEXED_4;
442-
case 8: return Png_Expand_INDEXED_8;
455+
case 1: return Expand_INDEXED_1;
456+
case 2: return Expand_INDEXED_2;
457+
case 4: return Expand_INDEXED_4;
458+
case 8: return Expand_INDEXED_8;
443459
}
444460
return null;
445461

446462
case PNG_COLOR_GRAYSCALE_A:
447463
switch (bitsPerSample) {
448-
case 8: return Png_Expand_GRAYSCALE_A_8;
464+
case 8: return Expand_GRAYSCALE_A_8;
449465
}
450466
return null;
451467

452468
case PNG_COLOR_RGB_A:
453469
switch (bitsPerSample) {
454-
case 8: return Png_Expand_RGB_A_8;
470+
case 8: return Expand_RGB_A_8;
455471
}
456472
return null;
457473
}

0 commit comments

Comments
 (0)