2014-02-20 3 views
1

Вот фрагмент кода, где я пытаюсь установить значок синей точки (Bgr32; 169x169) на графике (Bgra32 3985x3443) в элементе управления изображением WPF.WritableBitmap.WritePixels, отображающийся в неправильном месте

string s = new FileInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).DirectoryName + "\\lg_dot.jpg"; 
BitmapImage icon = new BitmapImage(new Uri(s)); 
var baseLayer = img_BackgroundLayer.Source as BitmapImage; 
WriteableBitmap composite = new WriteableBitmap(baseLayer); 

int bytesPerPixel = (int)(icon.Format.BitsPerPixel + 7)/8; 
int stride = (int)(bytesPerPixel * icon.Width); 
int size = stride * (int)icon.Height; 
byte[] pixels = new byte[size];     
icon.CopyPixels(pixels, stride, 0); 

composite.WritePixels(new Int32Rect(0, 0, (int)icon.Width, (int)icon.Height), pixels, stride, 1000, 1000); 

Обратите внимание, что я помещаю точку (значок) в (1000, 1000) на изображении. Если смотреть, однако, верхний левый угол от точки не равен (1000, 1000), то он равен примерно (760 760). Если я попытаюсь поместить значок на (2000,2000), он появится примерно в (1520,1520). Место, где появляется значок, всегда приблизительно (0.76 * X, 0.76 * Y), где X и Y - целевые координаты.

Я думаю, что знаю, что здесь происходит ... что-то связанное с помещением изображения Bgr32 на фон Bgra32 ... но я недостаточно умен, чтобы понять, как его решить.

ответ

0

Bytes в формуле пикселей:

(bits per pixel + 7)/8 

Stride формула:

bytes per pixel * image width 

Примечание байт и биты и использовать целые для расчета!

Таким образом, для 1024 пикселов широкого изображения:

Bgr32

  • байт на пиксель: (24 + 7)/8 = 3
  • шаг: 3 * 1024 = 3072

Bgra32

  • байт на пиксель: (32 + 7)/8 = 4
  • шаг: 4 * 1024 = 4096

Глядя на ваш код:

  • походку должно быть 3, а не 4: D

  • вы понапрасну с использованием шага для int[], sizeof(int) == 4

byte смещения пикселя в массиве изображения byte[]: шаг * у + х * байт на пиксель

int смещения пикселя в массиве изображения int[]: Y * ширина + x

К сожалению, вы обнаружили, что у вашего Image.Stretch установлено значение None?

Наконец, остерегайтесь компонентов заказа:

BGRA представлен как ARGB (вы не могли видеть ничего, если А 0, и вы думаете, вы установили B)

Последний совет: https://writeablebitmapex.codeplex.com/ мощь быть более легким для вас в конце.


EDIT

Это очень плохо, в моем случае это нуль, как BitmapFrameDecode не может быть преобразован в BitmapImage, что лучше сохранить ссылку на источник вместо:

var baseLayer = Image1.Source as BitmapImage; 

Формулы, которые я вам дал, верны, мне нужно было только изменить destX и desty, поскольку мой фон был не таким большим, как ваш.

var icon = new BitmapImage(new Uri("..\\..\\avatar92.jpg", UriKind.Relative)); 
var background = new BitmapImage(new Uri("..\\..\\canary_1024_600_a_0.jpg", UriKind.Relative)); 
var writeableBitmap = new WriteableBitmap(background); 

int bytesPerPixel = (icon.Format.BitsPerPixel + 7)/8; 
int stride = bytesPerPixel * icon.PixelWidth; 
int size = stride * icon.PixelHeight; 
var pixels = new byte[size]; 
icon.CopyPixels(pixels, stride, 0); 
writeableBitmap.WritePixels(new Int32Rect(0, 0, icon.PixelWidth, icon.PixelHeight), pixels, stride, 500, 500); 

Image1.Source = writeableBitmap; 

enter image description here

Опять

  • ли Image.Stretch == None?
  • Правильность изображения? они должны быть, я думаю: D
  • У растровых изображений одинакового формата? Не то, чтобы это не провалилось, если они разные, но вы получите всевозможные забавные сюрпризы, попробуйте, например, использовать файл .GIF и .JPEG.
  • Я действительно предлагаю вам использовать WriteableBitmapEx вместо этого, вы можете рисовать пиксели, линии, прямоугольники, формы и т.д. ...

Вот тот же результат с WriteableBitmapEx без необходимости иметь дело со всеми деталями, такими как походкой, массив, BPP, и т.д ...

var icon = new BitmapImage(new Uri("..\\..\\avatar92.jpg", UriKind.Relative)); 
var background = new BitmapImage(new Uri("..\\..\\canary_1024_600_a_0.jpg", UriKind.Relative)); 
var img1 = BitmapFactory.ConvertToPbgra32Format(icon); 
var img2 = BitmapFactory.ConvertToPbgra32Format(background); 
var img1Size = new Size(img1.PixelWidth, img1.PixelHeight); 
img2.Blit(new Rect(new Point(500, 500), img1Size), img1, new Rect(img1Size)); 
Image1.Source = img2; 

Если вы предпочитаете трудный путь, то убедитесь, что ваши растровые изображения имеют одинаковый формат: FormatConvertedBitmap

Если вы все еще не можете заставить его работать, подать Short, Self Contained, Correct (Compilable), Example и ссылки на два изображения, чтобы люди могли действительно помочь вам. Я ничего не нашел в вашем коде, поэтому я думаю, что есть что-то не так, но поскольку вы не вставляли весь код, который мы не можем сказать.

+0

Я отредактировал свое оригинальное сообщение, чтобы использовать то, что, как я думаю, понял из вашего ответа. Никаких изменений в поведении, значок по-прежнему появляется не в том месте. – davecove

+0

Взгляните на мое редактирование. – Aybe

+0

Благодарим вас за использование пакета WriteableBitmapEx. Это проще, и мне понадобятся все эти функции Extensions. У меня все еще есть одна и та же проблема, но я около 98.7% уверен, что знаю, что сейчас не так ... dpi двух изображений отличается. В вашем примере img1 равен 96dpi, а img2 - 125dpi. 96/125 = .763, поэтому моя иконка появляется на пикселе 763,763, когда я нацелен на 1000 1000. Есть ли в WriteableBitmapEx метод изменения dpi? Я не видел его в обозревателе объектов. – davecove

Смежные вопросы