?login_element?

Subversion Repositories NedoOS

Rev

Rev 68 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. LINEPNG=0x8008
  2. LINEPNGTEMP=0x9000 ;для конвертации 16bit->8bit (TODO в конце LINEPNGPRIOR)
  3. LINEPNGPRIOR=0xa008
  4.  
  5.         align 256
  6. PNGPAL
  7.         ds 768 ;TODO убрать в страничку
  8.  
  9. readpng
  10.         ld b,7
  11.         call read_b_bytes ;TODO test header
  12.  
  13. readpng_chunk
  14.         call RDWORDHSBLSBtohl
  15.         ex de,hl
  16.         call RDWORDHSBLSBtohl ;dehl=chunk size
  17.         exx
  18.         call GETDWORD_slow ;e,d,l,h
  19.  
  20.         ld a,e
  21.         cp 'I'
  22.         jr z,readpng_chunk_IHDR_IDAT
  23.         cp 'P'
  24.         jr z,readpng_chunk_PLTE
  25.         jr readpng_skiprestofchunk
  26.        
  27. readpng_chunk_IHDR_IDAT
  28.         ld a,d
  29.         cp 'D'
  30.         jp z,readpng_chunk_IDAT
  31.         cp 'E'
  32.         ret z ;IEND
  33. readpng_chunk_IHDR
  34.         call RDWORDHSBLSBtohl
  35.         call RDWORDHSBLSBtohl ;hl=width
  36.         call setpicwid
  37.         call RDWORDHSBLSBtohl
  38.         call RDWORDHSBLSBtohl ;hl=hgt
  39.         call setpichgt
  40.         call RDBYTE ;bit depth (глубина цвета 1, 2, 4, 8, 16)
  41.          ld (readpng_bitdepth),a
  42.         add a,7 ;8,9,11,15,23
  43.         rra
  44.         rra
  45.         rra
  46.         and 3 ;1,1,1,1,2
  47.         ld e,a
  48.         call RDBYTE ;color type (тип цвета: 1 (индексированный цвет - с палитрой) + 2 (цветное изображение, т.е. не Grayscale) + 4 (используется альфа-канал))
  49.          ld (readpng_palflag_bit0),a
  50.          rra
  51.          ld d,1
  52.          jr c,readpng_countbppok
  53.          rra
  54.          jr nc,$+4
  55.          ld d,3
  56.          rra
  57.          jr nc,$+3
  58.          inc d
  59. readpng_countbppok
  60.          ld a,d
  61.          dec e
  62.          jr z,$+3
  63.          add a,a
  64.         ld (png_bytesperpix),a
  65.  
  66.         call RDBYTE ;compression method (0 = deflate)
  67.         call RDBYTE ;filter method (=0)
  68.         call RDBYTE ;interlace method (0 (нет чередования) / 1 (Adam7 interlace)) ;TODO
  69.  
  70.         call initframe ;один раз на кадр после setpicwid, setpichgt и после установки gifframetime ;заказывает память под конверченный кадр
  71.  
  72.         call GETDWORD_slow ;e,d,l,h
  73.         jr readpng_chunk
  74.  
  75. readpng_chunk_PLTE
  76.         exx
  77.         ;hl=chunk size
  78.         dec hl
  79.         ld e,0
  80. readpng_chunk_PLTE0
  81.         ld d,PNGPAL/256
  82.         call RDBYTE
  83.         ld (de),a
  84.         inc d
  85.         call RDBYTE
  86.         ld (de),a
  87.         inc d
  88.         call RDBYTE
  89.         ld (de),a
  90.         inc e
  91.         ld bc,3
  92.         or a
  93.         sbc hl,bc
  94.         jp p,readpng_chunk_PLTE0
  95.  
  96.         call GETDWORD_slow ;e,d,l,h
  97.         jp readpng_chunk
  98.  
  99. readpng_skiprestofchunk
  100. ;after chunk name: skip chunk size + 4 bytes (CRC)
  101.         exx
  102. ;dehl=chunk size
  103. readpng_skiprestofchunk0
  104.         ld c,l ;1..0
  105.         xor a
  106.         ld b,a;0
  107.         dec c ;0..255
  108.         inc bc ;1..256
  109.         ;or a
  110.         sbc hl,bc
  111.         jr nc,$+3
  112.          dec de
  113.         ld b,c
  114.         call read_b_bytes
  115.         ld a,d
  116.         or e
  117.         or h
  118.         or l
  119.         jr nz,readpng_skiprestofchunk0
  120.         call GETDWORD_slow ;e,d,l,h
  121.         jp readpng_chunk
  122.  
  123. readpng_chunk_IDAT
  124. ;заказать память под блок данных hgt*(wid*bytesperpix+1):
  125. ; if bpp=1
  126. ; then RawLen:=IHDRData.Width div bp+1 {bp:=8 div BitDepth} {реально надо округление вверх??? TODO проверить - сделал вверх}
  127. ; else RawLen:=IHDRData.Width*bpp+1;
  128. ;теоретически сейчас в DISKBUF может быть больше, чем размер текущего IDAT (хотя реально разрезают IDAT по 8K)        
  129. ;TODO переставить указатель файла на текущий байт и прочитать на размер текущего IDAT (если это меньше DUSKBUFsz)
  130. ;а пока без перестановки указателя - узнаем, какую часть IDAT мы уже прочитали, и вычитаем её из chunk size
  131. ;chunksize -= DISKBUF+DISKBUFsz-(iy+1) ;может быть 0
  132. ;[chunksize += iy + (1 - (DISKBUF+DISKBUFsz)) ;может быть 0]
  133.         exx
  134. ;dehl=chunk size
  135.         push iy
  136.         pop bc
  137.         push hl
  138.         ld hl,DISKBUF+DISKBUFsz-1
  139.         or a
  140.         sbc hl,bc
  141.         ld b,h
  142.         ld c,l ;iy + (1 - (DISKBUF+DISKBUFsz))
  143.         pop hl
  144.         or a
  145.         sbc hl,bc
  146.         jr nc,$+3
  147.         dec de
  148.         ld (pngIDATremained),hl
  149.         ld (pngIDATremainedHSW),de
  150.  
  151.         ld hl,(freemem_hl)
  152.         ld a,(freemem_a)
  153.         ld (pngdepktoaddr),hl
  154.         ld (pngdepktoaddrHSB),a
  155.         ld (pngdecodefromaddr),hl
  156.         ld (pngdecodefromaddrHSB),a
  157.  
  158.         ld de,(curpicwid)
  159. png_bytesperpix=$+1
  160.         ld bc,0
  161.         call MULWORD ;hlbc=de*bc
  162.  
  163.         ld a,(readpng_bitdepth)
  164.         cp 8
  165.         jr nc,readpng_chunk_IDATlinesizeok ;нельзя генерить палитру, т.к. бывает YA?
  166.         cp 4
  167.          ld e,17
  168.         jr z,readpng_chunk_IDATlinesizediv2
  169.         cp 2
  170.          ld e,85
  171.         jr z,readpng_chunk_IDATlinesizediv4
  172.          ld e,255
  173.         inc bc
  174.         srl b
  175.         rr c
  176. readpng_chunk_IDATlinesizediv4
  177.         inc bc
  178.         srl b
  179.         rr c
  180. readpng_chunk_IDATlinesizediv2
  181.         inc bc
  182.         srl b
  183.         rr c
  184. ;сгенерировать нужную серую палитру:
  185.          ld a,(readpng_palflag_bit0)
  186.          rra
  187.          jr c,readpng_chunk_IDATlinesizeok ;настоящую палитру уже прочитали
  188.  
  189.         push hl
  190.         xor a
  191.         ld l,a
  192. ;4bits: step=17
  193. ;2bits: step=85
  194. ;1bit: step=255
  195. readpng_getgreypal0
  196.         ld h,PNGPAL/256
  197.         ld (hl),a
  198.         inc h
  199.         ld (hl),a
  200.         inc h
  201.         ld (hl),a
  202.         add a,e;step
  203.         inc l
  204.         jr nz,readpng_getgreypal0
  205.         pop hl
  206.  
  207.          ld a,1
  208.          ld (readpng_palflag_bit0),a
  209. readpng_chunk_IDATlinesizeok
  210.          ld (png_bytesperline),bc
  211.         inc bc ;every line starts with subfilter byte
  212.          ;bc=physical line data size
  213.         ld de,(curpichgt)
  214.         call MULWORD ;hlbc=de*bc = размер блока данных
  215.         ld d,b
  216.         ld e,c
  217. ;hlde=size
  218.         call reserve_mem ;портит номер банка в 0xc000
  219.          call gifsetpgLZW
  220.  
  221. ;zlib/gzip header:
  222.         call RDBYTE ;0xW8, W=max window
  223.         call RDBYTE ;7..6=compression level, 5=DICT (TODO read 4 bytes - и что с ними делать?), 4..0=for multiple of 31
  224. ;
  225.        
  226.         call INFLATING
  227.  
  228. ;render:
  229.         ld hl,LINEPNGPRIOR
  230.         ld de,LINEPNGPRIOR+1
  231.         ld bc,(png_bytesperline)
  232.         dec bc
  233.         ld (hl),BACKGROUNDCOLORLEVEL
  234.         ldir
  235.         ld hl,0
  236.         ld (LINEPNG-2),hl
  237.         ld (LINEPNG-4),hl ;чтобы не проверять k>=bpp
  238.         ld (LINEPNG-6),hl
  239.         ld (LINEPNG-8),hl ;чтобы не проверять k>=bpp
  240.         ld (LINEPNGPRIOR-2),hl
  241.         ld (LINEPNGPRIOR-4),hl ;чтобы не проверять k>=bpp
  242.         ld (LINEPNGPRIOR-6),hl
  243.         ld (LINEPNGPRIOR-8),hl ;чтобы не проверять k>=bpp
  244.  
  245. pngdecodefromaddr=$+1
  246.         ld hl,0
  247. pngdecodefromaddrHSB=$+1
  248.         ld a,0
  249.  
  250.         ld bc,(curpichgt)
  251. renderpng_lines0
  252.         push bc
  253.         call readbyte ;subfilter byte
  254.          ld lx,c
  255.          ;ld b,a
  256.          ;ld a,c
  257.          ;cp 5
  258.          ;ld a,b
  259.          ;jr nc,$
  260.  
  261.         ld de,LINEPNG
  262. png_bytesperline=$+1
  263.         ld bc,0
  264.         push bc
  265.         push af
  266.         push hl
  267.         call getfrommem
  268.         pop hl
  269.         pop af
  270.         pop bc
  271.         add hl,bc
  272.         adc a,0
  273.         push af
  274.         push hl
  275.        
  276.         ld bc,(png_bytesperpix)
  277.         ld de,LINEPNG
  278.         ld hl,LINEPNGPRIOR
  279.         push hl
  280.         push de
  281.         ;or a
  282.         sbc hl,bc
  283.         ex de,hl
  284.         ;or a
  285.         sbc hl,bc
  286.         exx
  287.         pop hl ;LINEPNG
  288.         pop de ;LINEPNGPRIOR
  289.         ld bc,(png_bytesperline)
  290.         ld a,lx
  291.         or a
  292.         jr z,pngfilterq
  293.         dec a
  294.         jr z,png_sub
  295.         dec a
  296.         jr z,png_up
  297.         dec a
  298.         jr z,png_average
  299.          ;dec a
  300.          ;jr nz,$
  301. png_paeth
  302. ;      if k>=bpp
  303. ;      then inc(ImageData[i],PaethPredictor(Raw[k-bpp],Prior[k],Prior[k-bpp]))
  304. ;      else inc(ImageData[i],PaethPredictor(0,Prior[k],0));
  305.         exx
  306.         ex de,hl
  307.         exx
  308. renderpng_paeth0
  309.         ld a,(de)
  310.         exx
  311.         call paethpredictor ;(de),a,(hl)
  312.         inc hl
  313.         inc de
  314.         exx
  315.         add a,(hl)
  316.         ld (hl),a
  317.         inc de
  318.         cpi
  319.         jp pe,renderpng_paeth0
  320.         jr pngfilterq
  321. png_sub
  322. ;      if k>=bpp
  323. ;      then inc(ImageData[i],Raw[k-Bpp]);
  324.         exx
  325.         push hl ;raw-
  326.         exx
  327.         pop de
  328. png_up
  329. ;      inc(ImageData[i],Prior[k]);
  330. renderpng_up0
  331.         ld a,(de) ;prior
  332.         add a,(hl)
  333.         ld (hl),a
  334.         inc de
  335.         cpi
  336.         jp pe,renderpng_up0
  337.         jr pngfilterq
  338. png_average
  339. ;      if k>=bpp
  340. ;      then inc(ImageData[i],(Raw[k-bpp]+Prior[k])div 2)
  341. ;      else inc(ImageData[i],Prior[k]div 2);
  342. renderpng_average0
  343.         ld a,(de)
  344.         exx
  345.         add a,(hl)
  346.         inc hl
  347.         exx
  348.         rra
  349.         add a,(hl)
  350.         ld (hl),a
  351.         inc de
  352.         cpi
  353.         jp pe,renderpng_average0
  354.        
  355. pngfilterq
  356.        
  357.         call islinevisible
  358.         jp nz,renderpng_lineinvisible
  359.        
  360. ;конвертировать составляющие из 16bit в 8bit:
  361.         ld hl,LINEPNG
  362.         ld de,LINEPNGPRIOR ;result of recolor
  363.         ld a,(readpng_bitdepth)
  364.         cp 16
  365.         ld a,(png_bytesperpix)
  366.         jr nz,pngrecolor16q
  367.         rra
  368.         push de
  369.         ld de,LINEPNGTEMP ;TODO в конце PRIOR
  370.         push de
  371.         ;jr $
  372.         ld bc,(png_bytesperline)
  373.         srl b
  374.         rr c
  375. pngrecolor160
  376.         inc hl
  377.         ldi
  378.         jp pe,pngrecolor160
  379.         pop hl
  380.         pop de ;будем перекодировать TEMP->PRIOR
  381. pngrecolor16q
  382. ;конвертировать из bpp в 24bit:
  383. ;hl=from
  384. ;de=to
  385. ;a=число цветовых составляющих(1..4)
  386.          ;jr $
  387.         ld bc,(curpicwid)
  388.         dec a
  389.         jr z,pngrecolor1
  390.         dec a
  391.         jp z,pngrecolor2
  392.         dec a
  393.         jp z,pngrecolor3
  394. ;32bpp: RGBA -> BGR
  395. pngrecolorRGBA0
  396.         ld a,(hl)
  397.         inc hl
  398.         ex af,af' ;R
  399.        ld a,(hl) ;G
  400.        inc hl
  401.        ldi ;B
  402.        ld (de),a ;G
  403.        inc de
  404.        ex af,af'
  405.         ld (de),a ;R
  406.         inc de
  407.         ex af,af'
  408.        inc hl ;skip A
  409.        jp pe,pngrecolorRGBA0
  410.        jp pngrecolorq
  411. pngrecolor1
  412.        ;jr $
  413. ;8bpp: Y -> BGR
  414. readpng_palflag_bit0=$+1
  415.        ld a,0
  416.        rra
  417.        jp nc,pngrecolorY0
  418. readpng_bitdepth=$+1
  419.        ld a,0
  420.        cp 8
  421.        jr z,pngrecolorPAL80
  422.        cp 4
  423.        jr z,pngrecolorPAL4
  424.        cp 2
  425.        jr z,pngrecolorPAL2
  426. pngrecolorPAL1
  427. ;bc = (bc+7)/8 = (bc-1)/8 + 1
  428.        dec bc
  429.        ld a,c
  430.        srl b
  431.        rra
  432.        srl b
  433.        rra
  434.        srl b
  435.        rra
  436.        ld c,a
  437.        inc bc
  438. pngrecolorPAL10
  439.        push hl
  440.        ld a,(hl)
  441.        scf
  442.        rla
  443. pngrecolorPAL100
  444.        ld l,0
  445.        rl l
  446.        call pngrepal
  447.        inc bc ;ldi compensation
  448.        add a,a
  449.        jr nz,pngrecolorPAL100
  450.        pop hl
  451.        cpi
  452.        jp pe,pngrecolorPAL10
  453.        jp pngrecolorq
  454. pngrecolorPAL4
  455. ;round least bit up
  456.        inc bc
  457.        res 0,c
  458. pngrecolorPAL40
  459.        push hl
  460.        ld a,(hl)
  461.        push af
  462.        rra
  463.        rra
  464.        rra
  465.        rra
  466.        and 0x0f
  467.        ld l,a
  468.        call pngrepal
  469.        pop af
  470.        and 0x0f
  471.        ld l,a
  472.        call pngrepal
  473.        pop hl
  474.        inc hl
  475.        jp pe,pngrecolorPAL40
  476.        jr pngrecolorq      
  477. pngrecolorPAL2        
  478. ;round 2 least bits up
  479.        inc bc
  480.        inc bc
  481.        inc bc
  482.        res 1,c
  483.        res 0,c
  484. pngrecolorPAL20
  485.        push hl
  486.        ld a,(hl)
  487.        call pngrepal2bits
  488.        call pngrepal2bits
  489.        call pngrepal2bits
  490.        call pngrepal2bits
  491.        pop hl
  492.        inc hl
  493.        jp pe,pngrecolorPAL20
  494.        jr pngrecolorq
  495. pngrecolorPAL80
  496.        push hl
  497.        ld l,(hl)
  498.        call pngrepal
  499.        pop hl
  500.        inc hl
  501.        jp pe,pngrecolorPAL80
  502.        jr pngrecolorq
  503. pngrecolorY0
  504.        ld a,(hl)
  505.        ldi ;B
  506.        ld (de),a ;G
  507.        inc de
  508.        ld (de),a ;R
  509.        inc de
  510.        jp pe,pngrecolorY0
  511.        jr pngrecolorq
  512. pngrecolor2
  513. ;16bpp: YA -> BGR
  514. pngrecolorYA0
  515.        ld a,(hl)
  516.        ldi ;B
  517.        ld (de),a ;G
  518.        inc de
  519.        ld (de),a ;R
  520.        inc de
  521.        inc hl ;skip A
  522.        jp pe,pngrecolorYA0
  523.        jr pngrecolorq
  524. pngrecolor3
  525. ;24bpp: RGB -> BGR
  526. pngrecolorRGB0
  527.        ld a,(hl)
  528.        inc hl
  529.        ex af,af' ;R
  530.         ld a,(hl) ;G
  531.         inc hl
  532.         ldi ;B
  533.         ld (de),a ;G
  534.         inc de
  535.         ex af,af'
  536.        ld (de),a ;R
  537.        inc de
  538.        ex af,af'        
  539.         jp pe,pngrecolorRGB0
  540.         jr pngrecolorq
  541. pngrecolorq
  542.         ld h,d
  543.         ld l,e
  544.         ld (hl),b;0
  545.         inc de
  546.         ld bc,7*3-1
  547.         ldir ;чтобы справа в остатке знакоместа была чернота (потом можно убрать, когда readchr будет это делать)
  548.  
  549.         ld hl,LINEPNGPRIOR ;recolored line
  550.         call drawscreenline_frombuf ;конвертируем LINEGIF в LINEPIXELS и выводим её на экран
  551.         call keepconvertedline ;запоминаем сконверченную строку из LINEPIXELS
  552.         call nextoldconvertedframeaddr ;смещаем адрес, откуда брать сконверченную строку из предыдущего кадра (gifoldconvertedframeaddr)
  553. renderpng_lineinvisible
  554.         call inccury
  555.  
  556.         ld hl,LINEPNG
  557.         ld de,LINEPNGPRIOR
  558.         ld bc,(png_bytesperline)
  559.         ldir ;TODO менять местами указатели
  560.        
  561.         pop hl
  562.         pop af
  563.        
  564.         pop bc
  565.         dec hl
  566.         cpi
  567.         jp pe,renderpng_lines0
  568.  
  569.         ret ;остальное нас не интересует (курсор файла после unzip в случайном положении?)
  570.  
  571. ;function TPNG.PaethPredictor(a,b,c:BYTE):byte;
  572. ; var
  573. ;   pa,pb,pc:integer;
  574. ; begin {PaethPredictor}
  575. ;   pc:=a+b-c;
  576. ;   pa:=abs(pc-a); pb:=abs(pc-b); pc:=abs(pc-c);
  577. ;   if(pa<=pb)and(pa<=pc)
  578. ;   then Result:=a
  579. ;   else
  580. ;    if pb>pc
  581. ;    then Result:=c
  582. ;    else Result:=b;
  583. ; end; {PaethPredictor}
  584. paethpredictor
  585. ;?a=(de),?b=a,?c=(hl)
  586. ;out: a
  587.         ld hx,a;?b
  588.         sub (hl);?c
  589.         jr nc,$+4
  590.         neg
  591.          ld ly,a;?pa,a ;pa=abs(b-c)
  592.          
  593.         ld a,(de);?a
  594.         sub (hl);?c
  595.         jr nc,$+4
  596.         neg
  597.          ld hy,a;?pb,a ;pb=abs(a-c)
  598.          
  599.         ld a,(de);?a
  600.         add a,hx;?b
  601.         rra
  602.         jr c,paeth1
  603.         sub (hl);?c ;a=(a+b-2c)/2
  604.         jr nc,$+4
  605.         neg
  606.         add a,a
  607.         jp paethpredok
  608. paeth1
  609.         sub (hl);?c ;a=(a+b-2c)/2 - 1/2 ;1 вместо 1.5, -1 вместо -0.5
  610.         jr nc,$+3
  611.         cpl ;-1 (означает -0.5) => 0 (означает 0.5)
  612.         scf
  613.         rla
  614. paethpredok
  615.         jr nc,$+3
  616.         sbc a,a
  617.          ld lx,a;?pc,a ;pc=abs(a+b-2c) ;если >255, то 255
  618.          
  619.         ld a,hy;?pb
  620.         cp ly;?pa
  621.         jr c,paethpredictor_resultnoa ;pa>pb
  622.         ld a,lx;?pc
  623.         cp ly;?pa
  624.         jr nc,paethpredictor_resulta ;(pa<=pb)and(pa<=pc)
  625. paethpredictor_resultnoa
  626.         ld a,lx;?pc
  627.         cp hy;?pb
  628.         jr c,paethpredictor_resultc ;pb>pc
  629.         ld a,hx;?b
  630.         ret
  631. paethpredictor_resultc
  632.         ld a,(hl);?c
  633.         ret
  634. paethpredictor_resulta
  635.         ld a,(de);?a
  636.         ret
  637.  
  638. pngrepal2bits
  639.         ld l,0
  640.         rla
  641.         rl l
  642.         rla
  643.         rl l
  644. pngrepal
  645. ;l=color index
  646. ;write 3 bytes from pal to (de)
  647. ;keeps a
  648. ;decrements bc with P/V flag
  649.         ld h,PNGPAL/256+2
  650.         ex af,af'
  651.        ld a,(hl) ;B
  652.        ld (de),a
  653.        inc de
  654.        dec h
  655.        ld a,(hl) ;G
  656.        ld (de),a
  657.        ex af,af'
  658.         inc de
  659.         dec h
  660.         ldi ;R
  661.         ret
  662.  
  663.