public override void CloneDataFromRead(PngChunk other) { PngChunkPLTE otherx = (PngChunkPLTE)other; this.SetNentries(otherx.GetNentries()); System.Array.Copy(otherx.entries, 0, entries, 0, numEntries); }
/// <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) { line = line.unpackToNewImageLine(); } bool isbyte = line.SampleType == Hjg.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 int[] Palette2rgb(ImageLine line, PngChunkPLTE pal, PngChunkTRNS trns, int[] buf) { bool flag = trns != null; int num = flag ? 4 : 3; int num2 = line.ImgInfo.Cols * num; if (buf == null || buf.Length < num2) { buf = new int[num2]; } if (!line.SamplesUnpacked) { line = line.unpackToNewImageLine(); } bool flag2 = line.SampleType == ImageLine.ESampleType.BYTE; int num3 = (trns != null) ? trns.GetPalletteAlpha().Length : 0; for (int i = 0; i < line.ImgInfo.Cols; i++) { int num4 = flag2 ? (line.ScanlineB[i] & 0xFF) : line.Scanline[i]; pal.GetEntryRgb(num4, buf, i * num); if (flag) { int num5 = buf[i * num + 3] = ((num4 < num3) ? trns.GetPalletteAlpha()[num4] : 255); } } return(buf); }
public static void doit(String orig) { string copy = TestsHelper.addSuffixToName(orig, "_tc"); PngReader pngr = FileHelper.CreatePngReader(orig); if (!pngr.ImgInfo.Indexed) { throw new Exception("Not indexed image"); } PngChunkPLTE plte = pngr.GetMetadata().GetPLTE(); PngChunkTRNS trns = pngr.GetMetadata().GetTRNS(); // transparency metadata, can be null bool alpha = trns != null; ImageInfo im2 = new ImageInfo(pngr.ImgInfo.Cols, pngr.ImgInfo.Rows, 8, alpha); PngWriter pngw = FileHelper.CreatePngWriter(copy, im2, true); pngw.CopyChunksFirst(pngr, ChunkCopyBehaviour.COPY_ALL_SAFE); int[] buf = null; for (int row = 0; row < pngr.ImgInfo.Rows; row++) { ImageLine line = pngr.ReadRowInt(row); buf = ImageLineHelper.Palette2rgb(line, plte, trns, buf); pngw.WriteRowInt(buf, row); } pngw.CopyChunksLast(pngr, ChunkCopyBehaviour.COPY_ALL_SAFE); pngr.End(); pngw.End(); Console.WriteLine("True color: " + copy); }
private static unsafe Bitmap ReadBitmap(int bitmapIndex, byte[][] buf, PngChunkPLTE pal) { var bmp = new Bitmap(32, 32, PixelFormat.Format32bppArgb); var data = bmp.LockBits( new Rectangle(0, 0, 32, 32), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); try { var ptr = (int *)data.Scan0; for (var y = 0; y < 32; y++) { var line = buf[y]; for (var x = 0; x < 32; x++) { var offset = (bitmapIndex * 32) + x; var bmpOffset = (y * 32) + x; int idx = line[offset]; var rgb = new int[3]; pal.GetEntryRgb(idx, rgb); var c = Color.FromArgb(rgb[0], rgb[1], rgb[2]); if (!PaletteFactory.TAPalette.Contains(c)) { throw new ArgumentException("Image contains colors not in the TA palette."); } ptr[bmpOffset] = c.ToArgb(); } } } finally { bmp.UnlockBits(data); } return(bmp); }
private void ConvertPalettedImage(BinaryReader reader, Stream outStream) { ImageInfo info = new ImageInfo(Header.Width, Header.Height, Header.BitDepth, false, false, true); PngWriter png = new PngWriter(outStream, info); // Add a palette to the PNG PngChunkPLTE plte = png.GetMetadata().CreatePLTEChunk(); plte.SetNentries(Header.NumberOfColours); // Populate the palette for (int i = 0; i < this.ColorTable.Length; i++) { var c = this.ColorTable[i]; plte.SetEntry(i, c.Red, c.Green, c.Blue); } int pixelsPerByte = 8 / Header.BitCount; int bytesPerLine = (Header.Width * Header.BitCount + 31) / 32 * 4; //if (Header.BitDepth == 8) // bytesPerLine = (Header.Width / 4 + 1) * 4; long dataStart = Header.DataOffset; int dataEnd = Header.FileSize - Header.DataOffset; //Header.ImageSize; for (int y = 0; y < Header.Height; y++) { // Seek to the start of the line Stream.Seek(dataStart + (dataEnd - (bytesPerLine * y) - bytesPerLine), SeekOrigin.Begin); byte[] bmpLine = new byte[bytesPerLine]; ImageLine pngLine = new ImageLine(info, ImageLine.ESampleType.BYTE); Stream.Read(bmpLine, 0, bytesPerLine); // Bitmap lines are already packed for palleted images, so just copy it over Array.Copy(bmpLine, 0, pngLine.ScanlineB, 0, Math.Min(bytesPerLine, Header.Width)); Stream.ReadByte(); //skip the padded byte png.WriteRow(pngLine, y); } png.End(); }
bool ReadPalette(PngChunkPLTE _palette) { int[] rgb = new int[4]; int c; for (c = 0; c < m_coloursInPalette; c++) { int c2 = c; if (m_config.m_colorRemapSourceToDest.ContainsKey(c)) { c2 = m_config.m_colorRemapSourceToDest[c]; } _palette.GetEntryRgb(c2, rgb); float fr = ((float)rgb[0]) / 255.0f; float fg = ((float)rgb[1]) / 255.0f; float fb = ((float)rgb[2]) / 255.0f; //float fa = ((float)a) / 255.0f; float fa = 1.0f; /* * if((c%16) == 0 ) * fa = 0.0f; * else * fa = 1.0f; */ Color col = new Color(fr, fg, fb, fa); m_palette.Add(col); m_colorUsed.Add(false); } while (c < 16) { m_palette.Add(new Color(1.0f, 0.0f, 1.0f, 1.0f)); m_colorUsed.Add(false); c++; } return(true); }
/// <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) { if (line is null) { throw new ArgumentNullException(nameof(line)); } if (pal is null) { throw new ArgumentNullException(nameof(pal)); } var isalpha = trns is object; var channels = isalpha ? 4 : 3; var nsamples = line.ImgInfo.Cols * channels; if (buf is null || buf.Length < nsamples) { buf = new int[nsamples]; } if (!line.SamplesUnpacked) { line = line.UnpackToNewImageLine(); } var isbyte = line.SampleType == Hjg.Pngcs.ImageLine.ESampleType.BYTE; var nindexesWithAlpha = trns?.GetPalletteAlpha().Length ?? 0; for (var c = 0; c < line.ImgInfo.Cols; c++) { var index = isbyte ? (line.ScanlineB[c] & 0xFF) : line.Scanline[c]; pal.GetEntryRgb(index, buf, c * channels); if (isalpha) { buf[(c * channels) + 3] = index < nindexesWithAlpha?trns.GetPalletteAlpha()[index] : 255; } } return(buf); }
static public PalettizedImage LoadPNG(string _path, PalettizedImageConfig _config) { PngReader pngr = FileHelper.CreatePngReader(_path); if (!pngr.ImgInfo.Indexed) { Debug.LogException(new UnityException("Image wasn't indexed")); return(null); } PngChunkPLTE palette = pngr.GetMetadata().GetPLTE(); PalettizedImage image = new PalettizedImage(pngr.ImgInfo.Cols, pngr.ImgInfo.Rows, palette.GetNentries()); image.SetConfig(_config); image.m_fileName = System.IO.Path.GetFileNameWithoutExtension(_path); image.ReadPalette(palette); image.ReadImage(pngr); return(image); }
private static void additionalTestPalette(string orig, string truecolor) { // covnert to true color 8 bits and check equality PngReader pngr = FileHelper.CreatePngReader(orig); PngChunkPLTE plte = pngr.GetMetadata().GetPLTE(); PngChunkTRNS trns = pngr.GetMetadata().GetTRNS(); string copy = TestsHelper.addSuffixToName(orig, "_tccopy"); bool alpha = trns != null; ImageInfo im2 = new ImageInfo(pngr.ImgInfo.Cols, pngr.ImgInfo.Rows, 8, alpha); PngWriter pngw = FileHelper.CreatePngWriter(copy, im2, true); pngw.CopyChunksFirst(pngr, ChunkCopyBehaviour.COPY_ALL_SAFE); int[] buf = null; for (int row = 0; row < pngr.ImgInfo.Rows; row++) { ImageLine line = pngr.ReadRowInt(row); buf = ImageLineHelper.Palette2rgb(line, plte, trns, buf); pngw.WriteRowInt(buf, row); } pngr.End(); pngw.End(); TestsHelper.testEqual(copy, truecolor); System.IO.File.Delete(copy); }
public static int[] Palette2rgb(ImageLine line, PngChunkPLTE pal, int[] buf) { return(Palette2rgb(line, pal, null, buf)); }
public sprite_params setup(PngReader _png_reader, bool _apply_palette, bool _crop_image, int _palette_slot) { sprite_params spr_params = new sprite_params(this); if (_png_reader == null) { return(spr_params); } int img_width = _png_reader.ImgInfo.Cols; int img_height = _png_reader.ImgInfo.Rows; List <byte[]> lines_arr = new List <byte[]>(img_height); int i; int j; int min_x = 0; int max_x = img_width - 1; int min_y = 0; int max_y = img_height - 1; byte[] pixels_line = null; PngChunkPLTE plte = _png_reader.GetMetadata().GetPLTE(); PngChunkTRNS trns = _png_reader.GetMetadata().GetTRNS(); ImageLine line = null; int alpha_ind = -1; int num_colors = plte.GetNentries(); // detect useful image borders { if (trns != null) { int size; alpha_ind = trns.GetPalletteAlpha().Length - 1; if (_crop_image) { min_x = img_width + 1; max_x = -1; min_y = img_height + 1; max_y = -1; } bool transp_line = false; for (i = 0; i < img_height; i++) { line = _png_reader.ReadRowByte(i); if (line.ImgInfo.Packed) { line = line.unpackToNewImageLine(); } pixels_line = new byte[img_width]; Array.Copy(line.GetScanlineByte(), pixels_line, img_width); lines_arr.Add(pixels_line); size = pixels_line.Length; transp_line = true; for (j = 0; j < size; j++) { // if pixel is not transparent if (_crop_image && (pixels_line[j] != alpha_ind)) { if (min_x > j) { min_x = j; } if (max_x < j) { max_x = j; } transp_line = false; } } // if line is not transparent if (_crop_image && !transp_line) { if (min_y > i) { min_y = i; } if (max_y < i) { max_y = i; } } } } // find nearest colors if (_apply_palette) { #if DEF_FIXED_LEN_PALETTE16_ARR palettes_array plt_arr = palettes_array.Instance; plt_arr.palette_index = _palette_slot; #endif for (i = 0; i < num_colors; i++) { #if DEF_FIXED_LEN_PALETTE16_ARR plt_arr.update_color(_palette_slot, i, utils.find_nearest_color_ind(plte.GetEntry((trns != null) ? (i + alpha_ind) % num_colors:i))); #else palette_group.Instance.get_palettes_arr()[i / utils.CONST_NUM_SMALL_PALETTES].get_color_inds()[i % utils.CONST_NUM_SMALL_PALETTES] = utils.find_nearest_color_ind(plte.GetEntry((trns != null) ? (i + alpha_ind) % num_colors:i)); #endif } #if DEF_FIXED_LEN_PALETTE16_ARR plt_arr.update_palette(); #else for (i = 0; i < utils.CONST_NUM_SMALL_PALETTES; i++) { palette_group.Instance.get_palettes_arr()[i].update(); } #endif #if DEF_NES palette_group.Instance.active_palette = 0; #endif } // fill the lines_arr if sprite has no transparency if (lines_arr.Count == 0) { for (i = 0; i < img_height; i++) { line = _png_reader.ReadRowByte(i); if (line.ImgInfo.Packed) { line = line.unpackToNewImageLine(); } pixels_line = new byte[img_width]; Array.Copy(line.GetScanlineByte(), pixels_line, img_width); lines_arr.Add(pixels_line); } } } return(cut_CHRs(spr_params, min_x, max_x, min_y, max_y, lines_arr, (trns != null), alpha_ind, num_colors, _crop_image, _palette_slot)); }
public static Image Load(Stream stream) { if (stream == null) { throw new ArgumentNullException("stream"); } PngReader pngReader = new PngReader(stream); pngReader.ShouldCloseStream = false; pngReader.ChunkLoadBehaviour = ChunkLoadBehaviour.LOAD_CHUNK_NEVER; pngReader.MaxTotalBytesRead = long.MaxValue; ImageLines imageLines = pngReader.ReadRowsByte(); pngReader.End(); if (imageLines.ImgInfo.BitDepth == 8 && imageLines.ImgInfo.Channels == 4) { Image image = new Image(pngReader.ImgInfo.Cols, pngReader.ImgInfo.Rows); int i = 0; int num = 0; for (; i < image.Height; i++) { byte[] array = imageLines.ScanlinesB[i]; int j = 0; int num2 = 0; for (; j < image.Width; j++) { byte r = array[num2++]; byte g = array[num2++]; byte b = array[num2++]; byte a = array[num2++]; image.Pixels[num++] = new Color(r, g, b, a); } } return(image); } if (imageLines.ImgInfo.BitDepth == 8 && imageLines.ImgInfo.Channels == 3) { Image image2 = new Image(pngReader.ImgInfo.Cols, pngReader.ImgInfo.Rows); int k = 0; int num3 = 0; for (; k < image2.Height; k++) { byte[] array2 = imageLines.ScanlinesB[k]; int l = 0; int num4 = 0; for (; l < image2.Width; l++) { byte r2 = array2[num4++]; byte g2 = array2[num4++]; byte b2 = array2[num4++]; image2.Pixels[num3++] = new Color(r2, g2, b2); } } return(image2); } if (imageLines.ImgInfo.BitDepth == 8 && imageLines.ImgInfo.Channels == 2 && imageLines.ImgInfo.Greyscale) { Image image3 = new Image(pngReader.ImgInfo.Cols, pngReader.ImgInfo.Rows); int m = 0; int num5 = 0; for (; m < image3.Height; m++) { byte[] array3 = imageLines.ScanlinesB[m]; int n = 0; int num6 = 0; for (; n < image3.Width; n++) { byte b3 = array3[num6++]; byte a2 = array3[num6++]; image3.Pixels[num5++] = new Color(b3, b3, b3, a2); } } return(image3); } if (imageLines.ImgInfo.BitDepth == 8 && imageLines.ImgInfo.Channels == 1 && imageLines.ImgInfo.Greyscale) { Image image4 = new Image(pngReader.ImgInfo.Cols, pngReader.ImgInfo.Rows); int num7 = 0; int num8 = 0; for (; num7 < image4.Height; num7++) { byte[] array4 = imageLines.ScanlinesB[num7]; int num9 = 0; int num10 = 0; for (; num9 < image4.Width; num9++) { byte b4 = array4[num10++]; image4.Pixels[num8++] = new Color(b4, b4, b4); } } return(image4); } if (imageLines.ImgInfo.BitDepth == 8 && imageLines.ImgInfo.Channels == 1 && imageLines.ImgInfo.Indexed) { PngChunkPLTE pngChunkPLTE = (PngChunkPLTE)pngReader.GetChunksList().GetById1("PLTE"); if (pngChunkPLTE == null) { throw new InvalidOperationException("PLTE chunk not found in indexed PNG."); } Image image5 = new Image(pngReader.ImgInfo.Cols, pngReader.ImgInfo.Rows); int num11 = 0; int num12 = 0; for (; num11 < image5.Height; num11++) { byte[] array5 = imageLines.ScanlinesB[num11]; int num13 = 0; int num14 = 0; for (; num13 < image5.Width; num13++) { byte n2 = array5[num14++]; int entry = pngChunkPLTE.GetEntry(n2); image5.Pixels[num12++] = new Color((entry >> 16) & 0xFF, (entry >> 8) & 0xFF, entry & 0xFF); } } return(image5); } throw new InvalidOperationException("Unsupported PNG pixel format."); }
public IEnumerable <RGBA> EnRGBA() { PngChunkPLTE oplte = null; PngChunkTRNS otrns = null; // transparency metadata, can be null if (pngr.ImgInfo.Indexed) { oplte = pngr.GetMetadata().GetPLTE(); otrns = pngr.GetMetadata().GetTRNS(); } for (var row = 0; row < pngr.ImgInfo.Rows; row++) { var line = pngr.ReadRowInt(row); if (pngr.ImgInfo.Indexed) { var rgrgba = ImageLineHelper.Palette2rgb(line, oplte, otrns, null); for (var irgba = 0; irgba < rgrgba.Length;) { yield return(new RGBA { r = rgrgba[irgba++], g = rgrgba[irgba++], b = rgrgba[irgba++], a = (otrns != null ? rgrgba[irgba++] : 255), }); } } else { if (pngr.ImgInfo.Packed) { line = line.unpackToNewImageLine(); } for (var col = 0; col < pngr.ImgInfo.Cols; col++) { switch (pngr.ImgInfo.Channels) { case 1: yield return(new RGBA { r = Read8(col, line), g = Read8(col, line), b = Read8(col, line), }); break; case 2: yield return(new RGBA { r = Read8(col * 2, line), g = Read8(col * 2, line), b = Read8(col * 2, line), a = Read8(col * 2 + 1, line), }); break; case 3: yield return(new RGBA { r = Read8(col * 3, line), g = Read8(col * 3 + 1, line), b = Read8(col * 3 + 2, line), }); break; case 4: yield return(new RGBA { r = Read8(col * 4, line), g = Read8(col * 4 + 1, line), b = Read8(col * 4 + 2, line), a = Read8(col * 4 + 3, line), }); break; } } } } }