?login_element?

Subversion Repositories NedoOS

Rev

Rev 344 | 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.  
  256.         ld de,LINEPNG
  257. png_bytesperline=$+1
  258.         ld bc,0
  259.         push bc
  260.         push af
  261.         push hl
  262.         call getfrommem
  263.         pop hl
  264.         pop af
  265.         pop bc
  266.         add hl,bc
  267.         adc a,0
  268.         push af
  269.         push hl
  270.        
  271.         ld bc,(png_bytesperpix)
  272.         ld de,LINEPNG
  273.         ld hl,LINEPNGPRIOR
  274.         push hl
  275.         push de
  276.         ;or a
  277.         sbc hl,bc
  278.         ex de,hl
  279.         ;or a
  280.         sbc hl,bc
  281.         exx
  282.         pop hl ;LINEPNG
  283.         pop de ;LINEPNGPRIOR
  284.         ld bc,(png_bytesperline)
  285.         ld a,lx
  286.         or a
  287.         jr z,pngfilterq
  288.         dec a
  289.         jr z,png_sub
  290.         dec a
  291.         jr z,png_up
  292.         dec a
  293.         jr z,png_average
  294.          ;dec a
  295.          ;jr nz,$
  296. png_paeth
  297. ;      if k>=bpp
  298. ;      then inc(ImageData[i],PaethPredictor(Raw[k-bpp],Prior[k],Prior[k-bpp]))
  299. ;      else inc(ImageData[i],PaethPredictor(0,Prior[k],0));
  300.         exx
  301.         ex de,hl
  302.         exx
  303. renderpng_paeth0
  304.         ld a,(de)
  305.         exx
  306.         call paethpredictor ;(de),a,(hl)
  307.         inc hl
  308.         inc de
  309.         exx
  310.         add a,(hl)
  311.         ld (hl),a
  312.         inc de
  313.         cpi
  314.         jp pe,renderpng_paeth0
  315.         jr pngfilterq
  316. png_sub
  317. ;      if k>=bpp
  318. ;      then inc(ImageData[i],Raw[k-Bpp]);
  319.         exx
  320.         push hl ;raw-
  321.         exx
  322.         pop de
  323. png_up
  324. ;      inc(ImageData[i],Prior[k]);
  325. renderpng_up0
  326.         ld a,(de) ;prior
  327.         add a,(hl)
  328.         ld (hl),a
  329.         inc de
  330.         cpi
  331.         jp pe,renderpng_up0
  332.         jr pngfilterq
  333. png_average
  334. ;      if k>=bpp
  335. ;      then inc(ImageData[i],(Raw[k-bpp]+Prior[k])div 2)
  336. ;      else inc(ImageData[i],Prior[k]div 2);
  337. renderpng_average0
  338.         ld a,(de)
  339.         exx
  340.         add a,(hl)
  341.         inc hl
  342.         exx
  343.         rra
  344.         add a,(hl)
  345.         ld (hl),a
  346.         inc de
  347.         cpi
  348.         jp pe,renderpng_average0
  349.        
  350. pngfilterq
  351.         call islinevisible
  352.         jp nz,renderpng_lineinvisible
  353.  
  354. ;конвертировать составляющие из 16bit в 8bit:
  355.         ld hl,LINEPNG
  356.         ld de,LINEPNGPRIOR ;result of recolor
  357.         ld a,(readpng_bitdepth)
  358.         cp 16
  359.         ld a,(png_bytesperpix)
  360.         jr nz,pngrecolor16q
  361.         rra
  362.         push de
  363.         ld de,LINEPNGTEMP ;TODO в конце PRIOR
  364.         push de
  365.         ld bc,(png_bytesperline)
  366.         srl b
  367.         rr c
  368. pngrecolor160
  369.         inc hl
  370.         ldi
  371.         jp pe,pngrecolor160
  372.         pop hl
  373.         pop de ;будем перекодировать TEMP->PRIOR
  374. pngrecolor16q
  375. ;конвертировать из bpp в 24bit:
  376. ;hl=from
  377. ;de=to
  378. ;a=число цветовых составляющих(1..4)
  379.         ld bc,(curpicwid)
  380.         dec a
  381.         jr z,pngrecolor1
  382.         dec a
  383.         jp z,pngrecolor2
  384.         dec a
  385.         jp z,pngrecolor3
  386. ;32bpp: RGBA -> BGR
  387. pngrecolorRGBA0
  388.         ld a,(hl)
  389.         inc hl
  390.         ex af,af' ;R
  391.        ld a,(hl) ;G
  392.        inc hl
  393.        ldi ;B
  394.        ld (de),a ;G
  395.        inc de
  396.        ex af,af'
  397.         ld (de),a ;R
  398.         inc de
  399.         ex af,af'
  400.        inc hl ;skip A
  401.        jp pe,pngrecolorRGBA0
  402.        jp pngrecolorq
  403. pngrecolor1
  404. ;8bpp: Y -> BGR
  405. readpng_palflag_bit0=$+1
  406.        ld a,0
  407.        rra
  408.        jp nc,pngrecolorY0
  409. readpng_bitdepth=$+1
  410.        ld a,0
  411.        cp 8
  412.        jr z,pngrecolorPAL80
  413.        cp 4
  414.        jr z,pngrecolorPAL4
  415.        cp 2
  416.        jr z,pngrecolorPAL2
  417. pngrecolorPAL1
  418. ;bc = (bc+7)/8 = (bc-1)/8 + 1
  419.        dec bc
  420.        ld a,c
  421.        srl b
  422.        rra
  423.        srl b
  424.        rra
  425.        srl b
  426.        rra
  427.        ld c,a
  428.        inc bc
  429. pngrecolorPAL10
  430.        push hl
  431.        ld a,(hl)
  432.        scf
  433.        rla
  434. pngrecolorPAL100
  435.        ld l,0
  436.        rl l
  437.        call pngrepal
  438.        inc bc ;ldi compensation
  439.        add a,a
  440.        jr nz,pngrecolorPAL100
  441.        pop hl
  442.        cpi
  443.        jp pe,pngrecolorPAL10
  444.        jp pngrecolorq
  445. pngrecolorPAL4
  446. ;round least bit up
  447.        inc bc
  448.        res 0,c
  449. pngrecolorPAL40
  450.        push hl
  451.        ld a,(hl)
  452.        push af
  453.        rra
  454.        rra
  455.        rra
  456.        rra
  457.        and 0x0f
  458.        ld l,a
  459.        call pngrepal
  460.        pop af
  461.        and 0x0f
  462.        ld l,a
  463.        call pngrepal
  464.        pop hl
  465.        inc hl
  466.        jp pe,pngrecolorPAL40
  467.        jr pngrecolorq      
  468. pngrecolorPAL2        
  469. ;round 2 least bits up
  470.        inc bc
  471.        inc bc
  472.        inc bc
  473.        res 1,c
  474.        res 0,c
  475. pngrecolorPAL20
  476.        push hl
  477.        ld a,(hl)
  478.        call pngrepal2bits
  479.        call pngrepal2bits
  480.        call pngrepal2bits
  481.        call pngrepal2bits
  482.        pop hl
  483.        inc hl
  484.        jp pe,pngrecolorPAL20
  485.        jr pngrecolorq
  486. pngrecolorPAL80
  487.        push hl
  488.        ld l,(hl)
  489.        call pngrepal
  490.        pop hl
  491.        inc hl
  492.        jp pe,pngrecolorPAL80
  493.        jr pngrecolorq
  494. pngrecolorY0
  495.        ld a,(hl)
  496.        ldi ;B
  497.        ld (de),a ;G
  498.        inc de
  499.        ld (de),a ;R
  500.        inc de
  501.        jp pe,pngrecolorY0
  502.        jr pngrecolorq
  503. pngrecolor2
  504. ;16bpp: YA -> BGR
  505. pngrecolorYA0
  506.        ld a,(hl)
  507.        ldi ;B
  508.        ld (de),a ;G
  509.        inc de
  510.        ld (de),a ;R
  511.        inc de
  512.        inc hl ;skip A
  513.        jp pe,pngrecolorYA0
  514.        jr pngrecolorq
  515. pngrecolor3
  516. ;24bpp: RGB -> BGR
  517. pngrecolorRGB0
  518.        ld a,(hl)
  519.        inc hl
  520.        ex af,af' ;R
  521.         ld a,(hl) ;G
  522.         inc hl
  523.         ldi ;B
  524.         ld (de),a ;G
  525.         inc de
  526.         ex af,af'
  527.        ld (de),a ;R
  528.        inc de
  529.        ex af,af'        
  530.         jp pe,pngrecolorRGB0
  531.         jr pngrecolorq
  532. pngrecolorq
  533.         ld h,d
  534.         ld l,e
  535.         ld (hl),b;0
  536.         inc de
  537.         ld bc,7*3-1
  538.         ldir ;чтобы справа в остатке знакоместа была чернота (потом можно убрать, когда readchr будет это делать)
  539.  
  540.         ld hl,LINEPNGPRIOR ;recolored line
  541.         call drawscreenline_frombuf ;конвертируем LINEGIF в LINEPIXELS и выводим её на экран
  542.         call keepconvertedline ;запоминаем сконверченную строку из LINEPIXELS
  543.         call nextoldconvertedframeaddr ;смещаем адрес, откуда брать сконверченную строку из предыдущего кадра (gifoldconvertedframeaddr)
  544. renderpng_lineinvisible
  545.         call inccury
  546.  
  547.         ld hl,LINEPNG
  548.         ld de,LINEPNGPRIOR
  549.         ld bc,(png_bytesperline)
  550.         ldir ;TODO менять местами указатели
  551.        
  552.         pop hl
  553.         pop af
  554.        
  555.         pop bc
  556.         dec hl
  557.         cpi
  558.         jp pe,renderpng_lines0
  559.  
  560.         ret ;остальное нас не интересует (курсор файла после unzip в случайном положении?)
  561.  
  562. ;function TPNG.PaethPredictor(a,b,c:BYTE):byte;
  563. ; var
  564. ;   pa,pb,pc:integer;
  565. ; begin {PaethPredictor}
  566. ;   pc:=a+b-c;
  567. ;   pa:=abs(pc-a); pb:=abs(pc-b); pc:=abs(pc-c);
  568. ;   if(pa<=pb)and(pa<=pc)
  569. ;   then Result:=a
  570. ;   else
  571. ;    if pb>pc
  572. ;    then Result:=c
  573. ;    else Result:=b;
  574. ; end; {PaethPredictor}
  575. paethpredictor
  576. ;?a=(de),?b=a,?c=(hl)
  577. ;out: a
  578.         ld hx,a;?b
  579.         sub (hl);?c
  580.         jr nc,$+4
  581.           neg
  582.          ld ly,a;?pa,a ;pa=abs(b-c)
  583.          
  584.         ld a,(de);?a
  585.         sub (hl);?c
  586.         jr nc,$+4
  587.           neg
  588.          ld hy,a;?pb,a ;pb=abs(a-c)
  589.          
  590.         ld a,(de);?a
  591.         add a,hx;?b
  592.         rra
  593.         jr c,paeth1
  594.         sub (hl);?c ;a=(a+b-2c)/2
  595.         jr nc,$+4
  596.           neg
  597.         add a,a
  598.         jp paethpredok
  599. paeth1
  600.         sub (hl);?c ;a=(a+b-2c)/2 - 1/2 ;1 вместо 1.5, -1 вместо -0.5
  601.         jr nc,$+3
  602.           cpl ;-1 (означает -0.5) => 0 (означает 0.5)
  603.         scf
  604.         rla
  605. paethpredok
  606.         jr nc,$+3
  607.           sbc a,a
  608.          ld lx,a;?pc,a ;pc=abs(a+b-2c) ;если >255, то 255
  609.          
  610.         ld a,hy;?pb
  611.         cp ly;?pa
  612.         jr c,paethpredictor_resultnoa ;pa>pb
  613.         ld a,lx;?pc
  614.         cp ly;?pa
  615.         jr nc,paethpredictor_resulta ;(pa<=pb)and(pa<=pc)
  616. paethpredictor_resultnoa
  617.         ld a,lx;?pc
  618.         cp hy;?pb
  619.         jr c,paethpredictor_resultc ;pb>pc
  620.         ld a,hx;?b
  621.         ret
  622. paethpredictor_resultc
  623.         ld a,(hl);?c
  624.         ret
  625. paethpredictor_resulta
  626.         ld a,(de);?a
  627.         ret
  628.  
  629. pngrepal2bits
  630.         ld l,0
  631.         rla
  632.         rl l
  633.         rla
  634.         rl l
  635. pngrepal
  636. ;l=color index
  637. ;write 3 bytes from pal to (de)
  638. ;keeps a
  639. ;decrements bc with P/V flag
  640.         ld h,PNGPAL/256+2
  641.         ex af,af'
  642.        ld a,(hl) ;B
  643.        ld (de),a
  644.        inc de
  645.        dec h
  646.        ld a,(hl) ;G
  647.        ld (de),a
  648.        ex af,af'
  649.         inc de
  650.         dec h
  651.         ldi ;R
  652.         ret
  653.