public sprite_data load_sprite_png(string _filename, string _name, bool _apply_palette, bool _crop_image, int _palette_slot) { PngReader png_reader = FileHelper.CreatePngReader(_filename); try { if (!png_reader.ImgInfo.Indexed) { throw new Exception(_filename + "\n\nNot indexed image!"); } if (png_reader.IsInterlaced()) { throw new Exception(_filename + "\n\nOnly non interlaced .PNG images are supported!"); } // if( ( png_reader.ImgInfo.Cols & 0x07 ) != 0 || ( png_reader.ImgInfo.Rows & 0x07 ) != 0 ) // { // png_reader.End(); // throw new Exception( _filename + "\n\nThe image size must be a multiple of 8 !" ); // } // if( ( ( png_reader.ImgInfo.Cols >> 3 ) * ( png_reader.ImgInfo.Rows >> 3 ) ) > utils.CONST_CHR_BANK_MAX_SPRITES_CNT ) // { // png_reader.End(); // throw new Exception( _filename + "\n\nThe imported image contains more than " + utils.CONST_CHR_BANK_MAX_SPRITES_CNT + " CHRs!" ); // } #if DEF_NES if (png_reader.GetMetadata().GetPLTE().MinBitDepth() != 2) { throw new Exception(_filename + "\n\nThe PNG image must have a 4 colors palette!"); } #elif DEF_SMS || DEF_PCE int img_bit_depth = png_reader.GetMetadata().GetPLTE().MinBitDepth(); if (img_bit_depth != 4 && img_bit_depth != 2) { throw new Exception(_filename + "\n\nThe PNG image must have a 4 or 2 bpp color depth!"); } if (png_reader.GetMetadata().GetPLTE().GetNentries() > 16) { throw new Exception(_filename + "\n\nThe PNG image must have a 16 or 4 colors palette!"); } #else ... #endif sprite_params spr_params = m_CHR_data_storage.create(png_reader, _apply_palette, _crop_image, _palette_slot); sprite_data spr = new sprite_data(_name); spr.setup(spr_params); spr.update_dimensions(); png_reader.End(); return(spr); }
public void setup(sprite_params _params) { m_offset_x = _params.m_offset_x; m_offset_y = _params.m_offset_y; m_size_x = _params.m_size_x; m_size_y = _params.m_size_y; m_CHR_data = _params.m_CHR_data; m_CHR_attr = _params.m_CHR_attr; m_CHR_data.link(); }
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)); }
private sprite_params cut_CHRs(sprite_params _spr_params, int _min_x, int _max_x, int _min_y, int _max_y, List <byte[]> _lines_arr, bool _alpha, int _alpha_ind, int _num_colors, bool _crop_image, int _palette_slot) { // cut sprite by tiles 8x8 { _spr_params.m_offset_x = _min_x; _spr_params.m_offset_y = _min_y; int dx_incr = _max_x - _min_x + 1; int dy_incr = _max_y - _min_y + 1; _spr_params.m_size_x = ((dx_incr % utils.CONST_CHR_SIDE_PIXELS_CNT != 0) ? (((dx_incr) + utils.CONST_CHR_SIDE_PIXELS_CNT) & -utils.CONST_CHR_SIDE_PIXELS_CNT):dx_incr) >> utils.CONST_CHR_SIDE_PIXELS_CNT_POW_BITS; _spr_params.m_size_y = ((dy_incr % utils.CONST_CHR_SIDE_PIXELS_CNT != 0) ? (((dy_incr) + utils.CONST_CHR_SIDE_PIXELS_CNT) & -utils.CONST_CHR_SIDE_PIXELS_CNT):dy_incr) >> utils.CONST_CHR_SIDE_PIXELS_CNT_POW_BITS; int x; int y; int i; byte[] pixels_line = null; byte[] pixels_row = new byte[utils.CONST_CHR_SIDE_PIXELS_CNT]; int n_lines = _lines_arr.Count; CHR_data chr_data = null; CHR_data_attr chr_attr = null; int chr_pos_x = 0; int chr_pos_y = 0; byte pix_ind = 0; int num_row_pixs = 0; int pix_acc = 0; int col_n; int row_n; int x_offset = 0; for (y = 0; y < _spr_params.m_size_y; y++) { x_offset = 0; for (x = 0; x < _spr_params.m_size_x; x++) { chr_pos_x = x * utils.CONST_CHR_SIDE_PIXELS_CNT; chr_pos_y = y * utils.CONST_CHR_SIDE_PIXELS_CNT; pix_acc = 0; chr_data = new CHR_data(); chr_attr = new CHR_data_attr(chr_pos_x, chr_pos_y); #if DEF_FIXED_LEN_PALETTE16_ARR chr_attr.palette_ind = _palette_slot; #endif chr_pos_x += _min_x; chr_pos_y += _min_y; // calc first non zero column if (_alpha) { pix_acc = 0; chr_pos_x += x_offset; for (col_n = 0; col_n < utils.CONST_CHR_SIDE_PIXELS_CNT; col_n++) { for (row_n = 0; row_n < utils.CONST_CHR_SIDE_PIXELS_CNT; row_n++) { pixels_line = (chr_pos_y + row_n < _lines_arr.Count) ? _lines_arr[chr_pos_y + row_n]:null; pix_ind = (chr_pos_x + col_n <= _max_x) ? (pixels_line != null ? pixels_line[chr_pos_x + col_n]:(_alpha ? (byte)_alpha_ind:(byte)0)):(_alpha ? (byte)_alpha_ind:(byte)0); if (_alpha && (_alpha_ind != 0)) { pix_ind += ( byte )(_num_colors - _alpha_ind); pix_ind %= ( byte )_num_colors; } pix_acc += pix_ind; } if (pix_acc != 0) { x_offset += col_n; chr_pos_x += col_n; chr_attr.x += x_offset; break; } } if (col_n == utils.CONST_CHR_SIDE_PIXELS_CNT) { continue; } } for (i = 0; i < utils.CONST_CHR_SIDE_PIXELS_CNT; i++) { pixels_line = (chr_pos_y + i < _lines_arr.Count) ? _lines_arr[chr_pos_y + i]:null; // copy line num_row_pixs = 0; do { pix_ind = (chr_pos_x + num_row_pixs <= _max_x) ? (pixels_line != null ? pixels_line[chr_pos_x + num_row_pixs]:(_alpha ? (byte)_alpha_ind:(byte)0)):(_alpha ? (byte)_alpha_ind:(byte)0); // fix the pixel index so that the first one will be transparency index if (_alpha && (_alpha_ind != 0)) { pix_ind += ( byte )(_num_colors - _alpha_ind); pix_ind %= ( byte )_num_colors; } pix_acc += pix_ind; pixels_row[num_row_pixs] = pix_ind; }while(++num_row_pixs < utils.CONST_CHR_SIDE_PIXELS_CNT); chr_data.push_line(pixels_row); } // save non-zero tile if (!_crop_image || (pix_acc != 0 || !_alpha)) { chr_attr.CHR_ind = m_CHR_arr.Count; _spr_params.m_CHR_attr.Add(chr_attr); m_CHR_arr.Add(chr_data); if (m_CHR_arr.Count >= utils.CONST_CHR_BANK_MAX_SPRITES_CNT) { break; } } } if (m_CHR_arr.Count >= utils.CONST_CHR_BANK_MAX_SPRITES_CNT) { MainForm.message_box("The CHR bank is full!", "Data Import", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Warning); break; } } } // convert tiles into pixels _spr_params.m_size_x <<= utils.CONST_CHR_SIDE_PIXELS_CNT_POW_BITS; _spr_params.m_size_y <<= utils.CONST_CHR_SIDE_PIXELS_CNT_POW_BITS; return(_spr_params); }
public sprite_params setup(Bitmap _bmp, bool _apply_palette, int _palette_slot) { sprite_params spr_params = new sprite_params(this); spr_params.m_CHR_data = this; int img_width = _bmp.Width; int img_height = _bmp.Height; 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 index_byte; byte[] pixels_line = null; Color[] plte = _bmp.Palette.Entries; #if DEF_NES int index_clamp_val = 3; int clrs_cnt = utils.CONST_PALETTE_SMALL_NUM_COLORS; #elif DEF_SMS || DEF_PCE int index_clamp_val = 15; int clrs_cnt = Math.Min(utils.CONST_PALETTE_SMALL_NUM_COLORS * utils.CONST_NUM_SMALL_PALETTES, plte.Length); #endif // detect valid borders of an image { BitmapData bmp_data = _bmp.LockBits(new Rectangle(0, 0, img_width, img_height), ImageLockMode.ReadOnly, _bmp.PixelFormat); if (bmp_data != null) { if (_apply_palette) // && plte.Length <= 16 ) <-- there are 256 colors palette on Linux here... why?!.. { // find nearest colors #if DEF_NES for (i = 0; i < clrs_cnt; i++) { palette_group.Instance.get_palettes_arr()[0].get_color_inds()[i] = utils.find_nearest_color_ind(plte[i % 4].ToArgb()); } palette_group.Instance.get_palettes_arr()[0].update(); palette_group.Instance.active_palette = 0; #elif DEF_SMS for (i = 0; i < clrs_cnt; i++) { 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[i % 16].ToArgb()); } for (i = 0; i < utils.CONST_NUM_SMALL_PALETTES; i++) { palette_group.Instance.get_palettes_arr()[i].update(); } #elif DEF_FIXED_LEN_PALETTE16_ARR palettes_array plt_arr = palettes_array.Instance; plt_arr.palette_index = _palette_slot; for (i = 0; i < clrs_cnt; i++) { plt_arr.update_color(_palette_slot, i, utils.find_nearest_color_ind(plte[i % 16].ToArgb())); } plt_arr.update_palette(); #endif } // fill the lines_arr // (indexed BMP has no transparency in fact) { IntPtr data_ptr = bmp_data.Scan0; for (i = 0; i < img_height; i++) { pixels_line = new byte[img_width]; for (j = 0; j < img_width; j++) { if (_bmp.PixelFormat == System.Drawing.Imaging.PixelFormat.Format8bppIndexed) { index_byte = Marshal.ReadByte(data_ptr, j + (i * bmp_data.Stride)); pixels_line[j] = ( byte )(index_byte & index_clamp_val); } else { index_byte = Marshal.ReadByte(data_ptr, (j >> 1) + (i * bmp_data.Stride)); pixels_line[j] = ( byte )((((j & 0x01) == 0x01) ? (index_byte & 0x0f):((index_byte & 0xf0) >> 4)) & index_clamp_val); } } lines_arr.Add(pixels_line); } } _bmp.UnlockBits(bmp_data); } } return(cut_CHRs(spr_params, min_x, max_x, min_y, max_y, lines_arr, false, -1, -1, false, _palette_slot)); }