private bool[,] ProcessImage(Func <bool[, ], bool[, ]> imageDataProcessor, FirmwareImageMetadata imageMetadata, bool rebuildCache = false)
        {
            var processedData      = imageDataProcessor(ImagePixelGrid.Data);
            var processedImageSize = processedData.GetSize();
            var imageSizeChanged   = imageMetadata.Width != processedImageSize.Width || imageMetadata.Height != processedImageSize.Height;

            imageMetadata.Width  = (byte)processedImageSize.Width;
            imageMetadata.Height = (byte)processedImageSize.Height;

            m_firmware.WriteImage(processedData, imageMetadata);

            if (imageSizeChanged || rebuildCache)
            {
                ImageCacheManager.RebuildCache(m_firmware);
                ImageListBox.Invalidate();
            }
            else
            {
                var cachedImage = BitmapProcessor.CreateBitmapFromRaw(processedData);
                ImageCacheManager.SetGlyphImage(imageMetadata.Index, imageMetadata.BlockType, cachedImage);
                ImageCacheManager.RebuildStringImageCache(m_firmware, imageMetadata.BlockType);
                var updateCache = new Action(() =>
                {
                    ImageListBox.Invoke(new Action(() =>
                    {
                        var itemRect = ImageListBox.GetItemRectangle(imageMetadata.Index - 1);
                        ImageListBox.Invalidate(itemRect);
                    }));
                });
                updateCache.BeginInvoke(null, null);
            }

            IsDirty = true;
            return(processedData);
        }
        private void Icb_SelectedValueChanged(object sender, EventArgs e)
        {
            var icb = sender as ComboBox;

            if (icb == null)
            {
                return;
            }

            var tag  = icb.Tag as Tuple <FirmwareStringMetadata, int>;
            var item = icb.SelectedItem as ImagedItem <byte>;

            if (tag == null)
            {
                return;
            }
            if (item == null)
            {
                return;
            }

            var value = item.Value;
            var idx   = CharLayoutPanel.Controls.IndexOf(icb);

            m_firmware.WriteChar(value, tag.Item2, tag.Item1);
            var itemRect = StringListBox.GetItemRectangle(LastSelectedStringListBoxItemIndex);

            StringListBox.Invalidate(itemRect);
            ImageCacheManager.RebuildStringImageCache(m_firmware, BlockType.Block1);

            UpdateStringPreview();

            if (value == 0x00)
            {
                for (var i = idx + 1; i < CharLayoutPanel.Controls.Count; i++)
                {
                    var relatedIcb = CharLayoutPanel.Controls[i] as ComboBox;
                    if (relatedIcb == null)
                    {
                        continue;
                    }

                    relatedIcb.SelectedIndex = 0;
                    relatedIcb.Enabled       = false;
                }
            }
            else if (idx + 1 < CharLayoutPanel.Controls.Count)
            {
                var relatedIcb = CharLayoutPanel.Controls[idx + 1] as ComboBox;
                if (relatedIcb == null)
                {
                    return;
                }

                if (relatedIcb.SelectedIndex == 0 && !relatedIcb.Enabled)
                {
                    relatedIcb.Enabled = true;
                }
            }

            IsDirty = true;
        }