/// <summary> /// Given an indexed line with a palette, unpacks as a RGB array /// </summary> /// <param name="line">ImageLine as returned from PngReader</param> /// <param name="pal">Palette chunk</param> /// <param name="trns">TRNS chunk (optional)</param> /// <param name="buf">Preallocated array, optional</param> /// <returns>R G B (one byte per sample)</returns> public static int[] Palette2rgb(ImageLine line, PngChunkPLTE pal, PngChunkTRNS trns, int[] buf) { bool isalpha = trns != null; int channels = isalpha ? 4 : 3; int nsamples = line.ImgInfo.Cols * channels; if (buf == null || buf.Length < nsamples) { buf = new int[nsamples]; } if (line.SamplesUnpacked == false) { line = line.unpackToNewImageLine(); } bool isbyte = line.SampleType == Pngcs.ImageLine.ESampleType.BYTE; int nindexesWithAlpha = trns != null?trns.GetPalletteAlpha().Length : 0; for (int c = 0; c < line.ImgInfo.Cols; c++) { int index = isbyte ? (line.ScanlineB[c] & 0xFF) : line.Scanline[c]; pal.GetEntryRgb(index, buf, c * channels); if (isalpha) { int alpha = index < nindexesWithAlpha?trns.GetPalletteAlpha()[index] : 255; buf[c * channels + 3] = alpha; } } return(buf); }
public static void SetPixel(ImageLine line, int col, int r, int g, int b, int a) { int offset = col * line.channels; if (line.IsInt()) { line.Scanline[offset++] = r; line.Scanline[offset++] = g; line.Scanline[offset] = b; if (line.ImgInfo.Alpha) { line.Scanline[offset + 1] = a; } } else { line.ScanlineB[offset++] = (byte)r; line.ScanlineB[offset++] = (byte)g; line.ScanlineB[offset] = (byte)b; if (line.ImgInfo.Alpha) { line.ScanlineB[offset + 1] = (byte)a; } } }
public static double ReadDouble(ImageLine line, int pos) { if (line.IsInt()) { return(line.Scanline[pos] / (line.MaxSampleVal + 0.9)); } else { return((line.ScanlineB[pos]) / (line.MaxSampleVal + 0.9)); } }
public static void WriteDouble(ImageLine line, double d, int pos) { if (line.IsInt()) { line.Scanline[pos] = (int)(d * (line.MaxSampleVal + 0.99)); } else { line.ScanlineB[pos] = (byte)(d * (line.MaxSampleVal + 0.99)); } }
public static int GetPixelToARGB8(ImageLine line, int column) { if (line.IsInt()) { return(ToARGB8(line.Scanline, column * line.channels, line.ImgInfo.Alpha)); } else { return(ToARGB8(line.ScanlineB, column * line.channels, line.ImgInfo.Alpha)); } }
public static void SetPixelFromARGB8(ImageLine line, int column, int argb) { if (line.IsInt()) { FromARGB8(argb, line.Scanline, column * line.channels, line.ImgInfo.Alpha); } else { FromARGB8(argb, line.ScanlineB, column * line.channels, line.ImgInfo.Alpha); } }
/// <summary> This uses the row number from the imageline! </summary> public void WriteRow(ImageLine line, int rownumber) { SetUseUnPackedMode(line.SamplesUnpacked); if (line.SampleType == ImageLine.ESampleType.INT) { WriteRowInt(line.Scanline, rownumber); } else { WriteRowByte(line.ScanlineB, rownumber); } }
public ImageLine ReadRowByte(int imageRow) { imgLine = new ImageLine( ImgInfo, ImageLine.ESampleType.BYTE, unpackedMode, null, null, imageRow ); ReadRowByte(imgLine.ScanlineB, imageRow); imgLine.FilterUsed = (FilterType)rowbfilter[0]; return(imgLine); }
/// <summary> /// Constructs and returns an ImageLine object backed by a matrix row. /// This is quite efficient, no deep copy. /// </summary> /// <param name="mrow">Row number inside the matrix</param> /// <returns></returns> public ImageLine GetImageLineAtMatrixRow(int mrow) { if (mrow < 0 || mrow > Nrows) { throw new PngjException("Bad row " + mrow + ". Should be positive and less than " + Nrows); } ImageLine imline = sampleType == ImageLine.ESampleType.INT ? new ImageLine(ImgInfo, sampleType, SamplesUnpacked, Scanlines[mrow], null) : new ImageLine(ImgInfo, sampleType, SamplesUnpacked, null, ScanlinesB[mrow]); imline.Rown = MatrixRowToImageRow(mrow); return(imline); }
public ImageLine packToNewImageLine() { ImageLine newline = new ImageLine(ImgInfo, SampleType, false); if (SampleType == ESampleType.INT) { packInplaceInt(ImgInfo, Scanline, newline.Scanline, false); } else { packInplaceByte(ImgInfo, ScanlineB, newline.ScanlineB, false); } return(newline); }
protected void EncodeRowFromInt(int[] row) { if (row.Length == ImgInfo.SamplesPerRowPacked && !needsPack) { // some duplication of code - because this case is typical and it works faster this way int j = 1; if (ImgInfo.BitDepth <= 8) { foreach (int x in row) // optimized { rowb[j++] = (byte)x; } } else { // 16 bitspc foreach (int x in row) // optimized { rowb[j++] = (byte)(x >> 8); rowb[j++] = (byte)(x); } } } else { // perhaps we need to pack? if (row.Length >= ImgInfo.SamplesPerRow && needsPack) { ImageLine.PackInplaceInt(ImgInfo, row, row, false); // row is packed in place! } int samplesPerRowPacked = ImgInfo.SamplesPerRowPacked; if (ImgInfo.BitDepth <= 8) { for (int i = 0, j = 1; i < samplesPerRowPacked; i++) { rowb[j++] = (byte)row[i]; } } else { // 16 bitspc for (int i = 0, j = 1; i < samplesPerRowPacked; i++) { rowb[j++] = (byte)(row[i] >> 8); rowb[j++] = (byte)(row[i]); } } } }
public ImageLine ReadRowByte(int nrow) { if (imgLine == null) { imgLine = new ImageLine(ImgInfo, ImageLine.ESampleType.BYTE, unpackedMode); } if (imgLine.Rown == nrow) // already read { return(imgLine); } ReadRowByte(imgLine.ScanlineB, nrow); imgLine.FilterUsed = (FilterType)rowbfilter[0]; imgLine.Rown = nrow; return(imgLine); }
public static void SetPixel(ImageLine line, int col, int value) { if (line.channels != 1) { throw new System.Exception("this method is for 1 channel images only"); } if (line.IsInt()) { line.Scanline[col] = value; } else { line.ScanlineB[col] = (byte)value; } }
protected void EncodeRowFromByte(byte[] row) { if (row.Length == ImgInfo.SamplesPerRowPacked && !needsPack) { // some duplication of code - because this case is typical and it works faster this way int j = 1; if (ImgInfo.BitDepth <= 8) { foreach (byte x in row) { // optimized rowb[j++] = x; } } else { // 16 bitspc foreach (byte x in row) { // optimized rowb[j] = x; j += 2; } } } else { // perhaps we need to pack? if (row.Length >= ImgInfo.SamplesPerRow && needsPack) { ImageLine.PackInplaceByte(ImgInfo, row, row, false); // row is packed in place! } if (ImgInfo.BitDepth <= 8) { for (int i = 0, j = 1; i < ImgInfo.SamplesPerRowPacked; i++) { rowb[j++] = row[i]; } } else { // 16 bitspc for (int i = 0, j = 1; i < ImgInfo.SamplesPerRowPacked; i++) { rowb[j++] = row[i]; rowb[j++] = 0; } } } }
public static byte[] Pack(ImageInfo imgInfo, byte[] src, byte[] dst, bool scale) { int len0 = imgInfo.SamplesPerRowPacked; if (dst == null || dst.Length < len0) { dst = new byte[len0]; } if (imgInfo.Packed) { ImageLine.PackInplaceByte(imgInfo, src, dst, scale); } else { Array.Copy(src, 0, dst, 0, len0); } return(dst); }
void decodeLastReadRowToByte(byte[] buffer, int bytesRead) // see http://www.libpng.org/pub/png/spec/1.2/PNG-DataRep.html { if (ImgInfo.BitDepth <= 8) { System.Array.Copy(rowb, 1, buffer, 0, bytesRead); } else// 16 bitspc { for (int i = 0, j = 1; j < bytesRead; i++, j += 2) { buffer[i] = rowb[j]; // 16 bits in 1 byte: this discards the LSB!!! } } if (ImgInfo.Packed && unpackedMode) { ImageLine.unpackInplaceByte(ImgInfo, buffer, buffer, false); } }
public static int[] Unpack(ImageInfo imgInfo, int[] src, int[] dst, bool scale) { int len1 = imgInfo.SamplesPerRow; int len0 = imgInfo.SamplesPerRowPacked; if (dst == null || dst.Length < len1) { dst = new int[len1]; } if (imgInfo.Packed) { ImageLine.UnpackInplaceInt(imgInfo, src, dst, scale); } else { Array.Copy(src, 0, dst, 0, len0); } return(dst); }
void decodeLastReadRowToInt(int[] buffer, int bytesRead) // see http://www.libpng.org/pub/png/spec/1.2/PNG-DataRep.html { if (ImgInfo.BitDepth <= 8) { for (int i = 0, j = 1; i < bytesRead; i++) { buffer[i] = (rowb[j++]); } } else // 16 bitspc { for (int i = 0, j = 1; j < bytesRead; i++) { buffer[i] = (rowb[j++] << 8) + rowb[j++]; } } if (ImgInfo.Packed && unpackedMode) { ImageLine.unpackInplaceInt(ImgInfo, buffer, buffer, false); } }
public static int[] Palette2rgb(ImageLine line, PngChunkPLTE pal, int[] buf) => Palette2rgb(line, pal, null, buf);
public static void SetPixel(ImageLine line, int col, int r, int g, int b) { SetPixel(line, col, r, g, b, line.MaxSampleVal); }