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);
            }
Beispiel #2
0
        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));
        }