This commit is contained in:
niko
2026-06-04 11:42:34 +02:00
parent f39ba70a9f
commit e720b98cd1
7488 changed files with 2493818 additions and 0 deletions
+669
View File
@@ -0,0 +1,669 @@
using System;
using System.Collections.Generic;
using System.IO;
using Hjg.Pngcs.Chunks;
using Hjg.Pngcs.Zlib;
namespace Hjg.Pngcs
{
// Token: 0x0200003F RID: 63
public class PngWriter
{
// Token: 0x17000037 RID: 55
// (get) Token: 0x06000248 RID: 584 RVA: 0x000097B0 File Offset: 0x000079B0
// (set) Token: 0x06000249 RID: 585 RVA: 0x000097B8 File Offset: 0x000079B8
public EDeflateCompressStrategy CompressionStrategy { get; set; }
// Token: 0x17000038 RID: 56
// (get) Token: 0x0600024A RID: 586 RVA: 0x000097C1 File Offset: 0x000079C1
// (set) Token: 0x0600024B RID: 587 RVA: 0x000097C9 File Offset: 0x000079C9
public int CompLevel { get; set; }
// Token: 0x17000039 RID: 57
// (get) Token: 0x0600024C RID: 588 RVA: 0x000097D2 File Offset: 0x000079D2
// (set) Token: 0x0600024D RID: 589 RVA: 0x000097DA File Offset: 0x000079DA
public bool ShouldCloseStream { get; set; }
// Token: 0x1700003A RID: 58
// (get) Token: 0x0600024E RID: 590 RVA: 0x000097E3 File Offset: 0x000079E3
// (set) Token: 0x0600024F RID: 591 RVA: 0x000097EB File Offset: 0x000079EB
public int IdatMaxSize { get; set; }
// Token: 0x1700003B RID: 59
// (get) Token: 0x06000250 RID: 592 RVA: 0x000097F4 File Offset: 0x000079F4
// (set) Token: 0x06000251 RID: 593 RVA: 0x000097FC File Offset: 0x000079FC
public int CurrentChunkGroup { get; private set; }
// Token: 0x06000252 RID: 594 RVA: 0x00009805 File Offset: 0x00007A05
public PngWriter(Stream outputStream, ImageInfo imgInfo)
: this(outputStream, imgInfo, "[NO FILENAME AVAILABLE]")
{
}
// Token: 0x06000253 RID: 595 RVA: 0x00009814 File Offset: 0x00007A14
public PngWriter(Stream outputStream, ImageInfo imgInfo, string filename)
{
this.filename = ((filename == null) ? "" : filename);
this.outputStream = outputStream;
this.ImgInfo = imgInfo;
this.CompLevel = 6;
this.ShouldCloseStream = true;
this.IdatMaxSize = 0;
this.CompressionStrategy = EDeflateCompressStrategy.Filtered;
this.rowb = new byte[imgInfo.BytesPerRow + 1];
this.rowbprev = new byte[this.rowb.Length];
this.rowbfilter = new byte[this.rowb.Length];
this.chunksList = new ChunksListForWrite(this.ImgInfo);
this.metadata = new PngMetadata(this.chunksList);
this.filterStrat = new FilterWriteStrategy(this.ImgInfo, FilterType.FILTER_DEFAULT);
this.unpackedMode = false;
this.needsPack = this.unpackedMode && imgInfo.Packed;
}
// Token: 0x06000254 RID: 596 RVA: 0x00009904 File Offset: 0x00007B04
private void init()
{
this.datStream = new PngIDatChunkOutputStream(this.outputStream, this.IdatMaxSize);
this.datStreamDeflated = ZlibStreamFactory.createZlibOutputStream(this.datStream, this.CompLevel, this.CompressionStrategy, true);
this.WriteSignatureAndIHDR();
this.WriteFirstChunks();
}
// Token: 0x06000255 RID: 597 RVA: 0x00009954 File Offset: 0x00007B54
private void reportResultsForFilter(int rown, FilterType type, bool tentative)
{
for (int i = 0; i < this.histox.Length; i++)
{
this.histox[i] = 0;
}
int num = 0;
for (int j = 1; j <= this.ImgInfo.BytesPerRow; j++)
{
int num2 = (int)this.rowbfilter[j];
if (num2 < 0)
{
num -= num2;
}
else
{
num += num2;
}
this.histox[num2 & 255]++;
}
this.filterStrat.fillResultsForFilter(rown, type, (double)num, this.histox, tentative);
}
// Token: 0x06000256 RID: 598 RVA: 0x000099E4 File Offset: 0x00007BE4
private void WriteEndChunk()
{
PngChunkIEND pngChunkIEND = new PngChunkIEND(this.ImgInfo);
pngChunkIEND.CreateRawChunk().WriteChunk(this.outputStream);
}
// Token: 0x06000257 RID: 599 RVA: 0x00009A10 File Offset: 0x00007C10
private void WriteFirstChunks()
{
this.CurrentChunkGroup = 1;
int num = this.chunksList.writeChunks(this.outputStream, this.CurrentChunkGroup);
this.CurrentChunkGroup = 2;
num = this.chunksList.writeChunks(this.outputStream, this.CurrentChunkGroup);
if (num > 0 && this.ImgInfo.Greyscale)
{
throw new PngjOutputException("cannot write palette for this format");
}
if (num == 0 && this.ImgInfo.Indexed)
{
throw new PngjOutputException("missing palette");
}
this.CurrentChunkGroup = 3;
num = this.chunksList.writeChunks(this.outputStream, this.CurrentChunkGroup);
this.CurrentChunkGroup = 4;
}
// Token: 0x06000258 RID: 600 RVA: 0x00009ABC File Offset: 0x00007CBC
private void WriteLastChunks()
{
this.CurrentChunkGroup = 5;
this.chunksList.writeChunks(this.outputStream, this.CurrentChunkGroup);
List<PngChunk> queuedChunks = this.chunksList.GetQueuedChunks();
if (queuedChunks.Count > 0)
{
throw new PngjOutputException(queuedChunks.Count + " chunks were not written! Eg: " + queuedChunks[0].ToString());
}
this.CurrentChunkGroup = 6;
}
// Token: 0x06000259 RID: 601 RVA: 0x00009B2C File Offset: 0x00007D2C
private void WriteSignatureAndIHDR()
{
this.CurrentChunkGroup = 0;
PngHelperInternal.WriteBytes(this.outputStream, PngHelperInternal.PNG_ID_SIGNATURE);
PngChunkIHDR pngChunkIHDR = new PngChunkIHDR(this.ImgInfo);
pngChunkIHDR.Cols = this.ImgInfo.Cols;
pngChunkIHDR.Rows = this.ImgInfo.Rows;
pngChunkIHDR.Bitspc = this.ImgInfo.BitDepth;
int num = 0;
if (this.ImgInfo.Alpha)
{
num += 4;
}
if (this.ImgInfo.Indexed)
{
num++;
}
if (!this.ImgInfo.Greyscale)
{
num += 2;
}
pngChunkIHDR.Colormodel = num;
pngChunkIHDR.Compmeth = 0;
pngChunkIHDR.Filmeth = 0;
pngChunkIHDR.Interlaced = 0;
pngChunkIHDR.CreateRawChunk().WriteChunk(this.outputStream);
}
// Token: 0x0600025A RID: 602 RVA: 0x00009BF4 File Offset: 0x00007DF4
protected void encodeRowFromByte(byte[] row)
{
if (row.Length == this.ImgInfo.SamplesPerRowPacked && !this.needsPack)
{
int num = 1;
if (this.ImgInfo.BitDepth <= 8)
{
foreach (byte b in row)
{
this.rowb[num++] = b;
}
return;
}
foreach (byte b2 in row)
{
this.rowb[num] = b2;
num += 2;
}
return;
}
else
{
if (row.Length >= this.ImgInfo.SamplesPerRow && this.needsPack)
{
ImageLine.packInplaceByte(this.ImgInfo, row, row, false);
}
if (this.ImgInfo.BitDepth <= 8)
{
int k = 0;
int num2 = 1;
while (k < this.ImgInfo.SamplesPerRowPacked)
{
this.rowb[num2++] = row[k];
k++;
}
return;
}
int l = 0;
int num3 = 1;
while (l < this.ImgInfo.SamplesPerRowPacked)
{
this.rowb[num3++] = row[l];
this.rowb[num3++] = 0;
l++;
}
return;
}
}
// Token: 0x0600025B RID: 603 RVA: 0x00009D1C File Offset: 0x00007F1C
protected void encodeRowFromInt(int[] row)
{
if (row.Length == this.ImgInfo.SamplesPerRowPacked && !this.needsPack)
{
int num = 1;
if (this.ImgInfo.BitDepth <= 8)
{
foreach (int num2 in row)
{
this.rowb[num++] = (byte)num2;
}
return;
}
foreach (int num3 in row)
{
this.rowb[num++] = (byte)(num3 >> 8);
this.rowb[num++] = (byte)num3;
}
return;
}
else
{
if (row.Length >= this.ImgInfo.SamplesPerRow && this.needsPack)
{
ImageLine.packInplaceInt(this.ImgInfo, row, row, false);
}
if (this.ImgInfo.BitDepth <= 8)
{
int k = 0;
int num4 = 1;
while (k < this.ImgInfo.SamplesPerRowPacked)
{
this.rowb[num4++] = (byte)row[k];
k++;
}
return;
}
int l = 0;
int num5 = 1;
while (l < this.ImgInfo.SamplesPerRowPacked)
{
this.rowb[num5++] = (byte)(row[l] >> 8);
this.rowb[num5++] = (byte)row[l];
l++;
}
return;
}
}
// Token: 0x0600025C RID: 604 RVA: 0x00009E5C File Offset: 0x0000805C
private void FilterRow(int rown)
{
if (this.filterStrat.shouldTestAll(rown))
{
this.FilterRowNone();
this.reportResultsForFilter(rown, FilterType.FILTER_NONE, true);
this.FilterRowSub();
this.reportResultsForFilter(rown, FilterType.FILTER_SUB, true);
this.FilterRowUp();
this.reportResultsForFilter(rown, FilterType.FILTER_UP, true);
this.FilterRowAverage();
this.reportResultsForFilter(rown, FilterType.FILTER_AVERAGE, true);
this.FilterRowPaeth();
this.reportResultsForFilter(rown, FilterType.FILTER_PAETH, true);
}
FilterType filterType = this.filterStrat.gimmeFilterType(rown, true);
this.rowbfilter[0] = (byte)filterType;
switch (filterType)
{
case FilterType.FILTER_NONE:
this.FilterRowNone();
break;
case FilterType.FILTER_SUB:
this.FilterRowSub();
break;
case FilterType.FILTER_UP:
this.FilterRowUp();
break;
case FilterType.FILTER_AVERAGE:
this.FilterRowAverage();
break;
case FilterType.FILTER_PAETH:
this.FilterRowPaeth();
break;
default:
throw new PngjOutputException("Filter type " + filterType + " not implemented");
}
this.reportResultsForFilter(rown, filterType, false);
}
// Token: 0x0600025D RID: 605 RVA: 0x00009F44 File Offset: 0x00008144
private void prepareEncodeRow(int rown)
{
if (this.datStream == null)
{
this.init();
}
this.rowNum++;
if (rown >= 0 && this.rowNum != rown)
{
throw new PngjOutputException(string.Concat(new object[] { "rows must be written in order: expected:", this.rowNum, " passed:", rown }));
}
byte[] array = this.rowb;
this.rowb = this.rowbprev;
this.rowbprev = array;
}
// Token: 0x0600025E RID: 606 RVA: 0x00009FCE File Offset: 0x000081CE
private void filterAndSend(int rown)
{
this.FilterRow(rown);
this.datStreamDeflated.Write(this.rowbfilter, 0, this.ImgInfo.BytesPerRow + 1);
}
// Token: 0x0600025F RID: 607 RVA: 0x00009FF8 File Offset: 0x000081F8
private void FilterRowAverage()
{
int bytesPerRow = this.ImgInfo.BytesPerRow;
int num = 1 - this.ImgInfo.BytesPixel;
int i = 1;
while (i <= bytesPerRow)
{
this.rowbfilter[i] = this.rowb[i] - (this.rowbprev[i] + ((num > 0) ? this.rowb[num] : 0)) / 2;
i++;
num++;
}
}
// Token: 0x06000260 RID: 608 RVA: 0x0000A05C File Offset: 0x0000825C
private void FilterRowNone()
{
for (int i = 1; i <= this.ImgInfo.BytesPerRow; i++)
{
this.rowbfilter[i] = this.rowb[i];
}
}
// Token: 0x06000261 RID: 609 RVA: 0x0000A090 File Offset: 0x00008290
private void FilterRowPaeth()
{
int bytesPerRow = this.ImgInfo.BytesPerRow;
int num = 1 - this.ImgInfo.BytesPixel;
int i = 1;
while (i <= bytesPerRow)
{
this.rowbfilter[i] = (byte)((int)this.rowb[i] - PngHelperInternal.FilterPaethPredictor((int)((num > 0) ? this.rowb[num] : 0), (int)this.rowbprev[i], (int)((num > 0) ? this.rowbprev[num] : 0)));
i++;
num++;
}
}
// Token: 0x06000262 RID: 610 RVA: 0x0000A104 File Offset: 0x00008304
private void FilterRowSub()
{
int i;
for (i = 1; i <= this.ImgInfo.BytesPixel; i++)
{
this.rowbfilter[i] = this.rowb[i];
}
int num = 1;
i = this.ImgInfo.BytesPixel + 1;
while (i <= this.ImgInfo.BytesPerRow)
{
this.rowbfilter[i] = this.rowb[i] - this.rowb[num];
i++;
num++;
}
}
// Token: 0x06000263 RID: 611 RVA: 0x0000A17C File Offset: 0x0000837C
private void FilterRowUp()
{
for (int i = 1; i <= this.ImgInfo.BytesPerRow; i++)
{
this.rowbfilter[i] = this.rowb[i] - this.rowbprev[i];
}
}
// Token: 0x06000264 RID: 612 RVA: 0x0000A1BC File Offset: 0x000083BC
private long SumRowbfilter()
{
long num = 0L;
for (int i = 1; i <= this.ImgInfo.BytesPerRow; i++)
{
if (this.rowbfilter[i] < 0)
{
num -= (long)((ulong)this.rowbfilter[i]);
}
else
{
num += (long)((ulong)this.rowbfilter[i]);
}
}
return num;
}
// Token: 0x06000265 RID: 613 RVA: 0x0000A208 File Offset: 0x00008408
private void CopyChunks(PngReader reader, int copy_mask, bool onlyAfterIdat)
{
bool flag = this.CurrentChunkGroup >= 4;
if (onlyAfterIdat && reader.CurrentChunkGroup < 6)
{
throw new PngjException("tried to copy last chunks but reader has not ended");
}
foreach (PngChunk pngChunk in reader.GetChunksList().GetChunks())
{
int chunkGroup = pngChunk.ChunkGroup;
if (chunkGroup >= 4 || !flag)
{
bool flag2 = false;
if (pngChunk.Crit)
{
if (pngChunk.Id.Equals("PLTE"))
{
if (this.ImgInfo.Indexed && ChunkHelper.maskMatch(copy_mask, ChunkCopyBehaviour.COPY_PALETTE))
{
flag2 = true;
}
if (!this.ImgInfo.Greyscale && ChunkHelper.maskMatch(copy_mask, ChunkCopyBehaviour.COPY_ALL))
{
flag2 = true;
}
}
}
else
{
bool flag3 = pngChunk is PngChunkTextVar;
bool safe = pngChunk.Safe;
if (ChunkHelper.maskMatch(copy_mask, ChunkCopyBehaviour.COPY_ALL))
{
flag2 = true;
}
if (safe && ChunkHelper.maskMatch(copy_mask, ChunkCopyBehaviour.COPY_ALL_SAFE))
{
flag2 = true;
}
if (pngChunk.Id.Equals("tRNS") && ChunkHelper.maskMatch(copy_mask, ChunkCopyBehaviour.COPY_TRANSPARENCY))
{
flag2 = true;
}
if (pngChunk.Id.Equals("pHYs") && ChunkHelper.maskMatch(copy_mask, ChunkCopyBehaviour.COPY_PHYS))
{
flag2 = true;
}
if (flag3 && ChunkHelper.maskMatch(copy_mask, ChunkCopyBehaviour.COPY_TEXTUAL))
{
flag2 = true;
}
if (ChunkHelper.maskMatch(copy_mask, ChunkCopyBehaviour.COPY_ALMOSTALL) && !ChunkHelper.IsUnknown(pngChunk) && !flag3 && !pngChunk.Id.Equals("hIST") && !pngChunk.Id.Equals("tIME"))
{
flag2 = true;
}
if (pngChunk is PngChunkSkipped)
{
flag2 = false;
}
}
if (flag2)
{
this.chunksList.Queue(PngChunk.CloneChunk<PngChunk>(pngChunk, this.ImgInfo));
}
}
}
}
// Token: 0x06000266 RID: 614 RVA: 0x0000A3F4 File Offset: 0x000085F4
public void CopyChunksFirst(PngReader reader, int copy_mask)
{
this.CopyChunks(reader, copy_mask, false);
}
// Token: 0x06000267 RID: 615 RVA: 0x0000A3FF File Offset: 0x000085FF
public void CopyChunksLast(PngReader reader, int copy_mask)
{
this.CopyChunks(reader, copy_mask, true);
}
// Token: 0x06000268 RID: 616 RVA: 0x0000A40C File Offset: 0x0000860C
public double ComputeCompressionRatio()
{
if (this.CurrentChunkGroup < 6)
{
throw new PngjException("must be called after End()");
}
double num = (double)this.datStream.GetCountFlushed();
double num2 = (double)((this.ImgInfo.BytesPerRow + 1) * this.ImgInfo.Rows);
return num / num2;
}
// Token: 0x06000269 RID: 617 RVA: 0x0000A458 File Offset: 0x00008658
public void End()
{
if (this.rowNum != this.ImgInfo.Rows - 1)
{
throw new PngjOutputException("all rows have not been written");
}
try
{
this.datStreamDeflated.Close();
this.datStream.Close();
this.WriteLastChunks();
this.WriteEndChunk();
if (this.ShouldCloseStream)
{
this.outputStream.Close();
}
}
catch (IOException ex)
{
throw new PngjOutputException(ex);
}
}
// Token: 0x0600026A RID: 618 RVA: 0x0000A4D4 File Offset: 0x000086D4
public string GetFilename()
{
return this.filename;
}
// Token: 0x0600026B RID: 619 RVA: 0x0000A4DC File Offset: 0x000086DC
public void WriteRow(ImageLine imgline, int rownumber)
{
this.SetUseUnPackedMode(imgline.SamplesUnpacked);
if (imgline.SampleType == ImageLine.ESampleType.INT)
{
this.WriteRowInt(imgline.Scanline, rownumber);
return;
}
this.WriteRowByte(imgline.ScanlineB, rownumber);
}
// Token: 0x0600026C RID: 620 RVA: 0x0000A50D File Offset: 0x0000870D
public void WriteRow(int[] newrow)
{
this.WriteRow(newrow, -1);
}
// Token: 0x0600026D RID: 621 RVA: 0x0000A517 File Offset: 0x00008717
public void WriteRow(int[] newrow, int rown)
{
this.WriteRowInt(newrow, rown);
}
// Token: 0x0600026E RID: 622 RVA: 0x0000A521 File Offset: 0x00008721
public void WriteRowInt(int[] newrow, int rown)
{
this.prepareEncodeRow(rown);
this.encodeRowFromInt(newrow);
this.filterAndSend(rown);
}
// Token: 0x0600026F RID: 623 RVA: 0x0000A538 File Offset: 0x00008738
public void WriteRowByte(byte[] newrow, int rown)
{
this.prepareEncodeRow(rown);
this.encodeRowFromByte(newrow);
this.filterAndSend(rown);
}
// Token: 0x06000270 RID: 624 RVA: 0x0000A550 File Offset: 0x00008750
public void WriteRowsInt(int[][] image)
{
for (int i = 0; i < this.ImgInfo.Rows; i++)
{
this.WriteRowInt(image[i], i);
}
}
// Token: 0x06000271 RID: 625 RVA: 0x0000A580 File Offset: 0x00008780
public void WriteRowsByte(byte[][] image)
{
for (int i = 0; i < this.ImgInfo.Rows; i++)
{
this.WriteRowByte(image[i], i);
}
}
// Token: 0x06000272 RID: 626 RVA: 0x0000A5AD File Offset: 0x000087AD
public PngMetadata GetMetadata()
{
return this.metadata;
}
// Token: 0x06000273 RID: 627 RVA: 0x0000A5B5 File Offset: 0x000087B5
public ChunksListForWrite GetChunksList()
{
return this.chunksList;
}
// Token: 0x06000274 RID: 628 RVA: 0x0000A5BD File Offset: 0x000087BD
public void SetFilterType(FilterType filterType)
{
this.filterStrat = new FilterWriteStrategy(this.ImgInfo, filterType);
}
// Token: 0x06000275 RID: 629 RVA: 0x0000A5D1 File Offset: 0x000087D1
public bool IsUnpackedMode()
{
return this.unpackedMode;
}
// Token: 0x06000276 RID: 630 RVA: 0x0000A5D9 File Offset: 0x000087D9
public void SetUseUnPackedMode(bool useUnpackedMode)
{
this.unpackedMode = useUnpackedMode;
this.needsPack = this.unpackedMode && this.ImgInfo.Packed;
}
// Token: 0x04000133 RID: 307
public readonly ImageInfo ImgInfo;
// Token: 0x04000134 RID: 308
protected readonly string filename;
// Token: 0x04000135 RID: 309
private FilterWriteStrategy filterStrat;
// Token: 0x04000136 RID: 310
private readonly PngMetadata metadata;
// Token: 0x04000137 RID: 311
private readonly ChunksListForWrite chunksList;
// Token: 0x04000138 RID: 312
protected byte[] rowb;
// Token: 0x04000139 RID: 313
protected byte[] rowbprev;
// Token: 0x0400013A RID: 314
protected byte[] rowbfilter;
// Token: 0x0400013B RID: 315
private int rowNum = -1;
// Token: 0x0400013C RID: 316
private readonly Stream outputStream;
// Token: 0x0400013D RID: 317
private PngIDatChunkOutputStream datStream;
// Token: 0x0400013E RID: 318
private AZlibOutputStream datStreamDeflated;
// Token: 0x0400013F RID: 319
private int[] histox = new int[256];
// Token: 0x04000140 RID: 320
private bool unpackedMode;
// Token: 0x04000141 RID: 321
private bool needsPack;
}
}