GDI+ Как изменить размер холста изображения.

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
viter.alex
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 221
Зарегистрирован: 27.07.2008 (Вс) 20:17
Откуда: Montreal

GDI+ Как изменить размер холста изображения.

Сообщение viter.alex » 13.01.2010 (Ср) 9:26

Столкнулся я с необходимостью получить уменьшенное изображение из файла картинки.
Сделал такой вариант:
Код: Выделить всё
Option Private Module
Option Explicit

Public Declare Function GdiplusStartup Lib "gdiplus" (token As Long, inputbuf As GdiplusStartupInput, Optional ByVal outputbuf As Long = 0) As GpStatus
Public Declare Function GdipCreateBitmapFromFile Lib "gdiplus" (ByVal filename As Long, bitmap As Long) As GpStatus
Public Declare Function GdipCreateHBITMAPFromBitmap Lib "gdiplus" (ByVal bitmap As Long, hbmReturn As Long, ByVal background As Long) As GpStatus
Public Declare Function GdipDisposeImage Lib "gdiplus" (ByVal image As Long) As GpStatus
Public Declare Function GdiplusShutdown Lib "gdiplus" (ByVal token As Long) As Long
Public Declare Function OleCreatePictureIndirect Lib "olepro32.dll" (PicDesc As PICTDESC, RefIID As GUID, ByVal fPictureOwnsHandle As Long, IPic As IPicture) As Long
Public Declare Function GdipGetImageDimension Lib "gdiplus" (ByVal image As Long, Width As Single, Height As Single) As GpStatus
Public Declare Function GdipGetImageWidth Lib "gdiplus" (ByVal image As Long, Width As Long) As GpStatus
Public Declare Function GdipGetImageHeight Lib "gdiplus" (ByVal image As Long, Height As Long) As GpStatus
Public Declare Function GdipGetImageHorizontalResolution Lib "gdiplus" (ByVal image As Long, resolution As Single) As GpStatus
Public Declare Function GdipGetImageVerticalResolution Lib "gdiplus" (ByVal image As Long, resolution As Single) As GpStatus
Public Declare Function GdipGetImageThumbnail Lib "gdiplus" (ByVal image As Long, ByVal thumbWidth As Long, ByVal thumbHeight As Long, thumbImage As Long, _
                        Optional ByVal callback As Long = 0, Optional ByVal callbackData As Long = 0) As GpStatus
Public Declare Function GdipLoadImageFromFile Lib "gdiplus" (ByVal filename As String, image As Long) As GpStatus

Public Enum GpStatus
  OK = 0
  GenericError = 1
  InvalidParameter = 2
  OutOfMemory = 3
  ObjectBusy = 4
  InsufficientBuffer = 5
  NotImplemented = 6
  Win32Error = 7
  WrongState = 8
  Aborted = 9
  FileNotFound = 10
  ValueOverflow = 11
  AccessDenied = 12
  UnknownImageFormat = 13
  FontFamilyNotFound = 14
  FontStyleNotFound = 15
  NotTrueTypeFont = 16
  UnsupportedGdiplusVersion = 17
  GdiplusNotInitialized = 18
  PropertyNotFound = 19
  PropertyNotSupported = 20
End Enum

Public Type GUID
  Data1 As Long
  Data2 As Integer
  Data3 As Integer
  Data4(0 To 7) As Byte
End Type

Public Type PICTDESC
  Size As Long
  Type As Long
  hPic As Long
  hPal As Long
End Type

Public Type GdiplusStartupInput
  GdiplusVersion As Long
  DebugEventCallback As Long
  SuppressBackgroundThread As Long
  SuppressExternalCodecs As Long
End Type


Public Function LoadImage(ByVal strFName As String) As IPicture
  Dim uGdiInput As GdiplusStartupInput
  Dim hGdiPlus As Long
  Dim hGdiImage As Long
  Dim hBitmap As Long
  Dim imgThumb As Long
  Dim imgHeight As Single, imgWidth As Single
  uGdiInput.GdiplusVersion = 1
 
  'Запускаем GDI+
  If GdiplusStartup(hGdiPlus, uGdiInput) = OK Then
    'Создаём изображение в памяти
    If GdipCreateBitmapFromFile(StrPtr(strFName), hGdiImage) = OK Then
      'Получаем размеры изображения
      Call GdipGetImageDimension(hGdiImage, imgWidth, imgHeight)
      'Делаем из изображения уменьшенное
      Call GdipGetImageThumbnail(hGdiImage, ItemWidth, ItemWidth * imgHeight / imgWidth, imgThumb)
      'Указатель на изображение
      Call GdipCreateHBITMAPFromBitmap(imgThumb, hBitmap, 0)
      'Конвертируем изображение в IPicture
      Set LoadImage = ConvertToIPicture(hBitmap)
      GdipDisposeImage hGdiImage
    End If
    GdiplusShutdown hGdiPlus
  Else
    MsgBox "Ошибка при загрузке GDI+!", vbCritical
  End If

End Function

Public Function ConvertToIPicture(ByVal hPic As Long) As IPicture
 
  Dim uPicInfo As PICTDESC
  Dim IID_IDispatch As GUID
  Dim IPic As IPicture
 
  Const PICTYPE_BITMAP = 1
 
  With IID_IDispatch
    .Data1 = &H7BF80980
    .Data2 = &HBF32
    .Data3 = &H101A
    .Data4(0) = &H8B
    .Data4(1) = &HBB
    .Data4(2) = &H0
    .Data4(3) = &HAA
    .Data4(4) = &H0
    .Data4(5) = &H30
    .Data4(6) = &HC
    .Data4(7) = &HAB
  End With
 
  With uPicInfo
    .Size = Len(uPicInfo)
    .Type = PICTYPE_BITMAP
    .hPic = hPic
    .hPal = 0
  End With
 
  OleCreatePictureIndirect uPicInfo, IID_IDispatch, True, IPic
 
  Set ConvertToIPicture = IPic
End Function

Основная функция LoadImage, которая возвращает IPicture для передачи картинки на панель инструментов Word.
Проблема в том, что мне нужно получить картинку с фиксированными размерами, но так, чтобы пропорции исходного изображения, которое может быть любым, не менялись.
Допустим мне нужно получить картинку 150×200 из изображения 600×480. Если его пропорционально уменьшить в четыре раза по ширине, то получим 150×120, меня это не устраивает. Нужно сделать, чтобы картинка 150×120 располагалась в центре холста с размерами 150×200. Пока что я использую GdipGetImageThumbnail, но она работает только с фиксированным размером и пропорции искажает.
Думаю, что нужно после загрузки изображения в память изменять холст так, чтобы пропорции становились равными пропорциям уменьшенного изображения, а затем уже получать Thumbnail. Т,е. в моём примере нужно изменить изображение с 640×480 до 640×800, дополнив недостающее изображение пустым фоном.
Но вот как менять холст? Создавать изображение с нужными пропорциями, а потом накладывать на него то, которое у меня есть?
Лучше день потерять — потом за пять минут долететь!

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: GDI+ Как изменить размер холста изображения.

Сообщение Mikle » 13.01.2010 (Ср) 11:21

Создавать изображение с нужными пропорциями, а потом накладывать на него то, которое у меня есть?

Именно так. И не нужно столько API деклараций, всё легко делается на VB6.

viter.alex
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 221
Зарегистрирован: 27.07.2008 (Вс) 20:17
Откуда: Montreal

Re: GDI+ Как изменить размер холста изображения.

Сообщение viter.alex » 13.01.2010 (Ср) 12:05

Вообще-то я делаю в VBA, а это накладывает свои ограничения.
Если можно сделать проще, подскажи как, хотя этот вариант меня по быстродействию устраивает. Проблема только с изменением размера холста.
Лучше день потерять — потом за пять минут долететь!

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: GDI+ Как изменить размер холста изображения.

Сообщение Mikle » 13.01.2010 (Ср) 22:34

Если я правильно понял, нужно что-то типа миниатюр для просмотра картинок в окне фиксированного размера.
Тогда зачем менять размер холста? Ведь придётся закрашивать лишнюю область каким-то цветом?
Я, вообще, не очень знаю VBA, но кое-что вышло. Сделай Image нужного размера и цвета, назовём его img0, поверх него расположим ещё один Image img1. Добавим кнопку с таким кодом:
Код: Выделить всё
Private Sub CommandButton1_Click()
    Dim pic As IPictureDisp
    Dim w As Single, h As Single
    img1.PictureSizeMode = fmPictureSizeModeStretch
    Set pic = LoadPicture("c:\temp\1.jpg")
    w = pic.Width
    h = pic.Height
    If w / h > img0.Width / img0.Height Then
        img1.Move img0.Left, img0.Top + img0.Height * (1 - h / w) * 0.5, img0.Width, img0.Height * h / w
    Else
        img1.Move img0.Left + img0.Width * (1 - w / h) * 0.5, img0.Top, img0.Width * w / h, img0.Height
    End If
    Set img1.Picture = pic
End Sub

Рисунок "c:\temp\1.jpg" масштабируется до нужного размера.

viter.alex
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 221
Зарегистрирован: 27.07.2008 (Вс) 20:17
Откуда: Montreal

Re: GDI+ Как изменить размер холста изображения.

Сообщение viter.alex » 14.01.2010 (Чт) 5:11

Нет, ты неправильно понял.
Мне нужно сделать такую штуку для Word 2007 и выше
Изображение
Вернее, как видно из рисунка, я её уже сделал. Всё отображается нормально если изображения одинакового размера (как на картинке). Но если изображения разные, то нормально отображается только первое, а все остальные подгоняются под его пропорции. Это происходит потому, что первое изображение задаёт размеры ячейки для картинки, а все остальные потом вписываются в эти ячейки.
Кроме того, если первое изображение по ширине меньше, чем минимальная ширина (которую я задаю), то оно растягивается и выглядит неаккуратно.
Изображение
Вот пример. Первое изображение правильно уменьшено и отображается без искажений. А второе изображение, хотя и было уменьшено правильно, растянулось до размеров первого, а в оригинале выглядит так:
Изображение
Нужно его поместить на полотно заданных размеров и уже картинку с изменённым полотном фиксированного размера отдавать Word'у.
Вот такую
Изображение
Надеюсь, так понятнее.
Лучше день потерять — потом за пять минут долететь!

iGrok
Артефакт VBStreets
Артефакт VBStreets
 
Сообщения: 4272
Зарегистрирован: 10.05.2007 (Чт) 16:11
Откуда: Сетевое сознание

Re: GDI+ Как изменить размер холста изображения.

Сообщение iGrok » 14.01.2010 (Чт) 14:20

Это и так было понятно. А чем тебя код Mikle не устраивает?
Просто вместо img0 бери размер, заданный первым изображением. А потом вписывай туда каждое последующее по формуле, предложенной Mikle.
label:
cli
jmp label

viter.alex
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 221
Зарегистрирован: 27.07.2008 (Вс) 20:17
Откуда: Montreal

Re: GDI+ Как изменить размер холста изображения.

Сообщение viter.alex » 14.01.2010 (Чт) 14:49

Но у меня же нет img0! Всё, что у меня есть, это процедура загрузки изображения для элемента галереи:
Код: Выделить всё
Sub getItemImage(control As IRibbonControl, index As Integer, ByRef image)

  'Загружаем изображение
  Set image = LoadImage(arImagePaths(index))

End Sub

Мне нужно туда передать уже готовое изображение. Т.е. то, что сделал Mikle, мне нужно сделать в памяти.

Чем чёрт не шутит, посмотрел TypeName(image) перед загрузкой изображения. Оказалось Nothing, т.е. это, похоже, просто область памяти, в которую мне нужно передать изображение. После загрузки изображения TypeName уже Picture

Added, кроме того, LoadPicture для Image не позволяет загрузить png и gif, а собственно ради них я и начал пользоваться gdi+
Лучше день потерять — потом за пять минут долететь!

iGrok
Артефакт VBStreets
Артефакт VBStreets
 
Сообщения: 4272
Зарегистрирован: 10.05.2007 (Чт) 16:11
Откуда: Сетевое сознание

Re: GDI+ Как изменить размер холста изображения.

Сообщение iGrok » 15.01.2010 (Пт) 0:38

Я не совсем понимаю.. Получается, ты занимаешься ТОЛЬКО загрузкой миниатюры из файла, а размещением занимается уже чужой код?
И тебе нужно отдать не просто отресайзенную картинку, а картинку с полями цвета фона, заданного размера?

Если так, то видимо действительно придётся, создавать изображение нужного размера, залитое нужным фоном, создавать второе изображение из файла, ресайзить, накладывать на первое по центру и уже эту картинку отдавать.
label:
cli
jmp label

viter.alex
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 221
Зарегистрирован: 27.07.2008 (Вс) 20:17
Откуда: Montreal

Re: GDI+ Как изменить размер холста изображения.

Сообщение viter.alex » 15.01.2010 (Пт) 4:09

Совершенно верно. Размещением занимается внутренний код Word, в который я никоим образом влезть не могу
Я пытаюсь сейчас экспериментировать с этими функциями, но толку пока что 0
Код: Выделить всё
Public Declare Function GdipGetImageGraphicsContext Lib "gdiplus" (ByVal image As Long, graphics As Long) As GpStatus
Public Declare Function GdipCreateFromHDC Lib "gdiplus" (ByVal hdc As Long, graphics As Long) As GpStatus
Public Declare Function GdipDrawRectangle Lib "gdiplus" (ByVal graphics As Long, ByVal pen As Long, ByVal x As Single, ByVal y As Single, ByVal Width As Single, ByVal Height As Single) As GpStatus
Public Declare Function GdipFillRectangle Lib "gdiplus" (ByVal graphics As Long, ByVal brush As Long, ByVal x As Single, ByVal y As Single, ByVal Width As Single, ByVal Height As Single) As GpStatus
Public Declare Function GdipCreateSolidFill Lib "gdiplus" (ByVal argb As Long, brush As Long) As GpStatus
Public Declare Function GdipCreatePen1 Lib "gdiplus" (ByVal color As Long, ByVal Width As Single, ByVal unit As GpUnit, pen As Long) As GpStatus
Public Declare Function GdipDrawImage Lib "gdiplus" (ByVal graphics As Long, ByVal image As Long, ByVal x As Single, ByVal y As Single) As GpStatus
Лучше день потерять — потом за пять минут долететь!

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Re: GDI+ Как изменить размер холста изображения.

Сообщение Nord777 » 15.01.2010 (Пт) 7:48

Я пытаюсь сейчас экспериментировать с этими функциями, но толку пока что 0
Создай проект на .Net.
Добейся должного функционирования.
Посмотри Reflector'ом какие функции и с какими параметрами вызываются.
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Re: GDI+ Как изменить размер холста изображения.

Сообщение Andrey Fedorov » 15.01.2010 (Пт) 12:17

Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

viter.alex
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 221
Зарегистрирован: 27.07.2008 (Вс) 20:17
Откуда: Montreal

Re: GDI+ Как изменить размер холста изображения.

Сообщение viter.alex » 15.01.2010 (Пт) 13:38

Спасибо, буду ковыряться. О результатах доложу

Added Ура! Получилось! Вот так теперь выглядит галерея с изображениями разного размера:
Изображение
Код: Выделить всё
Option Private Module
Option Explicit

'Graphics
Private Declare Function CreateCompatibleDC Lib "gdi32.dll" (ByVal hDC As Long) As Long
Private Declare Function GetDeviceCaps Lib "gdi32.dll" (ByVal hDC As Long, ByVal nIndex As Long) As Long
Private Declare Function CreateBitmap Lib "gdi32.dll" (ByVal nWidth As Long, ByVal nHeight As Long, ByVal nPlanes As Long, ByVal nBitCount As Long, lpBits As Any) As Long
Private Declare Function SelectObject Lib "gdi32.dll" (ByVal hDC As Long, ByVal hObject As Long) As Long
Private Declare Function CreateSolidBrush Lib "gdi32.dll" (ByVal crColor As Long) As Long
Private Declare Function PatBlt Lib "gdi32.dll" (ByVal hDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal dwRop As Long) As Long
Private Declare Function DeleteObject Lib "gdi32.dll" (ByVal hObject As Long) As Long
Private Declare Function DeleteDC Lib "gdi32.dll" (ByVal hDC As Long) As Long

Private Declare Function GdipCreateFromHDC Lib "gdiplus.dll" (ByVal hDC As Long, GpGraphics As Long) As Long
Private Declare Function GdipSetInterpolationMode Lib "gdiplus.dll" (ByVal graphics As Long, ByVal InterMode As InterpolationMode) As Long
Private Declare Function GdipDrawImageRectRectI Lib "gdiplus.dll" (ByVal graphics As Long, ByVal GpImage As Long, ByVal dstx As Long, ByVal dsty As Long, ByVal dstwidth As Long, ByVal dstheight As Long, ByVal srcx As Long, ByVal srcy As Long, ByVal srcwidth As Long, ByVal srcheight As Long, ByVal srcUnit As Long, ByVal ImageAttributes As Long, ByVal callback As Long, ByVal callbackData As Long) As Long
Private Declare Function GdipDrawImageRectI Lib "gdiplus.dll" (ByVal graphics As Long, ByVal img As Long, ByVal X As Long, ByVal Y As Long, ByVal Width As Long, ByVal Height As Long) As Long
Private Declare Function GdipDeleteGraphics Lib "gdiplus.dll" (ByVal graphics As Long) As Long

Public Declare Function GdiplusStartup Lib "gdiplus" (token As Long, inputbuf As GdiplusStartupInput, Optional ByVal outputbuf As Long = 0) As GpStatus
Public Declare Function GdiplusShutdown Lib "gdiplus" (ByVal token As Long) As Long

Public Declare Function GdipCreateBitmapFromFile Lib "gdiplus" (ByVal filename As Long, bitmap As Long) As GpStatus
Public Declare Function GdipCreateHBITMAPFromBitmap Lib "gdiplus" (ByVal bitmap As Long, hbmReturn As Long, ByVal background As Long) As GpStatus

Public Declare Function GdipLoadImageFromFile Lib "gdiplus" (ByVal filename As String, image As Long) As GpStatus
Public Declare Function GdipGetImageDimension Lib "gdiplus" (ByVal image As Long, Width As Single, Height As Single) As GpStatus
Public Declare Function GdipGetImageWidth Lib "gdiplus" (ByVal image As Long, Width As Long) As GpStatus
Public Declare Function GdipGetImageHeight Lib "gdiplus" (ByVal image As Long, Height As Long) As GpStatus
Public Declare Function GdipGetImageHorizontalResolution Lib "gdiplus" (ByVal image As Long, resolution As Single) As GpStatus
Public Declare Function GdipGetImageVerticalResolution Lib "gdiplus" (ByVal image As Long, resolution As Single) As GpStatus
Public Declare Function GdipDisposeImage Lib "gdiplus" (ByVal image As Long) As GpStatus

Private Declare Function OleCreatePictureIndirect Lib "olepro32.dll" (PicDesc As PICTDESC, RefIID As GUID, ByVal fPictureOwnsHandle As Long, IPic As IPicture) As Long

Private Enum SmoothingMode
    SmoothingModeInvalid = -1&
    SmoothingModeDefault = 0&
    SmoothingModeLow = 1&
    SmoothingModeHigh = 2&
    SmoothingModeNone = SmoothingModeHigh + 1
    SmoothingModeAntiAlias8x4 = SmoothingModeHigh + 2
    SmoothingModeAntiAlias = SmoothingModeAntiAlias8x4
    SmoothingModeAntiAlias8x8 = SmoothingModeHigh + 3
End Enum

Private Enum InterpolationMode
  InterpolationModeInvalid = SmoothingModeInvalid
  InterpolationModeDefault = SmoothingModeDefault
  InterpolationModeLowQuality = SmoothingModeLow
  InterpolationModeHighQuality = SmoothingModeHigh
  InterpolationModeBilinear = SmoothingModeHigh + 1
  InterpolationModeBicubic = SmoothingModeHigh + 2
  InterpolationModeNearestNeighbor = SmoothingModeHigh + 3
  InterpolationModeHighQualityBilinear = SmoothingModeHigh + 4
  InterpolationModeHighQualityBicubic = SmoothingModeHigh + 5
End Enum

Public Enum GpStatus
  OK = 0
  GenericError = 1
  InvalidParameter = 2
  OutOfMemory = 3
  ObjectBusy = 4
  InsufficientBuffer = 5
  NotImplemented = 6
  Win32Error = 7
  WrongState = 8
  Aborted = 9
  FileNotFound = 10
  ValueOverflow = 11
  AccessDenied = 12
  UnknownImageFormat = 13
  FontFamilyNotFound = 14
  FontStyleNotFound = 15
  NotTrueTypeFont = 16
  UnsupportedGdiplusVersion = 17
  GdiplusNotInitialized = 18
  PropertyNotFound = 19
  PropertyNotSupported = 20
End Enum

Private Type GUID
  Data1 As Long
  Data2 As Integer
  Data3 As Integer
  Data4(0 To 7) As Byte
End Type

Private Type PICTDESC
  Size As Long
  Type As Long
  hPic As Long
  hPal As Long
End Type

Public Type GdiplusStartupInput
  GdiplusVersion As Long
  DebugEventCallback As Long
  SuppressBackgroundThread As Long
  SuppressExternalCodecs As Long
End Type

Private Const PLANES = 14            '  Number of planes
Private Const BITSPIXEL = 12         '  Number of bits per pixel
Private Const PATCOPY = &HF00021     ' (DWORD) dest = pattern
Private Const UnitPixel = 2

Private hGdiPlus As Long
Private uGdiInput As GdiplusStartupInput

Public Function GDIPlusStartStop(Start As Boolean) As GpStatus
  'Запускаем GDI+
  If Start Then
    uGdiInput.GdiplusVersion = 1
    GDIPlusStartStop = GdiplusStartup(hGdiPlus, uGdiInput)
  Else
    GdiplusShutdown hGdiPlus
  End If
End Function

Public Function LoadImage(ByVal strFName As String) As IPicture
 
  Dim hGdiImage As Long
  Dim imgThumb As Long
  Dim imgHeight As Single, imgWidth As Single
  Dim hDC As Long
 
  'Создаём изображение в памяти
  If GdipCreateBitmapFromFile(StrPtr(strFName), hGdiImage) = OK Then
   
    'Инициализация графического контекста с заданным цветом
    InitDC hDC, imgThumb, RGB(0, 0, 0), ITEMWIDTH, ITEMHEIGHT
    'Уменьшаем изображение
    GdipResize hGdiImage, hDC, ITEMWIDTH, ITEMHEIGHT, True
    'Получаем указатель на битмап
    GetBitmap hDC, imgThumb
    'Конвертируем битмап в IPicture
    Set LoadImage = ConvertToIPicture(imgThumb) 'hBitmap
  End If

End Function

'Инициализация контекста устройства для рисования
Private Sub InitDC(hDC As Long, hBitmap As Long, BackColor As Long, Width As Long, Height As Long)
    Dim hBrush As Long

    'Создаёт контекст устройства в памяти, назначает для него битовое изображение и заливает его сплошным цветом.
    hDC = CreateCompatibleDC(ByVal 0&)
    hBitmap = CreateBitmap(Width, Height, GetDeviceCaps(hDC, PLANES), GetDeviceCaps(hDC, BITSPIXEL), ByVal 0&)
    hBitmap = SelectObject(hDC, hBitmap)
    hBrush = CreateSolidBrush(BackColor)
    hBrush = SelectObject(hDC, hBrush)
    PatBlt hDC, 0, 0, Width, Height, PATCOPY
    DeleteObject SelectObject(hDC, hBrush)
End Sub

'Изменение размера изображения, используя GDI+
Private Sub GdipResize(img As Long, hDC As Long, Width As Long, Height As Long, Optional RetainRatio As Boolean = False)
    Dim graphics   As Long      'Указатель на графический объект
    Dim OrWidth    As Long      'Ширина исходного изображения
    Dim OrHeight   As Long      'Высота исходного изображения
    Dim OrRatio    As Double    'Соотношение сторон исходного изображения
    Dim DesRatio   As Double    'Соотношение сторон уменьшенного изображения
    Dim DestX      As Long      'Положение уменьшенного по горизонтали
    Dim DestY      As Long      'Положение уменьшенного изображения по вертикали
    Dim DestWidth  As Long      'Ширина уменьшенного изображения
    Dim DestHeight As Long      'Высота уменьшенного изображения

    GdipCreateFromHDC hDC, graphics
    GdipSetInterpolationMode graphics, InterpolationModeHighQualityBicubic

    If RetainRatio Then
        GdipGetImageWidth img, OrWidth
        GdipGetImageHeight img, OrHeight

        OrRatio = OrWidth / OrHeight
        DesRatio = Width / Height

        'Вычисление положения уменьшенного изображения
        DestWidth = IIf(DesRatio < OrRatio, Width, Height * OrRatio)
        DestHeight = IIf(DesRatio < OrRatio, Width / OrRatio, Height)
        DestX = (Width - DestWidth) / 2
        DestY = (Height - DestHeight) / 2

        GdipDrawImageRectRectI graphics, img, DestX, DestY, DestWidth, DestHeight, 0, 0, OrWidth, OrHeight, UnitPixel, 0, 0, 0
    Else
        GdipDrawImageRectI graphics, img, 0, 0, Width, Height
    End If
   
    GdipDeleteGraphics graphics
End Sub

'Заменяет старое битовое изображение в контексте и возвращает новое
Private Sub GetBitmap(hDC As Long, hBitmap As Long)
    hBitmap = SelectObject(hDC, hBitmap)
    DeleteDC hDC
End Sub

'Создаёт IPicture по указателю на битовое изображение в памяти
Private Function ConvertToIPicture(ByVal hPic As Long) As IPicture
 
  Dim uPicInfo As PICTDESC
  Dim IID_IDispatch As GUID
  Dim IPic As IPicture
 
  Const PICTYPE_BITMAP = 1
 
  With IID_IDispatch
    .Data1 = &H7BF80980
    .Data2 = &HBF32
    .Data3 = &H101A
    .Data4(0) = &H8B
    .Data4(1) = &HBB
    .Data4(2) = &H0
    .Data4(3) = &HAA
    .Data4(4) = &H0
    .Data4(5) = &H30
    .Data4(6) = &HC
    .Data4(7) = &HAB
  End With
 
  With uPicInfo
    .Size = Len(uPicInfo)
    .Type = PICTYPE_BITMAP
    .hPic = hPic
    .hPal = 0
  End With
 
  OleCreatePictureIndirect uPicInfo, IID_IDispatch, True, IPic
 
  Set ConvertToIPicture = IPic
End Function

Чтобы использовать, нужно этот код вставить в модуль. Основная функция — LoadImage
Перед вызовом нужно инициазировать GDI+ GDIPlusStartStop(True). После вызова — отключить: GDIPlusStartStop(False)
ITEMWIDTH и ITEMHEIGHT — константы для ширины и высоты результирующего изображения. У меня они задаются в отдельном модуле.
Лучше день потерять — потом за пять минут долететь!


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: AhrefsBot, SemrushBot и гости: 1

    TopList