В верхней части класса, который я делаю:
private static Bitmap bmp2 = new Bitmap(@"C:\Temp\New folder (17)\radar001486.GIF");
Затем внутри метода, который я делаю:
private void test()
{
int current_list_length = pointtocolor.Count;
for (int kk=0;kk<current_list_length;kk++)
{
PointF pt = pointtocolor[kk];
e.FillEllipse(cloudColors[cloudColorIndex], pt.X * (float)currentFactor, pt.Y * (float)currentFactor, radius, radius);
bmp2.SetPixel((int)pt.X * (int)currentFactor, (int)pt.Y * (int)currentFactor, Color.Yellow);
}
bmp2.Save(@"c:\temp\yellowbmpcolor.bmp");
}
Как только он попадает внутрь цикла, он делает исключение в строке:
bmp2.SetPixel((int)pt.X * (int)currentFactor, (int)pt.Y * (int)currentFactor, Color.Yellow);
Если я изменю экземпляр bmp2 на:
private static Bitmap bmp2 = new Bitmap(@"C:\Temp\New folder (17)\radar001486.GIF");
Для
private static Bitmap bmp2 = new Bitmap(512,512);
Затем он будет работать, но я хочу, чтобы SetPixel пиксели поверх исходного радара001486.GIF, а не на новом пустом Bitmap.
Проблема в том, что вы используете GIF, поскольку он имеет индексированные пиксели. Попробуйте преобразовать его в png, если сможете; или если вы не можете, превратите его в неиндексированное изображение, используя:
public Bitmap CreateNonIndexedImage(Image src)
{
Bitmap newBmp = new Bitmap(src.Width, src.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
using (Graphics gfx = Graphics.FromImage(newBmp)) {
gfx.DrawImage(src, 0, 0);
}
return newBmp;
}
Примечание. Если у вас есть возможность сделать это (например, незагруженные изображения или у вас есть доступ к серверу), определите их преобразование в PNG.
Изображение, которое вы пытаетесь изменить, - это индексированный GIF. Это означает, что изображение не содержит серию пикселей с соответствующими значениями цвета (как это делает ваш новый Bitmap
); скорее, он содержит цветовую палитру в сочетании с серией пикселей со значениями индекса в палитре. Формат пикселя вашего изображения, загруженного с диска, вероятно, похож на Format8bppIndexed
.
Вы не можете использовать SetPixel
для этого типа изображения, потому что SetPixel
хочет напрямую установить значения R, G и B для пикселя. Это не то, как работает индексированное изображение.
Чтобы изменить этот вид изображения, у вас есть несколько вариантов:
Лучше всего использовать WPF, который имеет GifBitmapEncoder и GifBitmapDecoder. Это позволяет вам декодировать данные GIF во что-то, что WPF может нарисовать, а затем преобразовать обратно. Поскольку это использует DirectX, а не GDI +, у него нет ограничений таких вещей, как SetPixel
. Я действительно хотел бы предложить вам пойти по этому маршруту, если это возможно, но если нет:
Используйте GDI + для Преобразовать изображение в неиндексированный тип изображения, измените его и convert он вернулся. Это, как правило, ужасная идея: GDI + и индексированные форматы не ладят друг с другом, и это включает кодирование растрового изображения в качестве индексированного GIF. Качество изображения, вероятно, будет ужасным.
Отредактируйте данные байта напрямую. Для этого вам нужно извлечь данные GIF в массив и установить пиксели в правильные индексированные значения. Фокус здесь заключается в определении правильного значения индекса; или, если в палитре окажется пустой, вы можете просто добавить еще один. Вам нужно углубиться в формат GIF, чтобы понять это, хотя он, вероятно, будет наиболее эффективным с точки зрения как пространства, так и скорости без снижения качества изображения. Когда вы знаете, какое значение индекса для записи, вы делаете что-то вроде этого:
var data = image.LockBits(new Rectangle(0, 0, image.Width, image.Height),
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
var bytes = new byte[data.Height * data.Stride];
Marshal.Copy(data.Scan0, bytes, 0, bytes.Length);
bytes[5 * data.Stride + 5] = 1; // Set the pixel at (5, 5) to the color #1
Marshal.Copy(bytes, 0, data.Scan0, bytes.Length);
image.UnlockBits(data);
Проблема заключается в вашем типе изображения, так как он отлично работает с .jpeg. Вы можете получить Bitmap из Image
Попробуйте изменить на это:
private static Bitmap bmp2 = new Bitmap(Image.FromFile(@"C:\Temp\New folder (17)\radar001486.GIF"));
Вот мой полный тестовый код:
private Bitmap bmp2 = new Bitmap(Image.FromFile(@"e:\temp\temp\yourGIF.gif"));
public Form1()
{
InitializeComponent();
pictureBox1.Image = bmp2;
}
private void button2_Click(object sender, EventArgs e)
{
var sz = bmp2.Size;
for(int x= 0; x<sz.Width; x++)
{
for(int y=0; y<sz.Height; y++)
{
bmp2.SetPixel(x, y, Color.Yellow);
}
}
pictureBox1.Refresh();
}