diff --git a/Build/Projects/MonoGame.Framework.definition b/Build/Projects/MonoGame.Framework.definition index 8e8c96d1f2a..246e552e368 100644 --- a/Build/Projects/MonoGame.Framework.definition +++ b/Build/Projects/MonoGame.Framework.definition @@ -1215,12 +1215,6 @@ WindowsGL,Linux,MacOS - - WindowsGL,Linux,MacOS - - - WindowsGL,Linux,MacOS - diff --git a/MonoGame.Framework/Utilities/Imaging/ImageReader.cs b/MonoGame.Framework/Utilities/Imaging/ImageReader.cs index aba75f82d3d..57519217b54 100644 --- a/MonoGame.Framework/Utilities/Imaging/ImageReader.cs +++ b/MonoGame.Framework/Utilities/Imaging/ImageReader.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.IO; using System.Runtime.InteropServices; @@ -81,63 +80,5 @@ public byte[] Read(Stream stream, out int x, out int y, out int comp, int req_co _stream = null; } } - - public AnimatedGifFrame[] ReadAnimatedGif(Stream stream, out int x, out int y, out int comp, int req_comp) - { - try - { - x = y = comp = 0; - - var res = new List(); - _stream = stream; - - var context = new Imaging.stbi__context(); - Imaging.stbi__start_callbacks(context, _callbacks, null); - - if (Imaging.stbi__gif_test(context) == 0) - { - throw new Exception("Input stream is not GIF file."); - } - - var g = new Imaging.stbi__gif(); - - do - { - int ccomp; - var result = Imaging.stbi__gif_load_next(context, g, &ccomp, req_comp); - if (result == null) - { - break; - } - - comp = ccomp; - var c = req_comp != 0 ? req_comp : comp; - var data = new byte[g.w*g.h*c]; - Marshal.Copy(new IntPtr(result), data, 0, data.Length); - Operations.Free(result); - - var frame = new AnimatedGifFrame - { - Data = data, - Delay = g.delay - }; - res.Add(frame); - } while (true); - - Operations.Free(g._out_); - - if (res.Count > 0) - { - x = g.w; - y = g.h; - } - - return res.ToArray(); - } - finally - { - _stream = null; - } - } } } \ No newline at end of file diff --git a/MonoGame.Framework/Utilities/Imaging/ImageWriter.cs b/MonoGame.Framework/Utilities/Imaging/ImageWriter.cs index 64c4105a644..3cdbe704367 100644 --- a/MonoGame.Framework/Utilities/Imaging/ImageWriter.cs +++ b/MonoGame.Framework/Utilities/Imaging/ImageWriter.cs @@ -38,11 +38,6 @@ private int WriteCallback(void* context, void* data, int size) return size; } - private void WriteCallback2(void* context, void* data, int size) - { - WriteCallback(context, data, size); - } - public void Write(byte[] bytes, int x, int y, int comp, ImageWriterFormat format, Stream dest) { try @@ -59,7 +54,7 @@ public void Write(byte[] bytes, int x, int y, int comp, ImageWriterFormat format Imaging.stbi_write_tga_to_func(WriteCallback, null, x, y, comp, b); break; case ImageWriterFormat.Jpg: - Imaging.tje_encode_with_func(WriteCallback2, null, 2, x, y, comp, b); + Imaging.stbi_write_jpg_to_func(WriteCallback, null, x, y, comp, b, 90); break; case ImageWriterFormat.Png: diff --git a/MonoGame.Framework/Utilities/Imaging/Operations.cs b/MonoGame.Framework/Utilities/Imaging/Operations.cs index fc02209875a..1734b7833d6 100644 --- a/MonoGame.Framework/Utilities/Imaging/Operations.cs +++ b/MonoGame.Framework/Utilities/Imaging/Operations.cs @@ -1,16 +1,14 @@ -using System.Collections.Generic; +using System.Collections.Concurrent; namespace MonoGame.Utilities { internal static unsafe class Operations { - internal static Dictionary _pointers = new Dictionary(); - internal static long _allocatedTotal; - internal static object _lock = new object(); + internal static ConcurrentDictionary _pointers = new ConcurrentDictionary(); public static long AllocatedTotal { - get { return _allocatedTotal; } + get { return Pointer.AllocatedTotal; } } public static void* Malloc(long size) @@ -43,12 +41,11 @@ public static void MemMove(void* a, void* b, long size) public static void Free(void* a) { Pointer pointer; - if (!_pointers.TryGetValue((long) a, out pointer)) + if (!_pointers.TryRemove((long) a, out pointer)) { return; } - _pointers.Remove((long) pointer.Ptr); pointer.Dispose(); } @@ -70,7 +67,7 @@ public static void Free(void* a) var result = Malloc(newSize); Memcpy(result, a, pointer.Size); - _pointers.Remove((long) pointer.Ptr); + _pointers.TryRemove((long) pointer.Ptr, out pointer); pointer.Dispose(); return result; diff --git a/MonoGame.Framework/Utilities/Imaging/PinnedArray.cs b/MonoGame.Framework/Utilities/Imaging/PinnedArray.cs index eff500c168d..c90c7eea58a 100644 --- a/MonoGame.Framework/Utilities/Imaging/PinnedArray.cs +++ b/MonoGame.Framework/Utilities/Imaging/PinnedArray.cs @@ -5,9 +5,17 @@ namespace MonoGame.Utilities { internal abstract unsafe class Pointer : IDisposable { + protected static long _allocatedTotal; + protected static object _lock = new object(); + public abstract long Size { get; } public abstract void* Ptr { get; } + public static long AllocatedTotal + { + get { return _allocatedTotal; } + } + public abstract void Dispose(); public static implicit operator void*(Pointer ptr) @@ -86,9 +94,9 @@ public PinnedArray(T[] data) _size = 0; } - lock (Operations._lock) + lock (_lock) { - Operations._allocatedTotal += _size; + _allocatedTotal += _size; } } @@ -116,9 +124,9 @@ protected virtual void Dispose(bool disposing) return; } - lock (Operations._lock) + lock (_lock) { - Operations._allocatedTotal -= Size; + _allocatedTotal -= Size; } if (Data != null) diff --git a/MonoGame.Framework/Utilities/Imaging/Stb.Image.Generated.cs b/MonoGame.Framework/Utilities/Imaging/Stb.Image.Generated.cs index 5847f7cdd75..126855a2bdc 100644 --- a/MonoGame.Framework/Utilities/Imaging/Stb.Image.Generated.cs +++ b/MonoGame.Framework/Utilities/Imaging/Stb.Image.Generated.cs @@ -1,4 +1,4 @@ -// Generated by Sichem at 06.04.2017 1:02:24 +// Generated by Sichem at 1/6/2018 7:16:35 PM using System; using System.Runtime.InteropServices; @@ -24,6 +24,14 @@ public class stbi__context public byte* img_buffer_original_end; } + [StructLayout(LayoutKind.Sequential)] + public struct stbi__result_info + { + public int bits_per_channel; + public int num_channels; + public int channel_order; + } + [StructLayout(LayoutKind.Sequential)] public struct stbi__huffman { @@ -95,6 +103,8 @@ public struct stbi__bmp_data public const int STBI_grey_alpha = 2; public const int STBI_rgb = 3; public const int STBI_rgb_alpha = 4; + public const int STBI_ORDER_RGB = 0; + public const int STBI_ORDER_BGR = 1; public const int STBI__SCAN_load = 0; public const int STBI__SCAN_type = 1; public const int STBI__SCAN_header = 2; @@ -153,8 +163,32 @@ public struct stbi__bmp_data }; public static byte[] length_dezigzag = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - public static byte[] stbi__zdefault_length = new byte[288]; - public static byte[] stbi__zdefault_distance = new byte[32]; + + public static byte[] stbi__zdefault_length = + { + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, + 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8 + }; + + public static byte[] stbi__zdefault_distance = + { + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5 + }; + + public static byte[] png_sig = {137, 80, 78, 71, 13, 10, 26, 10}; public static byte[] first_row_filter = { @@ -163,14 +197,12 @@ public struct stbi__bmp_data }; public static byte[] stbi__depth_scale_table = {0, 0xff, 0x55, 0, 0x11, 0, 0, 0, 0x01}; - public static byte[] png_sig = { 137, 80, 78, 71, 13, 10, 26, 10 }; - public static int stbi__unpremultiply_on_load = (int) (0); public static int stbi__de_iphone_flag = (int) (0); public static void stbi__start_mem(stbi__context s, byte* buffer, int len) { - s.io.read = null; + s.io.read = (null); s.read_from_callbacks = (int) (0); s.img_buffer = s.img_buffer_original = buffer; s.img_buffer_end = s.img_buffer_original_end = buffer + len; @@ -193,55 +225,209 @@ public static void stbi__rewind(stbi__context s) s.img_buffer_end = s.img_buffer_original_end; } + public static int stbi__addsizes_valid(int a, int b) + { + if ((b) < (0)) return (int) (0); + return (a <= 2147483647 - b) ? 1 : 0; + } + + public static int stbi__mul2sizes_valid(int a, int b) + { + if (((a) < (0)) || ((b) < (0))) return (int) (0); + if ((b) == (0)) return (int) (1); + return (a <= 2147483647/b) ? 1 : 0; + } + + public static int stbi__mad2sizes_valid(int a, int b, int add) + { + return + (int) + (((stbi__mul2sizes_valid((int) (a), (int) (b))) != 0) && + ((stbi__addsizes_valid((int) (a*b), (int) (add))) != 0) + ? 1 + : 0); + } + + public static int stbi__mad3sizes_valid(int a, int b, int c, int add) + { + return + (int) + ((((stbi__mul2sizes_valid((int) (a), (int) (b))) != 0) && + ((stbi__mul2sizes_valid((int) (a*b), (int) (c))) != 0)) && + ((stbi__addsizes_valid((int) (a*b*c), (int) (add))) != 0) + ? 1 + : 0); + } + + public static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add) + { + return + (int) + (((((stbi__mul2sizes_valid((int) (a), (int) (b))) != 0) && + ((stbi__mul2sizes_valid((int) (a*b), (int) (c))) != 0)) && + ((stbi__mul2sizes_valid((int) (a*b*c), (int) (d))) != 0)) && + ((stbi__addsizes_valid((int) (a*b*c*d), (int) (add))) != 0) + ? 1 + : 0); + } + + public static void* stbi__malloc_mad2(int a, int b, int add) + { + if (stbi__mad2sizes_valid((int) (a), (int) (b), (int) (add)) == 0) return (null); + return stbi__malloc((ulong) (a*b + add)); + } + + public static void* stbi__malloc_mad3(int a, int b, int c, int add) + { + if (stbi__mad3sizes_valid((int) (a), (int) (b), (int) (c), (int) (add)) == 0) return (null); + return stbi__malloc((ulong) (a*b*c + add)); + } + + public static void* stbi__malloc_mad4(int a, int b, int c, int d, int add) + { + if (stbi__mad4sizes_valid((int) (a), (int) (b), (int) (c), (int) (d), (int) (add)) == 0) return (null); + return stbi__malloc((ulong) (a*b*c*d + add)); + } + public static void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) { stbi__vertically_flip_on_load = (int) (flag_true_if_should_flip); } - public static byte* stbi__load_main(stbi__context s, int* x, int* y, int* comp, int req_comp) + public static void* stbi__load_main(stbi__context s, int* x, int* y, int* comp, int req_comp, + stbi__result_info* ri, + int bpc) { - if ((stbi__jpeg_test(s)) != 0) return stbi__jpeg_load(s, x, y, comp, (int) (req_comp)); - if ((stbi__png_test(s)) != 0) return stbi__png_load(s, x, y, comp, (int) (req_comp)); - if ((stbi__bmp_test(s)) != 0) return stbi__bmp_load(s, x, y, comp, (int) (req_comp)); - if ((stbi__gif_test(s)) != 0) return stbi__gif_load(s, x, y, comp, (int) (req_comp)); - if ((stbi__tga_test(s)) != 0) return stbi__tga_load(s, x, y, comp, (int) (req_comp)); - return ((byte*) ((ulong) ((stbi__err("unknown image type")) != 0 ? (byte*) null : null))); + ri->bits_per_channel = (int) (8); + ri->channel_order = (int) (STBI_ORDER_RGB); + ri->num_channels = (int) (0); + if ((stbi__jpeg_test(s)) != 0) return stbi__jpeg_load(s, x, y, comp, (int) (req_comp), ri); + if ((stbi__png_test(s)) != 0) return stbi__png_load(s, x, y, comp, (int) (req_comp), ri); + if ((stbi__bmp_test(s)) != 0) return stbi__bmp_load(s, x, y, comp, (int) (req_comp), ri); + if ((stbi__gif_test(s)) != 0) return stbi__gif_load(s, x, y, comp, (int) (req_comp), ri); + if ((stbi__tga_test(s)) != 0) return stbi__tga_load(s, x, y, comp, (int) (req_comp), ri); + return ((byte*) ((ulong) ((stbi__err("unknown image type")) != 0 ? ((byte*) null) : (null)))); } - public static byte* stbi__load_flip(stbi__context s, int* x, int* y, int* comp, int req_comp) + public static byte* stbi__convert_16_to_8(ushort* orig, int w, int h, int channels) { - byte* result = stbi__load_main(s, x, y, comp, (int) (req_comp)); - if (((stbi__vertically_flip_on_load) != 0) && (result != null)) + int i; + int img_len = (int) (w*h*channels); + byte* reduced; + reduced = (byte*) (stbi__malloc((ulong) (img_len))); + if ((reduced) == (null)) + return ((byte*) ((ulong) ((stbi__err("outofmem")) != 0 ? ((byte*) null) : (null)))); + for (i = (int) (0); (i) < (img_len); ++i) + { + reduced[i] = ((byte) ((orig[i] >> 8) & 0xFF)); + } + free(orig); + return reduced; + } + + public static ushort* stbi__convert_8_to_16(byte* orig, int w, int h, int channels) + { + int i; + int img_len = (int) (w*h*channels); + ushort* enlarged; + enlarged = (ushort*) (stbi__malloc((ulong) (img_len*2))); + if ((enlarged) == (null)) + return (ushort*) ((byte*) ((ulong) ((stbi__err("outofmem")) != 0 ? ((byte*) null) : (null)))); + for (i = (int) (0); (i) < (img_len); ++i) { - int w = (int) (*x); - int h = (int) (*y); - int depth = (int) ((req_comp) != 0 ? req_comp : *comp); - int row; - int col; - int z; - byte temp; - for (row = (int) (0); (row) < (h >> 1); row++) + enlarged[i] = ((ushort) ((orig[i] << 8) + orig[i])); + } + free(orig); + return enlarged; + } + + public static void stbi__vertical_flip(void* image, int w, int h, int bytes_per_pixel) + { + int row; + ulong bytes_per_row = (ulong) (w*bytes_per_pixel); + byte* temp = stackalloc byte[2048]; + byte* bytes = (byte*) (image); + for (row = (int) (0); (row) < (h >> 1); row++) + { + byte* row0 = bytes + (ulong) row*bytes_per_row; + byte* row1 = bytes + (ulong) (h - row - 1)*bytes_per_row; + ulong bytes_left = (ulong) (bytes_per_row); + while ((bytes_left) != 0) { - for (col = (int) (0); (col) < (w); col++) - { - for (z = (int) (0); (z) < (depth); z++) - { - temp = (byte) (result[(row*w + col)*depth + z]); - result[(row*w + col)*depth + z] = (byte) (result[((h - row - 1)*w + col)*depth + z]); - result[((h - row - 1)*w + col)*depth + z] = (byte) (temp); - } - } + ulong bytes_copy = (ulong) (((bytes_left) < (2048)) ? bytes_left : 2048); + memcpy(temp, row0, (ulong) (bytes_copy)); + memcpy(row0, row1, (ulong) (bytes_copy)); + memcpy(row1, temp, (ulong) (bytes_copy)); + row0 += bytes_copy; + row1 += bytes_copy; + bytes_left -= (ulong) (bytes_copy); } } + } - return result; + public static byte* stbi__load_and_postprocess_8bit(stbi__context s, int* x, int* y, int* comp, int req_comp) + { + stbi__result_info ri = new stbi__result_info(); + void* result = stbi__load_main(s, x, y, comp, (int) (req_comp), &ri, (int) (8)); + if ((result) == (null)) return (null); + if (ri.bits_per_channel != 8) + { + result = stbi__convert_16_to_8((ushort*) (result), (int) (*x), (int) (*y), + (int) ((req_comp) == (0) ? *comp : req_comp)); + ri.bits_per_channel = (int) (8); + } + + if ((stbi__vertically_flip_on_load) != 0) + { + int channels = (int) ((req_comp) != 0 ? req_comp : *comp); + stbi__vertical_flip(result, (int) (*x), (int) (*y), (int) (channels)); + } + + return (byte*) (result); + } + + public static ushort* stbi__load_and_postprocess_16bit(stbi__context s, int* x, int* y, int* comp, int req_comp) + { + stbi__result_info ri = new stbi__result_info(); + void* result = stbi__load_main(s, x, y, comp, (int) (req_comp), &ri, (int) (16)); + if ((result) == (null)) return (null); + if (ri.bits_per_channel != 16) + { + result = stbi__convert_8_to_16((byte*) (result), (int) (*x), (int) (*y), + (int) ((req_comp) == (0) ? *comp : req_comp)); + ri.bits_per_channel = (int) (16); + } + + if ((stbi__vertically_flip_on_load) != 0) + { + int channels = (int) ((req_comp) != 0 ? req_comp : *comp); + stbi__vertical_flip(result, (int) (*x), (int) (*y), (int) (channels*2)); + } + + return (ushort*) (result); + } + + public static ushort* stbi_load_16_from_memory(byte* buffer, int len, int* x, int* y, int* channels_in_file, + int desired_channels) + { + stbi__context s = new stbi__context(); + stbi__start_mem(s, buffer, (int) (len)); + return stbi__load_and_postprocess_16bit(s, x, y, channels_in_file, (int) (desired_channels)); + } + + public static ushort* stbi_load_16_from_callbacks(stbi_io_callbacks clbk, void* user, int* x, int* y, + int* channels_in_file, int desired_channels) + { + stbi__context s = new stbi__context(); + stbi__start_callbacks(s, clbk, user); + return stbi__load_and_postprocess_16bit(s, x, y, channels_in_file, (int) (desired_channels)); } public static byte* stbi_load_from_memory(byte* buffer, int len, int* x, int* y, int* comp, int req_comp) { stbi__context s = new stbi__context(); stbi__start_mem(s, buffer, (int) (len)); - return stbi__load_flip(s, x, y, comp, (int) (req_comp)); + return stbi__load_and_postprocess_8bit(s, x, y, comp, (int) (req_comp)); } public static byte* stbi_load_from_callbacks(stbi_io_callbacks clbk, void* user, int* x, int* y, int* comp, @@ -249,7 +435,7 @@ public static void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip { stbi__context s = new stbi__context(); stbi__start_callbacks(s, clbk, user); - return stbi__load_flip(s, x, y, comp, (int) (req_comp)); + return stbi__load_and_postprocess_8bit(s, x, y, comp, (int) (req_comp)); } public static void stbi_hdr_to_ldr_gamma(float gamma) @@ -269,13 +455,15 @@ public static void stbi__refill_buffer(stbi__context s) { s.read_from_callbacks = (int) (0); s.img_buffer = s.buffer_start; - s.img_buffer_end = (byte*) s.buffer_start + 1; + s.img_buffer_end = s.buffer_start; + s.img_buffer_end++; *s.img_buffer = (byte) (0); } else { s.img_buffer = s.buffer_start; - s.img_buffer_end = (byte*) s.buffer_start + n; + s.img_buffer_end = s.buffer_start; + s.img_buffer_end += n; } } @@ -386,11 +574,11 @@ public static byte stbi__compute_y(int r, int g, int b) int j; byte* good; if ((req_comp) == (img_n)) return data; - good = (byte*) (stbi__malloc((ulong) (req_comp*x*y))); - if ((good) == null) + good = (byte*) (stbi__malloc_mad3((int) (req_comp), (int) (x), (int) (y), (int) (0))); + if ((good) == (null)) { free(data); - return ((byte*) ((ulong) ((stbi__err("outofmem")) != 0 ? (byte*) null : null))); + return ((byte*) ((ulong) ((stbi__err("outofmem")) != 0 ? ((byte*) null) : (null)))); } for (j = (int) (0); (j) < ((int) (y)); ++j) @@ -482,7 +670,121 @@ public static byte stbi__compute_y(int r, int g, int b) } break; default: + return ((byte*) ((ulong) ((stbi__err("0")) != 0 ? ((byte*) null) : (null)))); + } + } + free(data); + return good; + } + + public static ushort stbi__compute_y_16(int r, int g, int b) + { + return (ushort) (((r*77) + (g*150) + (29*b)) >> 8); + } + + public static ushort* stbi__convert_format16(ushort* data, int img_n, int req_comp, uint x, uint y) + { + int i; + int j; + ushort* good; + if ((req_comp) == (img_n)) return data; + good = (ushort*) (stbi__malloc((ulong) (req_comp*x*y*2))); + if ((good) == (null)) + { + free(data); + return (ushort*) ((byte*) ((ulong) ((stbi__err("outofmem")) != 0 ? ((byte*) null) : (null)))); + } + + for (j = (int) (0); (j) < ((int) (y)); ++j) + { + ushort* src = data + j*x*img_n; + ushort* dest = good + j*x*req_comp; + switch (((img_n)*8 + (req_comp))) + { + case ((1)*8 + (2)): + for (i = (int) (x - 1); (i) >= (0); --i , src += 1 , dest += 2) + { + dest[0] = (ushort) (src[0]); + dest[1] = (ushort) (0xffff); + } + break; + case ((1)*8 + (3)): + for (i = (int) (x - 1); (i) >= (0); --i , src += 1 , dest += 3) + { + dest[0] = (ushort) (dest[1] = (ushort) (dest[2] = (ushort) (src[0]))); + } + break; + case ((1)*8 + (4)): + for (i = (int) (x - 1); (i) >= (0); --i , src += 1 , dest += 4) + { + dest[0] = (ushort) (dest[1] = (ushort) (dest[2] = (ushort) (src[0]))); + dest[3] = (ushort) (0xffff); + } + break; + case ((2)*8 + (1)): + for (i = (int) (x - 1); (i) >= (0); --i , src += 2 , dest += 1) + { + dest[0] = (ushort) (src[0]); + } + break; + case ((2)*8 + (3)): + for (i = (int) (x - 1); (i) >= (0); --i , src += 2 , dest += 3) + { + dest[0] = (ushort) (dest[1] = (ushort) (dest[2] = (ushort) (src[0]))); + } + break; + case ((2)*8 + (4)): + for (i = (int) (x - 1); (i) >= (0); --i , src += 2 , dest += 4) + { + dest[0] = (ushort) (dest[1] = (ushort) (dest[2] = (ushort) (src[0]))); + dest[3] = (ushort) (src[1]); + } + break; + case ((3)*8 + (4)): + for (i = (int) (x - 1); (i) >= (0); --i , src += 3 , dest += 4) + { + dest[0] = (ushort) (src[0]); + dest[1] = (ushort) (src[1]); + dest[2] = (ushort) (src[2]); + dest[3] = (ushort) (0xffff); + } + break; + case ((3)*8 + (1)): + for (i = (int) (x - 1); (i) >= (0); --i , src += 3 , dest += 1) + { + dest[0] = (ushort) (stbi__compute_y_16((int) (src[0]), (int) (src[1]), (int) (src[2]))); + } + break; + case ((3)*8 + (2)): + for (i = (int) (x - 1); (i) >= (0); --i , src += 3 , dest += 2) + { + dest[0] = (ushort) (stbi__compute_y_16((int) (src[0]), (int) (src[1]), (int) (src[2]))); + dest[1] = (ushort) (0xffff); + } + break; + case ((4)*8 + (1)): + for (i = (int) (x - 1); (i) >= (0); --i , src += 4 , dest += 1) + { + dest[0] = (ushort) (stbi__compute_y_16((int) (src[0]), (int) (src[1]), (int) (src[2]))); + } + break; + case ((4)*8 + (2)): + for (i = (int) (x - 1); (i) >= (0); --i , src += 4 , dest += 2) + { + dest[0] = (ushort) (stbi__compute_y_16((int) (src[0]), (int) (src[1]), (int) (src[2]))); + dest[1] = (ushort) (src[3]); + } + break; + case ((4)*8 + (3)): + for (i = (int) (x - 1); (i) >= (0); --i , src += 4 , dest += 3) + { + dest[0] = (ushort) (src[0]); + dest[1] = (ushort) (src[1]); + dest[2] = (ushort) (src[2]); + } break; + default: + return (ushort*) ((byte*) ((ulong) ((stbi__err("0")) != 0 ? ((byte*) null) : (null)))); } } free(data); @@ -554,7 +856,7 @@ public static void stbi__build_fast_ac(short* fast_ac, stbi__huffman* h) { int k = (int) (((i << len) & ((1 << 9) - 1)) >> (9 - magbits)); int m = (int) (1 << (magbits - 1)); - if ((k) < (m)) k += (int) ((-1 << magbits) + 1); + if ((k) < (m)) k += (int) ((~0U << magbits) + 1); if (((k) >= (-128)) && (k <= 127)) fast_ac[i] = ((short) ((k << 8) + (run << 4) + (len + magbits))); } @@ -570,6 +872,10 @@ public static void stbi__grow_buffer_unsafe(stbi__jpeg j) if ((b) == (0xff)) { int c = (int) (stbi__get8(j.s)); + while ((c) == (0xff)) + { + c = (int) (stbi__get8(j.s)); + } if (c != 0) { j.marker = ((byte) (c)); @@ -622,8 +928,8 @@ public static int stbi__extend_receive(stbi__jpeg j, int n) uint k; int sgn; if ((j.code_bits) < (n)) stbi__grow_buffer_unsafe(j); - sgn = (int) ((int) (j.code_buffer) >> 31); - k = (uint) (_lrotl((uint) (j.code_buffer), (int) (n))); + sgn = (int) ((int) j.code_buffer >> 31); + k = (uint) (_lrotl(j.code_buffer, (int) (n))); j.code_buffer = (uint) (k & ~stbi__bmask[n]); k &= (uint) (stbi__bmask[n]); j.code_bits -= (int) (n); @@ -634,7 +940,7 @@ public static int stbi__jpeg_get_bits(stbi__jpeg j, int n) { uint k; if ((j.code_bits) < (n)) stbi__grow_buffer_unsafe(j); - k = (uint) (_lrotl((uint) (j.code_buffer), (int) (n))); + k = (uint) (_lrotl(j.code_buffer, (int) (n))); j.code_buffer = (uint) (k & ~stbi__bmask[n]); k &= (uint) (stbi__bmask[n]); j.code_bits -= (int) (n); @@ -652,7 +958,7 @@ public static int stbi__jpeg_get_bit(stbi__jpeg j) } public static int stbi__jpeg_decode_block(stbi__jpeg j, short* data, stbi__huffman* hdc, stbi__huffman* hac, - short* fac, int b, byte* dequant) + short* fac, int b, ushort* dequant) { int diff; int dc; @@ -1051,7 +1357,9 @@ public static void stbi__jpeg_reset(stbi__jpeg j) j.code_bits = (int) (0); j.code_buffer = (uint) (0); j.nomore = (int) (0); - j.img_comp[0].dc_pred = (int) (j.img_comp[1].dc_pred = (int) (j.img_comp[2].dc_pred = (int) (0))); + j.img_comp[0].dc_pred = + (int) + (j.img_comp[1].dc_pred = (int) (j.img_comp[2].dc_pred = (int) (j.img_comp[3].dc_pred = (int) (0)))); j.marker = (byte) (0xff); j.todo = (int) ((j.restart_interval) != 0 ? j.restart_interval : 0x7fffffff); j.eob_run = (int) (0); @@ -1078,8 +1386,8 @@ public static int stbi__parse_entropy_coded_data(stbi__jpeg z) if ( stbi__jpeg_decode_block(z, data, (stbi__huffman*) z.huff_dc + z.img_comp[n].hd, (stbi__huffman*) z.huff_ac + ha, - z.fast_ac[ha], (int) (n), - z.dequant[z.img_comp[n].tq]) == 0) return (int) (0); + z.fast_ac[ha], (int) (n), (ushort*) z.dequant[z.img_comp[n].tq]) == 0) + return (int) (0); z.idct_block_kernel(z.img_comp[n].data + z.img_comp[n].w2*j*8 + i*8, (int) (z.img_comp[n].w2), data); if (--z.todo <= 0) @@ -1118,7 +1426,8 @@ public static int stbi__parse_entropy_coded_data(stbi__jpeg z) stbi__jpeg_decode_block(z, data, (stbi__huffman*) z.huff_dc + z.img_comp[n].hd, (stbi__huffman*) z.huff_ac + ha, z.fast_ac[ha], (int) (n), - z.dequant[z.img_comp[n].tq]) == 0) return (int) (0); + (ushort*) z.dequant[z.img_comp[n].tq]) == 0) + return (int) (0); z.idct_block_kernel(z.img_comp[n].data + z.img_comp[n].w2*y2 + x2, (int) (z.img_comp[n].w2), data); } @@ -1216,7 +1525,7 @@ public static int stbi__parse_entropy_coded_data(stbi__jpeg z) } - public static void stbi__jpeg_dequantize(short* data, byte* dequant) + public static void stbi__jpeg_dequantize(short* data, ushort* dequant) { int i; for (i = (int) (0); (i) < (64); ++i) @@ -1241,7 +1550,7 @@ public static void stbi__jpeg_finish(stbi__jpeg z) for (i = (int) (0); (i) < (w); ++i) { short* data = z.img_comp[n].coeff + 64*(i + j*z.img_comp[n].coeff_w); - stbi__jpeg_dequantize(data, z.dequant[z.img_comp[n].tq]); + stbi__jpeg_dequantize(data, (ushort*) z.dequant[z.img_comp[n].tq]); z.idct_block_kernel(z.img_comp[n].data + z.img_comp[n].w2*j*8 + i*8, (int) (z.img_comp[n].w2), data); } @@ -1268,15 +1577,17 @@ public static int stbi__process_marker(stbi__jpeg z, int m) { int q = (int) (stbi__get8(z.s)); int p = (int) (q >> 4); + int sixteen = (p != 0) ? 1 : 0; int t = (int) (q & 15); int i; - if (p != 0) return (int) (stbi__err("bad DQT type")); + if ((p != 0) && (p != 1)) return (int) (stbi__err("bad DQT type")); if ((t) > (3)) return (int) (stbi__err("bad DQT table")); for (i = (int) (0); (i) < (64); ++i) { - z.dequant[t][stbi__jpeg_dezigzag[i]] = (byte) (stbi__get8(z.s)); + z.dequant[t][stbi__jpeg_dezigzag[i]] = + ((ushort) ((sixteen) != 0 ? stbi__get16be(z.s) : stbi__get8(z.s))); } - L -= (int) (65); + L -= (int) ((sixteen) != 0 ? 129 : 65); } return (int) ((L) == (0) ? 1 : 0); case 0xC4: @@ -1321,11 +1632,60 @@ public static int stbi__process_marker(stbi__jpeg z, int m) if ((((m) >= (0xE0)) && (m <= 0xEF)) || ((m) == (0xFE))) { - stbi__skip(z.s, (int) (stbi__get16be(z.s) - 2)); + L = (int) (stbi__get16be(z.s)); + if ((L) < (2)) + { + if ((m) == (0xFE)) return (int) (stbi__err("bad COM len")); + else return (int) (stbi__err("bad APP len")); + } + L -= (int) (2); + if (((m) == (0xE0)) && ((L) >= (5))) + { + byte* tag = stackalloc byte[5]; + tag[0] = (byte) ('J'); + tag[1] = (byte) ('F'); + tag[2] = (byte) ('I'); + tag[3] = (byte) ('F'); + tag[4] = (byte) ('\0'); + int ok = (int) (1); + int i; + for (i = (int) (0); (i) < (5); ++i) + { + if (stbi__get8(z.s) != tag[i]) ok = (int) (0); + } + L -= (int) (5); + if ((ok) != 0) z.jfif = (int) (1); + } + else if (((m) == (0xEE)) && ((L) >= (12))) + { + byte* tag = stackalloc byte[6]; + tag[0] = (byte) ('A'); + tag[1] = (byte) ('d'); + tag[2] = (byte) ('o'); + tag[3] = (byte) ('b'); + tag[4] = (byte) ('e'); + tag[5] = (byte) ('\0'); + int ok = (int) (1); + int i; + for (i = (int) (0); (i) < (6); ++i) + { + if (stbi__get8(z.s) != tag[i]) ok = (int) (0); + } + L -= (int) (6); + if ((ok) != 0) + { + stbi__get8(z.s); + stbi__get16be(z.s); + stbi__get16be(z.s); + z.app14_color_transform = (int) (stbi__get8(z.s)); + L -= (int) (6); + } + } + stbi__skip(z.s, (int) (L)); return (int) (1); } - return (int) (0); + return (int) (stbi__err("unknown marker")); } public static int stbi__process_scan_header(stbi__jpeg z) @@ -1375,6 +1735,32 @@ public static int stbi__process_scan_header(stbi__jpeg z) return (int) (1); } + public static int stbi__free_jpeg_components(stbi__jpeg z, int ncomp, int why) + { + int i; + for (i = (int) (0); (i) < (ncomp); ++i) + { + if ((z.img_comp[i].raw_data) != null) + { + free(z.img_comp[i].raw_data); + z.img_comp[i].raw_data = (null); + z.img_comp[i].data = (null); + } + if ((z.img_comp[i].raw_coeff) != null) + { + free(z.img_comp[i].raw_coeff); + z.img_comp[i].raw_coeff = null; + z.img_comp[i].coeff = null; + } + if ((z.img_comp[i].linebuf) != null) + { + free(z.img_comp[i].linebuf); + z.img_comp[i].linebuf = (null); + } + } + return (int) (why); + } + public static int stbi__process_frame_header(stbi__jpeg z, int scan) { stbi__context s = z.s; @@ -1394,12 +1780,12 @@ public static int stbi__process_frame_header(stbi__jpeg z, int scan) s.img_x = (uint) (stbi__get16be(s)); if ((s.img_x) == (0)) return (int) (stbi__err("0 width")); c = (int) (stbi__get8(s)); - if ((c != 3) && (c != 1)) return (int) (stbi__err("bad component count")); + if (((c != 3) && (c != 1)) && (c != 4)) return (int) (stbi__err("bad component count")); s.img_n = (int) (c); for (i = (int) (0); (i) < (c); ++i) { - z.img_comp[i].data = null; - z.img_comp[i].linebuf = null; + z.img_comp[i].data = (null); + z.img_comp[i].linebuf = (null); } if (Lf != 8 + 3*s.img_n) return (int) (stbi__err("bad SOF len")); z.rgb = (int) (0); @@ -1410,12 +1796,7 @@ public static int stbi__process_frame_header(stbi__jpeg z, int scan) rgb[1] = (byte) ('G'); rgb[2] = (byte) ('B'); z.img_comp[i].id = (int) (stbi__get8(s)); - if (z.img_comp[i].id != i + 1) - if (z.img_comp[i].id != i) - { - if (z.img_comp[i].id != rgb[i]) return (int) (stbi__err("bad component ID")); - ++z.rgb; - } + if (((s.img_n) == (3)) && ((z.img_comp[i].id) == (rgb[i]))) ++z.rgb; q = (int) (stbi__get8(s)); z.img_comp[i].h = (int) (q >> 4); if ((z.img_comp[i].h == 0) || ((z.img_comp[i].h) > (4))) return (int) (stbi__err("bad H")); @@ -1425,7 +1806,8 @@ public static int stbi__process_frame_header(stbi__jpeg z, int scan) if ((z.img_comp[i].tq) > (3)) return (int) (stbi__err("bad TQ")); } if (scan != STBI__SCAN_load) return (int) (1); - if (((1 << 30)/s.img_x/s.img_n) < (s.img_y)) return (int) (stbi__err("too large")); + if (stbi__mad3sizes_valid((int) (s.img_x), (int) (s.img_y), (int) (s.img_n), (int) (0)) == 0) + return (int) (stbi__err("too large")); for (i = (int) (0); (i) < (s.img_n); ++i) { if ((z.img_comp[i].h) > (h_max)) h_max = (int) (z.img_comp[i].h); @@ -1443,31 +1825,25 @@ public static int stbi__process_frame_header(stbi__jpeg z, int scan) z.img_comp[i].y = (int) ((s.img_y*z.img_comp[i].v + v_max - 1)/v_max); z.img_comp[i].w2 = (int) (z.img_mcu_x*z.img_comp[i].h*8); z.img_comp[i].h2 = (int) (z.img_mcu_y*z.img_comp[i].v*8); - z.img_comp[i].raw_data = stbi__malloc((ulong) (z.img_comp[i].w2*z.img_comp[i].h2 + 15)); - if ((z.img_comp[i].raw_data) == null) - { - for (--i; (i) >= (0); --i) - { - free(z.img_comp[i].raw_data); - z.img_comp[i].raw_data = null; - } - return (int) (stbi__err("outofmem")); - } + z.img_comp[i].coeff = null; + z.img_comp[i].raw_coeff = null; + z.img_comp[i].linebuf = (null); + z.img_comp[i].raw_data = stbi__malloc_mad2((int) (z.img_comp[i].w2), (int) (z.img_comp[i].h2), + (int) (15)); + if ((z.img_comp[i].raw_data) == (null)) + return (int) (stbi__free_jpeg_components(z, (int) (i + 1), (int) (stbi__err("outofmem")))); z.img_comp[i].data = (byte*) ((((long) z.img_comp[i].raw_data + 15) & ~15)); - z.img_comp[i].linebuf = null; if ((z.progressive) != 0) { - z.img_comp[i].coeff_w = (int) ((z.img_comp[i].w2 + 7) >> 3); - z.img_comp[i].coeff_h = (int) ((z.img_comp[i].h2 + 7) >> 3); - z.img_comp[i].raw_coeff = - malloc((ulong) (z.img_comp[i].coeff_w*z.img_comp[i].coeff_h*64*sizeof (short) + +15)); + z.img_comp[i].coeff_w = (int) (z.img_comp[i].w2/8); + z.img_comp[i].coeff_h = (int) (z.img_comp[i].h2/8); + z.img_comp[i].raw_coeff = stbi__malloc_mad3((int) (z.img_comp[i].w2), (int) (z.img_comp[i].h2), + (int) (2), + (int) (15)); + if ((z.img_comp[i].raw_coeff) == (null)) + return (int) (stbi__free_jpeg_components(z, (int) (i + 1), (int) (stbi__err("outofmem")))); z.img_comp[i].coeff = (short*) ((((long) z.img_comp[i].raw_coeff + 15) & ~15)); } - else - { - z.img_comp[i].coeff = null; - z.img_comp[i].raw_coeff = null; - } } return (int) (1); } @@ -1475,6 +1851,8 @@ public static int stbi__process_frame_header(stbi__jpeg z, int scan) public static int stbi__decode_jpeg_header(stbi__jpeg z, int scan) { int m; + z.jfif = (int) (0); + z.app14_color_transform = (int) (-1); z.marker = (byte) (0xff); m = (int) (stbi__get_marker(z)); if (!((m) == (0xd8))) return (int) (stbi__err("no SOI")); @@ -1500,8 +1878,8 @@ public static int stbi__decode_jpeg_image(stbi__jpeg j) int m; for (m = (int) (0); (m) < (4); m++) { - j.img_comp[m].raw_data = null; - j.img_comp[m].raw_coeff = null; + j.img_comp[m].raw_data = (null); + j.img_comp[m].raw_coeff = (null); } j.restart_interval = (int) (0); if (stbi__decode_jpeg_header(j, (int) (STBI__SCAN_load)) == 0) return (int) (0); @@ -1522,13 +1900,16 @@ public static int stbi__decode_jpeg_image(stbi__jpeg j) j.marker = (byte) (stbi__get8(j.s)); break; } - else if (x != 0) - { - return (int) (stbi__err("junk before marker")); - } } } } + else if (((m) == (0xdc))) + { + int Ld = (int) (stbi__get16be(j.s)); + uint NL = (uint) (stbi__get16be(j.s)); + if (Ld != 4) stbi__err("bad DNL len"); + if (NL != j.s.img_y) stbi__err("bad DNL height"); + } else { if (stbi__process_marker(j, (int) (m)) == 0) return (int) (0); @@ -1667,44 +2048,36 @@ public static void stbi__setup_jpeg(stbi__jpeg j) public static void stbi__cleanup_jpeg(stbi__jpeg j) { - int i; - for (i = (int) (0); (i) < (j.s.img_n); ++i) - { - if ((j.img_comp[i].raw_data) != null) - { - free(j.img_comp[i].raw_data); - j.img_comp[i].raw_data = null; - j.img_comp[i].data = null; - } - if ((j.img_comp[i].raw_coeff) != null) - { - free(j.img_comp[i].raw_coeff); - j.img_comp[i].raw_coeff = null; - j.img_comp[i].coeff = null; - } - if ((j.img_comp[i].linebuf) != null) - { - free(j.img_comp[i].linebuf); - j.img_comp[i].linebuf = null; - } - } + stbi__free_jpeg_components(j, (int) (j.s.img_n), (int) (0)); + } + + public static byte stbi__blinn_8x8(byte x, byte y) + { + uint t = (uint) (x*y + 128); + return (byte) ((t + (t >> 8)) >> 8); } public static byte* load_jpeg_image(stbi__jpeg z, int* out_x, int* out_y, int* comp, int req_comp) { int n; int decode_n; + int is_rgb; z.s.img_n = (int) (0); if (((req_comp) < (0)) || ((req_comp) > (4))) - return ((byte*) ((ulong) ((stbi__err("bad req_comp")) != 0 ? (byte*) null : null))); + return ((byte*) ((ulong) ((stbi__err("bad req_comp")) != 0 ? ((byte*) null) : (null)))); if (stbi__decode_jpeg_image(z) == 0) { stbi__cleanup_jpeg(z); - return null; + return (null); } - n = (int) ((req_comp) != 0 ? req_comp : z.s.img_n); - if (((z.s.img_n) == (3)) && ((n) < (3))) decode_n = (int) (1); + n = (int) ((req_comp) != 0 ? req_comp : (z.s.img_n) >= (3) ? 3 : 1); + is_rgb = + (int) + (((z.s.img_n) == (3)) && (((z.rgb) == (3)) || (((z.app14_color_transform) == (0)) && (z.jfif == 0))) + ? 1 + : 0); + if ((((z.s.img_n) == (3)) && ((n) < (3))) && (is_rgb == 0)) decode_n = (int) (1); else decode_n = (int) (z.s.img_n); { int k; @@ -1721,7 +2094,7 @@ public static void stbi__cleanup_jpeg(stbi__jpeg j) if (z.img_comp[k].linebuf == null) { stbi__cleanup_jpeg(z); - return ((byte*) ((ulong) ((stbi__err("outofmem")) != 0 ? (byte*) null : null))); + return ((byte*) ((ulong) ((stbi__err("outofmem")) != 0 ? ((byte*) null) : (null)))); } r.hs = (int) (z.img_h_max/z.img_comp[k].h); r.vs = (int) (z.img_v_max/z.img_comp[k].v); @@ -1735,11 +2108,11 @@ public static void stbi__cleanup_jpeg(stbi__jpeg j) else if (((r.hs) == (2)) && ((r.vs) == (2))) r.resample = z.resample_row_hv_2_kernel; else r.resample = stbi__resample_row_generic; } - output = (byte*) (stbi__malloc((ulong) (n*z.s.img_x*z.s.img_y + 1))); + output = (byte*) (stbi__malloc_mad3((int) (n), (int) (z.s.img_x), (int) (z.s.img_y), (int) (1))); if (output == null) { stbi__cleanup_jpeg(z); - return ((byte*) ((ulong) ((stbi__err("outofmem")) != 0 ? (byte*) null : null))); + return ((byte*) ((ulong) ((stbi__err("outofmem")) != 0 ? ((byte*) null) : (null)))); } for (j = (uint) (0); (j) < (z.s.img_y); ++j) { @@ -1763,7 +2136,7 @@ public static void stbi__cleanup_jpeg(stbi__jpeg j) byte* y = coutput[0]; if ((z.s.img_n) == (3)) { - if ((z.rgb) == (3)) + if ((is_rgb) != 0) { for (i = (uint) (0); (i) < (z.s.img_x); ++i) { @@ -1779,6 +2152,37 @@ public static void stbi__cleanup_jpeg(stbi__jpeg j) z.YCbCr_to_RGB_kernel(_out_, y, coutput[1], coutput[2], (int) (z.s.img_x), (int) (n)); } } + else if ((z.s.img_n) == (4)) + { + if ((z.app14_color_transform) == (0)) + { + for (i = (uint) (0); (i) < (z.s.img_x); ++i) + { + byte m = (byte) (coutput[3][i]); + _out_[0] = (byte) (stbi__blinn_8x8((byte) (coutput[0][i]), (byte) (m))); + _out_[1] = (byte) (stbi__blinn_8x8((byte) (coutput[1][i]), (byte) (m))); + _out_[2] = (byte) (stbi__blinn_8x8((byte) (coutput[2][i]), (byte) (m))); + _out_[3] = (byte) (255); + _out_ += n; + } + } + else if ((z.app14_color_transform) == (2)) + { + z.YCbCr_to_RGB_kernel(_out_, y, coutput[1], coutput[2], (int) (z.s.img_x), (int) (n)); + for (i = (uint) (0); (i) < (z.s.img_x); ++i) + { + byte m = (byte) (coutput[3][i]); + _out_[0] = (byte) (stbi__blinn_8x8((byte) (255 - _out_[0]), (byte) (m))); + _out_[1] = (byte) (stbi__blinn_8x8((byte) (255 - _out_[1]), (byte) (m))); + _out_[2] = (byte) (stbi__blinn_8x8((byte) (255 - _out_[2]), (byte) (m))); + _out_ += n; + } + } + else + { + z.YCbCr_to_RGB_kernel(_out_, y, coutput[1], coutput[2], (int) (z.s.img_x), (int) (n)); + } + } else for (i = (uint) (0); (i) < (z.s.img_x); ++i) { @@ -1789,30 +2193,79 @@ public static void stbi__cleanup_jpeg(stbi__jpeg j) } else { - byte* y = coutput[0]; - if ((n) == (1)) + if ((is_rgb) != 0) + { + if ((n) == (1)) + for (i = (uint) (0); (i) < (z.s.img_x); ++i) + { + *_out_++ = + (byte) + (stbi__compute_y((int) (coutput[0][i]), (int) (coutput[1][i]), + (int) (coutput[2][i]))); + } + else + { + for (i = (uint) (0); (i) < (z.s.img_x); ++i , _out_ += 2) + { + _out_[0] = + (byte) + (stbi__compute_y((int) (coutput[0][i]), (int) (coutput[1][i]), + (int) (coutput[2][i]))); + _out_[1] = (byte) (255); + } + } + } + else if (((z.s.img_n) == (4)) && ((z.app14_color_transform) == (0))) + { for (i = (uint) (0); (i) < (z.s.img_x); ++i) { - _out_[i] = (byte) (y[i]); + byte m = (byte) (coutput[3][i]); + byte r = (byte) (stbi__blinn_8x8((byte) (coutput[0][i]), (byte) (m))); + byte g = (byte) (stbi__blinn_8x8((byte) (coutput[1][i]), (byte) (m))); + byte b = (byte) (stbi__blinn_8x8((byte) (coutput[2][i]), (byte) (m))); + _out_[0] = (byte) (stbi__compute_y((int) (r), (int) (g), (int) (b))); + _out_[1] = (byte) (255); + _out_ += n; } - else + } + else if (((z.s.img_n) == (4)) && ((z.app14_color_transform) == (2))) + { for (i = (uint) (0); (i) < (z.s.img_x); ++i) { - *_out_++ = (byte) (y[i]); - *_out_++ = (byte) (255); + _out_[0] = + (byte) (stbi__blinn_8x8((byte) (255 - coutput[0][i]), (byte) (coutput[3][i]))); + _out_[1] = (byte) (255); + _out_ += n; } + } + else + { + byte* y = coutput[0]; + if ((n) == (1)) + for (i = (uint) (0); (i) < (z.s.img_x); ++i) + { + _out_[i] = (byte) (y[i]); + } + else + for (i = (uint) (0); (i) < (z.s.img_x); ++i) + { + *_out_++ = (byte) (y[i]); + *_out_++ = (byte) (255); + } + } } } stbi__cleanup_jpeg(z); *out_x = (int) (z.s.img_x); *out_y = (int) (z.s.img_y); - if ((comp) != null) *comp = (int) (z.s.img_n); + if ((comp) != null) *comp = (int) ((z.s.img_n) >= (3) ? 3 : 1); return output; } } - public static byte* stbi__jpeg_load(stbi__context s, int* x, int* y, int* comp, int req_comp) + public static void* stbi__jpeg_load(stbi__context s, int* x, int* y, int* comp, int req_comp, + stbi__result_info* ri) { byte* result; stbi__jpeg j = new stbi__jpeg(); @@ -1831,6 +2284,7 @@ public static int stbi__jpeg_test(stbi__context s) stbi__setup_jpeg(j); r = (int) (stbi__decode_jpeg_header(j, (int) (STBI__SCAN_type))); stbi__rewind(s); + return (int) (r); } @@ -1844,7 +2298,7 @@ public static int stbi__jpeg_info_raw(stbi__jpeg j, int* x, int* y, int* comp) if ((x) != null) *x = (int) (j.s.img_x); if ((y) != null) *y = (int) (j.s.img_y); - if ((comp) != null) *comp = (int) (j.s.img_n); + if ((comp) != null) *comp = (int) ((j.s.img_n) >= (3) ? 3 : 1); return (int) (1); } @@ -2001,7 +2455,7 @@ public static int stbi__zexpand(stbi__zbuf* z, sbyte* zout, int n) limit *= (int) (2); } q = (sbyte*) (realloc(z->zout_start, (ulong) (limit))); - if ((q) == null) return (int) (stbi__err("outofmem")); + if ((q) == (null)) return (int) (stbi__err("outofmem")); z->zout_start = q; z->zout = q + cur; z->zout_end = q + limit; @@ -2077,6 +2531,7 @@ public static int stbi__compute_huffman_codes(stbi__zbuf* a) int hlit = (int) (stbi__zreceive(a, (int) (5)) + 257); int hdist = (int) (stbi__zreceive(a, (int) (5)) + 1); int hclen = (int) (stbi__zreceive(a, (int) (4)) + 4); + int ntot = (int) (hlit + hdist); memset(((byte*) (codelength_sizes)), (int) (0), (ulong) (19*sizeof (byte))); for (i = (int) (0); (i) < (hclen); ++i) { @@ -2085,31 +2540,31 @@ public static int stbi__compute_huffman_codes(stbi__zbuf* a) } if (stbi__zbuild_huffman(&z_codelength, codelength_sizes, (int) (19)) == 0) return (int) (0); n = (int) (0); - while ((n) < (hlit + hdist)) + while ((n) < (ntot)) { int c = (int) (stbi__zhuffman_decode(a, &z_codelength)); if (((c) < (0)) || ((c) >= (19))) return (int) (stbi__err("bad codelengths")); if ((c) < (16)) lencodes[n++] = ((byte) (c)); - else if ((c) == (16)) - { - c = (int) (stbi__zreceive(a, (int) (2)) + 3); - memset(lencodes + n, (int) (lencodes[n - 1]), (ulong) (c)); - n += (int) (c); - } - else if ((c) == (17)) - { - c = (int) (stbi__zreceive(a, (int) (3)) + 3); - memset(lencodes + n, (int) (0), (ulong) (c)); - n += (int) (c); - } else { - c = (int) (stbi__zreceive(a, (int) (7)) + 11); - memset(lencodes + n, (int) (0), (ulong) (c)); + byte fill = (byte) (0); + if ((c) == (16)) + { + c = (int) (stbi__zreceive(a, (int) (2)) + 3); + if ((n) == (0)) return (int) (stbi__err("bad codelengths")); + fill = (byte) (lencodes[n - 1]); + } + else if ((c) == (17)) c = (int) (stbi__zreceive(a, (int) (3)) + 3); + else + { + c = (int) (stbi__zreceive(a, (int) (7)) + 11); + } + if ((ntot - n) < (c)) return (int) (stbi__err("bad codelengths")); + memset(lencodes + n, (int) (fill), (ulong) (c)); n += (int) (c); } } - if (n != hlit + hdist) return (int) (stbi__err("bad codelengths")); + if (n != ntot) return (int) (stbi__err("bad codelengths")); if (stbi__zbuild_huffman(&a->z_length, lencodes, (int) (hlit)) == 0) return (int) (0); if (stbi__zbuild_huffman(&a->z_distance, lencodes + hlit, (int) (hdist)) == 0) return (int) (0); return (int) (1); @@ -2155,31 +2610,6 @@ public static int stbi__parse_zlib_header(stbi__zbuf* a) return (int) (1); } - public static void stbi__init_zdefaults() - { - int i; - for (i = (int) (0); i <= 143; ++i) - { - stbi__zdefault_length[i] = (byte) (8); - } - for (; i <= 255; ++i) - { - stbi__zdefault_length[i] = (byte) (9); - } - for (; i <= 279; ++i) - { - stbi__zdefault_length[i] = (byte) (7); - } - for (; i <= 287; ++i) - { - stbi__zdefault_length[i] = (byte) (8); - } - for (i = (int) (0); i <= 31; ++i) - { - stbi__zdefault_distance[i] = (byte) (5); - } - } - public static int stbi__parse_zlib(stbi__zbuf* a, int parse_header) { int final; @@ -2203,7 +2633,6 @@ public static int stbi__parse_zlib(stbi__zbuf* a, int parse_header) { if ((type) == (1)) { - if (stbi__zdefault_distance[31] == 0) stbi__init_zdefaults(); fixed (byte* b = stbi__zdefault_length) { if (stbi__zbuild_huffman(&a->z_length, b, (int) (288)) == 0) return (int) (0); @@ -2236,7 +2665,7 @@ public static int stbi__do_zlib(stbi__zbuf* a, sbyte* obuf, int olen, int exp, i { stbi__zbuf a = new stbi__zbuf(); sbyte* p = (sbyte*) (stbi__malloc((ulong) (initial_size))); - if ((p) == null) return null; + if ((p) == (null)) return (null); a.zbuffer = (byte*) (buffer); a.zbuffer_end = (byte*) (buffer) + len; if ((stbi__do_zlib(&a, p, (int) (initial_size), (int) (1), (int) (1))) != 0) @@ -2247,7 +2676,7 @@ public static int stbi__do_zlib(stbi__zbuf* a, sbyte* obuf, int olen, int exp, i else { free(a.zout_start); - return null; + return (null); } } @@ -2262,7 +2691,7 @@ public static int stbi__do_zlib(stbi__zbuf* a, sbyte* obuf, int olen, int exp, i { stbi__zbuf a = new stbi__zbuf(); sbyte* p = (sbyte*) (stbi__malloc((ulong) (initial_size))); - if ((p) == null) return null; + if ((p) == (null)) return (null); a.zbuffer = (byte*) (buffer); a.zbuffer_end = (byte*) (buffer) + len; if ((stbi__do_zlib(&a, p, (int) (initial_size), (int) (1), (int) (parse_header))) != 0) @@ -2273,7 +2702,7 @@ public static int stbi__do_zlib(stbi__zbuf* a, sbyte* obuf, int olen, int exp, i else { free(a.zout_start); - return null; + return (null); } } @@ -2292,7 +2721,7 @@ public static int stbi_zlib_decode_buffer(sbyte* obuffer, int olen, sbyte* ibuff { stbi__zbuf a = new stbi__zbuf(); sbyte* p = (sbyte*) (stbi__malloc((ulong) (16384))); - if ((p) == null) return null; + if ((p) == (null)) return (null); a.zbuffer = (byte*) (buffer); a.zbuffer_end = (byte*) (buffer) + len; if ((stbi__do_zlib(&a, p, (int) (16384), (int) (1), (int) (0))) != 0) @@ -2303,7 +2732,7 @@ public static int stbi_zlib_decode_buffer(sbyte* obuffer, int olen, sbyte* ibuff else { free(a.zout_start); - return null; + return (null); } } @@ -2362,32 +2791,24 @@ public static int stbi__paeth(int a, int b, int c) int output_bytes = (int) (out_n*bytes); int filter_bytes = (int) (img_n*bytes); int width = (int) (x); - a._out_ = (byte*) (stbi__malloc((ulong) (x*y*output_bytes))); + a._out_ = (byte*) (stbi__malloc_mad3((int) (x), (int) (y), (int) (output_bytes), (int) (0))); if (a._out_ == null) return (int) (stbi__err("outofmem")); img_width_bytes = (uint) (((img_n*x*depth) + 7) >> 3); img_len = (uint) ((img_width_bytes + 1)*y); - if (((s.img_x) == (x)) && ((s.img_y) == (y))) - { - if (raw_len != img_len) return (int) (stbi__err("not enough pixels")); - } - else - { - if ((raw_len) < (img_len)) return (int) (stbi__err("not enough pixels")); - } - + if ((raw_len) < (img_len)) return (int) (stbi__err("not enough pixels")); for (j = (uint) (0); (j) < (y); ++j) { byte* cur = a._out_ + stride*j; - byte* prior = cur - stride; + byte* prior; int filter = (int) (*raw++); if ((filter) > (4)) return (int) (stbi__err("invalid filter")); if ((depth) < (8)) { cur += x*out_n - img_width_bytes; - prior = cur - stride; filter_bytes = (int) (1); width = (int) (img_width_bytes); } + prior = cur - stride; if ((j) == (0)) filter = (int) (first_row_filter[filter]); for (k = (int) (0); (k) < (filter_bytes); ++k) { @@ -2694,6 +3115,8 @@ public static int stbi__paeth(int a, int b, int c) int depth, int color, int interlaced) { + int bytes = (int) ((depth) == (16) ? 2 : 1); + int out_bytes = (int) (out_n*bytes); byte* final; int p; if (interlaced == 0) @@ -2702,7 +3125,7 @@ public static int stbi__paeth(int a, int b, int c) (stbi__create_png_image_raw(a, image_data, (uint) (image_data_len), (int) (out_n), (uint) (a.s.img_x), (uint) (a.s.img_y), (int) (depth), (int) (color))); - final = (byte*) (stbi__malloc((ulong) (a.s.img_x*a.s.img_y*out_n))); + final = (byte*) (stbi__malloc_mad3((int) (a.s.img_x), (int) (a.s.img_y), (int) (out_bytes), (int) (0))); for (p = (int) (0); (p) < (7); ++p) { int* xorig = stackalloc int[7]; @@ -2760,8 +3183,8 @@ public static int stbi__paeth(int a, int b, int c) { int out_y = (int) (j*yspc[p] + yorig[p]); int out_x = (int) (i*xspc[p] + xorig[p]); - memcpy(final + out_y*a.s.img_x*out_n + out_x*out_n, a._out_ + (j*x + i)*out_n, - (ulong) (out_n)); + memcpy(final + out_y*a.s.img_x*out_bytes + out_x*out_bytes, a._out_ + (j*x + i)*out_bytes, + (ulong) (out_bytes)); } } free(a._out_); @@ -2832,8 +3255,8 @@ public static int stbi__expand_png_palette(stbi__png a, byte* palette, int len, byte* p; byte* temp_out; byte* orig = a._out_; - p = (byte*) (stbi__malloc((ulong) (pixel_count*pal_img_n))); - if (p == null) return (int) (stbi__err("outofmem")); + p = (byte*) (stbi__malloc_mad2((int) (pixel_count), (int) (pal_img_n), (int) (0))); + if ((p) == (null)) return (int) (stbi__err("outofmem")); temp_out = p; if ((pal_img_n) == (3)) { @@ -2864,24 +3287,6 @@ public static int stbi__expand_png_palette(stbi__png a, byte* palette, int len, return (int) (1); } - public static int stbi__reduce_png(stbi__png p) - { - int i; - int img_len = (int) (p.s.img_x*p.s.img_y*p.s.img_out_n); - byte* reduced; - ushort* orig = (ushort*) (p._out_); - if (p.depth != 16) return (int) (1); - reduced = (byte*) (stbi__malloc((ulong) (img_len))); - if (p == null) return (int) (stbi__err("outofmem")); - for (i = (int) (0); (i) < (img_len); ++i) - { - reduced[i] = ((byte) ((orig[i] >> 8) & 0xFF)); - } - p._out_ = reduced; - free(orig); - return (int) (1); - } - public static void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) { stbi__unpremultiply_on_load = (int) (flag_true_if_should_unpremultiply); @@ -2918,9 +3323,10 @@ public static void stbi__de_iphone(stbi__png z) byte t = (byte) (p[0]); if ((a) != 0) { - p[0] = (byte) (p[2]*255/a); - p[1] = (byte) (p[1]*255/a); - p[2] = (byte) (t*255/a); + byte half = (byte) (a/2); + p[0] = (byte) ((p[2]*255 + half)/a); + p[1] = (byte) ((p[1]*255 + half)/a); + p[2] = (byte) ((t*255 + half)/a); } else { @@ -2961,9 +3367,9 @@ public static int stbi__parse_png_file(stbi__png z, int scan, int req_comp) int color = (int) (0); int is_iphone = (int) (0); stbi__context s = z.s; - z.expanded = null; - z.idata = null; - z._out_ = null; + z.expanded = (null); + z.idata = (null); + z._out_ = (null); if (stbi__check_png_header(s) == 0) return (int) (0); if ((scan) == (STBI__SCAN_type)) return (int) (1); for (;;) @@ -3058,7 +3464,7 @@ public static int stbi__parse_png_file(stbi__png z, int scan, int req_comp) { for (k = (int) (0); (k) < (s.img_n); ++k) { - tc16[k] = (ushort) (stbi__get16be(s)); + tc16[k] = ((ushort) (stbi__get16be(s))); } } else @@ -3091,7 +3497,7 @@ public static int stbi__parse_png_file(stbi__png z, int scan, int req_comp) idata_limit *= (uint) (2); } p = (byte*) (realloc(z.idata, (ulong) (idata_limit))); - if (p == null) return (int) (stbi__err("outofmem")); + if ((p) == (null)) return (int) (stbi__err("outofmem")); z.idata = p; } if (stbi__getn(s, z.idata + ioff, (int) (c.length)) == 0) return (int) (stbi__err("outofdata")); @@ -3104,7 +3510,7 @@ public static int stbi__parse_png_file(stbi__png z, int scan, int req_comp) uint bpl; if ((first) != 0) return (int) (stbi__err("first not IHDR")); if (scan != STBI__SCAN_load) return (int) (1); - if ((z.idata) == null) return (int) (stbi__err("no IDAT")); + if ((z.idata) == (null)) return (int) (stbi__err("no IDAT")); bpl = (uint) ((s.img_x*z.depth + 7)/8); raw_len = (uint) (bpl*s.img_y*s.img_n + s.img_y); z.expanded = @@ -3112,9 +3518,9 @@ public static int stbi__parse_png_file(stbi__png z, int scan, int req_comp) (stbi_zlib_decode_malloc_guesssize_headerflag((sbyte*) (z.idata), (int) (ioff), (int) (raw_len), (int*) (&raw_len), is_iphone != 0 ? 0 : 1)); - if ((z.expanded) == null) return (int) (0); + if ((z.expanded) == (null)) return (int) (0); free(z.idata); - z.idata = null; + z.idata = (null); if (((((req_comp) == (s.img_n + 1)) && (req_comp != 3)) && (pal_img_n == 0)) || ((has_trans) != 0)) s.img_out_n = (int) (s.img_n + 1); @@ -3144,15 +3550,19 @@ public static int stbi__parse_png_file(stbi__png z, int scan, int req_comp) if (stbi__expand_png_palette(z, palette, (int) (pal_len), (int) (s.img_out_n)) == 0) return (int) (0); } + else if ((has_trans) != 0) + { + ++s.img_n; + } free(z.expanded); - z.expanded = null; + z.expanded = (null); return (int) (1); } default: if ((first) != 0) return (int) (stbi__err("first not IHDR")); if ((c.type & (1 << 29)) == (0)) { - var invalid_chunk = "XXXX PNG chunk not known"; + string invalid_chunk = "XXXX PNG chunk not known"; return (int) (stbi__err(invalid_chunk)); } stbi__skip(s, (int) (c.length)); @@ -3162,28 +3572,29 @@ public static int stbi__parse_png_file(stbi__png z, int scan, int req_comp) } } - public static byte* stbi__do_png(stbi__png p, int* x, int* y, int* n, int req_comp) + public static void* stbi__do_png(stbi__png p, int* x, int* y, int* n, int req_comp, stbi__result_info* ri) { - byte* result = null; + void* result = (null); if (((req_comp) < (0)) || ((req_comp) > (4))) - return ((byte*) ((ulong) ((stbi__err("bad req_comp")) != 0 ? (byte*) null : null))); + return ((byte*) ((ulong) ((stbi__err("bad req_comp")) != 0 ? ((byte*) null) : (null)))); if ((stbi__parse_png_file(p, (int) (STBI__SCAN_load), (int) (req_comp))) != 0) { - if ((p.depth) == (16)) - { - if (stbi__reduce_png(p) == 0) - { - return result; - } - } + if ((p.depth) < (8)) ri->bits_per_channel = (int) (8); + else ri->bits_per_channel = (int) (p.depth); result = p._out_; - p._out_ = null; + p._out_ = (null); if (((req_comp) != 0) && (req_comp != p.s.img_out_n)) { - result = stbi__convert_format(result, (int) (p.s.img_out_n), (int) (req_comp), (uint) (p.s.img_x), - (uint) (p.s.img_y)); + if ((ri->bits_per_channel) == (8)) + result = stbi__convert_format((byte*) (result), (int) (p.s.img_out_n), (int) (req_comp), + (uint) (p.s.img_x), + (uint) (p.s.img_y)); + else + result = stbi__convert_format16((ushort*) (result), (int) (p.s.img_out_n), (int) (req_comp), + (uint) (p.s.img_x), + (uint) (p.s.img_y)); p.s.img_out_n = (int) (req_comp); - if ((result) == null) return result; + if ((result) == (null)) return result; } *x = (int) (p.s.img_x); *y = (int) (p.s.img_y); @@ -3191,19 +3602,20 @@ public static int stbi__parse_png_file(stbi__png z, int scan, int req_comp) } free(p._out_); - p._out_ = null; + p._out_ = (null); free(p.expanded); - p.expanded = null; + p.expanded = (null); free(p.idata); - p.idata = null; + p.idata = (null); return result; } - public static byte* stbi__png_load(stbi__context s, int* x, int* y, int* comp, int req_comp) + public static void* stbi__png_load(stbi__context s, int* x, int* y, int* comp, int req_comp, + stbi__result_info* ri) { stbi__png p = new stbi__png(); p.s = s; - return stbi__do_png(p, x, y, comp, (int) (req_comp)); + return stbi__do_png(p, x, y, comp, (int) (req_comp), ri); } public static int stbi__png_test(stbi__context s) @@ -3328,7 +3740,7 @@ public static int stbi__shiftsigned(int v, int shift, int bits) { int hsz; if ((stbi__get8(s) != 'B') || (stbi__get8(s) != 'M')) - return ((byte*) ((ulong) ((stbi__err("not BMP")) != 0 ? (byte*) null : null))); + return ((byte*) ((ulong) ((stbi__err("not BMP")) != 0 ? ((byte*) null) : (null)))); stbi__get32le(s); stbi__get16le(s); stbi__get16le(s); @@ -3336,7 +3748,7 @@ public static int stbi__shiftsigned(int v, int shift, int bits) info->hsz = (int) (hsz = (int) (stbi__get32le(s))); info->mr = (uint) (info->mg = (uint) (info->mb = (uint) (info->ma = (uint) (0)))); if (((((hsz != 12) && (hsz != 40)) && (hsz != 56)) && (hsz != 108)) && (hsz != 124)) - return ((byte*) ((ulong) ((stbi__err("unknown BMP")) != 0 ? (byte*) null : null))); + return ((byte*) ((ulong) ((stbi__err("unknown BMP")) != 0 ? ((byte*) null) : (null)))); if ((hsz) == (12)) { s.img_x = (uint) (stbi__get16le(s)); @@ -3348,14 +3760,16 @@ public static int stbi__shiftsigned(int v, int shift, int bits) s.img_y = (uint) (stbi__get32le(s)); } - if (stbi__get16le(s) != 1) return ((byte*) ((ulong) ((stbi__err("bad BMP")) != 0 ? (byte*) null : null))); + if (stbi__get16le(s) != 1) + return ((byte*) ((ulong) ((stbi__err("bad BMP")) != 0 ? ((byte*) null) : (null)))); info->bpp = (int) (stbi__get16le(s)); - if ((info->bpp) == (1)) return ((byte*) ((ulong) ((stbi__err("monochrome")) != 0 ? (byte*) null : null))); + if ((info->bpp) == (1)) + return ((byte*) ((ulong) ((stbi__err("monochrome")) != 0 ? ((byte*) null) : (null)))); if (hsz != 12) { int compress = (int) (stbi__get32le(s)); if (((compress) == (1)) || ((compress) == (2))) - return ((byte*) ((ulong) ((stbi__err("BMP RLE")) != 0 ? (byte*) null : null))); + return ((byte*) ((ulong) ((stbi__err("BMP RLE")) != 0 ? ((byte*) null) : (null)))); stbi__get32le(s); stbi__get32le(s); stbi__get32le(s); @@ -3396,17 +3810,17 @@ public static int stbi__shiftsigned(int v, int shift, int bits) info->mb = (uint) (stbi__get32le(s)); if (((info->mr) == (info->mg)) && ((info->mg) == (info->mb))) { - return ((byte*) ((ulong) ((stbi__err("bad BMP")) != 0 ? (byte*) null : null))); + return ((byte*) ((ulong) ((stbi__err("bad BMP")) != 0 ? ((byte*) null) : (null)))); } } - else return ((byte*) ((ulong) ((stbi__err("bad BMP")) != 0 ? (byte*) null : null))); + else return ((byte*) ((ulong) ((stbi__err("bad BMP")) != 0 ? ((byte*) null) : (null)))); } } else { int i; if ((hsz != 108) && (hsz != 124)) - return ((byte*) ((ulong) ((stbi__err("bad BMP")) != 0 ? (byte*) null : null))); + return ((byte*) ((ulong) ((stbi__err("bad BMP")) != 0 ? ((byte*) null) : (null)))); info->mr = (uint) (stbi__get32le(s)); info->mg = (uint) (stbi__get32le(s)); info->mb = (uint) (stbi__get32le(s)); @@ -3429,7 +3843,8 @@ public static int stbi__shiftsigned(int v, int shift, int bits) return (void*) (1); } - public static byte* stbi__bmp_load(stbi__context s, int* x, int* y, int* comp, int req_comp) + public static void* stbi__bmp_load(stbi__context s, int* x, int* y, int* comp, int req_comp, + stbi__result_info* ri) { byte* _out_; uint mr = (uint) (0); @@ -3447,7 +3862,7 @@ public static int stbi__shiftsigned(int v, int shift, int bits) int target; stbi__bmp_data info = new stbi__bmp_data(); info.all_a = (uint) (255); - if ((stbi__bmp_parse_header(s, &info)) == null) return null; + if ((stbi__bmp_parse_header(s, &info)) == (null)) return (null); flip_vertically = (int) (((int) (s.img_y)) > (0) ? 1 : 0); s.img_y = (uint) (abs((int) (s.img_y))); mr = (uint) (info.mr); @@ -3467,15 +3882,17 @@ public static int stbi__shiftsigned(int v, int shift, int bits) s.img_n = (int) ((ma) != 0 ? 4 : 3); if (((req_comp) != 0) && ((req_comp) >= (3))) target = (int) (req_comp); else target = (int) (s.img_n); - _out_ = (byte*) (stbi__malloc((ulong) (target*s.img_x*s.img_y))); - if (_out_ == null) return ((byte*) ((ulong) ((stbi__err("outofmem")) != 0 ? (byte*) null : null))); + if (stbi__mad3sizes_valid((int) (target), (int) (s.img_x), (int) (s.img_y), (int) (0)) == 0) + return ((byte*) ((ulong) ((stbi__err("too large")) != 0 ? ((byte*) null) : (null)))); + _out_ = (byte*) (stbi__malloc_mad3((int) (target), (int) (s.img_x), (int) (s.img_y), (int) (0))); + if (_out_ == null) return ((byte*) ((ulong) ((stbi__err("outofmem")) != 0 ? ((byte*) null) : (null)))); if ((info.bpp) < (16)) { int z = (int) (0); if (((psize) == (0)) || ((psize) > (256))) { free(_out_); - return ((byte*) ((ulong) ((stbi__err("invalid")) != 0 ? (byte*) null : null))); + return ((byte*) ((ulong) ((stbi__err("invalid")) != 0 ? ((byte*) null) : (null)))); } for (i = (int) (0); (i) < (psize); ++i) { @@ -3491,7 +3908,7 @@ public static int stbi__shiftsigned(int v, int shift, int bits) else { free(_out_); - return ((byte*) ((ulong) ((stbi__err("bad bpp")) != 0 ? (byte*) null : null))); + return ((byte*) ((ulong) ((stbi__err("bad bpp")) != 0 ? ((byte*) null) : (null)))); } pad = (int) ((-width) & 3); for (j = (int) (0); (j) < ((int) (s.img_y)); ++j) @@ -3550,7 +3967,7 @@ public static int stbi__shiftsigned(int v, int shift, int bits) if (((mr == 0) || (mg == 0)) || (mb == 0)) { free(_out_); - return ((byte*) ((ulong) ((stbi__err("bad masks")) != 0 ? (byte*) null : null))); + return ((byte*) ((ulong) ((stbi__err("bad masks")) != 0 ? ((byte*) null) : (null)))); } rshift = (int) (stbi__high_bit((uint) (mr)) - 7); rcount = (int) (stbi__bitcount((uint) (mr))); @@ -3625,7 +4042,7 @@ public static int stbi__shiftsigned(int v, int shift, int bits) if (((req_comp) != 0) && (req_comp != target)) { _out_ = stbi__convert_format(_out_, (int) (target), (int) (req_comp), (uint) (s.img_x), (uint) (s.img_y)); - if ((_out_) == null) return _out_; + if ((_out_) == (null)) return _out_; } *x = (int) (s.img_x); @@ -3643,10 +4060,7 @@ public static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rg return (int) (STBI_grey); case 15: case 16: - if (bits_per_pixel == 16) - { - if ((is_grey) != 0) return (int) (STBI_grey_alpha); - } + if (((bits_per_pixel) == (16)) && ((is_grey) != 0)) return (int) (STBI_grey_alpha); if ((is_rgb16) != null) *is_rgb16 = (int) (1); return (int) (STBI_rgb); case 24: @@ -3729,14 +4143,14 @@ public static int stbi__tga_info(stbi__context s, int* x, int* y, int* comp) stbi__rewind(s); return (int) (0); } - tga_comp = (int) (stbi__tga_get_comp((int) (tga_colormap_bpp), (int) (0), null)); + tga_comp = (int) (stbi__tga_get_comp((int) (tga_colormap_bpp), (int) (0), (null))); } else { tga_comp = (int) (stbi__tga_get_comp((int) (tga_bits_per_pixel), - (((tga_image_type) == (3))) || (((tga_image_type) == (11))) ? 1 : 0, null)); + (((tga_image_type) == (3))) || (((tga_image_type) == (11))) ? 1 : 0, (null))); } if (tga_comp == 0) @@ -3793,12 +4207,13 @@ public static void stbi__tga_read_rgb16(stbi__context s, byte* _out_) int r = (int) ((px >> 10) & fiveBitMask); int g = (int) ((px >> 5) & fiveBitMask); int b = (int) (px & fiveBitMask); - _out_[0] = (byte) ((r*255)/31); - _out_[1] = (byte) ((g*255)/31); - _out_[2] = (byte) ((b*255)/31); + _out_[0] = ((byte) ((r*255)/31)); + _out_[1] = ((byte) ((g*255)/31)); + _out_[2] = ((byte) ((b*255)/31)); } - public static byte* stbi__tga_load(stbi__context s, int* x, int* y, int* comp, int req_comp) + public static void* stbi__tga_load(stbi__context s, int* x, int* y, int* comp, int req_comp, + stbi__result_info* ri) { int tga_offset = (int) (stbi__get8(s)); int tga_indexed = (int) (stbi__get8(s)); @@ -3816,10 +4231,12 @@ public static void stbi__tga_read_rgb16(stbi__context s, byte* _out_) int tga_rgb16 = (int) (0); int tga_inverted = (int) (stbi__get8(s)); byte* tga_data; - byte* tga_palette = null; + byte* tga_palette = (null); int i; int j; byte* raw_data = stackalloc byte[4]; + raw_data[0] = (byte) (0); + int RLE_count = (int) (0); int RLE_repeating = (int) (0); int read_next_pixel = (int) (1); @@ -3834,14 +4251,15 @@ public static void stbi__tga_read_rgb16(stbi__context s, byte* _out_) tga_comp = (int) (stbi__tga_get_comp((int) (tga_palette_bits), (int) (0), &tga_rgb16)); else tga_comp = - (int) - (stbi__tga_get_comp((int) (tga_bits_per_pixel), ((tga_image_type) == (3)) ? 1 : 0, &tga_rgb16)); - if (tga_comp == 0) return ((byte*) ((ulong) ((stbi__err("bad format")) != 0 ? (byte*) null : null))); + (int) (stbi__tga_get_comp((int) (tga_bits_per_pixel), (tga_image_type) == (3) ? 1 : 0, &tga_rgb16)); + if (tga_comp == 0) return ((byte*) ((ulong) ((stbi__err("bad format")) != 0 ? ((byte*) null) : (null)))); *x = (int) (tga_width); *y = (int) (tga_height); if ((comp) != null) *comp = (int) (tga_comp); - tga_data = (byte*) (stbi__malloc((ulong) (tga_width*tga_height*tga_comp))); - if (tga_data == null) return ((byte*) ((ulong) ((stbi__err("outofmem")) != 0 ? (byte*) null : null))); + if (stbi__mad3sizes_valid((int) (tga_width), (int) (tga_height), (int) (tga_comp), (int) (0)) == 0) + return ((byte*) ((ulong) ((stbi__err("too large")) != 0 ? ((byte*) null) : (null)))); + tga_data = (byte*) (stbi__malloc_mad3((int) (tga_width), (int) (tga_height), (int) (tga_comp), (int) (0))); + if (tga_data == null) return ((byte*) ((ulong) ((stbi__err("outofmem")) != 0 ? ((byte*) null) : (null)))); stbi__skip(s, (int) (tga_offset)); if (((tga_indexed == 0) && (tga_is_RLE == 0)) && (tga_rgb16 == 0)) { @@ -3857,11 +4275,11 @@ public static void stbi__tga_read_rgb16(stbi__context s, byte* _out_) if ((tga_indexed) != 0) { stbi__skip(s, (int) (tga_palette_start)); - tga_palette = (byte*) (stbi__malloc((ulong) (tga_palette_len*tga_comp))); + tga_palette = (byte*) (stbi__malloc_mad2((int) (tga_palette_len), (int) (tga_comp), (int) (0))); if (tga_palette == null) { free(tga_data); - return ((byte*) ((ulong) ((stbi__err("outofmem")) != 0 ? (byte*) null : null))); + return ((byte*) ((ulong) ((stbi__err("outofmem")) != 0 ? ((byte*) null) : (null)))); } if ((tga_rgb16) != 0) { @@ -3876,7 +4294,7 @@ public static void stbi__tga_read_rgb16(stbi__context s, byte* _out_) { free(tga_data); free(tga_palette); - return ((byte*) ((ulong) ((stbi__err("bad palette")) != 0 ? (byte*) null : null))); + return ((byte*) ((ulong) ((stbi__err("bad palette")) != 0 ? ((byte*) null) : (null)))); } } for (i = (int) (0); (i) < (tga_width*tga_height); ++i) @@ -3949,7 +4367,7 @@ public static void stbi__tga_read_rgb16(stbi__context s, byte* _out_) } } } - if (tga_palette != null) + if (tga_palette != (null)) { free(tga_palette); } @@ -4077,7 +4495,7 @@ public static void stbi__out_gif_code(stbi__gif g, ushort code) int clear; stbi__gif_lzw* p; lzw_cs = (byte) (stbi__get8(s)); - if ((lzw_cs) > (12)) return null; + if ((lzw_cs) > (12)) return (null); clear = (int) (1 << lzw_cs); first = (uint) (1); codesize = (int) (lzw_cs + 1); @@ -4131,19 +4549,21 @@ public static void stbi__out_gif_code(stbi__gif g, ushort code) else if (code <= avail) { if ((first) != 0) - return ((byte*) ((ulong) ((stbi__err("no clear code")) != 0 ? (byte*) null : null))); + return ((byte*) ((ulong) ((stbi__err("no clear code")) != 0 ? ((byte*) null) : (null)))); if ((oldcode) >= (0)) { p = (stbi__gif_lzw*) g.codes + avail++; if ((avail) > (4096)) - return ((byte*) ((ulong) ((stbi__err("too many codes")) != 0 ? (byte*) null : null))); + return + ((byte*) ((ulong) ((stbi__err("too many codes")) != 0 ? ((byte*) null) : (null)))); p->prefix = ((short) (oldcode)); p->first = (byte) (g.codes[oldcode].first); p->suffix = (byte) (((code) == (avail)) ? p->first : g.codes[code].first); } else if ((code) == (avail)) return - ((byte*) ((ulong) ((stbi__err("illegal code in raster")) != 0 ? (byte*) null : null))); + ((byte*) + ((ulong) ((stbi__err("illegal code in raster")) != 0 ? ((byte*) null) : (null)))); stbi__out_gif_code(g, (ushort) (code)); if (((avail & codemask) == (0)) && (avail <= 0x0FFF)) { @@ -4154,7 +4574,8 @@ public static void stbi__out_gif_code(stbi__gif g, ushort code) } else { - return ((byte*) ((ulong) ((stbi__err("illegal code in raster")) != 0 ? (byte*) null : null))); + return + ((byte*) ((ulong) ((stbi__err("illegal code in raster")) != 0 ? ((byte*) null) : (null)))); } } } @@ -4164,7 +4585,7 @@ public static void stbi__fill_gif_background(stbi__gif g, int x0, int y0, int x1 { int x; int y; - byte* c = (byte*) g.pal + g.bgindex*4; + byte* c = (byte*) g.pal + g.bgindex; for (y = (int) (y0); (y) < (y1); y += (int) (4*g.w)) { for (x = (int) (x0); (x) < (x1); x += (int) (4)) @@ -4183,9 +4604,11 @@ public static void stbi__fill_gif_background(stbi__gif g, int x0, int y0, int x1 int i; byte* prev_out = null; if (((g._out_) == null) && (stbi__gif_header(s, g, comp, (int) (0)) == 0)) return null; + if (stbi__mad3sizes_valid((int) (g.w), (int) (g.h), (int) (4), (int) (0)) == 0) + return ((byte*) ((ulong) ((stbi__err("too large")) != 0 ? ((byte*) null) : (null)))); prev_out = g._out_; - g._out_ = (byte*) (stbi__malloc((ulong) (4*g.w*g.h))); - if ((g._out_) == null) return ((byte*) ((ulong) ((stbi__err("outofmem")) != 0 ? (byte*) null : null))); + g._out_ = (byte*) (stbi__malloc_mad3((int) (4), (int) (g.w), (int) (g.h), (int) (0))); + if ((g._out_) == null) return ((byte*) ((ulong) ((stbi__err("outofmem")) != 0 ? ((byte*) null) : (null)))); switch ((g.eflags & 0x1C) >> 2) { case 0: @@ -4227,7 +4650,8 @@ public static void stbi__fill_gif_background(stbi__gif g, int x0, int y0, int x1 w = (int) (stbi__get16le(s)); h = (int) (stbi__get16le(s)); if (((x + w) > (g.w)) || ((y + h) > (g.h))) - return ((byte*) ((ulong) ((stbi__err("bad Image Descriptor")) != 0 ? (byte*) null : null))); + return + ((byte*) ((ulong) ((stbi__err("bad Image Descriptor")) != 0 ? ((byte*) null) : (null)))); g.line_size = (int) (g.w*4); g.start_x = (int) (x*4); g.start_y = (int) (y*g.line_size); @@ -4261,9 +4685,11 @@ public static void stbi__fill_gif_background(stbi__gif g, int x0, int y0, int x1 } g.color_table = (byte*) (g.pal); } - else return ((byte*) ((ulong) ((stbi__err("missing color table")) != 0 ? (byte*) null : null))); + else + return + ((byte*) ((ulong) ((stbi__err("missing color table")) != 0 ? ((byte*) null) : (null)))); o = stbi__process_gif_raster(s, g); - if ((o) == null) return null; + if ((o) == (null)) return (null); if (prev_trans != -1) g.pal[g.transparent*4 + 3] = ((byte) (prev_trans)); return o; } @@ -4294,12 +4720,13 @@ public static void stbi__fill_gif_background(stbi__gif g, int x0, int y0, int x1 case 0x3B: return null; default: - return ((byte*) ((ulong) ((stbi__err("unknown code")) != 0 ? (byte*) null : null))); + return ((byte*) ((ulong) ((stbi__err("unknown code")) != 0 ? ((byte*) null) : (null)))); } } } - public static byte* stbi__gif_load(stbi__context s, int* x, int* y, int* comp, int req_comp) + public static void* stbi__gif_load(stbi__context s, int* x, int* y, int* comp, int req_comp, + stbi__result_info* ri) { byte* u = null; stbi__gif g = new stbi__gif(); @@ -4329,10 +4756,10 @@ public static int stbi__bmp_info(stbi__context s, int* x, int* y, int* comp) info.all_a = (uint) (255); p = stbi__bmp_parse_header(s, &info); stbi__rewind(s); - if ((p) == null) return (int) (0); - *x = (int) (s.img_x); - *y = (int) (s.img_y); - *comp = (int) ((info.ma) != 0 ? 4 : 3); + if ((p) == (null)) return (int) (0); + if ((x) != null) *x = (int) (s.img_x); + if ((y) != null) *y = (int) (s.img_y); + if ((comp) != null) *comp = (int) ((info.ma) != 0 ? 4 : 3); return (int) (1); } diff --git a/MonoGame.Framework/Utilities/Imaging/Stb.Image.cs b/MonoGame.Framework/Utilities/Imaging/Stb.Image.cs index 9a1a3975956..d2df16567b6 100644 --- a/MonoGame.Framework/Utilities/Imaging/Stb.Image.cs +++ b/MonoGame.Framework/Utilities/Imaging/Stb.Image.cs @@ -55,7 +55,7 @@ public class stbi__jpeg public stbi__context s; public readonly PinnedArray huff_dc = new PinnedArray(4); public readonly PinnedArray huff_ac = new PinnedArray(4); - public readonly PinnedArray[] dequant; + public readonly PinnedArray[] dequant; public readonly PinnedArray[] fast_ac; @@ -78,6 +78,8 @@ public class stbi__jpeg public int succ_high; public int succ_low; public int eob_run; + public int jfif; + public int app14_color_transform; // Adobe APP14 tag public int rgb; public int scan_n; @@ -108,10 +110,10 @@ public stbi__jpeg() fast_ac[i] = new PinnedArray(1 << STBI__ZFAST_BITS); } - dequant = new PinnedArray[4]; + dequant = new PinnedArray[4]; for (var i = 0; i < dequant.Length; ++i) { - dequant[i] = new PinnedArray(64); + dequant[i] = new PinnedArray(64); } } }; diff --git a/MonoGame.Framework/Utilities/Imaging/Stb.ImageWrite.Generated.cs b/MonoGame.Framework/Utilities/Imaging/Stb.ImageWrite.Generated.cs index c2cbdea0010..bd192cdf9ca 100644 --- a/MonoGame.Framework/Utilities/Imaging/Stb.ImageWrite.Generated.cs +++ b/MonoGame.Framework/Utilities/Imaging/Stb.ImageWrite.Generated.cs @@ -1,4 +1,4 @@ -// Generated by Sichem at 01.04.2017 10:16:07 +// Generated by Sichem at 10/14/2017 7:35:48 AM using System; using System.Runtime.InteropServices; @@ -63,6 +63,202 @@ unsafe partial class Imaging 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D }; + public static byte[] stbiw__jpg_ZigZag = + { + 0, 1, 5, 6, 14, 15, 27, 28, 2, 4, 7, 13, 16, 26, 29, 42, 3, 8, 12, 17, 25, + 30, 41, 43, 9, 11, 18, 24, 31, 40, 44, 53, 10, 19, 23, 32, 39, 45, 52, 54, 20, 22, 33, 38, 46, 51, 55, 60, + 21, 34, 37, + 47, 50, 56, 59, 61, 35, 36, 48, 49, 57, 58, 62, 63 + }; + + public static byte[] std_dc_luminance_nrcodes = {0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}; + public static byte[] std_dc_luminance_values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; + public static byte[] std_ac_luminance_nrcodes = {0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d}; + + public static byte[] std_ac_luminance_values = + { + 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, + 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, + 0xd1, + 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, + 0x2a, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, + 0x56, + 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, + 0xa2, + 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, + 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, + 0xe3, + 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa + }; + + public static byte[] std_dc_chrominance_nrcodes = {0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0}; + public static byte[] std_dc_chrominance_values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; + public static byte[] std_ac_chrominance_nrcodes = {0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77}; + + public static byte[] std_ac_chrominance_values = + { + 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, + 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, + 0x33, + 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, + 0x27, + 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, + 0x54, + 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, + 0x77, + 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, + 0xb9, + 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, + 0xda, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa + }; + + public static ushort[,] YDC_HT = + { + {0, 2}, {2, 3}, {3, 3}, {4, 3}, {5, 3}, {6, 3}, {14, 4}, {30, 5}, {62, 6}, {126, 7}, + {254, 8}, {510, 9} + }; + + public static ushort[,] UVDC_HT = + { + {0, 2}, {1, 2}, {2, 2}, {6, 3}, {14, 4}, {30, 5}, {62, 6}, {126, 7}, {254, 8}, + {510, 9}, {1022, 10}, {2046, 11} + }; + + public static ushort[,] YAC_HT = + { + {10, 4}, {0, 2}, {1, 2}, {4, 3}, {11, 4}, {26, 5}, {120, 7}, {248, 8}, {1014, 10}, + {65410, 16}, {65411, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {12, 4}, {27, 5}, {121, 7}, + {502, 9}, + {2038, 11}, {65412, 16}, {65413, 16}, {65414, 16}, {65415, 16}, {65416, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, + {0, 0}, {28, 5}, {249, 8}, {1015, 10}, {4084, 12}, {65417, 16}, {65418, 16}, {65419, 16}, {65420, 16}, + {65421, 16}, + {65422, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {58, 6}, {503, 9}, {4085, 12}, {65423, 16}, + {65424, 16}, + {65425, 16}, {65426, 16}, {65427, 16}, {65428, 16}, {65429, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, + {59, 6}, {1016, 10}, {65430, 16}, {65431, 16}, {65432, 16}, {65433, 16}, {65434, 16}, {65435, 16}, + {65436, 16}, + {65437, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {122, 7}, {2039, 11}, {65438, 16}, {65439, 16}, + {65440, 16}, {65441, 16}, {65442, 16}, {65443, 16}, {65444, 16}, {65445, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, + {0, 0}, {123, 7}, {4086, 12}, {65446, 16}, {65447, 16}, {65448, 16}, {65449, 16}, {65450, 16}, {65451, 16}, + {65452, 16}, {65453, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {250, 8}, {4087, 12}, {65454, 16}, + {65455, 16}, {65456, 16}, {65457, 16}, {65458, 16}, {65459, 16}, {65460, 16}, {65461, 16}, {0, 0}, {0, 0}, + {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {504, 9}, {32704, 15}, {65462, 16}, {65463, 16}, {65464, 16}, {65465, 16}, + {65466, 16}, + {65467, 16}, {65468, 16}, {65469, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {505, 9}, {65470, 16}, + {65471, 16}, {65472, 16}, {65473, 16}, {65474, 16}, {65475, 16}, {65476, 16}, {65477, 16}, {65478, 16}, + {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {506, 9}, {65479, 16}, {65480, 16}, {65481, 16}, {65482, 16}, + {65483, 16}, + {65484, 16}, {65485, 16}, {65486, 16}, {65487, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {1017, 10}, + {65488, 16}, {65489, 16}, {65490, 16}, {65491, 16}, {65492, 16}, {65493, 16}, {65494, 16}, {65495, 16}, + {65496, 16}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1018, 10}, {65497, 16}, {65498, 16}, {65499, 16}, + {65500, 16}, + {65501, 16}, {65502, 16}, {65503, 16}, {65504, 16}, {65505, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, + {2040, 11}, {65506, 16}, {65507, 16}, {65508, 16}, {65509, 16}, {65510, 16}, {65511, 16}, {65512, 16}, + {65513, 16}, + {65514, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {65515, 16}, {65516, 16}, {65517, 16}, + {65518, 16}, + {65519, 16}, {65520, 16}, {65521, 16}, {65522, 16}, {65523, 16}, {65524, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, + {2041, 11}, {65525, 16}, {65526, 16}, {65527, 16}, {65528, 16}, {65529, 16}, {65530, 16}, {65531, 16}, + {65532, 16}, + {65533, 16}, {65534, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} + }; + + public static ushort[,] UVAC_HT = + { + {0, 2}, {1, 2}, {4, 3}, {10, 4}, {24, 5}, {25, 5}, {56, 6}, {120, 7}, {500, 9}, + {1014, 10}, {4084, 12}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {11, 4}, {57, 6}, {246, 8}, {501, 9}, + {2038, 11}, {4085, 12}, {65416, 16}, {65417, 16}, {65418, 16}, {65419, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, + {0, 0}, {26, 5}, {247, 8}, {1015, 10}, {4086, 12}, {32706, 15}, {65420, 16}, {65421, 16}, {65422, 16}, + {65423, 16}, + {65424, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {27, 5}, {248, 8}, {1016, 10}, {4087, 12}, + {65425, 16}, + {65426, 16}, {65427, 16}, {65428, 16}, {65429, 16}, {65430, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, + {58, 6}, {502, 9}, {65431, 16}, {65432, 16}, {65433, 16}, {65434, 16}, {65435, 16}, {65436, 16}, {65437, 16}, + {65438, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {59, 6}, {1017, 10}, {65439, 16}, {65440, 16}, + {65441, 16}, {65442, 16}, {65443, 16}, {65444, 16}, {65445, 16}, {65446, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, + {0, 0}, {121, 7}, {2039, 11}, {65447, 16}, {65448, 16}, {65449, 16}, {65450, 16}, {65451, 16}, {65452, 16}, + {65453, 16}, {65454, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {122, 7}, {2040, 11}, {65455, 16}, + {65456, 16}, {65457, 16}, {65458, 16}, {65459, 16}, {65460, 16}, {65461, 16}, {65462, 16}, {0, 0}, {0, 0}, + {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {249, 8}, {65463, 16}, {65464, 16}, {65465, 16}, {65466, 16}, {65467, 16}, + {65468, 16}, + {65469, 16}, {65470, 16}, {65471, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {503, 9}, {65472, 16}, + {65473, 16}, {65474, 16}, {65475, 16}, {65476, 16}, {65477, 16}, {65478, 16}, {65479, 16}, {65480, 16}, + {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {504, 9}, {65481, 16}, {65482, 16}, {65483, 16}, {65484, 16}, + {65485, 16}, + {65486, 16}, {65487, 16}, {65488, 16}, {65489, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {505, 9}, + {65490, 16}, {65491, 16}, {65492, 16}, {65493, 16}, {65494, 16}, {65495, 16}, {65496, 16}, {65497, 16}, + {65498, 16}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {506, 9}, {65499, 16}, {65500, 16}, {65501, 16}, {65502, 16}, + {65503, 16}, {65504, 16}, {65505, 16}, {65506, 16}, {65507, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, + {2041, 11}, {65508, 16}, {65509, 16}, {65510, 16}, {65511, 16}, {65512, 16}, {65513, 16}, {65514, 16}, + {65515, 16}, + {65516, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {16352, 14}, {65517, 16}, {65518, 16}, + {65519, 16}, + {65520, 16}, {65521, 16}, {65522, 16}, {65523, 16}, {65524, 16}, {65525, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, + {1018, 10}, {32707, 15}, {65526, 16}, {65527, 16}, {65528, 16}, {65529, 16}, {65530, 16}, {65531, 16}, + {65532, 16}, + {65533, 16}, {65534, 16}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} + }; + + public static int[] YQT = + { + 16, 11, 10, 16, 24, 40, 51, 61, 12, 12, 14, 19, 26, 58, 60, 55, 14, 13, 16, 24, 40, 57, 69, + 56, 14, 17, 22, 29, 51, 87, 80, 62, 18, 22, 37, 56, 68, 109, 103, 77, 24, 35, 55, 64, 81, 104, 113, 92, 49, + 64, 78, + 87, 103, 121, 120, 101, 72, 92, 95, 98, 112, 100, 103, 99 + }; + + public static int[] UVQT = + { + 17, 18, 24, 47, 99, 99, 99, 99, 18, 21, 26, 66, 99, 99, 99, 99, 24, 26, 56, 99, 99, 99, 99, + 99, 47, 66, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99 + }; + + public static float[] aasf = + { + 1.0f*2.828427125f, 1.387039845f*2.828427125f, 1.306562965f*2.828427125f, + 1.175875602f*2.828427125f, 1.0f*2.828427125f, 0.785694958f*2.828427125f, 0.541196100f*2.828427125f, + 0.275899379f*2.828427125f + }; + + public static byte[] head0 = + { + 0xFF, 0xD8, 0xFF, 0xE0, 0, 0x10, (byte) ('J'), (byte) ('F'), (byte) ('I'), (byte) ('F'), + 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0xFF, 0xDB, 0, 0x84, 0 + }; + + public static byte[] head2 = {0xFF, 0xDA, 0, 0xC, 3, 1, 0, 2, 0x11, 3, 0x11, 0, 0x3F, 0}; + + public static void stbiw__putc(stbi__write_context s, byte c) + { + s.func(s.context, &c, (int) (1)); + } + public static void stbiw__write3(stbi__write_context s, byte a, byte b, byte c) { byte* arr = stackalloc byte[3]; @@ -86,8 +282,6 @@ public static void stbiw__write3(stbi__write_context s, byte a, byte b, byte c) switch (comp) { case 1: - s.func(s.context, d, (int) (1)); - break; case 2: if ((expand_mono) != 0) stbiw__write3(s, (byte) (d[0]), (byte) (d[0]), (byte) (d[0])); else s.func(s.context, d, (int) (1)); @@ -683,7 +877,7 @@ public static byte stbiw__paeth(int a, int b, int c) firstmap[2] = (int) (0); firstmap[3] = (int) (5); firstmap[4] = (int) (6); - int* mymap = (j) != 0 ? mapping : firstmap; + int* mymap = (j != 0) ? mapping : firstmap; int best = (int) (0); int bestval = (int) (0x7fffffff); for (p = (int) (0); (p) < (2); ++p) @@ -832,5 +1026,373 @@ public static byte stbiw__paeth(int a, int b, int c) stbiw__wpcrc(&o, (int) (0)); return _out_; } + + public static void stbiw__jpg_writeBits(stbi__write_context s, int* bitBufP, int* bitCntP, ushort bs0, + ushort bs1) + { + int bitBuf = (int) (*bitBufP); + int bitCnt = (int) (*bitCntP); + bitCnt += (int) (bs1); + bitBuf |= (int) (bs0 << (24 - bitCnt)); + while ((bitCnt) >= (8)) + { + byte c = (byte) ((bitBuf >> 16) & 255); + stbiw__putc(s, (byte) (c)); + if ((c) == (255)) + { + stbiw__putc(s, (byte) (0)); + } + bitBuf <<= 8; + bitCnt -= (int) (8); + } + *bitBufP = (int) (bitBuf); + *bitCntP = (int) (bitCnt); + } + + public static void stbiw__jpg_DCT(float* d0p, float* d1p, float* d2p, float* d3p, float* d4p, float* d5p, + float* d6p, + float* d7p) + { + float d0 = (float) (*d0p); + float d1 = (float) (*d1p); + float d2 = (float) (*d2p); + float d3 = (float) (*d3p); + float d4 = (float) (*d4p); + float d5 = (float) (*d5p); + float d6 = (float) (*d6p); + float d7 = (float) (*d7p); + float z1; + float z2; + float z3; + float z4; + float z5; + float z11; + float z13; + float tmp0 = (float) (d0 + d7); + float tmp7 = (float) (d0 - d7); + float tmp1 = (float) (d1 + d6); + float tmp6 = (float) (d1 - d6); + float tmp2 = (float) (d2 + d5); + float tmp5 = (float) (d2 - d5); + float tmp3 = (float) (d3 + d4); + float tmp4 = (float) (d3 - d4); + float tmp10 = (float) (tmp0 + tmp3); + float tmp13 = (float) (tmp0 - tmp3); + float tmp11 = (float) (tmp1 + tmp2); + float tmp12 = (float) (tmp1 - tmp2); + d0 = (float) (tmp10 + tmp11); + d4 = (float) (tmp10 - tmp11); + z1 = (float) ((tmp12 + tmp13)*0.707106781f); + d2 = (float) (tmp13 + z1); + d6 = (float) (tmp13 - z1); + tmp10 = (float) (tmp4 + tmp5); + tmp11 = (float) (tmp5 + tmp6); + tmp12 = (float) (tmp6 + tmp7); + z5 = (float) ((tmp10 - tmp12)*0.382683433f); + z2 = (float) (tmp10*0.541196100f + z5); + z4 = (float) (tmp12*1.306562965f + z5); + z3 = (float) (tmp11*0.707106781f); + z11 = (float) (tmp7 + z3); + z13 = (float) (tmp7 - z3); + *d5p = (float) (z13 + z2); + *d3p = (float) (z13 - z2); + *d1p = (float) (z11 + z4); + *d7p = (float) (z11 - z4); + *d0p = (float) (d0); + *d2p = (float) (d2); + *d4p = (float) (d4); + *d6p = (float) (d6); + } + + public static void stbiw__jpg_calcBits(int val, ushort* bits) + { + int tmp1 = (int) ((val) < (0) ? -val : val); + val = (int) ((val) < (0) ? val - 1 : val); + bits[1] = (ushort) (1); + while ((tmp1 >>= 1) != 0) + { + ++bits[1]; + } + bits[0] = (ushort) (val & ((1 << bits[1]) - 1)); + } + + public static int stbiw__jpg_processDU(stbi__write_context s, int* bitBuf, int* bitCnt, float* CDU, float* fdtbl, + int DC, ushort[,] HTDC, ushort[,] HTAC) + { + ushort* EOB = stackalloc ushort[2]; + EOB[0] = (ushort) (HTAC[0x00, 0]); + EOB[1] = (ushort) (HTAC[0x00, 1]); + + ushort* M16zeroes = stackalloc ushort[2]; + M16zeroes[0] = (ushort) (HTAC[0xF0, 0]); + M16zeroes[1] = (ushort) (HTAC[0xF0, 1]); + + int dataOff; + int i; + int diff; + int end0pos; + int* DU = stackalloc int[64]; + for (dataOff = (int) (0); (dataOff) < (64); dataOff += (int) (8)) + { + stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff + 1], &CDU[dataOff + 2], &CDU[dataOff + 3], &CDU[dataOff + 4], + &CDU[dataOff + 5], &CDU[dataOff + 6], &CDU[dataOff + 7]); + } + for (dataOff = (int) (0); (dataOff) < (8); ++dataOff) + { + stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff + 8], &CDU[dataOff + 16], &CDU[dataOff + 24], + &CDU[dataOff + 32], + &CDU[dataOff + 40], &CDU[dataOff + 48], &CDU[dataOff + 56]); + } + for (i = (int) (0); (i) < (64); ++i) + { + float v = (float) (CDU[i]*fdtbl[i]); + DU[stbiw__jpg_ZigZag[i]] = ((int) ((v) < (0) ? v - 0.5f : v + 0.5f)); + } + diff = (int) (DU[0] - DC); + if ((diff) == (0)) + { + stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[0, 0], HTDC[0, 1]); + } + else + { + ushort* bits = stackalloc ushort[2]; + stbiw__jpg_calcBits((int) (diff), bits); + stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[bits[1], 0], HTDC[bits[1], 1]); + stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits[0], bits[1]); + } + + end0pos = (int) (63); + for (; ((end0pos) > (0)) && ((DU[end0pos]) == (0)); --end0pos) + { + } + if ((end0pos) == (0)) + { + stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB[0], EOB[1]); + return (int) (DU[0]); + } + + for (i = (int) (1); i <= end0pos; ++i) + { + int startpos = (int) (i); + int nrzeroes; + ushort* bits = stackalloc ushort[2]; + for (; ((DU[i]) == (0)) && (i <= end0pos); ++i) + { + } + nrzeroes = (int) (i - startpos); + if ((nrzeroes) >= (16)) + { + int lng = (int) (nrzeroes >> 4); + int nrmarker; + for (nrmarker = (int) (1); nrmarker <= lng; ++nrmarker) + { + stbiw__jpg_writeBits(s, bitBuf, bitCnt, M16zeroes[0], M16zeroes[1]); + } + nrzeroes &= (int) (15); + } + stbiw__jpg_calcBits((int) (DU[i]), bits); + stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTAC[(nrzeroes << 4) + bits[1], 0], + HTAC[(nrzeroes << 4) + bits[1], 1]); + stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits[0], bits[1]); + } + if (end0pos != 63) + { + stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB[0], EOB[1]); + } + + return (int) (DU[0]); + } + + public static int stbi_write_jpg_core(stbi__write_context s, int width, int height, int comp, void* data, + int quality) + { + int row; + int col; + int i; + int k; + float* fdtbl_Y = stackalloc float[64]; + float* fdtbl_UV = stackalloc float[64]; + byte* YTable = stackalloc byte[64]; + byte* UVTable = stackalloc byte[64]; + if (((((data == null) || (width == 0)) || (height == 0)) || ((comp) > (4))) || ((comp) < (1))) + { + return (int) (0); + } + + quality = (int) ((quality) != 0 ? quality : 90); + quality = (int) ((quality) < (1) ? 1 : (quality) > (100) ? 100 : quality); + quality = (int) ((quality) < (50) ? 5000/quality : 200 - quality*2); + for (i = (int) (0); (i) < (64); ++i) + { + int uvti; + int yti = (int) ((YQT[i]*quality + 50)/100); + YTable[stbiw__jpg_ZigZag[i]] = ((byte) ((yti) < (1) ? 1 : (yti) > (255) ? 255 : yti)); + uvti = (int) ((UVQT[i]*quality + 50)/100); + UVTable[stbiw__jpg_ZigZag[i]] = ((byte) ((uvti) < (1) ? 1 : (uvti) > (255) ? 255 : uvti)); + } + for (row = (int) (0) , k = (int) (0); (row) < (8); ++row) + { + for (col = (int) (0); (col) < (8); ++col , ++k) + { + fdtbl_Y[k] = (float) (1/(YTable[stbiw__jpg_ZigZag[k]]*aasf[row]*aasf[col])); + fdtbl_UV[k] = (float) (1/(UVTable[stbiw__jpg_ZigZag[k]]*aasf[row]*aasf[col])); + } + } + { + byte* head1 = stackalloc byte[24]; + head1[0] = (byte) (0xFF); + head1[1] = (byte) (0xC0); + head1[2] = (byte) (0); + head1[3] = (byte) (0x11); + head1[4] = (byte) (8); + head1[5] = (byte) (height >> 8); + head1[6] = (byte) ((height) & 0xff); + head1[7] = (byte) (width >> 8); + head1[8] = (byte) ((width) & 0xff); + head1[9] = (byte) (3); + head1[10] = (byte) (1); + head1[11] = (byte) (0x11); + head1[12] = (byte) (0); + head1[13] = (byte) (2); + head1[14] = (byte) (0x11); + head1[15] = (byte) (1); + head1[16] = (byte) (3); + head1[17] = (byte) (0x11); + head1[18] = (byte) (1); + head1[19] = (byte) (0xFF); + head1[20] = (byte) (0xC4); + head1[21] = (byte) (0x01); + head1[22] = (byte) (0xA2); + head1[23] = (byte) (0); + + fixed (byte* h = head0) + { + s.func(s.context, h, head0.Length); + } + + + s.func(s.context, YTable, 64); + stbiw__putc(s, (byte) (1)); + s.func(s.context, UVTable, 64); + s.func(s.context, head1, 24); + + fixed (byte* d = &std_dc_luminance_nrcodes[1]) + { + s.func(s.context, d, std_dc_chrominance_nrcodes.Length - 1); + } + + fixed (byte* d = std_dc_luminance_values) + { + s.func(s.context, d, std_dc_chrominance_values.Length); + } + + stbiw__putc(s, (byte) (0x10)); + + fixed (byte* a = &std_ac_luminance_nrcodes[1]) + { + s.func(s.context, a, std_ac_luminance_nrcodes.Length - 1); + } + + fixed (byte* a = std_ac_luminance_values) + { + s.func(s.context, a, std_ac_luminance_values.Length); + } + + stbiw__putc(s, (byte) (1)); + + fixed (byte* c = &std_dc_chrominance_nrcodes[1]) + { + s.func(s.context, c, std_dc_chrominance_nrcodes.Length - 1); + } + + fixed (byte* c = std_dc_chrominance_values) + { + s.func(s.context, c, std_dc_chrominance_values.Length); + } + + stbiw__putc(s, (byte) (0x11)); + + + fixed (byte* c = &std_ac_chrominance_nrcodes[1]) + { + s.func(s.context, c, std_ac_chrominance_nrcodes.Length - 1); + } + + fixed (byte* c = std_ac_chrominance_values) + { + s.func(s.context, c, std_ac_chrominance_values.Length); + } + + fixed (byte* c = head2) + { + s.func(s.context, c, head2.Length); + } + } + + { + ushort* fillBits = stackalloc ushort[2]; + fillBits[0] = (ushort) (0x7F); + fillBits[1] = (ushort) (7); + byte* imageData = (byte*) (data); + int DCY = (int) (0); + int DCU = (int) (0); + int DCV = (int) (0); + int bitBuf = (int) (0); + int bitCnt = (int) (0); + int ofsG = (int) ((comp) > (2) ? 1 : 0); + int ofsB = (int) ((comp) > (2) ? 2 : 0); + int x; + int y; + int pos; + float* YDU = stackalloc float[64]; + float* UDU = stackalloc float[64]; + float* VDU = stackalloc float[64]; + + for (y = (int) (0); (y) < (height); y += (int) (8)) + { + for (x = (int) (0); (x) < (width); x += (int) (8)) + { + for (row = (int) (y) , pos = (int) (0); (row) < (y + 8); ++row) + { + for (col = (int) (x); (col) < (x + 8); ++col , ++pos) + { + int p = (int) (row*width*comp + col*comp); + float r; + float g; + float b; + if ((row) >= (height)) + { + p -= (int) (width*comp*(row + 1 - height)); + } + if ((col) >= (width)) + { + p -= (int) (comp*(col + 1 - width)); + } + r = (float) (imageData[p + 0]); + g = (float) (imageData[p + ofsG]); + b = (float) (imageData[p + ofsB]); + YDU[pos] = (float) (+0.29900f*r + 0.58700f*g + 0.11400f*b - 128); + UDU[pos] = (float) (-0.16874f*r - 0.33126f*g + 0.50000f*b); + VDU[pos] = (float) (+0.50000f*r - 0.41869f*g - 0.08131f*b); + } + } + + DCY = + (int) (stbiw__jpg_processDU(s, &bitBuf, &bitCnt, YDU, fdtbl_Y, (int) (DCY), YDC_HT, YAC_HT)); + DCU = + (int) + (stbiw__jpg_processDU(s, &bitBuf, &bitCnt, UDU, fdtbl_UV, (int) (DCU), UVDC_HT, UVAC_HT)); + DCV = + (int) + (stbiw__jpg_processDU(s, &bitBuf, &bitCnt, VDU, fdtbl_UV, (int) (DCV), UVDC_HT, UVAC_HT)); + } + } + stbiw__jpg_writeBits(s, &bitBuf, &bitCnt, fillBits[0], fillBits[1]); + } + + stbiw__putc(s, (byte) (0xFF)); + stbiw__putc(s, (byte) (0xD9)); + return (int) (1); + } } } \ No newline at end of file diff --git a/MonoGame.Framework/Utilities/Imaging/Stb.ImageWrite.cs b/MonoGame.Framework/Utilities/Imaging/Stb.ImageWrite.cs index 94dee906291..2de1e54dcd6 100644 --- a/MonoGame.Framework/Utilities/Imaging/Stb.ImageWrite.cs +++ b/MonoGame.Framework/Utilities/Imaging/Stb.ImageWrite.cs @@ -1,4 +1,6 @@ -namespace MonoGame.Utilities +using System.Text; + +namespace MonoGame.Utilities { unsafe partial class Imaging { @@ -113,10 +115,24 @@ int stride_bytes { int len; var png = stbi_write_png_to_mem((byte*) (data), stride_bytes, x, y, comp, &len); - if ((png) == ((byte*) ((void*) (0)))) return 0; + if (png == null) return 0; func(context, png, len); free(png); return 1; } + + public static int stbi_write_jpg_to_func(WriteCallback func, + void* context, + int x, + int y, + int comp, + void* data, + int quality + ) + { + stbi__write_context s = new stbi__write_context(); + stbi__start_write_callbacks(s, func, context); + return stbi_write_jpg_core(s, x, y, comp, data, quality); + } } } \ No newline at end of file diff --git a/MonoGame.Framework/Utilities/Imaging/TinyJpeg.Generated.cs b/MonoGame.Framework/Utilities/Imaging/TinyJpeg.Generated.cs deleted file mode 100644 index c2ce0db5f6f..00000000000 --- a/MonoGame.Framework/Utilities/Imaging/TinyJpeg.Generated.cs +++ /dev/null @@ -1,675 +0,0 @@ -// Generated by Sichem at 01.04.2017 10:50:02 - -using System; -using System.Runtime.InteropServices; - -namespace MonoGame.Utilities -{ - unsafe partial class Imaging - { - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct TJEJPEGHeader - { - public ushort SOI; - public ushort APP0; - public ushort jfif_len; - public fixed byte jfif_id [5]; - public ushort version; - public byte units; - public ushort x_density; - public ushort y_density; - public byte x_thumb; - public byte y_thumb; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct TJEComponentSpec - { - public byte component_id; - public byte sampling_factors; - public byte qt; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct TJEFrameHeader - { - public ushort SOF; - public ushort len; - public byte precision; - public ushort height; - public ushort width; - public byte num_components; - public TJEComponentSpec component_spec0; - public TJEComponentSpec component_spec1; - public TJEComponentSpec component_spec2; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct TJEFrameComponentSpec - { - public byte component_id; - public byte dc_ac; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct TJEScanHeader - { - public ushort SOS; - public ushort len; - public byte num_components; - public TJEFrameComponentSpec component_spec0; - public TJEFrameComponentSpec component_spec1; - public TJEFrameComponentSpec component_spec2; - public byte first; - public byte last; - public byte ah_al; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct TJEProcessedQT - { - public fixed float chroma [64]; - public fixed float luma [64]; - } - - public const int TJEI_DC = 0; - public const int TJEI_AC = 1; - public const int TJEI_LUMA_DC = 0; - public const int TJEI_LUMA_AC = 1; - public const int TJEI_CHROMA_DC = 2; - public const int TJEI_CHROMA_AC = 3; - - public static PinnedArray tjei_default_qt_luma_from_spec = - new PinnedArray(new byte[] - { - 16, 11, 10, 16, 24, 40, 51, 61, 12, 12, 14, 19, 26, 58, 60, 55, 14, 13, 16, 24, 40, 57, 69, 56, 14, 17, - 22, 29, 51, - 87, 80, 62, 18, 22, 37, 56, 68, 109, 103, 77, 24, 35, 55, 64, 81, 104, 113, 92, 49, 64, 78, 87, 103, 121, - 120, 101, - 72, 92, 95, 98, 112, 100, 103, 99 - }); - - public static PinnedArray tjei_default_qt_chroma_from_paper = - new PinnedArray(new byte[] - { - 16, 12, 14, 14, 18, 24, 49, 72, 11, 10, 16, 24, 40, 51, 61, 12, 13, 17, 22, 35, 64, 92, 14, 16, 22, 37, - 55, 78, 95, - 19, 24, 29, 56, 64, 87, 98, 26, 40, 51, 68, 81, 103, 112, 58, 57, 87, 109, 104, 121, 100, 60, 69, 80, - 103, 113, 120, - 103, 55, 56, 62, 77, 92, 101, 99 - }); - - public static PinnedArray tjei_default_ht_luma_dc_len = - new PinnedArray(new byte[] {0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}); - - public static PinnedArray tjei_default_ht_luma_dc = - new PinnedArray(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}); - - public static PinnedArray tjei_default_ht_chroma_dc_len = - new PinnedArray(new byte[] {0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0}); - - public static PinnedArray tjei_default_ht_chroma_dc = - new PinnedArray(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}); - - public static PinnedArray tjei_default_ht_luma_ac_len = - new PinnedArray(new byte[] {0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d}); - - public static PinnedArray tjei_default_ht_luma_ac = - new PinnedArray(new byte[] - { - 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, - 0x71, 0x14, - 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72, - 0x82, 0x09, - 0x0A, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, - 0x39, 0x3A, - 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, - 0x64, 0x65, - 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, - 0x87, 0x88, - 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, - 0xA8, 0xA9, - 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, - 0xC9, 0xCA, - 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, - 0xE9, 0xEA, - 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA - }); - - public static PinnedArray tjei_default_ht_chroma_ac_len = - new PinnedArray(new byte[] {0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77}); - - public static PinnedArray tjei_default_ht_chroma_ac = - new PinnedArray(new byte[] - { - 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, - 0x22, 0x32, - 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, - 0x0A, 0x16, - 0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36, 0x37, - 0x38, 0x39, - 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, - 0x63, 0x64, - 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, - 0x85, 0x86, - 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, - 0xA6, 0xA7, - 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, - 0xC7, 0xC8, - 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, - 0xE8, 0xE9, - 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA - }); - - public static PinnedArray tjei_zig_zag = - new PinnedArray(new byte[] - { - 0, 1, 5, 6, 14, 15, 27, 28, 2, 4, 7, 13, 16, 26, 29, 42, 3, 8, 12, 17, 25, 30, 41, 43, 9, 11, 18, 24, 31, - 40, 44, 53, - 10, 19, 23, 32, 39, 45, 52, 54, 20, 22, 33, 38, 46, 51, 55, 60, 21, 34, 37, 47, 50, 56, 59, 61, 35, 36, - 48, 49, 57, - 58, 62, 63 - }); - - public static ushort tjei_be_word(ushort le_word) - { - ushort lo = (ushort) (le_word & 0x00ff); - ushort hi = (ushort) ((le_word & 0xff00) >> 8); - return (ushort) ((lo << 8) | hi); - } - - public static void tjei_write(TJEState state, void* data, ulong num_bytes, ulong num_elements) - { - ulong to_write = (ulong) (num_bytes*num_elements); - ulong capped_count = - (ulong) - (((to_write) < (1024 - 1 - state.output_buffer_count)) - ? (to_write) - : (1024 - 1 - state.output_buffer_count)); - memcpy((byte*) state.output_buffer + state.output_buffer_count, data, (ulong) (capped_count)); - state.output_buffer_count += (ulong) (capped_count); - if ((state.output_buffer_count) == (1024 - 1)) - { - state.write_context.func(state.write_context.context, state.output_buffer, - (int) (state.output_buffer_count)); - state.output_buffer_count = (ulong) (0); - } - - if ((capped_count) < (to_write)) - { - tjei_write(state, (byte*) (data) + capped_count, (ulong) (to_write - capped_count), (ulong) (1)); - } - - } - - public static void tjei_write_DQT(TJEState state, byte* matrix, byte id) - { - ushort DQT = (ushort) (tjei_be_word((ushort) (0xffdb))); - tjei_write(state, &DQT, (ulong) (sizeof (ushort)), (ulong) (1)); - ushort len = (ushort) (tjei_be_word((ushort) (0x0043))); - tjei_write(state, &len, (ulong) (sizeof (ushort)), (ulong) (1)); - byte precision_and_id = (byte) (id); - tjei_write(state, &precision_and_id, (ulong) (sizeof (byte)), (ulong) (1)); - tjei_write(state, matrix, (ulong) (64*sizeof (byte)), (ulong) (1)); - } - - public static void tjei_write_DHT(TJEState state, byte* matrix_len, byte* matrix_val, int ht_class, byte id) - { - int num_values = (int) (0); - for (int i = (int) (0); (i) < (16); ++i) - { - num_values += (int) (matrix_len[i]); - } - ushort DHT = (ushort) (tjei_be_word((ushort) (0xffc4))); - ushort len = (ushort) (tjei_be_word((ushort) (2 + 1 + 16 + (ushort) (num_values)))); - byte tc_th = (byte) ((((byte) (ht_class)) << 4) | id); - tjei_write(state, &DHT, (ulong) (sizeof (ushort)), (ulong) (1)); - tjei_write(state, &len, (ulong) (sizeof (ushort)), (ulong) (1)); - tjei_write(state, &tc_th, (ulong) (sizeof (byte)), (ulong) (1)); - tjei_write(state, matrix_len, (ulong) (sizeof (byte)), (ulong) (16)); - tjei_write(state, matrix_val, (ulong) (sizeof (byte)), (ulong) (num_values)); - } - - public static byte* tjei_huff_get_code_lengths(byte* huffsize, byte* bits) - { - int k = (int) (0); - for (int i = (int) (0); (i) < (16); ++i) - { - for (int j = (int) (0); (j) < (bits[i]); ++j) - { - huffsize[k++] = ((byte) (i + 1)); - } - huffsize[k] = (byte) (0); - } - return huffsize; - } - - public static ushort* tjei_huff_get_codes(ushort* codes, byte* huffsize, int count) - { - ushort code = (ushort) (0); - int k = (int) (0); - byte sz = (byte) (huffsize[0]); - for (;;) - { - do - { - codes[k++] = (ushort) (code++); - } while ((huffsize[k]) == (sz)); - if ((huffsize[k]) == (0)) - { - return codes; - } - do - { - code = ((ushort) (code << 1)); - ++sz; - } while (huffsize[k] != sz); - } - } - - public static void tjei_huff_get_extended(byte* out_ehuffsize, ushort* out_ehuffcode, byte* huffval, - byte* huffsize, - ushort* huffcode, int count) - { - int k = (int) (0); - do - { - byte val = (byte) (huffval[k]); - out_ehuffcode[val] = (ushort) (huffcode[k]); - out_ehuffsize[val] = (byte) (huffsize[k]); - k++; - } while ((k) < (count)); - } - - public static void tjei_calculate_variable_length_int(int value, ushort* _out_) - { - int abs_val = (int) (value); - if ((value) < (0)) - { - abs_val = (int) (-abs_val); - --value; - } - - _out_[1] = (ushort) (1); - while ((abs_val >>= 1) != 0) - { - ++_out_[1]; - } - _out_[0] = ((ushort) (value & ((1 << _out_[1]) - 1))); - } - - public static void tjei_write_bits(TJEState state, uint* bitbuffer, uint* location, ushort num_bits, ushort bits) - { - uint nloc = (uint) (*location + num_bits); - *bitbuffer |= ((uint) (bits << (int) (32 - nloc))); - *location = (uint) (nloc); - while ((*location) >= (8)) - { - byte c = (byte) ((*bitbuffer) >> 24); - tjei_write(state, &c, (ulong) (1), (ulong) (1)); - if ((c) == (0xff)) - { - sbyte z = (sbyte) (0); - tjei_write(state, &z, (ulong) (1), (ulong) (1)); - } - *bitbuffer <<= 8; - *location -= (uint) (8); - } - } - - public static void tjei_fdct(float* data) - { - float tmp0; - float tmp1; - float tmp2; - float tmp3; - float tmp4; - float tmp5; - float tmp6; - float tmp7; - float tmp10; - float tmp11; - float tmp12; - float tmp13; - float z1; - float z2; - float z3; - float z4; - float z5; - float z11; - float z13; - float* dataptr; - int ctr; - dataptr = data; - for (ctr = (int) (7); (ctr) >= (0); ctr--) - { - tmp0 = (float) (dataptr[0] + dataptr[7]); - tmp7 = (float) (dataptr[0] - dataptr[7]); - tmp1 = (float) (dataptr[1] + dataptr[6]); - tmp6 = (float) (dataptr[1] - dataptr[6]); - tmp2 = (float) (dataptr[2] + dataptr[5]); - tmp5 = (float) (dataptr[2] - dataptr[5]); - tmp3 = (float) (dataptr[3] + dataptr[4]); - tmp4 = (float) (dataptr[3] - dataptr[4]); - tmp10 = (float) (tmp0 + tmp3); - tmp13 = (float) (tmp0 - tmp3); - tmp11 = (float) (tmp1 + tmp2); - tmp12 = (float) (tmp1 - tmp2); - dataptr[0] = (float) (tmp10 + tmp11); - dataptr[4] = (float) (tmp10 - tmp11); - z1 = (float) ((tmp12 + tmp13)*((float) (0.707106781))); - dataptr[2] = (float) (tmp13 + z1); - dataptr[6] = (float) (tmp13 - z1); - tmp10 = (float) (tmp4 + tmp5); - tmp11 = (float) (tmp5 + tmp6); - tmp12 = (float) (tmp6 + tmp7); - z5 = (float) ((tmp10 - tmp12)*((float) (0.382683433))); - z2 = (float) (((float) (0.541196100))*tmp10 + z5); - z4 = (float) (((float) (1.306562965))*tmp12 + z5); - z3 = (float) (tmp11*((float) (0.707106781))); - z11 = (float) (tmp7 + z3); - z13 = (float) (tmp7 - z3); - dataptr[5] = (float) (z13 + z2); - dataptr[3] = (float) (z13 - z2); - dataptr[1] = (float) (z11 + z4); - dataptr[7] = (float) (z11 - z4); - dataptr += 8; - } - dataptr = data; - for (ctr = (int) (8 - 1); (ctr) >= (0); ctr--) - { - tmp0 = (float) (dataptr[8*0] + dataptr[8*7]); - tmp7 = (float) (dataptr[8*0] - dataptr[8*7]); - tmp1 = (float) (dataptr[8*1] + dataptr[8*6]); - tmp6 = (float) (dataptr[8*1] - dataptr[8*6]); - tmp2 = (float) (dataptr[8*2] + dataptr[8*5]); - tmp5 = (float) (dataptr[8*2] - dataptr[8*5]); - tmp3 = (float) (dataptr[8*3] + dataptr[8*4]); - tmp4 = (float) (dataptr[8*3] - dataptr[8*4]); - tmp10 = (float) (tmp0 + tmp3); - tmp13 = (float) (tmp0 - tmp3); - tmp11 = (float) (tmp1 + tmp2); - tmp12 = (float) (tmp1 - tmp2); - dataptr[8*0] = (float) (tmp10 + tmp11); - dataptr[8*4] = (float) (tmp10 - tmp11); - z1 = (float) ((tmp12 + tmp13)*((float) (0.707106781))); - dataptr[8*2] = (float) (tmp13 + z1); - dataptr[8*6] = (float) (tmp13 - z1); - tmp10 = (float) (tmp4 + tmp5); - tmp11 = (float) (tmp5 + tmp6); - tmp12 = (float) (tmp6 + tmp7); - z5 = (float) ((tmp10 - tmp12)*((float) (0.382683433))); - z2 = (float) (((float) (0.541196100))*tmp10 + z5); - z4 = (float) (((float) (1.306562965))*tmp12 + z5); - z3 = (float) (tmp11*((float) (0.707106781))); - z11 = (float) (tmp7 + z3); - z13 = (float) (tmp7 - z3); - dataptr[8*5] = (float) (z13 + z2); - dataptr[8*3] = (float) (z13 - z2); - dataptr[8*1] = (float) (z11 + z4); - dataptr[8*7] = (float) (z11 - z4); - dataptr++; - } - } - - public static void tjei_encode_and_write_MCU(TJEState state, float* mcu, float* qt, byte* huff_dc_len, - ushort* huff_dc_code, byte* huff_ac_len, ushort* huff_ac_code, int* pred, uint* bitbuffer, uint* location) - { - int* du = stackalloc int[64]; - float* dct_mcu = stackalloc float[64]; - memcpy(dct_mcu, mcu, (ulong) (64*sizeof (float))); - tjei_fdct(dct_mcu); - for (int i = (int) (0); (i) < (64); ++i) - { - state.fval = (float) (dct_mcu[i]); - state.fval *= (float) (qt[i]); - state.fval = (float) (floorf((float) (state.fval + 1024 + 0.5f))); - state.fval -= (float) (1024); - int val = (int) (state.fval); - du[tjei_zig_zag[i]] = (int) (val); - } - ushort* vli = stackalloc ushort[2]; - int diff = (int) (du[0] - *pred); - *pred = (int) (du[0]); - if (diff != 0) - { - tjei_calculate_variable_length_int((int) (diff), vli); - tjei_write_bits(state, bitbuffer, location, (ushort) (huff_dc_len[vli[1]]), - (ushort) (huff_dc_code[vli[1]])); - tjei_write_bits(state, bitbuffer, location, (ushort) (vli[1]), (ushort) (vli[0])); - } - else - { - tjei_write_bits(state, bitbuffer, location, (ushort) (huff_dc_len[0]), (ushort) (huff_dc_code[0])); - } - - int last_non_zero_i = (int) (0); - for (int i = (int) (63); (i) > (0); --i) - { - if (du[i] != 0) - { - last_non_zero_i = (int) (i); - break; - } - } - for (int i = (int) (1); i <= last_non_zero_i; ++i) - { - int zero_count = (int) (0); - while ((du[i]) == (0)) - { - ++zero_count; - ++i; - if ((zero_count) == (16)) - { - tjei_write_bits(state, bitbuffer, location, (ushort) (huff_ac_len[0xf0]), - (ushort) (huff_ac_code[0xf0])); - zero_count = (int) (0); - } - } - tjei_calculate_variable_length_int((int) (du[i]), vli); - ushort sym1 = (ushort) ((ushort) (((ushort) (zero_count) << 4) | vli[1])); - tjei_write_bits(state, bitbuffer, location, (ushort) (huff_ac_len[sym1]), (ushort) (huff_ac_code[sym1])); - tjei_write_bits(state, bitbuffer, location, (ushort) (vli[1]), (ushort) (vli[0])); - } - if (last_non_zero_i != 63) - { - tjei_write_bits(state, bitbuffer, location, (ushort) (huff_ac_len[0]), (ushort) (huff_ac_code[0])); - } - - return; - } - - public static int tjei_encode_main(TJEState state, byte* src_data, int width, int height, int src_num_components) - { - if ((src_num_components != 3) && (src_num_components != 4)) - { - return (int) (0); - } - - if (((width) > (0xffff)) || ((height) > (0xffff))) - { - return (int) (0); - } - - TJEProcessedQT pqt = new TJEProcessedQT(); - float* aan_scales = stackalloc float[8]; - aan_scales[0] = (float) (1.0f); - aan_scales[1] = (float) (1.387039845f); - aan_scales[2] = (float) (1.306562965f); - aan_scales[3] = (float) (1.175875602f); - aan_scales[4] = (float) (1.0f); - aan_scales[5] = (float) (0.785694958f); - aan_scales[6] = (float) (0.541196100f); - aan_scales[7] = (float) (0.275899379f); - - for (int y = (int) (0); (y) < (8); y++) - { - for (int x = (int) (0); (x) < (8); x++) - { - int i = (int) (y*8 + x); - pqt.luma[y*8 + x] = (float) (1.0f/(8*aan_scales[x]*aan_scales[y]*state.qt_luma[tjei_zig_zag[i]])); - pqt.chroma[y*8 + x] = - (float) (1.0f/(8*aan_scales[x]*aan_scales[y]*state.qt_chroma[tjei_zig_zag[i]])); - } - } - { - TJEJPEGHeader header = new TJEJPEGHeader(); - header.SOI = (ushort) (tjei_be_word((ushort) (0xffd8))); - header.APP0 = (ushort) (tjei_be_word((ushort) (0xffe0))); - ushort jfif_len = (ushort) (20 - 4); - header.jfif_len = (ushort) (tjei_be_word((ushort) (jfif_len))); - memcpy(header.jfif_id, (void*) (tjeik_jfif_id), (ulong) (5)); - header.version = (ushort) (tjei_be_word((ushort) (0x0102))); - header.units = (byte) (0x01); - header.x_density = (ushort) (tjei_be_word((ushort) (0x0060))); - header.y_density = (ushort) (tjei_be_word((ushort) (0x0060))); - header.x_thumb = (byte) (0); - header.y_thumb = (byte) (0); - tjei_write(state, &header, (ulong) sizeof (TJEJPEGHeader), (ulong) (1)); - } - - { - TJEJPEGComment com = new TJEJPEGComment(); - ushort com_len = (ushort) (2 + tjeik_com_str.Count); - com.com = (ushort) (tjei_be_word((ushort) (0xfffe))); - com.com_len = (ushort) (tjei_be_word((ushort) (com_len))); - memcpy(com.com_str, (void*) (tjeik_com_str), (ulong) (tjeik_com_str.Count)); - tjei_write(state, &com, (ulong) sizeof (TJEJPEGComment), 1); - } - - tjei_write_DQT(state, state.qt_luma, (byte) (0x00)); - tjei_write_DQT(state, state.qt_chroma, (byte) (0x01)); - { - TJEFrameHeader header = new TJEFrameHeader(); - header.SOF = (ushort) (tjei_be_word((ushort) (0xffc0))); - header.len = (ushort) (tjei_be_word((ushort) (8 + 3*3))); - header.precision = (byte) (8); - header.width = (ushort) (tjei_be_word((ushort) (width))); - header.height = (ushort) (tjei_be_word((ushort) (height))); - header.num_components = (byte) (3); - byte* tables = stackalloc byte[3]; - tables[0] = (byte) (0); - tables[1] = (byte) (1); - tables[2] = (byte) (1); - TJEComponentSpec spec = new TJEComponentSpec(); - spec.component_id = ((byte) (0 + 1)); - spec.sampling_factors = ((byte) (0x11)); - spec.qt = (byte) (tables[0]); - header.component_spec0 = (TJEComponentSpec) (spec); - spec.component_id = ((byte) (1 + 1)); - spec.qt = (byte) (tables[1]); - header.component_spec1 = (TJEComponentSpec) (spec); - spec.component_id = ((byte) (2 + 1)); - spec.qt = (byte) (tables[2]); - header.component_spec2 = (TJEComponentSpec) (spec); - tjei_write(state, &header, (ulong) sizeof (TJEFrameHeader), 1); - } - - tjei_write_DHT(state, state.ht_bits[TJEI_LUMA_DC], state.ht_vals[TJEI_LUMA_DC], (int) (TJEI_DC), (byte) (0)); - tjei_write_DHT(state, state.ht_bits[TJEI_LUMA_AC], state.ht_vals[TJEI_LUMA_AC], (int) (TJEI_AC), (byte) (0)); - tjei_write_DHT(state, state.ht_bits[TJEI_CHROMA_DC], state.ht_vals[TJEI_CHROMA_DC], (int) (TJEI_DC), - (byte) (1)); - tjei_write_DHT(state, state.ht_bits[TJEI_CHROMA_AC], state.ht_vals[TJEI_CHROMA_AC], (int) (TJEI_AC), - (byte) (1)); - { - TJEScanHeader header = new TJEScanHeader(); - header.SOS = (ushort) (tjei_be_word((ushort) (0xffda))); - header.len = (ushort) (tjei_be_word((ushort) (6 + (sizeof (TJEFrameComponentSpec)*3)))); - header.num_components = (byte) (3); - byte* tables = stackalloc byte[3]; - tables[0] = (byte) (0x00); - tables[1] = (byte) (0x11); - tables[2] = (byte) (0x11); - TJEFrameComponentSpec cs = new TJEFrameComponentSpec(); - cs.component_id = ((byte) (0 + 1)); - cs.dc_ac = (byte) (tables[0]); - header.component_spec0 = (TJEFrameComponentSpec) (cs); - cs.component_id = ((byte) (1 + 1)); - cs.dc_ac = (byte) (tables[1]); - header.component_spec1 = (TJEFrameComponentSpec) (cs); - cs.component_id = ((byte) (2 + 1)); - cs.dc_ac = (byte) (tables[2]); - header.component_spec2 = (TJEFrameComponentSpec) (cs); - header.first = (byte) (0); - header.last = (byte) (63); - header.ah_al = (byte) (0); - tjei_write(state, &header, (ulong) sizeof (TJEScanHeader), 1); - } - - float* du_y = stackalloc float[64]; - float* du_b = stackalloc float[64]; - float* du_r = stackalloc float[64]; - int pred_y = (int) (0); - int pred_b = (int) (0); - int pred_r = (int) (0); - uint bitbuffer = (uint) (0); - uint location = (uint) (0); - for (int y = (int) (0); (y) < (height); y += (int) (8)) - { - for (int x = (int) (0); (x) < (width); x += (int) (8)) - { - for (int off_y = (int) (0); (off_y) < (8); ++off_y) - { - for (int off_x = (int) (0); (off_x) < (8); ++off_x) - { - int block_index = (int) (off_y*8 + off_x); - int src_index = (int) ((((y + off_y)*width) + (x + off_x))*src_num_components); - int col = (int) (x + off_x); - int row = (int) (y + off_y); - if ((row) >= (height)) - { - src_index -= (int) ((width*(row - height + 1))*src_num_components); - } - if ((col) >= (width)) - { - src_index -= (int) ((col - width + 1)*src_num_components); - } - byte r = (byte) (src_data[src_index + 0]); - byte g = (byte) (src_data[src_index + 1]); - byte b = (byte) (src_data[src_index + 2]); - float luma = (float) (0.299f*r + 0.587f*g + 0.114f*b - 128); - float cb = (float) (-0.1687f*r - 0.3313f*g + 0.5f*b); - float cr = (float) (0.5f*r - 0.4187f*g - 0.0813f*b); - du_y[block_index] = (float) (luma); - du_b[block_index] = (float) (cb); - du_r[block_index] = (float) (cr); - } - } - tjei_encode_and_write_MCU(state, du_y, pqt.luma, - ((byte*) state.ehuffsize + TJEI_LUMA_DC*257), ((ushort*) state.ehuffcode + TJEI_LUMA_DC*256), - ((byte*) state.ehuffsize + TJEI_LUMA_AC*257), ((ushort*) state.ehuffcode + TJEI_LUMA_AC*256), - &pred_y, &bitbuffer, &location); - tjei_encode_and_write_MCU(state, du_b, pqt.chroma, - ((byte*) state.ehuffsize + TJEI_CHROMA_DC*257), - ((ushort*) state.ehuffcode + TJEI_CHROMA_DC*256), - ((byte*) state.ehuffsize + TJEI_CHROMA_AC*257), - ((ushort*) state.ehuffcode + TJEI_CHROMA_AC*256), &pred_b, - &bitbuffer, &location); - tjei_encode_and_write_MCU(state, du_r, pqt.chroma, - ((byte*) state.ehuffsize + TJEI_CHROMA_DC*257), - ((ushort*) state.ehuffcode + TJEI_CHROMA_DC*256), - ((byte*) state.ehuffsize + TJEI_CHROMA_AC*257), - ((ushort*) state.ehuffcode + TJEI_CHROMA_AC*256), &pred_r, - &bitbuffer, &location); - } - } - { - if (((location) > (0)) && ((location) < (8))) - { - tjei_write_bits(state, &bitbuffer, &location, (ushort) (8 - location), (ushort) (0)); - } - } - - ushort EOI = (ushort) (tjei_be_word((ushort) (0xffd9))); - tjei_write(state, &EOI, (ulong) (sizeof (ushort)), (ulong) (1)); - if ((state.output_buffer_count) != 0) - { - state.write_context.func(state.write_context.context, state.output_buffer, - (int) (state.output_buffer_count)); - state.output_buffer_count = (ulong) (0); - } - - return (int) (1); - } - } -} \ No newline at end of file diff --git a/MonoGame.Framework/Utilities/Imaging/TinyJpeg.cs b/MonoGame.Framework/Utilities/Imaging/TinyJpeg.cs deleted file mode 100644 index 3bde402e368..00000000000 --- a/MonoGame.Framework/Utilities/Imaging/TinyJpeg.cs +++ /dev/null @@ -1,203 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace MonoGame.Utilities -{ - partial class Imaging - { - public static readonly PinnedArray tjeik_jfif_id = new PinnedArray(new[] - { - (byte) 'J', - (byte) 'F', - (byte) 'I', - (byte) 'F', - (byte) 0 - }); - - public static readonly PinnedArray tjeik_com_str = new PinnedArray(new[] - { - (byte) 'C', - (byte) 'r', - (byte) 'e', - (byte) 'a', - (byte) 't', - (byte) 'e', - (byte) 'd', - (byte) ' ', - (byte) 'b', - (byte) 'y', - (byte) ' ', - (byte) 'T', - (byte) 'i', - (byte) 'n', - (byte) 'y', - (byte) ' ', - (byte) 'J', - (byte) 'P', - (byte) 'E', - (byte) 'G', - (byte) ' ', - (byte) 'E', - (byte) 'n', - (byte) 'c', - (byte) 'o', - (byte) 'd', - (byte) 'e', - (byte) 'r' - }); - - public unsafe delegate void WriteCallback2(void* context, void* data, int size); - - public unsafe class TJEWriteContext - { - public void* context = null; - public WriteCallback2 func; - } - - public unsafe class TJEState - { - public PinnedArray ehuffsize = new PinnedArray(4*257); - public PinnedArray ehuffcode = new PinnedArray(4*256); - public byte*[] ht_bits = new byte*[4]; - public byte*[] ht_vals = new byte*[4]; - public PinnedArray qt_luma = new PinnedArray(64); - public PinnedArray qt_chroma = new PinnedArray(64); - public TJEWriteContext write_context = new TJEWriteContext(); - public ulong output_buffer_count; - public PinnedArray output_buffer = new PinnedArray(1024); - public float fval; - - public TJEState() - { - for (var i = 0; i < 4; ++i) - { - ht_bits[i] = null; - ht_vals[i] = null; - } - - memset(ehuffsize.Ptr, 0, ehuffsize.Size); - memset(ehuffcode, 0, ehuffcode.Size); - memset(qt_luma.Ptr, 0, qt_luma.Size); - memset(qt_chroma.Ptr, 0, qt_chroma.Size); - memset(output_buffer.Ptr, 0, output_buffer.Size); - } - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public unsafe struct TJEJPEGComment - { - public ushort com; - public ushort com_len; - public fixed sbyte com_str [28]; - } - - private static float floorf(float f) - { - return (float) Math.Floor(f); - } - - public static unsafe void tjei_huff_expand(TJEState state) - { - state.ht_bits[TJEI_LUMA_DC] = tjei_default_ht_luma_dc_len; - state.ht_bits[TJEI_LUMA_AC] = tjei_default_ht_luma_ac_len; - state.ht_bits[TJEI_CHROMA_DC] = tjei_default_ht_chroma_dc_len; - state.ht_bits[TJEI_CHROMA_AC] = tjei_default_ht_chroma_ac_len; - state.ht_vals[TJEI_LUMA_DC] = tjei_default_ht_luma_dc; - state.ht_vals[TJEI_LUMA_AC] = tjei_default_ht_luma_ac; - state.ht_vals[TJEI_CHROMA_DC] = tjei_default_ht_chroma_dc; - state.ht_vals[TJEI_CHROMA_AC] = tjei_default_ht_chroma_ac; - var spec_tables_len = stackalloc int[4]; - for (var i = 0; i < 4; ++i) - { - spec_tables_len[i] = 0; - for (var k = 0; k < 16; ++k) - { - spec_tables_len[i] += state.ht_bits[i][k]; - } - } - var huffsize = stackalloc byte[4*257]; - var huffcode = stackalloc ushort[4*256]; - for (var i = 0; i < 4; ++i) - { - tjei_huff_get_code_lengths(huffsize + i*257, state.ht_bits[i]); - tjei_huff_get_codes(huffcode + i*256, huffsize + i*257, - spec_tables_len[i]); - } - - for (var i = 0; i < 4; ++i) - { - var count = spec_tables_len[i]; - tjei_huff_get_extended((byte*) state.ehuffsize + i*257, - (ushort*) state.ehuffcode + i*256, - state.ht_vals[i], - huffsize + i*257, - huffcode + i*256, - count); - } - } - - public static unsafe int tje_encode_with_func(WriteCallback2 func, - void* context, - int quality, - int width, - int height, - int num_components, - byte* src_data) - { - if (quality < 1 || quality > 3) - { - throw new Exception("[ERROR] -- Valid 'quality' values are 1 (lowest), 2, or 3 (highest)"); - } - - var state = new TJEState(); - - byte qt_factor = 1; - switch (quality) - { - case 3: - for (int i = 0; i < 64; ++i) - { - state.qt_luma[i] = 1; - state.qt_chroma[i] = 1; - } - break; - case 1: - case 2: - if (quality == 2) - { - qt_factor = 10; - } - // don't break. fall through. - for (int i = 0; i < 64; ++i) - { - state.qt_luma[i] = (byte) (tjei_default_qt_luma_from_spec[i]/qt_factor); - if (state.qt_luma[i] == 0) - { - state.qt_luma[i] = 1; - } - state.qt_chroma[i] = (byte) (tjei_default_qt_chroma_from_paper[i]/qt_factor); - if (state.qt_chroma[i] == 0) - { - state.qt_chroma[i] = 1; - } - } - break; - default: - throw new Exception("invalid code path"); - } - - var wc = new TJEWriteContext - { - context = context, - func = func - }; - - state.write_context = wc; - tjei_huff_expand(state); - - var result = tjei_encode_main(state, src_data, width, height, num_components); - - return result; - } - } -} \ No newline at end of file