powered by simpleCommunicator - 2.0.55     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Корректная конвертация ч/б TIFF(200х100)->BMP,JPG и т.п.
12 сообщений из 12, страница 1 из 1
Корректная конвертация ч/б TIFF(200х100)->BMP,JPG и т.п.
    #36433617
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пока что терзаю wiaaut.dll:
Код следующего типа делает чего надо, напр.в bmp (напр.если 1 страница):
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
Private Sub Command1_Click()
   Dim Img 'As ImageFile
    Dim IP 'As ImageProcess

    Set Img = CreateObject("WIA.ImageFile")
    Set IP = CreateObject("WIA.ImageProcess")

    Img.LoadFile "test.tif"

    While (IP.Filters.Count >  0 )
        IP.Filters.Remove  1 
    Wend
    IP.Filters.Add IP.FilterInfos("Convert").FilterID
    IP.Filters( 1 ).Properties("FormatID").Value = wiaFormatBMP
    Set Img = IP.Apply(Img)

    Img.SaveFile "test.bmp"
End Sub
Все прилично, получаем ч/б bmp приемлемых размеров (Bit Depth или PixelDepth =1)

Но это хорошо, когда tiff 200х200,
а если он 200х100, то при конвертации в картинку типа jpg-bmp его надо растягивать по высоте вдвое, иначе изображение будет сжато по вертикали.
Ладно, делаем так, "выкрутились":
Код: plaintext
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.
29.
30.
31.
32.
33.
34.
35.
36.
37.
Private Sub Command1_Click()
    Dim w As Integer, h As Integer
    Dim Img As ImageFile
    Dim IP As ImageProcess

    Set Img = CreateObject("WIA.ImageFile")
    Set IP = CreateObject("WIA.ImageProcess")

    Img.LoadFile "test.tif"
    w = Img.Width
    h = Img.Height
    MsgBox Img.PixelDepth 'дает 1
    
    While (IP.Filters.Count >  0 )
        IP.Filters.Remove  1 
    Wend
    IP.Filters.Add IP.FilterInfos("Scale").FilterID
    IP.Filters( 1 ).Properties( 1 ).Value = w 'ширина
    If Img.VerticalResolution <  110  Then '204х98
        IP.Filters( 1 ).Properties( 2 ).Value = h *  2  'высота
    Else '204х196
        IP.Filters( 1 ).Properties( 2 ).Value = h 'высота
    End If
    IP.Filters( 1 ).Properties( 3 ).Value = False
    Set Img = IP.Apply(Img)
    MsgBox Img.PixelDepth '32 о-па!!!

    While (IP.Filters.Count >  0 )
        IP.Filters.Remove  1 
    Wend
    IP.Filters.Add IP.FilterInfos("Convert").FilterID
    IP.Filters( 1 ).Properties("FormatID").Value = wiaFormatBMP
    'IP.Filters(1).Properties("FormatID").Value = wiaFormatJPEG
    'IP.Filters(1).Properties("Quality").Value = 1
    Set Img = IP.Apply(Img)

    Img.SaveFile "test.bmp"
End Sub
Проблема в том что фильтр "Scale" автоматом бабахает 32 бита цветности, и если это bmp, то размер несчастной картинки тянет на 16МБ, что ни в какие ворота.

В то же время редактор Paint при растягивании картинки по вертикали вдвое и сохр. в ч/б BMP делает приличную картинку.
Как вернуть Img.PixelDepth назад в 1 или запретить увеличение до 32 я не знаю.

В принципе еще существует GDI+ но это сложнее для понимания, и боюсь что наступлю на те же грабли. Задача собственно б/м прилично(без раздувания) растянуть Img, оставаясь в черно-белом цвете.
Обратил внимание еще что при моем растягивании разрешение меняется с 204х98 на 96х96,
размер с 1728х1194 на 1728х2388 точек .
Чет я не допонимаю...
...
Рейтинг: 0 / 0
Корректная конвертация ч/б TIFF(200х100)->BMP,JPG и т.п.
    #36434154
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Можно конечно чуть улучшить ситуацию для 200х100, забабахав проможуточную конвертацию
tif=>gif=>bmp
Код: plaintext
1.
2.
3.
4.
5.
While (IP.Filters.Count >  0 )
 IP.Filters.Remove  1 
Wend
IP.Filters.Add IP.FilterInfos("Convert").FilterID
IP.Filters( 1 ).Properties("FormatID").Value = wiaFormatGIF
Set Img = IP.Apply(Img)
тогда глубина цвета будет хотя бы 8 а не 32 (3МБ вместо 16 для bmp)
но это конечно плохой вариант.

Если не применять scale-фильтр, то
сжатый bmp (глубина 1) можно растянуть в paint в 2 раза
и получится 1728х2388 203х97 объемом в моем случае 0,5MB (jpg соотв.сильно меньше) к чему и имеет смысл стремиться.
Только б вот как растянуть программно и правильно...
...
Рейтинг: 0 / 0
Корректная конвертация ч/б TIFF(200х100)->BMP,JPG и т.п.
    #36441208
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Бенедикт,ау.
Я так понимаю вы единственный кто здесь в этом чего-то реально шарит.
Если есть время, гляньте..
P.S. я отчаялся делать поиск по словам WIA, GDI, stretch и т.п. и сделал поиск по слову Бенедикт
...и это дало нек. положительные результаты

Способ tiff->(bmp,jpg..) я нашел, но немного кривоватый.

если 200х200 то просто конвертация через WIA (ч/б палитра сохраняется)
здесь просто,не стоит заморачиваться

если 200х100 (требуется растяжение в 2 раза)
изобрел гибрид (WIA)+(GDI)+(GDI+)

1) Конвертация через WIA без растягивания строго в bmp (ч/б палитра сохраняется)
2) Открываем этот tmp-bmp через GDI как StdPicture
3) Растягиваем через GDI в 2 раза
4) Сохраняем через GdipCreateBitmapFromHBITMAP (GDI+) в bmp,jpg,png,gif

п.п. 2-4 делаются как здесь
/topic/360201#3424634

FitToSizeBitmap слегка переписывается, чтоб растягивала-сжимала
SavePictureToJPEG() ->по аналогии делаем SavePictureToBMP(),png и т.п.
это осилил.
Получается примерно следующее:

Код: plaintext
Private Sub ConvertToBMP_GDI(startFile As String, targetFileName As String)\n    Dim w As Integer, h As Integer\n    Dim Img \'As ImageFile\n    Dim Img1 \'As ImageFile\n    Dim IP \'As ImageProcess\n    Dim i As Integer\n    Dim rezult\n    Dim tmpTarget As String\n    Dim tmpTargetTemp As String\n    Dim SrcPic As StdPicture, DstPic As StdPicture\n    \n    If Len(Dir(startFile)) =  0  Then Exit Sub\n    Set Img = CreateObject("WIA.ImageFile")\n    Set IP = CreateObject("WIA.ImageProcess")\n    Img.LoadFile startFile\n    For i =  1  To Img.FrameCount\n        DoEvents\n        While (IP.Filters.Count >  0 )\n            IP.Filters.Remove  1 \n        Wend\n        IP.Filters.Add IP.FilterInfos("Convert").FilterID\n        IP.Filters( 1 ).Properties("FormatID").Value = wiaFormatBMP\n        Img.ActiveFrame = i\n        Set Img1 = IP.Apply(Img)\n        If Img.FrameCount >  1  Then\n            tmpTarget = Left(targetFileName, InStr(targetFileName, ".bmp") -  1 ) & " (page " & i & ").bmp"\n            If Len(Dir(tmpTarget)) >  0  Then\n                rezult = MsgBox("File exists. Overwrite?", vbYesNo + vbExclamation, "Warning")\n                If rezult = vbNo Then GoTo NotChangeBMP\n                DeleteFile tmpTarget\n            End If\n            On Error Resume Next\n            If Img1.VerticalResolution <  110  Then \'204х98\n                tmpTargetTemp = Left(tmpTarget, Len(tmpTarget) -  3 ) & "tmp" \'*.tmp\n                If Len(Dir(tmpTargetTemp)) >  0  Then\n                    DeleteFile tmpTargetTemp\n                End If\n                Img1.SaveFile tmpTargetTemp\n                Set SrcPic = LoadPicture(tmpTargetTemp)\n                Set DstPic = FitToSizeBitmap(SrcPic.Handle,  2 ) \'модифицирована,растягивает в 2р.по вертикали\n                SavePictureToBMP DstPic, tmpTarget\n                DeleteFile tmpTargetTemp\n            Else\n                Img1.SaveFile tmpTarget\n            End If\n        Else\n            If Len(Dir(targetFileName)) >  0  Then\n                rezult = MsgBox("File exists. Overwrite?", vbYesNo + vbExclamation, "Warning")\n                If rezult = vbNo Then GoTo NotChangeBMP\n                DeleteFile targetFileName\n            End If\n            On Error Resume Next\n            If Img1.VerticalResolution <  110  Then \'204х98\n                tmpTargetTemp = Left(targetFileName, Len(targetFileName) -  3 ) & "tmp" \'*.tmp\n                If Len(Dir(tmpTargetTemp)) >  0  Then\n                    DeleteFile tmpTargetTemp\n                End If\n                Img1.SaveFile tmpTargetTemp\n                Set SrcPic = LoadPicture(tmpTargetTemp)\n                Set DstPic = FitToSizeBitmap(SrcPic.Handle,  2 ) \'модифицирована,растягивает в 2р.по вертикали\n                SavePictureToBMP DstPic, targetFileName\n                DeleteFile tmpTargetTemp\n            Else\n                Img1.SaveFile targetFileName\n            End If\n        End If\nNotChangeBMP:\n    Next i\n    Set Img = Nothing\n    Set Img1 = Nothing\n    Set IP = Nothing\nEnd Sub

Для конвертации в bmp и png выигрыш в размере файла получается значительный(сохранение ч/б палитры), для jpg и gif особой разницы если просто делать фильтр "Scale" через WIA это не дает, т.к. все равно будет соотв. 24bit и 8bit, хотя кажется все равно чуть быстрее.
Код конечно получился через одно место (промежуточный bmp на диск), окультурить бы.

По идее взять бы класс CMultiFrameImage из примеров приведенных Бенедиктом.
/topic/711100&hl=
и дописать его на предмет сохранения в разные форматы...
Но я не мастер по классам, это раз, у меня не получилось.

Во вторых, возникли сомнения на счет GDI+
Я игрался с этим примером
/topic/585476&hl=tipp0658
http://www.activevb.de/tipps/vb6tipps/tipp0658.html
да он открывает файл через GDI+
функцией DrawImageFromFile
но увы сразу делает его цветным.
т.е. также как и WIA
и если собака в этом, т.е. GDI+ (а WIA как было упомянуто основана на GDI+) не умеет преобразовывать не раскрашивая в 32 bit, то тогда дело дохлое и любые усилия будут напрасны.

А открывать сразу через GDI (без +) я не могу, т.к. у меня tiff и нужен + либо WIA, что тоже самое, сохранение во временный tmp-bmp конечно вариант, и задачу можно считать решенной,но все же.
И еще (мелочи конечно...) разрешение 96х96 экрана кот. делает FitToSizeBitmap....
вообще-то красивше и правильнее было бы оставить оригинальное, т.е. 204х98 в моем случае

Специалисты, Бенедикт, что скажете?
...
Рейтинг: 0 / 0
Корректная конвертация ч/б TIFF(200х100)->BMP,JPG и т.п.
    #36444980
Фотография Бенедикт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77,

мне сейчас трудно найти время для форума.
Посмотрите приложенный обновлённый класс CMultiFrameImage, в нём появился метод Frame1bpp (перевод в формат 1 бит на точку и масштабирование по вертикали средствами GDI). Результат можно напрямую сохранять в .bmp стандартной функцией SavePicture, но она не пишет разрешение. Но лучше придумать что-нибудь другое, сохранять в тот же TIFF с помощью GDI+, например.
...
Рейтинг: 0 / 0
Корректная конвертация ч/б TIFF(200х100)->BMP,JPG и т.п.
    #36446896
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Бенедикт,
спасибо что откликнулись.
Если делать совсем красиво, то боюсь нужна чуть ваша помощь.

Frame1bpp я проверил, все работает, она по сути заменяет шаг
1) Конвертация через WIA без растягивания строго в bmp (ч/б палитра сохраняется)
(см.мое сообщение)
а также вбирает в себя
3) Растягиваем через GDI в 2 раза

>можно напрямую сохранять в .bmp стандартной функцией SavePicture
это по сути подводит меня к моему промежуточному tmp-bmp
после чего все делается точно также:
2) Открываем этот tmp-bmp через GDI как StdPicture
//3) Растягиваем через GDI в 2 раза// этот шаг теперь не нужен, т.к. уже растянули
4) Сохраняем через GdipCreateBitmapFromHBITMAP (GDI+) в bmp,jpg,png,gif

Воткнуть сохранение через GdipCreateBitmapFromHBITMAP (GDI+) в ваш класс я попытался, но у меня не получилось

Попытался также
1) тупо добавить ModuleGDIp (независимый от класса) из вашего же примера
2) переписать Frame1bpp->Frame1bppL, удалив
Set Frame1bpp = CreateIPictureDispFromHBITMAP(hbmDst)
и заменив на
Frame1bppL = hbmDst
3) на этом этапе отвязаться от класса и сделав
Код: plaintext
1.
2.
3.
4.
5.
6.
Private Sub Command1_Click()
Dim hndl As Long
 m_mfi.LoadFromFile "test.tif"
 hndl = m_mfi.Frame1bppL( 1 ,  0 ,  0 ,  2 )
 MsgBox hndl
 SaveHBitmapToBMP hndl, "new.bmp"
End Sub
где SaveHBitmapToBMP суть переписанная
Код: plaintext
1.
Public Function SavePictureToBMP( _
   Picture As StdPicture, FileName As String) As Boolean
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
Public Function SaveHBitmapToBMP( _
   hImg As Long, FileName As String) As Boolean
 Dim gplRet      As Long
  Dim uEncCLSID   As CLSID
 Dim uEncParams  As EncoderParameters

 Dim GpInput As GdiplusStartupInput
 GpInput.GdiplusVersion =  1 
    GetEncoderClsID "image/bmp", uEncCLSID 'image/png","image/gif"...
    gplRet = GdipSaveImageToFile(hImg, StrPtr(FileName), uEncCLSID, Null)
    SaveHBitmapToBMP = gplRet = [OK]
    gplRet = GdipDisposeImage(hImg)
 
 GdiplusShutdown GdIHandle
End Function

MsgBox hndl возвращает long, но на этапе
SaveHBitmapToBMP VB рушится,
поэтому и остается сохранять SavePicture, а потом переоткрывать как StdPicture

Либо нужен ответ на вопрос
Как конвертировать IPictureDisp->StdPicture,
хотя чувствую что это также лишне как и tmp-bmp

>сохранять в тот же TIFF с помощью GDI+,
сохранять TIFF меня как раз меньше всего интересует, т.к. у меня на входе он и так всегда есть,
если только переконвертация в различные другие форматы lwz/uncompressed и т.п.
а вот jpg/png/gif/bmp и надо, но это я повторюсь уже осилил
"image/bmp", uEncCLSID 'image/png","image/gif"...
вопрос как подвести ваш класс к этому шагу(как вставить в класс этот шаг) без временных bmp
...
Рейтинг: 0 / 0
Корректная конвертация ч/б TIFF(200х100)->BMP,JPG и т.п.
    #36448458
Фотография Бенедикт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77,

IPictureDisp отличается от StdPicture, если не ошибаюсь, только тем, что к StdPicture можно применить New. Объект типа StdPicture поддерживает интерфейсы IPictureDisp, IPicture, IDispatch, IUnknown. При Type = PICTYPE_BITMAP (1) свойство Handle возвращает HBITMAP, т. е. не надо промежуточных сохранений во временный bmp, чувство не обманывает.

Null это что?

Добавил метод SaveFrameAs1bppPNG(), на основе Frame1bpp(). Хотя, конечно, для единства стиля лучше бы перейти к решению на GDI+ только.
...
Рейтинг: 0 / 0
Корректная конвертация ч/б TIFF(200х100)->BMP,JPG и т.п.
    #36449143
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Бенедикт,
спасибо,так конечно сильно красивше.
Да еще и с заданием разрешения, круто.
если в другие форматы
1) to GIF-> элементарно заменой на "image/gif" (8bit будет естественно)
Я правильно понял что GIF нестандартные Resolution не поддерживает?
2) to JPEG пришлось чуть дописать: (24bit будет естественно)
Код: plaintext
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.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
Private Type CLSID 'частный вид GUID-а
   Data1         As Long
   Data2         As Integer
   Data3         As Integer
   Data4( 0  To  7 ) As Byte
End Type
Private Enum EncoderParameterValueType
   [EncoderParameterValueTypeByte] =  1 
   [EncoderParameterValueTypeASCII] =  2 
   [EncoderParameterValueTypeShort] =  3 
   [EncoderParameterValueTypeLong] =  4 
   [EncoderParameterValueTypeRational] =  5 
   [EncoderParameterValueTypeLongRange] =  6 
   [EncoderParameterValueTypeUndefined] =  7 
   [EncoderParameterValueTypeRationalRange] =  8 
End Enum

Private Type EncoderParameter
   GUID           As CLSID
   NumberOfValues As Long
   Type           As EncoderParameterValueType
   Value          As Long
End Type

Private Type EncoderParameters
   Count     As Long
   Parameter As EncoderParameter
End Type
Public Sub SaveFrameAs1bppJPEG( _
   ByVal FileName As String, _
   Optional ByVal nFrame As Long =  0 , _
   Optional ByVal DpiX As Single =  0 , Optional ByVal DpiY As Single =  0 , _
   Optional ByVal dHeightScale As Double =  1 , Optional ByVal JPGQuality As Long =  100 )
 Dim nSrcWidth As Long
 Dim nSrcHeight As Long
 Dim bmiDst As BITMAPINFO2
 Dim pBits As Long
 Dim hbmDst As Long
 Dim picSrc As IPictureDisp
 Dim hdcDst As Long
 Dim hbmOldDst As Long
 Dim nBitmap As Long
 Dim EncoderCLSID As GUID
 Dim uEncParams  As EncoderParameters
 
 nSrcWidth = FrameWidth(nFrame)
 nSrcHeight = FrameHeight(nFrame)
 With bmiDst.bmiHeader
    .biSize = LenB(bmiDst.bmiHeader)
    .biWidth = nSrcWidth
    .biHeight = nSrcHeight * dHeightScale
    .biPlanes =  1 
    .biBitCount =  1 
    .biCompression = BI_RGB
 End With
 With bmiDst.bmiColors( 1 )
    .rgbBlue =  255 
    .rgbGreen =  255 
    .rgbRed =  255 
 End With
 hbmDst = CreateDIBSection( 0 , bmiDst, DIB_RGB_COLORS, pBits,  0 ,  0 )
 
 hdcDst = CreateCompatibleDC( 0 )
 hbmOldDst = SelectObject(hdcDst, hbmDst)
 
 Set picSrc = Frame(nFrame)
 picSrc.Render CLng(hdcDst),  0 &, CLng(nSrcHeight * dHeightScale), _
               CLng(nSrcWidth), CLng(-nSrcHeight * dHeightScale), _
                0 &,  0 &, CLng(picSrc.Width), CLng(picSrc.Height), ByVal  0 &
 Set picSrc = Nothing
 
 SelectObject hdcDst, hbmOldDst: hbmOldDst =  0 
 DeleteDC hdcDst: hdcDst =  0 
 
 If GdipExec(GdipCreateBitmapFromGdiDib(bmiDst, pBits, nBitmap)) = OK Then
    If (DpiX >  0 ) And (DpiY >  0 ) Then _
       GdipExec GdipBitmapSetResolution(nBitmap, DpiX, DpiY)
       
 If JPGQuality >  100  Then JPGQuality =  100 
 If JPGQuality <  1  Then JPGQuality =  1 
    'Установка качества
    uEncParams.Count =  1 
    With uEncParams.Parameter
       .NumberOfValues =  1 
       .Type = [EncoderParameterValueTypeLong]
       With .GUID
          .Data1 = &H1D5BE4B5
          .Data2 = &HFA4A
          .Data3 = &H452D
          .Data4( 0 ) = &H9C
          .Data4( 1 ) = &HDD
          .Data4( 2 ) = &H5D
          .Data4( 3 ) = &HB3
          .Data4( 4 ) = &H51
          .Data4( 5 ) = &H5
          .Data4( 6 ) = &HE7
          .Data4( 7 ) = &HEB
       End With
       'CLSIDFromString StrPtr(EncoderQuality), .GUID
       .Value = VarPtr(JPGQuality)
    End With
       
    If GetEncoderClsID("image/jpeg", EncoderCLSID) >  0  Then _
       GdipExec GdipSaveImageToFile(nBitmap, StrPtr(FileName), EncoderCLSID, _
                                     uEncParams)
    GdipExec GdipDisposeImage(nBitmap): nBitmap =  0 
 End If
 
 DeleteObject hbmDst: hbmDst =  0 : pBits =  0 
End Sub
3) to BMP возникла одна проблема:
If GetEncoderClsID("image/bmp", EncoderCLSID) > 0
похоже 0 дает, если убрать условие то все корректно.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
Public Sub SaveFrameAs1bppBMP( _
...
       GdipExec GdipBitmapSetResolution(nBitmap, DpiX, DpiY)
    'If GetEncoderClsID("image/bmp", EncoderCLSID) > 0 Then
    GetEncoderClsID "image/bmp", EncoderCLSID
       GdipExec GdipSaveImageToFile(nBitmap, StrPtr(FileName), EncoderCLSID, _
                                    ByVal  0 &)
...
4) to TIFF надо разбираться отдельно, но это пока не входит в мои текущие потребности, хотя конечно надо бы сообразить с разными компрессиями+многостраничный и с указанием сохраняемых страниц,все или диапазон..., пока голова чуть варит на эту тему...

>Хотя, конечно, для единства стиля лучше бы перейти к решению на GDI+
да GDI+ похоже цветность очень любит добавлять при преобразованиях типа растяжение

>Null это что?
Гы...Null это нуль, пустое место...что-ли
Ну я документацию то C-шную читал про параметр uEncParams
ByVal 0& для меня тупого сложно родить, vbNull не прокатил, а Null съелся, в синенький окрасился, заработало, я и успокоился. Извините, если что не так.
...
Рейтинг: 0 / 0
Корректная конвертация ч/б TIFF(200х100)->BMP,JPG и т.п.
    #36450930
Фотография Бенедикт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77,

>1) ...
Я правильно понял что GIF нестандартные Resolution не поддерживает?
В кратком описании формата GIF полей для хранения разрешения картинки в явном виде нет. Не смотрел, есть ли в полной спецификации.

>3)
Да, ошибка, надо сравнивать номер кодировщика на >= 0.

>да GDI+ похоже цветность очень любит добавлять при преобразованиях типа растяжение
... но зато имеет функцию GdipBitmapConvertFormat().

>Null
VB-шный Null это Variant подтипа vbNull (к тому же в данном случае передаваемый по ссылке), сравните с ((void *)0) (C) или 0 (C++).
...
Рейтинг: 0 / 0
Корректная конвертация ч/б TIFF(200х100)->BMP,JPG и т.п.
    #36453788
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо, Бенедикт.
В принципе крайние варианты и так получились очень неплохие.
Будет настроение, поиграюся еще, тема графики довольно интересна для меня...
...
Рейтинг: 0 / 0
Корректная конвертация ч/б TIFF(200х100)->BMP,JPG и т.п.
    #36485946
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Бенедикт,
попытаюсь продолжить тему, сейчас решил повозиться с tiff форматами.
Продвижения есть, но куча вопросов:
По образу-подобию создаем в вашем
CMultiFrameImage
ф-цию SaveMultiFrameAs1bppTIFF
Код: plaintext
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.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
Public Sub SaveMultiFrameAs1bppTIFF( _
   ByVal FileName As String, _
   Optional ByVal startFrame As Long =  0 , Optional ByVal endFrame As Long =  0 , _
   Optional ByVal DpiX As Single =  0 , Optional ByVal DpiY As Single =  0 , _
   Optional ByVal dHeightScale As Double =  1 , Optional ByVal eTifCompression As TifCompressionType = TiffCompressionNone)
 Dim nSrcWidth As Long
 Dim nSrcHeight As Long
 Dim bmiDst As BITMAPINFO2
 Dim pBits As Long
 Dim hbmDst As Long
 Dim picSrc As IPictureDisp
 Dim hdcDst As Long
 Dim hbmOldDst As Long
 Dim nBitmap() As Long
 Dim EncoderCLSID As GUID
 Dim uEncParams  As EncoderParameters1
 Dim paramValue As Long
 Dim i As Long
 
 Dim startF As Long
 Dim endF As Long
 If (startFrame =  0 ) Or (startFrame > FrameCount) Then
    startF =  1 
 Else
    startF = startFrame
 End If
 If (endFrame =  0 ) Or (endFrame > FrameCount) Then
    endF = FrameCount
 ElseIf (endFrame < startF) Then
    endF = startF
 Else
    endF = endFrame
 End If
 
     '// Ermitteln der CLSID vom mimeType Encoder
    Call GetEncoderClsID("image/tiff", EncoderCLSID)
    
    ' Initialisieren der Encoderparameter
    uEncParams.Count =  2 
    With uEncParams.Parameter1( 0 ) ' Tiff Kompression
        ' Setzen der Kompression GUID
        CLSIDFromString StrPtr(EncoderCompression), .GUID
        .NumberOfValues =  1 
        .Type = [EncoderParameterValueTypeLong]
        .Value = VarPtr(eTifCompression)
    End With
    
    With uEncParams.Parameter1( 1 ) ' EncoderSaveFlag
        ' Setzen der EncoderSave GUID
        CLSIDFromString StrPtr(EncoderSaveFlag), .GUID
        .NumberOfValues =  1 
        .Type = [EncoderParameterValueTypeLong]
        .Value = VarPtr(paramValue)
    End With

 ReDim nBitmap(startF To endF)
 
 For i = startF To endF
    nSrcWidth = FrameWidth(i)
    nSrcHeight = FrameHeight(i)
    With bmiDst.bmiHeader
        .biSize = LenB(bmiDst.bmiHeader)
        .biWidth = nSrcWidth
        .biHeight = nSrcHeight * dHeightScale
        .biPlanes =  1 
        .biBitCount =  1 
        .biCompression = BI_RGB
    End With
    With bmiDst.bmiColors( 1 )
        .rgbBlue =  255 
        .rgbGreen =  255 
        .rgbRed =  255 
    End With
    hbmDst = CreateDIBSection( 0 , bmiDst, DIB_RGB_COLORS, pBits,  0 ,  0 )
 
    hdcDst = CreateCompatibleDC( 0 )
    hbmOldDst = SelectObject(hdcDst, hbmDst)
 
    Set picSrc = Frame(i)
    picSrc.Render CLng(hdcDst),  0 &, CLng(nSrcHeight * dHeightScale), _
                    CLng(nSrcWidth), CLng(-nSrcHeight * dHeightScale), _
                     0 &,  0 &, CLng(picSrc.Width), CLng(picSrc.Height), ByVal  0 &
    Set picSrc = Nothing
 
    SelectObject hdcDst, hbmOldDst: hbmOldDst =  0 
    DeleteDC hdcDst: hdcDst =  0 
 
    If GdipExec(GdipCreateBitmapFromGdiDib(bmiDst, pBits, nBitmap(i))) = OK Then
        If (DpiX >  0 ) And (DpiY >  0 ) Then _
            GdipExec GdipBitmapSetResolution(nBitmap(i), DpiX, DpiY)
            
            
             If i = startF Then
                ' erstes Bild als Tiff speichern
                paramValue = EncoderValueMultiFrame
                If GdipExec(GdipSaveImageToFile(nBitmap(startF), _
                                               StrPtr(FileName), _
                                               EncoderCLSID, _
                                               uEncParams)) <> OK Then
                    GoTo DelObj 'Exit For
                End If
            Else
                ' weitere Bilder in Tiff(lBitmap(0)) hinzufьgen
                paramValue = EncoderValueFrameDimensionPage
                If GdipExec(GdipSaveAddImage(nBitmap(startF), _
                                            nBitmap(i), _
                                            uEncParams)) <> OK Then
                    GoTo DelObj 'Exit For
                End If
            End If
    End If
DelObj:
    DeleteObject hbmDst: hbmDst =  0 : pBits =  0 
 Next i
 
    ' abschlieЯen des speicherns
    paramValue = EncoderValueFlush
    GdipExec GdipSaveAdd(nBitmap(startF), uEncParams)
    
    For i = startF To endF
        ' Destroy the bitmaps
        GdipExec GdipDisposeImage(nBitmap(i)): nBitmap(i) =  0 
    Next i

    Erase nBitmap
End Sub
Немножко переделал,
использовал http://www.activevb.de/tipps/vb6tipps/tipp0660.html
но суть понятна.

Проблема #1
Если StartFrame=EndFrame, т.е. выдергивается одна страница (можно даже сильно упростить приведенный код без добавления Multi), то эта страница при любых tiff-compression получается слегка бракованная. Т.е. она нормальная с т.зр. виндов, но может не восприниматься другими программами. Поиск дал намек. Проблема возникает в tag=266 Reserved Bit Order или FillOrder
Для исправления достаточно сделать:
Код: plaintext
tiffset.exe -s  266   1  test.tif
Но суть в том, что приведенный код этого не делает, если 1 страница. (проблема либо из-за GDI-преобразований, либо из за проекций на IPictureDisplay). Вылечить можно? Если больше одной страницы то все нормально. Немецкий код(ссылка выше) работает в этом отношении нормально даже при одной странице.

Проблема #2
Код: plaintext
 TiffCompressionCCITT3 = EncoderValueConstants.EncoderValueCompressionCCITT3
Это что-то ужасное.
Сразу скажу, что немецкий код с этим форматом не всегда справляется даже с точки зрения самих виндов. Если например исходный tiff был в TiffCompressionCCITT4, то это черный квадрат.
Код основанный на CMultiFrameImage (приведен выше) с т.зр. виндов справляется лучше (с учетом поправки на проблему 1), однако даже если заставить манипуляцией с tag=266 этот файл увидеть в "неродном" вьюере, то он будет битый (с полосами и т.п.), а многостраничный будет сильно битым.

Проблема #3
Связана с задачей конвертирования 204x98 в 204x196.
1) Во-первых надо растянуть по вертикали в 2 раза 1728х1190 скажем =>1728x2380
2) Во вторых надо изменить разрешение:
GdipExec GdipBitmapSetResolution(nBitmap(i), DpiX, 2*DpiY)
(со вторым проблем нет)

(приведенный код основанный на CMultiFrameImage с этой задачей справляется, но есть проблема 1, кот. меня не очень радует)

Сразу скажу что для всех форматов кроме CCITT3 немецкий код мне нравится больше, т.к. он не порождает проблему 1, да и быстрее, т.к. сразу закладывает из файла в nBitmap а не в IDisplay, не вызывает GDI(без+) и т.п.
Логично задать вопрос: м.б. можно все-таки через GDI+ сделать
GdipExec GdipBitmapУстановитьШиринуВысоту(nBitmap(i), ширина, 2*высота)
работая непосредственно с nBitmap без проекций на картинки, ну и соотв. без игр с туда-сюда цветностью.
...
Рейтинг: 0 / 0
Корректная конвертация ч/б TIFF(200х100)->BMP,JPG и т.п.
    #36486368
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
>Проблема #2
>TiffCompressionCCITT3
Блин, с этими CCITT Group 3 (1D Fax) Reversed Bit Order файлами даже libtiff не справляется.

tiffcp.exe "test.tif",5,6 "testx.tif" (вытащить-слепить стр.6,7)
tiffsplit.exe "test.tif" (разбить на страницы)

Если test.tif CCITT Group 3, то файлы, производимые этими командами будут битые

Kodac Imaging однако коректно справляется...

Microsoft Fax напр. использует CCITT4, там проблем нет.
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Корректная конвертация ч/б TIFF(200х100)->BMP,JPG и т.п.
    #37202976
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
БенедиктДмитрий77,

Добавил метод SaveFrameAs1bppPNG(), на основе Frame1bpp(). Хотя, конечно, для единства стиля лучше бы перейти к решению на GDI+ только.

Бенедикт,
Вернулся к этой теме.
Допустим у меня есть картинка 2386х1620, а мне надо получить 1728х2340 (изменить размеры)
По высоте, ладно, научился, там все сделано; а сжать/растянуть по ширине, у меня через render получилось почему-то зеркально только, либо черный лист.
Или допустим ширину привести к 1728, а высоту пропорционально, но при этом нарастить лист "белым" до размера 2340
Или наоборот привести высоту к 2340, а ширину нарастить до 1728 белыми полями. (т.е. вписать в рамку максимально).

Или если я хочу перевернуть картинку на 90градусов?

Уж больно ваш этот класс нравится...

Задача как бы получить "правильный tiff" из произвольного рисунка (произв. размер, разрешение, ориентация).
Как tiff а не png, и как задать компрессиию - это я знаю
Правильный -это
1728х2340 204х196 рисунок максимально вписан; вертикальная ориентация
либо
1728х1171 204х98 рисунок максимально вписан+сжат вдвое по вертикали; вертикальная ориентация

Сейчас пытаюсь хотя бы "растянуть" по W и H до произв. размера - по H без проблем, а по W ерунда пока.
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Корректная конвертация ч/б TIFF(200х100)->BMP,JPG и т.п.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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