Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Чудовищная порча картинки в Net-Picturebox / 13 сообщений из 13, страница 1 из 1
07.03.2015, 02:04
    #38897751
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Чудовищная порча картинки в Net-Picturebox
Короче скрин прилагаю.
В качестве источника изображения используется ч/б файл (глубина цвета 1),
который масштабируется под размер Picturebox.
Для масштабирования используем GDI+
в .Net напр. New Bitmap(file/другой bitmap) (можно ручками через Graphics в полном соответствии с чистым GDI+) -но это одно и то же.

Задница в том что при отображении в .Net-Picturebox изображение рисуется точками и без всякого сглаживания.
На 8-ке еще не очень заметно (хотя подозрение возникло еще вчера),
но попробовал на XP и меня взбесило.

Потом попробовал просто загрузить файл в PictureBox :
Код: vbnet
1.
   PictureBox1.Image = New Bitmap("winXP.tif")


Такое же дерьмо.
Эффект похож на то как изображаются подобные (ч/б) картинки в стандартных просмотрщиках на XP (хорошо) и на вистообразных Vista-8.1 (х*ево).
В VB6-Picturebox все всегда отображается хорошо (со сглаживанием), и на Win8.1 тоже.

Предполагаю, виноват Picturebox в .Net. Такое качество устраивать не может.
Че делать то?
...
Рейтинг: 0 / 0
07.03.2015, 02:28
    #38897755
hVostt
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Чудовищная порча картинки в Net-Picturebox
Дмитрий77но попробовал на XP и меня взбесило.

зато в Windows 95 уже всё ОК, правда в DOS 6.11 не очень, тоже не знаю что с этим делать.
...
Рейтинг: 0 / 0
07.03.2015, 02:33
    #38897756
hVostt
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Чудовищная порча картинки в Net-Picturebox
...
Рейтинг: 0 / 0
07.03.2015, 02:52
    #38897758
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Чудовищная порча картинки в Net-Picturebox
hVostt,

хорош язвить.
На 8.1-ке ситуация сильно лучше, но "точки" в левой картинке все равно глаза режут, или не видно?

Предлагаешь дербанить класс PictureBox?
Потому что от того способ готовки самого bitmap абсолютно не влияет на визуальное качество отображаемой картинки.
...
Рейтинг: 0 / 0
07.03.2015, 03:31
    #38897759
hVostt
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Чудовищная порча картинки в Net-Picturebox
Дмитрий77,

чё гадать на кофейной гуще-то?

ясен пень, что дело в режимах интерполяции и сглаживания .

что касается отрисовки пискельных изображений в масштабе 1:1 — то никакое уродование изображения недопустимо, оно должно отображаться как есть. при масштабировании исопльзуется интерполяция. в VB6, сделанном для тупой деревенщины заранее задан тот режим интерполяции, который бы устроил большинство. я же дал ссылку, вся необходимая инфа по этой теме гуглится за 5 секунд. зачем вот это вот гадать, как там в Window 8, XP, или ещё где-то? один и тот же алгоритм будет одинаково работать хоть на холодильнике, хоть на космическом оборудовании.
...
Рейтинг: 0 / 0
07.03.2015, 03:45
    #38897760
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Чудовищная порча картинки в Net-Picturebox
hVostt,

ну хорошо у меня получилось.
Я сделал с теми же флагами, с которыми делал zoom подобным картинкам через GDI+.

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
Public Class Form1
  Dim PictureBox1 As New myPicBox

  Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    Me.Panel1.Controls.Add(PictureBox1)
    PictureBox1.Dock = DockStyle.Fill
    PictureBox1.SizeMode = PictureBoxSizeMode.Zoom
  End Sub

  Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Button1.Click
    PictureBox1.Image = New Bitmap("WinXP.tif")
  End Sub
End Class

Public Class myPicBox
  Inherits PictureBox

  Protected Overloads Overrides Sub OnPaint(ByVal pe As PaintEventArgs)
    pe.Graphics.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
    pe.Graphics.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality
    pe.Graphics.CompositingQuality = Drawing2D.CompositingQuality.HighQuality

    pe.Graphics.CompositingMode = Drawing2D.CompositingMode.SourceOver
    pe.Graphics.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBilinear
    MyBase.OnPaint(pe)
  End Sub

End Class



Все, стало как в VB6. Отлично.
Но я вынужден добавлять эти Picturebox-ы кодом, чего я делать не люблю.

Как мне это применить к уже нарисованным оригинальным Picturebox? Присобачивая класс через HandleCreated/HandleDestroyed (как делаю для WndProc)?


>в VB6, сделанном для тупой деревенщины заранее задан тот режим интерполяции, который бы устроил большинство.
Ну и нормально там по дефолту.
А в .Net извини, делать такое дефолтное гавно без возможности хотя бы задать что-то в штатных свойствах контрола, это думаю неправильно.
...
Рейтинг: 0 / 0
07.03.2015, 03:50
    #38897762
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Чудовищная порча картинки в Net-Picturebox
hVostt,

да спасибо тебе,
а то до меня бы не доперло как и что искать. Мне всего-то от GDI+ надо zoom, отображение и сохранение в различных форматах, причем все ч/б, а тут такая подстава на ровном месте.
...
Рейтинг: 0 / 0
07.03.2015, 03:53
    #38897763
hVostt
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Чудовищная порча картинки в Net-Picturebox
Дмитрий77Но я вынужден добавлять эти Picturebox-ы кодом, чего я делать не люблю.

Ну ок, определи где-нибудь в публичном статическом классе вот этот метод:

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
Protected Overloads Overrides Sub OnPaint(ByVal pe As PaintEventArgs)
    pe.Graphics.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
    pe.Graphics.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality
    pe.Graphics.CompositingQuality = Drawing2D.CompositingQuality.HighQuality

    pe.Graphics.CompositingMode = Drawing2D.CompositingMode.SourceOver
    pe.Graphics.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBilinear
    MyBase.OnPaint(pe)
  End Sub



И затем указывай его для события OnPaint во всех своих PictureBox-ах.
...
Рейтинг: 0 / 0
07.03.2015, 04:19
    #38897766
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Чудовищная порча картинки в Net-Picturebox
hVostt,

извини, но сейчас откровенно туплю.
>И затем указывай его для события OnPaint во всех своих PictureBox
я положил PictureBox2 на форму, вижу только событие Paint.
Ну попробовал на дурака:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
  Private Sub PictureBox2_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox2.Paint
    With e.Graphics
      .SmoothingMode = Drawing2D.SmoothingMode.HighQuality
      .PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality
      .CompositingQuality = Drawing2D.CompositingQuality.HighQuality

      .CompositingMode = Drawing2D.CompositingMode.SourceOver
      .InterpolationMode = Drawing2D.InterpolationMode.HighQualityBilinear
    End With
  End Sub


Оно естественно не работает.
Я так понимаю надо класс как выше (myPicBox) где-то пристыковать к уже имеющемуся PictureBox-у, но где не понимаю.
...
Рейтинг: 0 / 0
07.03.2015, 05:58
    #38897770
hVostt
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Чудовищная порча картинки в Net-Picturebox
Дмитрий77,

фих его знает как оно там в VB.NET, но вот вариант на C#

от такой публичный статический класс со статическим методом:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
using System;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public static class MyStaticClass
    {
        public static void PictureBoxOnPaint(object sender, PaintEventArgs e)
        {
            e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
            e.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
            e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
            e.Graphics.CompositingMode = CompositingMode.SourceOver;
            e.Graphics.InterpolationMode = InterpolationMode.HighQualityBilinear;
        }
    }
}



затем

ВАРИАНТ 1

в код формы ручками прописываешь по 1 строчке для каждого PictureBox-а

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            // метод 1
            this.Paint += MyStaticClass.PictureBoxOnPaint;
        }
    }



ВАРИАНТ 2

опять таки в код формы надо прописать один метод

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // метод 2
        private void CommonPaint(object sender, PaintEventArgs e)
        {
            MyStaticClass.PictureBoxOnPaint(sender, e);
        }

    }



и можно етот метод теперь для каждого бокса выбирать из дропдауна
...
Рейтинг: 0 / 0
07.03.2015, 07:23
    #38897781
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Чудовищная порча картинки в Net-Picturebox
hVostt,

Мои изыскания на эту тему следующие:


1.
Код: vbnet
1.
2.
3.
 Dim PictureBox1 As New myPicBox
...
 Me.Panel1.Controls.Add(PictureBox1)


Мало того что неудобно, так еще и динамическое Dock=Fill хаотически глючит, т.е. рисунок начинает когда ему вздумается залезать под скажем верхнюю и нижнюю панельки.

2. Ну в принципе я тут нашел другой метод. Кидаешь куда надо родной PictureBox. Идешь в файл Private Sub InitializeComponent()
-в VB.Net это в отдельном "скрытом" файле, там тупо в 2-х или 3-х местах меняешь As...Picturebox на As myPicBox - и усе, он остается в конструкторе но уже как myPicBox - с переопределенной OnPaint.

3. За поддержку спасибо, надо будет воспроизвести что ты сделал, м.б. пригодится как нибудь.


НО САМЫЙ П...Ц НЕ В ЭТОМ
Не надо ничего этого. PictureBox не виноват.

Виновато:
Код: vbnet
1.
New Bitmap("WinXP.tif")



Если по-порядку:
1. У меня в VB6 был такой хороший код (когда я делаю Zoom):

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
 hwndRef = GetActiveWindow
  hdcRef = GetDC(hwndRef)
  hdcDst = CreateCompatibleDC(hdcRef)
  hbmDst = CreateCompatibleBitmap(hdcRef, nDstWidth, nDstHeight)
  ReleaseDC hwndRef, hdcRef: hdcRef = 0: hwndRef = 0
 
  hbmDstOld = SelectObject(hdcDst, hbmDst)
 
  If GdipExec(GdipCreateFromHDC(hdcDst, hGraphics)) = OK Then
    GdipExec GdipSetSmoothingMode(hGraphics, SmoothingModeHighQuality)
    GdipExec GdipSetPixelOffsetMode(hGraphics, PixelOffsetModeHighQuality)
    GdipExec GdipSetCompositingQuality(hGraphics, CompositingQualityHighQuality)

    GdipExec GdipSetCompositingMode(hGraphics, CompositingModeSourceOver)
    GdipExec GdipSetInterpolationMode(hGraphics, _
     InterpolationModeHighQualityBilinear)
    GdipExec GdipDrawImageRectI(hGraphics, m_nBitmap, 0, 0, _
     nDstWidth, nDstHeight)
    
    GdipExec GdipDeleteGraphics(hGraphics): hGraphics = 0
  End If
  SelectObject hdcDst, hbmDstOld: hbmDstOld = 0
  DeleteDC hdcDst: hdcDst = 0
 
  If nFrame > 0 Then frameIndex = nActiveFrame
 
  Set Zoom = CreateIPictureDispFromHBITMAP(hbmDst)



2. Я его тупо и честно перекатал на .Net 17349261
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
    Dim bmDst As New Bitmap(nDstWidth, nDstHeight)
    Using gr As Graphics = Graphics.FromImage(bmDst)
      gr.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
      gr.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality
      gr.CompositingQuality = Drawing2D.CompositingQuality.HighQuality

      gr.CompositingMode = Drawing2D.CompositingMode.SourceOver
      gr.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBilinear
      gr.DrawImage(m_Bitmap, 0, 0, nDstWidth, nDstHeight)
    End Using
...
    Return bmDst



3. Потом меня вдруг "стукнуло", что нахрена все это нужно, типа какая в .Net афигенная автоматика и я сдуру заменяю все эти интерполяции 2-мя строчками :
Код: vbnet
1.
2.
    Dim bmDst As Bitmap = Nothing
    Try : bmDst = New Bitmap(m_Bitmap, nDstWidth, nDstHeight) : Catch : End Try


4. На 8.1 я сходу не понял что натворил, там качество хоть и теряется, но мало заметно.
5. А сегодня пошел тестить на XP и увидел.
6. Поскольку мини-тест (после подсказки с OnPaint) я делал одной строчкой без своего MultiPage класса
Код: vbnet
1.
PictureBox1.Image = New Bitmap("winXP.tif")


то ошибочно решили что проблема в Picturebox, и правка OnPaint типа лечит.
7. У меня глаза еще раз округлились, когда я имплементировал этот OnPaint в проект, пошел проверять на XP и увидел ту же мазню из точек.

Т.е. я подсунул в Picturebox исходно испорченный Zoom-bitmap низкого качества и OnPaint здесь уже не поможет.
Когда вернул на место интерполяции в ф-ции Zoom, все стало нормально с дефолтным PictureBox.

Короче зло сидит в конструкциях вида
Код: vbnet
1.
2.
New Bitmap(m_Bitmap, nDstWidth, nDstHeight)
New Bitmap(filename)


а никак ни в OnPaint Picturebox-а.
...
Рейтинг: 0 / 0
07.03.2015, 07:35
    #38897782
hVostt
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Чудовищная порча картинки в Net-Picturebox
Дмитрий77,

фух, ну слава богу, разобрались
...
Рейтинг: 0 / 0
07.03.2015, 08:59
    #38897793
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Чудовищная порча картинки в Net-Picturebox
hVostt,
коль уж тему затронули

hVosttзатем...ВАРИАНТ 1
На VB это будет думаю так:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
Public Class Form1
  Dim mystatic As New MyStaticClass

  Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    PictureBox1.Image = New Bitmap("WinXP.tif")
  End Sub

  Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    AddHandler Me.PictureBox1.Paint, AddressOf mystatic.PictureBoxOnPaint
  End Sub

End Class

Public Class MyStaticClass
  Public Sub PictureBoxOnPaint(sender As Object, e As PaintEventArgs)
    e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
    e.Graphics.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality
    e.Graphics.CompositingQuality = Drawing2D.CompositingQuality.HighQuality

    e.Graphics.CompositingMode = Drawing2D.CompositingMode.SourceOver
    e.Graphics.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBilinear
  End Sub

End Class



Но это эквивалентно моей попытке выше:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
  Private Sub PictureBox2_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox2.Paint
    With e.Graphics
      .SmoothingMode = Drawing2D.SmoothingMode.HighQuality
      .PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality
      .CompositingQuality = Drawing2D.CompositingQuality.HighQuality

      .CompositingMode = Drawing2D.CompositingMode.SourceOver
      .InterpolationMode = Drawing2D.InterpolationMode.HighQualityBilinear
    End With
  End Sub


с разницей что ты посылаешь обработку события в "другой класс" (чтоб типа не дублировать одинаковый код).

Только это никоим образом ни переопределяет внутреннюю On Paint() для уже добавленного оригинальногоо контрола и дает нуль эффекта.

Я гуглил,
но думаю единственный способ влезть в OnPaint() это переопределить контрол о чем говорилось выше.
А в плане "бытового комфорта" (если это уместно так назвать), кинуть на форму оригинальный и поменять его класс в паре строчек сгенерированного студией кода.

Ну, проблема то решена.
Зато теперь знаю что через New Bitmap(file) даже элементарную картинку грузить нежелательно.
Буду пользоваться своим мультифрейм классом, который готовит эту картинку с интерполяцией.
...
Рейтинг: 0 / 0
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Чудовищная порча картинки в Net-Picturebox / 13 сообщений из 13, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]