Просмотр незжатого TIFF с цифровых камер

Раздел посвящен программированию с использованием Power Basic.
volo
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 142
Зарегистрирован: 10.12.2004 (Пт) 11:18
Откуда: Soviet Union

Просмотр незжатого TIFF с цифровых камер

Сообщение volo » 25.01.2007 (Чт) 20:22

Код: Выделить всё
'Tiff view solution, Example for PB
'Vladimir Shulakov
'sp@zdt.ru
'----------------------------------------------------
'compiler directives

#COMPILE EXE
#DIM ALL
#REGISTER NONE
#INCLUDE "WIN32API.INC"

$TIFFFile = "E:\1.tif"
'__________________________________________
'
TYPE TIF_HEADER
     TIFFbyte   AS INTEGER
     version    AS INTEGER
     nPTR       AS LONG
END TYPE
'__________________________________________
'
TYPE TIF_ENTRY
      TIFFTag   AS LONG
      TypeX     AS LONG
      nLength   AS LONG
      nPTR      AS LONG
END TYPE


'__________________________________________
'
%TIFFbyte       = 1
%TIFFascii      = 2
%TIFFshort      = 3
%TIFFlong       = 4
%TIFFrational   = 5

%TIFFNewSubfile         = 254
%TIFFSubfileType        = 255
%TIFFImageWidth         = 256
%TIFFImageLength        = 257
%TIFFBitsPerSample      = 258
%TIFFCompression        = 259
%TIFFStripnPTRs         = 273
%TIFFRowsPerStrip       = 278
%TIFFStripByteCounts    = 279
%TIFFSamplesPerPixel    = 277
%TIFFPlanarConfiguration= 284
%TIFFGroup3Options      = 292
%TIFFGroup4Options      = 293
%TIFFFillOrder          = 266
%TIFFThreshholding      = 263
%TIFFCellWidth          = 264
%TIFFCellLength         = 265
%TIFFMinSampleValue     = 280
%TIFFMaxSampleValue     = 281
%TIFFPhotometricInterp  = 262
%TIFFGrayResponseUnit   = 290
%TIFFGrayResponseCurve  = 291
%TIFFColorResponseUnit  = 300
%TIFFColorResponseCurves= 301
%TIFFXResolution        = 282
%TIFFYResolution        = 283
%TIFFResolutionUnit     = 296
%TIFFOrientation        = 274
%TIFFDocumentName       = 269
%TIFFPageName           = 285
%TIFFXPosition          = 286
%TIFFYPosition          = 287
%TIFFPageNumber         = 297
%TIFFImageDescription   = 270
%TIFFMake               = 271
%TIFFModel              = 272
%TIFFFreenPTRs          = 288
%TIFFFreeByteCounts     = 289
%TIFFPredictor          = 317
%TIFFtagPALETTE         = 320


GLOBAL ImageData() AS RGBquad           ' tiff image 32 bit data
GLOBAL TIFFBUFF()  AS RGBtriple         ' tiff file data, 24 bit data
GLOBAL FilePointer AS LONG
GLOBAL hdlg        AS LONG

DECLARE FUNCTION getWord(BYVAL LONG,BYVAL LONG) AS LONG
DECLARE FUNCTION getLong(BYVAL LONG,BYVAL LONG) AS LONG
DECLARE FUNCTION ViewTIFF(FileName AS STRING, BYVAL hWnd AS LONG) AS LONG
'______________________________________________________________________________
'
FUNCTION nShl(BYVAL nVar AS LONG, BYVAL nShift AS LONG) AS LONG
    ! mov ecx,nShift
    ! shl nVar,cl
    ! mov eax,nVar
    ! mov FUNCTION,eax
END FUNCTION
'______________________________________________________________________________
'
FUNCTION nShr(BYVAL nVar AS LONG, BYVAL nShift AS LONG) AS LONG
    ! mov ecx,nShift
    ! shr nVar,cl
    ! mov eax,nVar
    ! mov FUNCTION,eax
END FUNCTION
'______________________________________________________________________________
'
CALLBACK FUNCTION hdlgproc() AS LONG
    IF CBMSG = %WM_COMMAND THEN
        CALL ViewTIFF ($TIFFFile, CBHNDL)          ' load tiff
    END IF
END FUNCTION
'______________________________________________________________________________
'
FUNCTION PBMAIN
    DIM TIFFBUFF(1:1)
    DIM ImageData(1:1)

    DIALOG NEW 0&, "tiff view demo",,,400,300,%WS_SYSMENU  TO hdlg
    CONTROL ADD BUTTON, hdlg, 100,"load tiff", 5,5,40,15
    DIALOG SHOW MODAL hdlg CALL hdlgproc

END FUNCTION

'______________________________________________________________________________
'
FUNCTION ViewTIFF(FileName AS STRING, BYVAL hWnd AS LONG) AS LONG

    LOCAL nWidth     AS LONG
    LOCAL nHeight    AS LONG
    LOCAL i          AS LONG
    LOCAL k          AS LONG
    LOCAL j          AS LONG
    LOCAL entry      AS LONG

    LOCAL tif_head   AS TIF_HEADER
    LOCAL tifen      AS TIF_ENTRY
    LOCAL BmTiff     AS BITMAPINFO

    LOCAL TiffReady  AS LONG
    LOCAL Temp       AS LONG
    LOCAL TIFFSpec   AS LONG
    LOCAL nPTR       AS LONG
    LOCAL nPTR1      AS LONG
    LOCAL nPTR2      AS LONG
    LOCAL x          AS LONG


    ON ERROR GOTO ErrorSolution
    FUNCTION    = %FALSE
    FilePointer = 1&

    OPEN FileName FOR BINARY ACCESS READ AS #1&
        i = getWord(1, %TRUE)
        IF      i = &h4949 THEN
                TIFFSpec = %TRUE
        ELSEIF  i = &h4D4D THEN
            TIFFSpec = %FALSE
        ELSE
        CLOSE #1&
        EXIT FUNCTION
    END IF

    tif_head.version = getWord(1, TIFFSpec)
    IF tif_head.version <> 42 THEN
        CLOSE #1
        EXIT FUNCTION
    END IF
    tif_head.nPTR   = getLong(1, TIFFSpec)
    nPTR1           = tif_head.nPTR
    FilePointer     = nPTR1 + 1&
    entry           = getWord(1, TIFFSpec)
   
    FOR i = 0& TO entry - 1&
        tifen.TIFFTag    = getWord(1&, TIFFSpec)
        tifen.TypeX      = getWord(1&, TIFFSpec)
        IF tifen.TypeX   = %TIFFlong THEN
           tifen.nLength = getLong(1&, TIFFSpec)
           tifen.nPTR    = getLong(1&, TIFFSpec)
        ELSE
           tifen.nLength = getWord(1&, TIFFSpec)
           getWord 1, TIFFSpec
           tifen.nPTR    = getWord(1&, TIFFSpec)
           Temp          = getWord(1&, TIFFSpec)
        END IF

        SELECT CASE tifen.TIFFTag
            CASE %TIFFSubfileType, %TIFFCompression, %TIFFPlanarConfiguration
                IF tifen.nPTR <> 1 THEN
                    CLOSE #1
                    EXIT FUNCTION
                END IF
               
            CASE %TIFFImageWidth
                nWidth = tifen.nPTR
               
            CASE %TIFFImageLength
                nHeight = tifen.nPTR
               
            CASE %TIFFBitsPerSample
                IF tifen.nLength <> 3 THEN
                    CLOSE #1
                    EXIT FUNCTION
                END IF
               
            CASE %TIFFPhotometricInterp
                Temp = tifen.nPTR
                IF (Temp <> 2&) AND (Temp <> 3&) AND (Temp <> 1&) THEN TiffReady = 1&

            CASE %TIFFStripnPTRs
                nPTR2 = tifen.nPTR
               
        END SELECT
    NEXT i
   
    IF nWidth = 0& OR nHeight = 0& THEN
        CLOSE #1
        EXIT FUNCTION
    END IF

    REDIM ImageData(nWidth * (nHeight+4&))
    REDIM TIFFBUFF(0& TO nWidth-1&)'


        IF TiffReady = 0& THEN
            FilePointer =  nPTR2 + 1&
            nPTR = 0&
            FOR i = 0& TO nHeight - 1&
                GET #1, FilePointer, TIFFBUFF()
                FilePointer = FilePointer + (nWidth * 3&)
                ! mov x,1&
                FOR j = 0& TO nWidth - 1&
                    ImageData(nPTR).rgbblue    = TIFFBUFF(x).rgbtred
                    ImageData(nPTR).rgbgreen   = TIFFBUFF(x).rgbtgreen
                    ImageData(nPTR).rgbred     = TIFFBUFF(x).rgbtblue
                    ! inc x
                    ! inc nPTR
                NEXT j
            NEXT i
        END IF
    CLOSE #1

    '************************************************************************
   
        BmTiff.bmiHeader.biSize         = 40
        BmTiff.bmiHeader.biWidth        = nWidth
        BmTiff.bmiHeader.biHeight       = nHeight
        BmTiff.bmiHeader.biPlanes       = 1
        BmTiff.bmiHeader.biCompression  = %BI_RGB
        BmTiff.bmiHeader.biBitCount     = 32

        LOCAL hdc AS LONG
        hdc = getdc(hwnd)
        SetStretchBltMode hdc, %Halftone
        StretchDIBits hdc, 0, 0, 595, 459, 0, 0, nWidth, nHeight, BYVAL VARPTR(ImageData(0)), BmTiff, %DIB_RGB_COLORS,%SrcCopy
        ReleaseDC hWnd,hDC

        FUNCTION = %TRUE
        EXIT FUNCTION
ErrorSolution:
    ERRCLEAR
    CLOSE #1
    FUNCTION = %FALSE
END FUNCTION

'___________________________________________________________________________
'
FUNCTION getWord(BYVAL fn AS LONG,BYVAL TIFFSpec AS LONG) AS LONG
    #REGISTER NONE
    LOCAL a     AS STRING

    GET$ fn,2,a
    IF TIFFSpec = %TRUE THEN
        FUNCTION = CVWRD(a)
    ELSE
        FUNCTION = CVWRD(STRREVERSE$(a))
    END IF
END FUNCTION
'_________________________________________________________________________________
'
FUNCTION getLong(BYVAL fn AS LONG, BYVAL TIFFSpec AS LONG) AS LONG
    #REGISTER NONE
    LOCAL a     AS STRING
 
    GET$ fn,4,a
    IF TIFFSpec = %TRUE THEN
        FUNCTION = CVL(a)
    ELSE
        FUNCTION = CVL(STRREVERSE$(a))
    END IF
END FUNCTION


Dark Machine
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 126
Зарегистрирован: 26.05.2004 (Ср) 13:12

Сообщение Dark Machine » 26.01.2007 (Пт) 9:53

Отличный пример!

Можно прикрутить алгоритм LZW или RLE ( http://pbcrypto.com/view.php?algorithm=lzw ) и получится обработка TIFF с сжатыми данными. :wink:

volo
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 142
Зарегистрирован: 10.12.2004 (Пт) 11:18
Откуда: Soviet Union

Сообщение volo » 26.01.2007 (Пт) 10:09

Dark Machine писал(а):Отличный пример!

Можно прикрутить алгоритм LZW или RLE ( http://pbcrypto.com/view.php?algorithm=lzw ) и получится обработка TIFF с сжатыми данными. :wink:



Давай пробуй сделать с LZW, если есть время. В принципе
где то LZW был еще на основном PB форуме


Единственное не помню точно, то ли сжатие идет "по строчно", то ли всего массива

Dark Machine
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 126
Зарегистрирован: 26.05.2004 (Ср) 13:12

Сообщение Dark Machine » 26.01.2007 (Пт) 15:15

Какой версией компилировал?

volo
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 142
Зарегистрирован: 10.12.2004 (Пт) 11:18
Откуда: Soviet Union

Сообщение volo » 26.01.2007 (Пт) 16:07

Dark Machine писал(а):Какой версией компилировал?



проверенной 7, 8 начал, но после первого глюка вернул на 7

Dark Machine
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 126
Зарегистрирован: 26.05.2004 (Ср) 13:12

Сообщение Dark Machine » 26.01.2007 (Пт) 17:12

Можно точнее - где был глюк? посмотрю, может удастся на 8-ом сделать.

volo
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 142
Зарегистрирован: 10.12.2004 (Пт) 11:18
Откуда: Soviet Union

Сообщение volo » 26.01.2007 (Пт) 18:45

Dark Machine писал(а):Можно точнее - где был глюк? посмотрю, может удастся на 8-ом сделать.



сам глюк возник при разкодировке направленности TIFF,
(направленности порядка чтения тифа)

Ковырятся времени не было, потому сразу кинул на 7
где-то при раскладке TIFFSpec, то ли с INTEGER неправильное определение с преобразованием толи еще где.

Это исходник в принципе более причесан, чем был изначальный вариант.
Не исключаю, что может работать в 8

Dark Machine
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 126
Зарегистрирован: 26.05.2004 (Ср) 13:12

Сообщение Dark Machine » 29.01.2007 (Пн) 13:46

Что-то не запускается. ни в 7-ом ни 8-ом.
Приаттачил тестовые изображения.
В 8-ой версии значение entry всегда 0.
В 7-ой версии выполняется вот эта часть и все.
CASE %TIFFSubfileType, %TIFFCompression, %TIFFPlanarConfiguration
IF tifen.nPTR <> 1 THEN CLOSE #1: EXIT FUNCTION
Вложения
tif_files.zip
(15.46 Кб) Скачиваний: 151

volo
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 142
Зарегистрирован: 10.12.2004 (Пт) 11:18
Откуда: Soviet Union

Сообщение volo » 29.01.2007 (Пн) 20:36

Dark Machine писал(а):Что-то не запускается. ни в 7-ом ни 8-ом.
Приаттачил тестовые изображения.
В 8-ой версии значение entry всегда 0.
В 7-ой версии выполняется вот эта часть и все.
CASE %TIFFSubfileType, %TIFFCompression, %TIFFPlanarConfiguration
IF tifen.nPTR <> 1 THEN CLOSE #1: EXIT FUNCTION


Завтра гляну по свободе.

volo
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 142
Зарегистрирован: 10.12.2004 (Пт) 11:18
Откуда: Soviet Union

Сообщение volo » 30.01.2007 (Вт) 10:27

Dark Machine писал(а):Что-то не запускается. ни в 7-ом ни 8-ом.
Приаттачил тестовые изображения.
В 8-ой версии значение entry всегда 0.
В 7-ой версии выполняется вот эта часть и все.
CASE %TIFFSubfileType, %TIFFCompression, %TIFFPlanarConfiguration
IF tifen.nPTR <> 1 THEN CLOSE #1: EXIT FUNCTION


1.
тестировал изображения для теста. TIFF формат именно этих файлов не читается, но при сохранении фотошопом как TIFF, без спецификаций цвета, Image compression - none, byte order - IBM PC --> работает.

см. рабочий формат:
Tiff image - 5MB

и тест2
test23.tif

навскидку, - видимо не совсем "простой" формат первончальных Tiff изображений.

volo
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 142
Зарегистрирован: 10.12.2004 (Пт) 11:18
Откуда: Soviet Union

возвращаясб к TIFF

Сообщение volo » 05.03.2007 (Пн) 10:11

Выпало немного времени, вернулся к тестированию TIFF. Обнаружил интересные особенности.

1. TIFF no-compressed от Фотошопа:

ссылку на данные находит:
Код: Выделить всё
CASE %TIFFStripnPTRs
                nPTR2 = tifen.nPTR
...
' при чтении из файла - работает:
FilePointer =  nPTR2 + 1





2. TIFF no-compressed от Nikon камер:

ссылку на данные находит:
Код: Выделить всё
CASE %TIFFStripnPTRs
                nPTR2 = tifen.nPTR
...
' при чтении из файла - работает:
FilePointer =  nPTR2'+'nheight*3/2


разница Смещения получается примерно в половину величиниы высоты. Т.е. для двух "почти одинаковых" TIFF файлов смещение относительно nPTR2 должно быть нулевым.

Может у кого есть мысли относительно разницы смещения по nPTR2 ?
Черкните прау строк.

Dark Machine
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 126
Зарегистрирован: 26.05.2004 (Ср) 13:12

Сообщение Dark Machine » 05.03.2007 (Пн) 14:06

Пока не смотрел, но вот это nheight*3/2 всегда будет возвращять вещественное значение.
Последний раз занимался TIFF файлами в 2000 году, когда писал программу для печати на EPSON принтерах с использованием ESC/P2 и сжатие TIFF под DOS. Да...а, много головной боли доставило :)

volo
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 142
Зарегистрирован: 10.12.2004 (Пт) 11:18
Откуда: Soviet Union

Сообщение volo » 05.03.2007 (Пн) 15:41

Dark Machine писал(а):Пока не смотрел, но вот это nheight*3/2 всегда будет возвращять вещественное значение.
Последний раз занимался TIFF файлами в 2000 году, когда писал программу для печати на EPSON принтерах с использованием ESC/P2 и сжатие TIFF под DOS. Да...а, много головной боли доставило :)



Поковырялся с самими изображениями, получилось следующее:

Несжатые Tiffы с камеры имеют сформировнный массив ссылок на "полосы" (хотя в принципе все изображение, данные, лежат последовательно)

%TIFFStripnPTRs дает ссылку на первый элемент массива ссылок на полосы и т.д. В массиве (Long) находится уже ссылка на полосу данных.

В принципе данные с Nikon-ов читаются нормально при:
Код: Выделить всё
        IF TiffReady = 0& THEN

            SEEK #1,nPTR2
            nPTR2 = getLong(1&, TIFFSpec)
            SEEK #1,nPtr2
            FOR i = 0& TO nHeight - 1&
                GET #1,, TIFFBUFF()
                FOR j = 0& TO  nWidth - 1&
                    pDIBS0(j,(nHeight - 1&) - i) = TIFFBUFF(j).rgbtred + TIFFBUFF(j).rgbtgreen * 256 + TIFFBUFF(j).rgbtblue * 65536
                NEXT j
            NEXT i
        END IF


Т.е. %TIFFStripnPTRs дает смещение, из него извлекаем ссылку на данные.

----------------------------------

В случае фотошопа - картина получилась иная:

%TIFFStripnPTRs дает прямую ссылку на массив данных,
т.е. работает напрямую (как в выше имеющемся примере загрузки)
Код: Выделить всё
        IF TiffReady = 0& THEN
            SEEK #1,nPtr2
            FOR i = 0& TO nHeight - 1&
                GET #1,, TIFFBUFF()
                FOR j = 0& TO  nWidth - 1&
                    pDIBS0(j,(nHeight - 1&) - i) = TIFFBUFF(j).rgbtred + TIFFBUFF(j).rgbtgreen * 256 + TIFFBUFF(j).rgbtblue * 65536
                NEXT j
            NEXT i
        END IF


Вернуться в Power Basic

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

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5

    TopList