1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
|
/// Copyright (c) 2008 Jeffrey Powers for Fluxcapacity Open Source.
/// Under the MIT License, details: License.txt.
using System;
using System.Collections.Generic;
using System.Text;
namespace FluxJpeg.Core
{
public class JpegHeader
{
public byte Marker;
public byte[] Data;
internal bool IsJFIF = false;
public new string ToString { get { return Encoding.UTF8.GetString(Data, 0, Data.Length); } }
}
public class DecodedJpeg
{
private Image _image; public Image Image { get { return _image; } }
internal int[] BlockWidth;
internal int[] BlockHeight;
internal int Precision = 8;
internal int[] HsampFactor = { 1, 1, 1 };
internal int[] VsampFactor = { 1, 1, 1 };
internal bool[] lastColumnIsDummy = new bool[] { false, false, false };
internal bool[] lastRowIsDummy = new bool[] { false, false, false };
internal int[] compWidth, compHeight;
internal int MaxHsampFactor;
internal int MaxVsampFactor;
public bool HasJFIF { get; private set; }
private List<JpegHeader> _metaHeaders;
public IList<JpegHeader> MetaHeaders { get { return _metaHeaders.AsReadOnly(); } }
public DecodedJpeg(Image image, IEnumerable<JpegHeader> metaHeaders)
{
_image = image;
// Handles null as an empty list
_metaHeaders = (metaHeaders == null) ?
new List<JpegHeader>(0) : new List<JpegHeader>(metaHeaders);
// Check if the JFIF header was present
foreach (JpegHeader h in _metaHeaders)
if (h.IsJFIF) { HasJFIF = true; break; }
int components = _image.ComponentCount;
compWidth = new int[components];
compHeight = new int[components];
BlockWidth = new int[components];
BlockHeight = new int[components];
Initialize();
}
public DecodedJpeg(Image image)
: this(image, null)
{
_metaHeaders = new List<JpegHeader>();
string comment = "Jpeg Codec | fluxcapacity.net ";
_metaHeaders.Add(
new JpegHeader() {
Marker = JPEGMarker.COM,
Data = System.Text.Encoding.UTF8.GetBytes(comment)
}
);
}
/// <summary>
/// This method creates and fills three arrays, Y, Cb, and Cr using the input image.
/// </summary>
private void Initialize()
{
int w = _image.Width, h = _image.Height;
int y;
MaxHsampFactor = 1;
MaxVsampFactor = 1;
for (y = 0; y < _image.ComponentCount; y++)
{
MaxHsampFactor = Math.Max(MaxHsampFactor, HsampFactor[y]);
MaxVsampFactor = Math.Max(MaxVsampFactor, VsampFactor[y]);
}
for (y = 0; y < _image.ComponentCount; y++)
{
compWidth[y] = (((w % 8 != 0) ? ((int)Math.Ceiling((double)w / 8.0)) * 8 : w) / MaxHsampFactor) * HsampFactor[y];
if (compWidth[y] != ((w / MaxHsampFactor) * HsampFactor[y]))
{
lastColumnIsDummy[y] = true;
}
// results in a multiple of 8 for compWidthz
// this will make the rest of the program fail for the unlikely
// event that someone tries to compress an 16 x 16 pixel image
// which would of course be worse than pointless
BlockWidth[y] = (int)Math.Ceiling((double)compWidth[y] / 8.0);
compHeight[y] = (((h % 8 != 0) ? ((int)Math.Ceiling((double)h / 8.0)) * 8 : h) / MaxVsampFactor) * VsampFactor[y];
if (compHeight[y] != ((h / MaxVsampFactor) * VsampFactor[y]))
{
lastRowIsDummy[y] = true;
}
BlockHeight[y] = (int)Math.Ceiling((double)compHeight[y] / 8.0);
}
}
}
}
|